1pub mod boot;
4pub mod diagnostics;
5pub mod fatal;
6mod fault;
7mod interrupted;
8use core::sync::atomic::{AtomicUsize, Ordering};
9
10use ax_memory_addr::VirtAddr;
11pub use diagnostics::BacktraceRegisters;
12pub use fault::PageFaultFlags;
13pub use interrupted::{InterruptedContext, InterruptedPrivilege};
14
15pub use crate::arch::current::{context::TrapFrame as UserRegisters, trap::KernelTrapFrame};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum TrapOrigin {
20 Kernel,
22 User,
24}
25
26pub type IrqHandler = fn(usize, TrapOrigin, Option<InterruptedContext>) -> bool;
28
29pub type PageFaultHandler = fn(VirtAddr, PageFaultFlags) -> bool;
31
32pub type BreakpointHandler = fn(&mut KernelTrapFrame<'_>) -> bool;
34
35pub type DebugHandler = fn(&mut KernelTrapFrame<'_>) -> bool;
37
38fn default_irq_handler(
39 irq: usize,
40 _origin: TrapOrigin,
41 _context: Option<InterruptedContext>,
42) -> bool {
43 trace!("IRQ {} triggered", irq);
44 false
45}
46
47fn default_page_fault_handler(addr: VirtAddr, flags: PageFaultFlags) -> bool {
48 warn!("Page fault at {:#x} with flags {:?}", addr, flags);
49 false
50}
51
52fn default_breakpoint_handler(_tf: &mut KernelTrapFrame<'_>) -> bool {
53 false
54}
55
56fn default_debug_handler(_tf: &mut KernelTrapFrame<'_>) -> bool {
57 false
58}
59
60static IRQ_HANDLER: AtomicUsize = AtomicUsize::new(0);
61static PAGE_FAULT_HANDLER: AtomicUsize = AtomicUsize::new(0);
62static BREAKPOINT_HANDLER: AtomicUsize = AtomicUsize::new(0);
63static DEBUG_HANDLER: AtomicUsize = AtomicUsize::new(0);
64
65pub fn set_irq_handler(handler: IrqHandler) -> IrqHandler {
67 let old = IRQ_HANDLER.swap(handler as usize, Ordering::AcqRel);
68 if old == 0 {
69 default_irq_handler
70 } else {
71 unsafe { core::mem::transmute::<usize, IrqHandler>(old) }
73 }
74}
75
76pub fn set_page_fault_handler(handler: PageFaultHandler) -> PageFaultHandler {
78 let old = PAGE_FAULT_HANDLER.swap(handler as usize, Ordering::AcqRel);
79 if old == 0 {
80 default_page_fault_handler
81 } else {
82 unsafe { core::mem::transmute::<usize, PageFaultHandler>(old) }
84 }
85}
86
87pub fn set_breakpoint_handler(handler: BreakpointHandler) -> BreakpointHandler {
89 let old = BREAKPOINT_HANDLER.swap(handler as usize, Ordering::AcqRel);
90 if old == 0 {
91 default_breakpoint_handler
92 } else {
93 unsafe { core::mem::transmute::<usize, BreakpointHandler>(old) }
95 }
96}
97
98pub fn set_debug_handler(handler: DebugHandler) -> DebugHandler {
100 let old = DEBUG_HANDLER.swap(handler as usize, Ordering::AcqRel);
101 if old == 0 {
102 default_debug_handler
103 } else {
104 unsafe { core::mem::transmute::<usize, DebugHandler>(old) }
106 }
107}
108
109pub fn dispatch_irq(irq: usize, origin: TrapOrigin, context: Option<InterruptedContext>) -> bool {
111 let handler = IRQ_HANDLER.load(Ordering::Acquire);
112 let handler = if handler == 0 {
113 default_irq_handler
114 } else {
115 unsafe { core::mem::transmute::<usize, IrqHandler>(handler) }
117 };
118 handler(irq, origin, context)
119}
120
121pub fn dispatch_page_fault(addr: VirtAddr, flags: PageFaultFlags) -> bool {
123 let handler = PAGE_FAULT_HANDLER.load(Ordering::Acquire);
124 let handler = if handler == 0 {
125 default_page_fault_handler
126 } else {
127 unsafe { core::mem::transmute::<usize, PageFaultHandler>(handler) }
129 };
130 handler(addr, flags)
131}
132
133pub fn irq_handler(irq: usize) -> bool {
135 dispatch_irq(irq, TrapOrigin::Kernel, None)
136}
137
138pub fn page_fault_handler(addr: VirtAddr, flags: PageFaultFlags) -> bool {
140 dispatch_page_fault(addr, flags)
141}
142
143#[inline]
146pub(crate) fn call_page_fault_handler_with_parent_irqs(
147 addr: VirtAddr,
148 flags: PageFaultFlags,
149 parent_irqs_enabled: bool,
150) -> bool {
151 if parent_irqs_enabled {
152 crate::asm::enable_irqs();
153 }
154 let handled = page_fault_handler(addr, flags);
155 if parent_irqs_enabled {
156 crate::asm::disable_irqs();
157 }
158 handled
159}
160
161pub fn breakpoint_handler(tf: &mut KernelTrapFrame<'_>) -> bool {
180 let handler = BREAKPOINT_HANDLER.load(Ordering::Acquire);
181 let handler = if handler == 0 {
182 default_breakpoint_handler
183 } else {
184 unsafe { core::mem::transmute::<usize, BreakpointHandler>(handler) }
186 };
187 handler(tf)
188}
189
190pub fn debug_handler(tf: &mut KernelTrapFrame<'_>) -> bool {
211 let handler = DEBUG_HANDLER.load(Ordering::Acquire);
212 let handler = if handler == 0 {
213 default_debug_handler
214 } else {
215 unsafe { core::mem::transmute::<usize, DebugHandler>(handler) }
217 };
218 handler(tf)
219}
220
221#[cfg(target_arch = "loongarch64")]
222pub use crate::arch::current::unaligned::{
223 UnalignedAccess, UnalignedAccessType, UnalignedError, UnalignedPageFault,
224};