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 Breakpoint,
26 IllegalInstruction,
28 Misaligned,
30 Other,
32}
33
34#[repr(C)]
35#[derive(Debug, PartialEq, Eq)]
36struct ExceptionTableEntry {
37 #[cfg(target_arch = "aarch64")]
38 from: i32,
39 #[cfg(target_arch = "aarch64")]
40 to: i32,
41 #[cfg(not(target_arch = "aarch64"))]
42 from: usize,
43 #[cfg(not(target_arch = "aarch64"))]
44 to: usize,
45}
46
47impl ExceptionTableEntry {
48 #[inline]
49 fn from_addr(&self) -> usize {
50 #[cfg(target_arch = "aarch64")]
51 {
52 let base = (&self.from as *const i32) as isize;
53 return (base + self.from as isize) as usize;
54 }
55
56 #[cfg(not(target_arch = "aarch64"))]
57 {
58 self.from
59 }
60 }
61
62 #[inline]
63 fn to_addr(&self) -> usize {
64 #[cfg(target_arch = "aarch64")]
65 {
66 let base = (&self.to as *const i32) as isize;
67 return (base + self.to as isize) as usize;
68 }
69
70 #[cfg(not(target_arch = "aarch64"))]
71 {
72 self.to
73 }
74 }
75}
76
77unsafe extern "C" {
78 static _ex_table_start: [ExceptionTableEntry; 0];
79 static _ex_table_end: [ExceptionTableEntry; 0];
80}
81
82impl TrapFrame {
83 pub(crate) fn fixup_exception(&mut self) -> bool {
84 let entries = unsafe {
85 core::slice::from_raw_parts(
86 _ex_table_start.as_ptr(),
87 _ex_table_end
88 .as_ptr()
89 .offset_from_unsigned(_ex_table_start.as_ptr()),
90 )
91 };
92 match entries.binary_search_by_key(&self.ip(), ExceptionTableEntry::from_addr) {
93 Ok(entry) => {
94 self.set_ip(entries[entry].to_addr());
95 true
96 }
97 Err(_) => false,
98 }
99 }
100}
101
102pub(crate) fn init_exception_table() {
103 let ex_table = unsafe {
105 core::slice::from_raw_parts_mut(
106 _ex_table_start.as_ptr().cast_mut(),
107 _ex_table_end
108 .as_ptr()
109 .offset_from_unsigned(_ex_table_start.as_ptr()),
110 )
111 };
112 ex_table.sort_unstable_by_key(ExceptionTableEntry::from_addr);
113}