15#include <kernel/version.h>
36 static const char* names[] = {
42 "bound range exceeded",
44 "device not available",
46 "coprocessor segment overrun",
48 "segment not present",
57 "virtualization exception",
58 "control protection exception",
61 if (vector <
sizeof(names) /
sizeof(names[0]))
65 return "unknown exception";
79 LOG_PANIC(
"rsp: %04llx:0x%016llx rflags: 0x%08llx\n", frame->
ss, frame->
rsp, frame->
rflags & 0xFFFFFFFF);
81 LOG_PANIC(
"rax: 0x%016llx rbx: 0x%016llx rcx: 0x%016llx\n", frame->
rax, frame->
rbx, frame->
rcx);
82 LOG_PANIC(
"rdx: 0x%016llx rsi: 0x%016llx rdi: 0x%016llx\n", frame->
rdx, frame->
rsi, frame->
rdi);
83 LOG_PANIC(
"rbp: 0x%016llx r08: 0x%016llx r09: 0x%016llx\n", frame->
rbp, frame->
r8, frame->
r9);
84 LOG_PANIC(
"r10: 0x%016llx r11: 0x%016llx r12: 0x%016llx\n", frame->
r10, frame->
r11, frame->
r12);
85 LOG_PANIC(
"r13: 0x%016llx r14: 0x%016llx r15: 0x%016llx\n", frame->
r13, frame->
r14, frame->
r15);
142 LOG_PANIC(
"stack dump (around rsp=0x%016llx):\n", rsp);
144 const int linesToDump = 8;
145 const int bytesPerLine = 16;
146 uint64_t startaAddr = (rsp - (linesToDump / 2 - 1) * bytesPerLine) & ~(bytesPerLine - 1);
148 for (
int i = 0; i < linesToDump; i++)
150 uint64_t lineAddr = startaAddr + (i * bytesPerLine);
154 for (
int j = 0; j < bytesPerLine; j++)
169 for (
int j = 0; j < bytesPerLine; j++)
175 LOG_PANIC(
"%c", (c >= 32 && c <= 126) ? c :
'.');
184 if (rsp >= lineAddr && rsp < lineAddr + bytesPerLine)
188 uint64_t offsetInLine = rsp - lineAddr;
189 for (
uint64_t k = 0; k < offsetInLine; k++)
202 LOG_PANIC(
" [0x%016llx] <user space address>\n", addr);
209 LOG_PANIC(
" [0x%016llx] <unknown>\n", addr);
223 while (rbp !=
NULL && rbp != prevFrame)
238 if (returnAddress == 0)
240 LOG_PANIC(
" [0x%016llx] <null return address>\n", returnAddress);
246 LOG_PANIC(
" [0x%016llx] <failed to resolve>\n", returnAddress);
274 if (expectedCpuId == self->
id)
277 const char* message =
"!!! KERNEL DOUBLE PANIC ON SAME CPU !!!\n";
301 LOG_PANIC(
"!!! KERNEL PANIC (%s version %s) !!!\n", OS_NAME, OS_VERSION);
304 if (currentThread ==
NULL)
321 uint64_t totalPages = freePages + reservedPages;
323 LOG_PANIC(
"memory: %lluK/%lluK available (%lluK kernel code/data, %lluK reserved)\n",
332 LOG_PANIC(
"cr0=0x%016llx cr2=0x%016llx cr3=0x%016llx cr4=0x%016llx\n", cr0, cr2, cr3, cr4);
387 LOG_PANIC(
"page fault details: A %s operation to a %s page caused a %s.\n",
388 (frame->
errorCode & 2) ?
"write" :
"read", (frame->
errorCode & 4) ?
"user-mode" :
"kernel-mode",
389 (frame->
errorCode & 1) ?
"protection violation" :
"non-present page fault");
392 LOG_PANIC(
" (Reserved bit violation)\n");
401 LOG_PANIC(
" (Faulting address is NULL)\n");
405 LOG_PANIC(
" (Faulting address is in kernel binary region)\n");
409 LOG_PANIC(
" (Faulting address is in kernel heap region)\n");
413 LOG_PANIC(
" (Faulting address is in kernel stacks region)\n");
429 LOG_PANIC(
"!!! Please restart your machine !!!\n");
431#ifdef QEMU_EXIT_ON_PANIC
static void io_out8(port_t port, uint8_t val)
Write an 8-bit value to an I/O port.
uint64_t cpu_halt_others(void)
Halts all other CPUs.
static cpu_t * cpu_get_unsafe(void)
Gets the current CPU structure without disabling interrupts.
#define QEMU_EXIT_ON_PANIC_PORT
QEMU exit port for panic.
#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(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 various logging buffers.
void log_nprint(log_level_t level, const char *string, uint64_t length)
Print a unformatted log message.
#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_used_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.
uint64_t symbol_resolve_addr(symbol_info_t *outSymbol, void *addr)
Resolve a symbol by address.
#define errno
Error number variable.
#define PAGE_SIZE
The size of a memory page in bytes.
#define NULL
Pointer error value.
#define ERR
Integer error value.
static void panic_direct_stack_trace(void)
static atomic_uint32_t panicCpuId
static bool panic_is_valid_address(uintptr_t addr)
static void panic_unwind_stack(uintptr_t *rbp)
static void panic_registers(const interrupt_frame_t *frame)
static bool panic_is_valid_stack_frame(uintptr_t ptr)
static uint64_t panic_print_trace_address(uintptr_t addr)
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 char * strerror(int errnum)
_PUBLIC size_t strlen(const char *s)
thread_t *volatile runThread
The currently running thread on this CPU.
thread_t *volatile idleThread
The idle thread for this CPU.
Symbol information structure.
char name[SYMBOL_MAX_NAME]
Thread of execution structure.
process_t * process
The parent process that the thread executes within.
tid_t id
The thread id, unique within a process_t.