13#include <kernel/version.h>
100 if (addr >= symbol->
start && addr < symbol->end)
104 *offset = addr - symbol->
start;
115 static const char* names[] = {
121 "bound range exceeded",
123 "device not available",
125 "coprocessor segment overrun",
127 "segment not present",
129 "general protection",
136 "virtualization exception",
137 "control protection exception",
140 if (vector <
sizeof(names) /
sizeof(names[0]))
142 return names[vector];
144 return "unknown exception";
155 LOG_PANIC(
"<%s+0x%llx>", symbol, offset);
159 LOG_PANIC(
"rsp: %04llx:0x%016llx rflags: 0x%08llx\n", frame->
ss, frame->
rsp, frame->
rflags & 0xFFFFFFFF);
161 LOG_PANIC(
"rax: 0x%016llx rbx: 0x%016llx rcx: 0x%016llx\n", frame->
rax, frame->
rbx, frame->
rcx);
162 LOG_PANIC(
"rdx: 0x%016llx rsi: 0x%016llx rdi: 0x%016llx\n", frame->
rdx, frame->
rsi, frame->
rdi);
163 LOG_PANIC(
"rbp: 0x%016llx r08: 0x%016llx r09: 0x%016llx\n", frame->
rbp, frame->
r8, frame->
r9);
164 LOG_PANIC(
"r10: 0x%016llx r11: 0x%016llx r12: 0x%016llx\n", frame->
r10, frame->
r11, frame->
r12);
165 LOG_PANIC(
"r13: 0x%016llx r14: 0x%016llx r15: 0x%016llx\n", frame->
r13, frame->
r14, frame->
r15);
171 LOG_PANIC(
"stack dump (around rsp=0x%016llx):\n", rsp);
173 const int linesToDump = 8;
174 const int bytesPerLine = 16;
175 uint64_t startaAddr = (rsp - (linesToDump / 2 - 1) * bytesPerLine) & ~(bytesPerLine - 1);
177 for (
int i = 0; i < linesToDump; i++)
179 uint64_t lineAddr = startaAddr + (i * bytesPerLine);
183 for (
int j = 0; j < bytesPerLine; j++)
198 for (
int j = 0; j < bytesPerLine; j++)
204 LOG_PANIC(
"%c", (c >= 32 && c <= 126) ? c :
'.');
213 if (rsp >= lineAddr && rsp < lineAddr + bytesPerLine)
217 uint64_t offsetInLine = rsp - lineAddr;
218 for (
uint64_t k = 0; k < offsetInLine; k++)
231 LOG_PANIC(
" [0x%016llx] <user space address>\n", addr);
239 LOG_PANIC(
" [0x%016llx] <unknown>\n", addr);
243 LOG_PANIC(
" [0x%016llx] <%s+0x%llx>\n", addr, symbol, offset);
250 void* currentFrame = __builtin_frame_address(0);
251 void* prevFrame =
NULL;
254 while (currentFrame !=
NULL && currentFrame != prevFrame)
267 void* returnAddress = *((
void**)currentFrame + 1);
268 if (returnAddress ==
NULL)
275 prevFrame = currentFrame;
276 currentFrame = *((
void**)currentFrame);
289 while (rbp !=
NULL && rbp != prevFrame)
302 if (prevFrame && rbp <= prevFrame)
308 if (returnAddress == 0)
341 symbol->start =
start;
371 if (expectedCpuId == self->
id)
373 const char* message =
"!!! KERNEL DOUBLE PANIC ON SAME CPU !!!\n";
391 LOG_PANIC(
"!!! KERNEL PANIC (%s version %s) !!!\n", OS_NAME, OS_VERSION);
395 if (currentThread ==
NULL)
413 uint64_t totalPages = freePages + reservedPages;
415 LOG_PANIC(
"memory: %lluK/%lluK available (%lluK kernel code/data, %lluK reserved)\n",
424 LOG_PANIC(
"cr0=0x%016llx cr2=0x%016llx cr3=0x%016llx cr4=0x%016llx\n", cr0, cr2, cr3, cr4);
479 LOG_PANIC(
"page fault details: A %s operation to a %s page caused a %s.\n",
480 (frame->
errorCode & 2) ?
"write" :
"read", (frame->
errorCode & 4) ?
"user-mode" :
"kernel-mode",
481 (frame->
errorCode & 1) ?
"protection violation" :
"non-present page fault");
484 LOG_PANIC(
" (Reserved bit violation)\n");
493 LOG_PANIC(
" (Faulting address is NULL)\n");
497 LOG_PANIC(
" (Faulting address is in kernel binary region)\n");
501 LOG_PANIC(
" (Faulting address is in kernel heap region)\n");
505 LOG_PANIC(
" (Faulting address is in kernel stacks region)\n");
516 LOG_PANIC(
"skipping stack dump due to page fault in kernel stack region\n");
529 LOG_PANIC(
"!!! Please restart your machine !!!\n");
531#ifdef QEMU_ISA_DEBUG_EXIT
#define MAX_NAME
Maximum length of names.
#define QEMU_ISA_DEBUG_EXIT_PORT
static void port_outb(uint16_t port, uint8_t val)
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
void smp_halt_others(void)
Halts all CPUs except the current one.
#define PANIC_NO_CPU_ID
Cpu ID indicating no CPU has panicked yet.
void panic_stack_trace(const interrupt_frame_t *frame)
Print a stack trace from a interrupt frame.
void panic_symbols_init(const boot_kernel_t *kernel)
Initialize panic symbols from the bootloader-provided kernel information.
void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
#define PANIC_MAX_STACK_FRAMES
Maximum stack frames to capture in a panic.
#define LOG_MAX_BUFFER
Maximum buffer size for a single log line.
void log_write(const char *string, uint64_t length)
Write directly to the log outputs without any formatting or headers.
#define LOG_PANIC(format,...)
void log_screen_enable(void)
Enable logging to the screen.
uint64_t pmm_free_amount(void)
Retrieves the amount of free physical memory.
uint64_t pmm_reserved_amount(void)
Retrieves the amount of reserved physical memory.
#define VMM_KERNEL_HEAP_MAX
The maximum address for the kernel heap.
#define VMM_KERNEL_STACKS_MAX
The maximum address for kernel stacks.
#define VMM_KERNEL_BINARY_MAX
The maximum address for the content of the kernel binary.
#define VMM_KERNEL_STACKS_MIN
The minimum address for kernel stacks.
#define VMM_IDENTITY_MAPPED_MIN
The minimum address for the identity mapped physical memory.
#define VMM_USER_SPACE_MAX
The maximum address for user space.
#define VMM_KERNEL_BINARY_MIN
The minimum address for the content of the kernel binary./*#end#*/.
#define VMM_USER_SPACE_MIN
The minimum address for user space.
#define VMM_KERNEL_HEAP_MIN
The minimum address for the kernel heap.
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
#define LIST_CREATE(name)
Creates a list initializer.
static void list_push(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
static void list_init(list_t *list)
Initializes a list.
#define PAGE_SIZE
Memory page size.
#define NULL
Pointer error value.
static atomic_uint32_t panicCpudId
static void panic_direct_stack_trace(void)
static bool symbolsLoaded
static bool panic_is_valid_stack_frame(void *ptr)
static bool panic_is_valid_address(uintptr_t addr)
static const char * panic_resolve_symbol(uintptr_t addr, uintptr_t *offset)
static void panic_print_trace_address(uintptr_t addr)
static void panic_registers(const interrupt_frame_t *frame)
static char panicBuffer[LOG_MAX_BUFFER]
static void panic_print_stack_dump(const interrupt_frame_t *frame)
static const char * panic_get_exception_name(uint64_t vector)
#define CR0_TASK_SWITCHED
#define CR0_EXTENSION_TYPE
#define CR0_NUMERIC_ERROR_ENABLE
#define CR0_WRITE_PROTECT
#define CR0_ALIGNMENT_MASK
static uint64_t cr2_read()
#define CR0_NOT_WRITE_THROUGH
#define CR0_CACHE_DISABLE
#define CR0_PAGING_ENABLE
static uint64_t cr3_read()
#define CR0_MONITOR_CO_PROCESSOR
#define CR0_PROTECTED_MODE_ENABLE
static uint64_t cr0_read()
static uint64_t cr4_read()
#define va_start(ap, parmN)
__builtin_va_list va_list
#define atomic_compare_exchange_strong(object, expected, desired)
#define ATOMIC_VAR_INIT(value)
__UINTPTR_TYPE__ uintptr_t
_PUBLIC int vsnprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format, va_list arg)
_PUBLIC void * malloc(size_t size)
_PUBLIC char * strerror(int errnum)
_PUBLIC char * strncpy(char *_RESTRICT s1, const char *_RESTRICT s2, size_t n)
_PUBLIC size_t strlen(const char *s)
thread_t * runThread
The currently running thread.
thread_t * idleThread
The thread that runs when the owner CPU is idling.
uintptr_t guardBottom
The bottom of the guard page, this address is inclusive.
Thread of execution structure.
process_t * process
The parent process that the thread executes within.
stack_pointer_t kernelStack
The kernel stack of the thread.
tid_t id
The thread id, unique within a process_t.