1919#include "../libk/ports.h"
2020#include "../libk/string.h"
2121#include "../libk/debug/log.h"
22+ #include "../drv/vga.h"
2223#include "../kernel/sched.h"
2324#include <stdint.h>
2425
@@ -30,8 +31,138 @@ void register_interrupt_handler(uint8_t interrupt, isr_handler_t handler, const
3031 interrupt_handlers [interrupt ] = handler ;
3132}
3233
34+ static const char * exception_title (uint64_t int_no )
35+ {
36+ switch (int_no ) {
37+ case DIVISION_BY_ZERO : return "Division by zero" ;
38+ case DEBUG_EXCEPTION : return "Debug exception" ;
39+ case NON_MASKABLE_INTERRUPT : return "Non-maskable interrupt" ;
40+ case BREAKPOINT_EXCEPTION : return "Breakpoint" ;
41+ case OVERFLOW_EXCEPTION : return "Overflow" ;
42+ case BOUND_RANGE_EXCEEDED : return "Bound range exceeded" ;
43+ case INVALID_OPCODE_EXCEPTION : return "Invalid opcode" ;
44+ case DEVICE_NOT_AVAILABLE : return "Device not available" ;
45+ case DOUBLE_FAULT : return "Double fault" ;
46+ case INVALID_TSS : return "Invalid TSS" ;
47+ case SEGMENT_NOT_PRESENT : return "Segment not present" ;
48+ case STACK_SEGMENT_FAULT : return "Stack segment fault" ;
49+ case GENERAL_PROTECTION_FAULT : return "General protection fault" ;
50+ case PAGE_FAULT : return "Page fault" ;
51+ case X87_FLOATING_POINT : return "x87 floating point exception" ;
52+ case ALIGNMENT_CHECK : return "Alignment check" ;
53+ case MACHINE_CHECK : return "Machine check" ;
54+ case SIMD_FLOATING_POINT : return "SIMD floating point exception" ;
55+ case VIRTUALIZATION_EXCEPTION : return "Virtualization exception" ;
56+ case SECURITY_EXCEPTION : return "Security exception" ;
57+ default : return "CPU exception" ;
58+ }
59+ }
60+
61+ static const char * exception_splash (uint64_t int_no )
62+ {
63+ switch (int_no ) {
64+ case DIVISION_BY_ZERO : return "DIV0" ;
65+ case INVALID_OPCODE_EXCEPTION : return "UD" ;
66+ case DOUBLE_FAULT : return "DF" ;
67+ case INVALID_TSS : return "TSS" ;
68+ case SEGMENT_NOT_PRESENT : return "SNP" ;
69+ case STACK_SEGMENT_FAULT : return "SS" ;
70+ case GENERAL_PROTECTION_FAULT : return "GPF" ;
71+ case PAGE_FAULT : return "PF" ;
72+ case ALIGNMENT_CHECK : return "AC" ;
73+ case MACHINE_CHECK : return "MC" ;
74+ case SIMD_FLOATING_POINT : return "SIMD" ;
75+ default : return "EXCEPTION" ;
76+ }
77+ }
78+
79+ static void halt_forever (void )
80+ {
81+ for (;;)
82+ asm volatile ("cli; hlt" );
83+ }
84+
85+ static void kernel_exception_screen (registers_t * regs )
86+ {
87+ uint64_t cr2 = 0 ;
88+ if (regs -> int_no == PAGE_FAULT )
89+ asm volatile ("mov %%cr2, %0" : "=r" (cr2 ));
90+ task_t * task = sched_current_task ();
91+ const char * task_name = task ? task -> name : "kernel" ;
92+ int pid = task ? task -> pid : -1 ;
93+ uint16_t selector = (uint16_t )((regs -> err_code >> 3 ) & 0x1fff );
94+ char info [1536 ];
95+
96+ if (regs -> int_no == PAGE_FAULT ) {
97+ snprintf (info , sizeof (info ),
98+ "Task: %s (PID %d)\n"
99+ "Fault address: 0x%016lx\n"
100+ "Error: 0x%016lx %s %s %s\n"
101+ "RIP=0x%016lx RSP=0x%016lx RFLAGS=0x%016lx\n"
102+ "RAX=0x%016lx RBX=0x%016lx RCX=0x%016lx\n"
103+ "RDX=0x%016lx RSI=0x%016lx RDI=0x%016lx\n"
104+ "RBP=0x%016lx R8 =0x%016lx R9 =0x%016lx\n"
105+ "R10=0x%016lx R11=0x%016lx R12=0x%016lx\n"
106+ "R13=0x%016lx R14=0x%016lx R15=0x%016lx\n"
107+ "CS=0x%04lx SS=0x%04lx" ,
108+ task_name , pid , cr2 , regs -> err_code ,
109+ (regs -> err_code & 1 ) ? "protection" : "not-present" ,
110+ (regs -> err_code & 2 ) ? "write" : "read" ,
111+ (regs -> err_code & 4 ) ? "user" : "supervisor" ,
112+ regs -> rip , regs -> userrsp , regs -> rflags ,
113+ regs -> rax , regs -> rbx , regs -> rcx , regs -> rdx ,
114+ regs -> rsi , regs -> rdi , regs -> rbp ,
115+ regs -> r8 , regs -> r9 , regs -> r10 , regs -> r11 ,
116+ regs -> r12 , regs -> r13 , regs -> r14 , regs -> r15 ,
117+ regs -> cs , regs -> ss );
118+ } else if (regs -> int_no == GENERAL_PROTECTION_FAULT ) {
119+ snprintf (info , sizeof (info ),
120+ "Task: %s (PID %d)\n"
121+ "Error: 0x%016lx selector=0x%04x %s\n"
122+ "RIP=0x%016lx RSP=0x%016lx RFLAGS=0x%016lx\n"
123+ "RAX=0x%016lx RBX=0x%016lx RCX=0x%016lx\n"
124+ "RDX=0x%016lx RSI=0x%016lx RDI=0x%016lx\n"
125+ "RBP=0x%016lx R8 =0x%016lx R9 =0x%016lx\n"
126+ "R10=0x%016lx R11=0x%016lx R12=0x%016lx\n"
127+ "R13=0x%016lx R14=0x%016lx R15=0x%016lx\n"
128+ "CS=0x%04lx SS=0x%04lx" ,
129+ task_name , pid , regs -> err_code , selector ,
130+ (regs -> err_code & 1 ) ? "external" : "internal" ,
131+ regs -> rip , regs -> userrsp , regs -> rflags ,
132+ regs -> rax , regs -> rbx , regs -> rcx , regs -> rdx ,
133+ regs -> rsi , regs -> rdi , regs -> rbp ,
134+ regs -> r8 , regs -> r9 , regs -> r10 , regs -> r11 ,
135+ regs -> r12 , regs -> r13 , regs -> r14 , regs -> r15 ,
136+ regs -> cs , regs -> ss );
137+ } else {
138+ snprintf (info , sizeof (info ),
139+ "Task: %s (PID %d)\n"
140+ "Interrupt: %lu Error: 0x%016lx\n"
141+ "RIP=0x%016lx RSP=0x%016lx RFLAGS=0x%016lx\n"
142+ "RAX=0x%016lx RBX=0x%016lx RCX=0x%016lx\n"
143+ "RDX=0x%016lx RSI=0x%016lx RDI=0x%016lx\n"
144+ "RBP=0x%016lx R8 =0x%016lx R9 =0x%016lx\n"
145+ "R10=0x%016lx R11=0x%016lx R12=0x%016lx\n"
146+ "R13=0x%016lx R14=0x%016lx R15=0x%016lx\n"
147+ "CS=0x%04lx SS=0x%04lx" ,
148+ task_name , pid , regs -> int_no , regs -> err_code ,
149+ regs -> rip , regs -> userrsp , regs -> rflags ,
150+ regs -> rax , regs -> rbx , regs -> rcx , regs -> rdx ,
151+ regs -> rsi , regs -> rdi , regs -> rbp ,
152+ regs -> r8 , regs -> r9 , regs -> r10 , regs -> r11 ,
153+ regs -> r12 , regs -> r13 , regs -> r14 , regs -> r15 ,
154+ regs -> cs , regs -> ss );
155+ }
156+
157+ vga_crash_screen (exception_splash (regs -> int_no ), exception_title (regs -> int_no ), info );
158+ halt_forever ();
159+ }
160+
33161void isr_handler (registers_t * regs )
34162{
163+ if (regs -> int_no < 32 && !(regs -> cs & 3 ))
164+ kernel_exception_screen (regs );
165+
35166 switch (regs -> int_no ) {
36167 case DIVISION_BY_ZERO :
37168 if (regs -> cs & 3 ) {
0 commit comments