From 70099da49712e8cca7a15ba938a0f2c6a7830aa8 Mon Sep 17 00:00:00 2001 From: Sainnhe Park Date: Sun, 9 Jan 2022 17:13:30 +0800 Subject: [PATCH] CPU Exception --- src/interrupts.rs | 19 +++++++++++++++++++ src/lib.rs | 14 ++++++++++++++ src/main.rs | 4 ++++ 3 files changed, 37 insertions(+) create mode 100644 src/interrupts.rs diff --git a/src/interrupts.rs b/src/interrupts.rs new file mode 100644 index 0000000..6b94536 --- /dev/null +++ b/src/interrupts.rs @@ -0,0 +1,19 @@ +use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use crate::println; +use lazy_static::lazy_static; + +lazy_static! { + static ref IDT: InterruptDescriptorTable = { + let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + idt + }; +} + +pub fn init_idt() { + IDT.load(); +} + +extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { + println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); +} diff --git a/src/lib.rs b/src/lib.rs index 6bfd3ea..da85caa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,10 +3,12 @@ #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] +#![feature(abi_x86_interrupt)] use core::panic::PanicInfo; pub mod serial; pub mod vga_buffer; +pub mod interrupts; pub trait Testable { fn run(&self) -> (); @@ -41,6 +43,7 @@ pub fn test_panic_handler(info: &PanicInfo) -> ! { #[cfg(test)] #[no_mangle] pub extern "C" fn _start() -> ! { + init(); test_main(); loop {} } @@ -51,6 +54,14 @@ fn panic(info: &PanicInfo) -> ! { test_panic_handler(info) } +#[test_case] +fn test_breakpoint_exception() { + x86_64::instructions::interrupts::int3(); + // 如果程序继续运行则说明测试成功 + // 用 cargo test 运行全部测试 + // 或 cargo test --lib 仅运行库测试 +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub enum QemuExitCode { @@ -67,3 +78,6 @@ pub fn exit_qemu(exit_code: QemuExitCode) { } } +pub fn init() { + interrupts::init_idt(); +} diff --git a/src/main.rs b/src/main.rs index 7fdc618..4f867d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,10 @@ use anos::println; pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); + anos::init(); + x86_64::instructions::interrupts::int3(); + println!("It didn't crash!"); + #[cfg(test)] test_main();