1use ax_memory_addr::VirtAddr;
2
3use crate::{TrapFrame, trap::PageFaultFlags, uspace::ExceptionInfo};
4
5#[derive(Debug, Clone, Copy)]
8pub enum ReturnReason {
9 Interrupt,
11 Syscall,
13 PageFault(VirtAddr, PageFaultFlags),
15 Exception(ExceptionInfo),
17 Unknown,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum ExceptionKind {
24 #[cfg(target_arch = "x86_64")]
25 Debug,
27 Breakpoint,
29 IllegalInstruction,
31 Misaligned,
33 Other,
35}
36
37#[repr(C)]
38#[derive(Debug, PartialEq, Eq)]
39struct ExceptionTableEntry {
40 #[cfg(target_arch = "aarch64")]
41 from: i32,
42 #[cfg(target_arch = "aarch64")]
43 to: i32,
44 #[cfg(not(target_arch = "aarch64"))]
45 from: usize,
46 #[cfg(not(target_arch = "aarch64"))]
47 to: usize,
48}
49
50impl ExceptionTableEntry {
51 #[inline]
52 fn source_addr(&self) -> usize {
53 #[cfg(target_arch = "aarch64")]
54 {
55 let base = (&self.from as *const i32) as isize;
56 return (base + self.from as isize) as usize;
57 }
58
59 #[cfg(not(target_arch = "aarch64"))]
60 {
61 self.from
62 }
63 }
64
65 #[inline]
66 fn to_addr(&self) -> usize {
67 #[cfg(target_arch = "aarch64")]
68 {
69 let base = (&self.to as *const i32) as isize;
70 return (base + self.to as isize) as usize;
71 }
72
73 #[cfg(not(target_arch = "aarch64"))]
74 {
75 self.to
76 }
77 }
78}
79
80unsafe extern "C" {
81 static _ex_table_start: [ExceptionTableEntry; 0];
82 static _ex_table_end: [ExceptionTableEntry; 0];
83}
84
85impl TrapFrame {
86 pub(crate) fn fixup_exception(&mut self) -> bool {
87 let entries = unsafe {
88 core::slice::from_raw_parts(
89 _ex_table_start.as_ptr(),
90 _ex_table_end
91 .as_ptr()
92 .offset_from_unsigned(_ex_table_start.as_ptr()),
93 )
94 };
95 match entries.binary_search_by_key(&self.ip(), ExceptionTableEntry::source_addr) {
96 Ok(entry) => {
97 self.set_ip(entries[entry].to_addr());
98 true
99 }
100 Err(_) => false,
101 }
102 }
103}
104
105pub(crate) fn init_exception_table() {
106 let ex_table = unsafe {
108 core::slice::from_raw_parts_mut(
109 _ex_table_start.as_ptr().cast_mut(),
110 _ex_table_end
111 .as_ptr()
112 .offset_from_unsigned(_ex_table_start.as_ptr()),
113 )
114 };
115 ex_table.sort_unstable_by_key(ExceptionTableEntry::source_addr);
116}