Skip to main content

ax_cpu/
uspace_common.rs

1use ax_memory_addr::VirtAddr;
2
3use crate::{TrapFrame, trap::PageFaultFlags, uspace::ExceptionInfo};
4
5/// A reason as to why the control of the CPU is returned from
6/// the user space to the kernel.
7#[derive(Debug, Clone, Copy)]
8pub enum ReturnReason {
9    /// An interrupt.
10    Interrupt,
11    /// A system call.
12    Syscall,
13    /// A page fault.
14    PageFault(VirtAddr, PageFaultFlags),
15    /// Other kinds of exceptions.
16    Exception(ExceptionInfo),
17    /// Unknown reason.
18    Unknown,
19}
20
21/// A generalized kind for [`ExceptionInfo`].
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum ExceptionKind {
24    #[cfg(target_arch = "x86_64")]
25    /// A debug exception.
26    Debug,
27    /// A breakpoint exception.
28    Breakpoint,
29    /// An illegal instruction exception.
30    IllegalInstruction,
31    /// A misaligned access exception.
32    Misaligned,
33    /// Other kinds of exceptions.
34    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    // Sort exception table
107    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}