Skip to content

Commit ebb80ab

Browse files
authored
Merge pull request #227 from rust-osdev/const_int
As this feature is stabilized in the latest nightly, no feature flags need to be added.
2 parents 4d5058c + 5988eb1 commit ebb80ab

File tree

3 files changed

+43
-23
lines changed

3 files changed

+43
-23
lines changed

src/instructions/interrupts.rs

+8-17
Original file line numberDiff line numberDiff line change
@@ -155,22 +155,13 @@ pub fn int3() {
155155

156156
/// Generate a software interrupt by invoking the `int` instruction.
157157
///
158-
/// This currently needs to be a macro because the `int` argument needs to be an
159-
/// immediate. This macro will be replaced by a generic function when support for
160-
/// const generics is implemented in Rust.
158+
/// ## Safety
159+
/// Invoking an arbitrary interrupt is unsafe. It can cause your system to
160+
/// crash if you invoke a double-fault (#8) or machine-check (#18) exception.
161+
/// It can also cause memory/register corruption depending on the interrupt
162+
/// implementation (if it expects values/pointers to be passed in registers).
163+
#[inline]
161164
#[cfg(feature = "inline_asm")]
162-
#[macro_export]
163-
macro_rules! software_interrupt {
164-
($x:expr) => {{
165-
asm!("int {id}", id = const $x, options(nomem, nostack));
166-
}};
167-
}
168-
169-
/// Not implemented
170-
#[cfg(not(feature = "inline_asm"))]
171-
#[macro_export]
172-
macro_rules! software_interrupt {
173-
($x:expr) => {{
174-
compile_error!("software_interrupt not implemented for non-nightly");
175-
}};
165+
pub unsafe fn software_interrupt<const ID: u8>() {
166+
asm!("int {}", const ID, options(nomem, nostack));
176167
}

testing/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ authors = ["Philipp Oppermann <[email protected]>"]
55
edition = "2018"
66

77
[[test]]
8-
name = "breakpoint_exception"
8+
name = "interrupt_handling"
99
harness = false
1010

1111
[[test]]

testing/tests/breakpoint_exception.rs renamed to testing/tests/interrupt_handling.rs

+34-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use core::sync::atomic::{AtomicUsize, Ordering};
77
use lazy_static::lazy_static;
88
use testing::{exit_qemu, serial_print, serial_println, QemuExitCode};
99

10+
use x86_64::instructions::interrupts;
11+
1012
static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0);
13+
static INTERRUPT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0);
1114

1215
#[no_mangle]
1316
pub extern "C" fn _start() -> ! {
@@ -16,13 +19,10 @@ pub extern "C" fn _start() -> ! {
1619
init_test_idt();
1720

1821
// invoke a breakpoint exception
19-
x86_64::instructions::interrupts::int3();
22+
interrupts::int3();
2023

2124
match BREAKPOINT_HANDLER_CALLED.load(Ordering::SeqCst) {
22-
1 => {
23-
serial_println!("[ok]");
24-
exit_qemu(QemuExitCode::Success);
25-
}
25+
1 => {}
2626
0 => {
2727
serial_println!("[failed]");
2828
serial_println!(" Breakpoint handler was not called.");
@@ -35,6 +35,29 @@ pub extern "C" fn _start() -> ! {
3535
}
3636
}
3737

38+
serial_print!("interrupt 42... ");
39+
unsafe { interrupts::software_interrupt::<42>() };
40+
serial_print!("interrupt 77... ");
41+
unsafe { interrupts::software_interrupt::<77>() };
42+
serial_print!("interrupt 42... ");
43+
unsafe { interrupts::software_interrupt::<42>() };
44+
45+
match INTERRUPT_HANDLER_CALLED.load(Ordering::SeqCst) {
46+
3 => {}
47+
0 => {
48+
serial_println!("[failed]");
49+
serial_println!(" Interrupt handler was not called.");
50+
exit_qemu(QemuExitCode::Failed);
51+
}
52+
other => {
53+
serial_println!("[failed]");
54+
serial_println!(" Interrupt handler was called {} times", other);
55+
exit_qemu(QemuExitCode::Failed);
56+
}
57+
}
58+
59+
serial_println!("[ok]");
60+
exit_qemu(QemuExitCode::Success);
3861
loop {}
3962
}
4063

@@ -49,6 +72,8 @@ lazy_static! {
4972
static ref TEST_IDT: InterruptDescriptorTable = {
5073
let mut idt = InterruptDescriptorTable::new();
5174
idt.breakpoint.set_handler_fn(breakpoint_handler);
75+
idt[42].set_handler_fn(interrupt_handler);
76+
idt[77].set_handler_fn(interrupt_handler);
5277
idt
5378
};
5479
}
@@ -60,3 +85,7 @@ pub fn init_test_idt() {
6085
extern "x86-interrupt" fn breakpoint_handler(_stack_frame: &mut InterruptStackFrame) {
6186
BREAKPOINT_HANDLER_CALLED.fetch_add(1, Ordering::SeqCst);
6287
}
88+
89+
extern "x86-interrupt" fn interrupt_handler(_stack_frame: &mut InterruptStackFrame) {
90+
INTERRUPT_HANDLER_CALLED.fetch_add(1, Ordering::SeqCst);
91+
}

0 commit comments

Comments
 (0)