diff --git a/testing/Cargo.toml b/testing/Cargo.toml index fe08cc67c..7a32657c1 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Philipp Oppermann "] edition = "2018" [[test]] -name = "breakpoint_exception" +name = "interrupt_handling" harness = false [[test]] diff --git a/testing/tests/breakpoint_exception.rs b/testing/tests/interrupt_handling.rs similarity index 55% rename from testing/tests/breakpoint_exception.rs rename to testing/tests/interrupt_handling.rs index 573819030..120f95515 100644 --- a/testing/tests/breakpoint_exception.rs +++ b/testing/tests/interrupt_handling.rs @@ -7,7 +7,10 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use lazy_static::lazy_static; use testing::{exit_qemu, serial_print, serial_println, QemuExitCode}; +use x86_64::instructions::interrupts; + static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); +static INTERRUPT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); #[no_mangle] pub extern "C" fn _start() -> ! { @@ -16,13 +19,10 @@ pub extern "C" fn _start() -> ! { init_test_idt(); // invoke a breakpoint exception - x86_64::instructions::interrupts::int3(); + interrupts::int3(); match BREAKPOINT_HANDLER_CALLED.load(Ordering::SeqCst) { - 1 => { - serial_println!("[ok]"); - exit_qemu(QemuExitCode::Success); - } + 1 => {} 0 => { serial_println!("[failed]"); serial_println!(" Breakpoint handler was not called."); @@ -35,6 +35,29 @@ pub extern "C" fn _start() -> ! { } } + serial_print!("interrupt 42... "); + unsafe { interrupts::software_interrupt::<42>() }; + serial_print!("interrupt 77... "); + unsafe { interrupts::software_interrupt::<77>() }; + serial_print!("interrupt 42... "); + unsafe { interrupts::software_interrupt::<42>() }; + + match INTERRUPT_HANDLER_CALLED.load(Ordering::SeqCst) { + 3 => {} + 0 => { + serial_println!("[failed]"); + serial_println!(" Interrupt handler was not called."); + exit_qemu(QemuExitCode::Failed); + } + other => { + serial_println!("[failed]"); + serial_println!(" Interrupt handler was called {} times", other); + exit_qemu(QemuExitCode::Failed); + } + } + + serial_println!("[ok]"); + exit_qemu(QemuExitCode::Success); loop {} } @@ -49,6 +72,8 @@ lazy_static! { static ref TEST_IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); + idt[42].set_handler_fn(interrupt_handler); + idt[77].set_handler_fn(interrupt_handler); idt }; } @@ -60,3 +85,7 @@ pub fn init_test_idt() { extern "x86-interrupt" fn breakpoint_handler(_stack_frame: InterruptStackFrame) { BREAKPOINT_HANDLER_CALLED.fetch_add(1, Ordering::SeqCst); } + +extern "x86-interrupt" fn interrupt_handler(_stack_frame: InterruptStackFrame) { + INTERRUPT_HANDLER_CALLED.fetch_add(1, Ordering::SeqCst); +}