summaryrefslogtreecommitdiff
path: root/kernel/src/interrupts/exception_handlers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/interrupts/exception_handlers.rs')
-rw-r--r--kernel/src/interrupts/exception_handlers.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/kernel/src/interrupts/exception_handlers.rs b/kernel/src/interrupts/exception_handlers.rs
new file mode 100644
index 0000000..a3ecf9d
--- /dev/null
+++ b/kernel/src/interrupts/exception_handlers.rs
@@ -0,0 +1,95 @@
+use super::Interrupts;
+use crate::io::qemu;
+use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
+
+macro_rules! exception_default {
+ ($stack_frame: expr) => {
+ format_args!(
+ "instruction addr: 0x{:08x}\nstack addr: 0x{:08x}\nflags: 0x{:x}",
+ $stack_frame.instruction_pointer.as_u64(),
+ $stack_frame.stack_pointer.as_u64(),
+ $stack_frame.cpu_flags,
+ )
+ };
+}
+
+static mut expected_fault: Interrupts = Interrupts::None;
+
+pub unsafe fn expect_fault(int: Interrupts) {
+ if expected_fault == Interrupts::None {
+ expected_fault = int;
+ }
+}
+
+fn get_expected_fault() -> Interrupts {
+ unsafe { expected_fault }
+}
+
+pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFrame) {
+ match get_expected_fault() {
+ Interrupts::Breakpoint => qemu::exit_qemu(qemu::QemuExitCode::Success),
+ _ => panic!(
+ "BREAKPOINT exception thrown\n\n{}",
+ exception_default!(stack_frame)
+ ),
+ }
+}
+
+pub extern "x86-interrupt" fn general_protection_fault_handler(
+ stack_frame: &mut InterruptStackFrame,
+ error_code: u64,
+) {
+ match get_expected_fault() {
+ Interrupts::GeneralProtectionFault => qemu::exit_qemu(qemu::QemuExitCode::Success),
+ _ => panic!(
+ "GENERAL PROTECTION exception thrown\nerror code: {:x}\n{}",
+ error_code,
+ exception_default!(stack_frame)
+ ),
+ }
+}
+
+pub extern "x86-interrupt" fn page_fault_handler(
+ stack_frame: &mut InterruptStackFrame,
+ error_code: PageFaultErrorCode,
+) {
+ use x86_64::registers::control::Cr2;
+
+ match get_expected_fault() {
+ Interrupts::PageFault => qemu::exit_qemu(qemu::QemuExitCode::Success),
+ _ => panic!(
+ "PAGE FAULT while accessing address: 0x{:08x}\nerror code: {:?}(0x{:x})\n{}",
+ Cr2::read().as_u64(),
+ error_code,
+ error_code.bits(),
+ exception_default!(stack_frame)
+ ),
+ }
+}
+
+pub extern "x86-interrupt" fn segment_not_present_handler(
+ stack_frame: &mut InterruptStackFrame,
+ error_code: u64,
+) {
+ match get_expected_fault() {
+ Interrupts::NotPresent => qemu::exit_qemu(qemu::QemuExitCode::Success),
+ _ => panic!(
+ "SEGMENT NOT PRESENT exception\nerror code: 0x{:x}\n{}",
+ error_code,
+ exception_default!(stack_frame)
+ ),
+ }
+}
+
+pub extern "x86-interrupt" fn double_fault_handler(
+ stack_frame: &mut InterruptStackFrame,
+ _error_code: u64, // code is always zero
+) {
+ match get_expected_fault() {
+ Interrupts::DoubleFault => qemu::exit_qemu(qemu::QemuExitCode::Success),
+ _ => panic!(
+ "DOUBLE FAULT\nthis is a fatal exception\n{}",
+ exception_default!(stack_frame)
+ ),
+ }
+}