axhal/
trap.rs

1//! Trap handling.
2
3use linkme::distributed_slice as def_trap_handler;
4use memory_addr::VirtAddr;
5use page_table_entry::MappingFlags;
6
7pub use linkme::distributed_slice as register_trap_handler;
8
9use crate::arch::TrapFrame;
10
11/// A slice of IRQ handler functions.
12#[def_trap_handler]
13pub static IRQ: [fn(usize) -> bool];
14
15/// A slice of page fault handler functions.
16#[def_trap_handler]
17pub static PAGE_FAULT: [fn(VirtAddr, MappingFlags, bool) -> bool];
18
19/// A slice of syscall handler functions.
20#[cfg(feature = "uspace")]
21#[def_trap_handler]
22pub static SYSCALL: [fn(&mut TrapFrame, usize) -> isize];
23
24/// A slice of callbacks to be invoked after a trap.
25#[linkme::distributed_slice]
26pub static POST_TRAP: [fn(&mut TrapFrame, bool)];
27
28#[allow(unused_macros)]
29macro_rules! handle_trap {
30    ($trap:ident, $($args:tt)*) => {{
31        let mut iter = $crate::trap::$trap.iter();
32        if let Some(func) = iter.next() {
33            if iter.next().is_some() {
34                warn!("Multiple handlers for trap {} are not currently supported", stringify!($trap));
35            }
36            func($($args)*)
37        } else {
38            warn!("No registered handler for trap {}", stringify!($trap));
39            false
40        }
41    }}
42}
43
44#[unsafe(no_mangle)]
45pub(crate) fn post_trap_callback(tf: &mut TrapFrame, from_user: bool) {
46    for cb in crate::trap::POST_TRAP.iter() {
47        cb(tf, from_user);
48    }
49}
50
51/// Call the external syscall handler.
52#[cfg(feature = "uspace")]
53pub(crate) fn handle_syscall(tf: &mut TrapFrame, syscall_num: usize) -> isize {
54    SYSCALL[0](tf, syscall_num)
55}