1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
//! CPU exception handler
const kata_memory = @import("../kata/memory.zig");
const memory = @import("../asm/memory.zig");
const panic = @import("panic.zig");
const sensei = @import("../kata/sensei/sensei.zig");
const serial = @import("../drivers/serial/serial.zig");
const types = @import("types.zig");
const NAMES = [_][]const u8{
"Division By Zero",
"Debug",
"Non-Maskable Interrupt",
"Breakpoint",
"Overflow",
"Bound Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved",
};
var in_exception: bool = false;
export fn exception_handler(frame_ptr: u64) void {
const frame = @as(*types.ExceptionFrame, @ptrFromInt(frame_ptr));
// Prevent infinite recursion if exception handler itself faults
if (in_exception) {
serial.print("NESTED EXCEPTION - HALTING\n");
while (true) {
asm volatile ("cli; hlt");
}
}
in_exception = true;
// Handle page faults - check for stack growth
if (frame.int_num == 14) {
const cr2 = memory.read_page_fault_address();
const is_not_present = (frame.error_code & 1) == 0;
const is_rsvd = (frame.error_code & 8) != 0;
// Check if fault is in user stack region (demand paging)
if (sensei.get_current_kata()) |kata| {
if (cr2 >= kata.user_stack_bottom and cr2 < kata.user_stack_top and is_not_present and !is_rsvd) {
if (kata_memory.grow_stack(kata, cr2)) {
in_exception = false;
return;
}
}
}
}
serial.print("\n!!! EXCEPTION: ");
if (frame.int_num < NAMES.len) {
serial.print(NAMES[frame.int_num]);
} else {
serial.print("Unknown");
}
serial.print(" !!!\n");
serial.printf("Vector: {x}\n", .{frame.int_num});
serial.printf("Error Code: {x}\n", .{frame.error_code});
serial.printf("RIP: {x}\n", .{frame.rip});
serial.printf("CS: {x}\n", .{frame.cs});
serial.printf("RFLAGS: {x}\n", .{frame.rflags});
serial.printf("RSP: {x}\n", .{frame.rsp});
serial.printf("SS: {x}\n", .{frame.ss});
if (frame.int_num == 14) {
const cr2 = memory.read_page_fault_address();
serial.printf("CR2 (fault addr): {x}\n", .{cr2});
if (sensei.get_current_kata()) |kata| {
serial.printf("Stack: bottom={x} committed={x} top={x}\n", .{ kata.user_stack_bottom, kata.user_stack_committed, kata.user_stack_top });
serial.printf("Kata: id={x} PT={x}\n", .{ kata.id, kata.page_table });
}
serial.print("Fault type: ");
if ((frame.error_code & 1) == 0) {
serial.print("Page not present");
} else {
serial.print("Protection violation");
}
if ((frame.error_code & 2) != 0) {
serial.print(", Write");
} else {
serial.print(", Read");
}
if ((frame.error_code & 4) != 0) {
serial.print(", User mode");
} else {
serial.print(", Kernel mode");
}
if ((frame.error_code & 8) != 0) {
serial.print(", RESERVED BIT SET");
}
serial.print("\n");
serial.printf("CR3 (page table): {x}\n", .{memory.read_page_table_base()});
}
serial.print("\nRegisters:\n");
serial.printf("RAX: {x} RBX: {x}\n", .{ frame.rax, frame.rbx });
serial.printf("RCX: {x} RDX: {x}\n", .{ frame.rcx, frame.rdx });
serial.printf("RSI: {x} RDI: {x}\n", .{ frame.rsi, frame.rdi });
serial.printf("RBP: {x}\n", .{frame.rbp});
serial.printf("R8: {x} R9: {x}\n", .{ frame.r8, frame.r9 });
serial.printf("R10: {x} R11: {x}\n", .{ frame.r10, frame.r11 });
serial.printf("R12: {x} R13: {x}\n", .{ frame.r12, frame.r13 });
serial.printf("R14: {x} R15: {x}\n", .{ frame.r14, frame.r15 });
panic.collapse(if (frame.int_num < NAMES.len) NAMES[frame.int_num] else "Unknown Exception", null);
}
|