fast_trap/
lib.rs

1//! 快速陷入处理。
2
3#![no_std]
4#![feature(naked_functions)]
5#![deny(warnings, missing_docs)]
6
7mod entire;
8mod fast;
9mod hal;
10
11pub use entire::*;
12pub use fast::*;
13pub use hal::{FlowContext, load_direct_trap_entry, reuse_stack_for_trap, soft_trap, trap_entry};
14
15use core::{
16    alloc::Layout,
17    marker::PhantomPinned,
18    mem::{MaybeUninit, align_of, forget},
19    ops::Range,
20    ptr::NonNull,
21};
22
23/// 游离的陷入栈。
24pub struct FreeTrapStack(NonNull<TrapHandler>);
25
26/// 已加载的陷入栈。
27pub struct LoadedTrapStack(usize);
28
29/// 构造陷入栈失败。
30#[derive(Debug)]
31pub struct IllegalStack;
32
33impl FreeTrapStack {
34    /// 在内存块上构造游离的陷入栈。
35    pub fn new(
36        range: Range<usize>,
37        drop: fn(Range<usize>),
38
39        context_ptr: NonNull<FlowContext>,
40        fast_handler: FastHandler,
41    ) -> Result<Self, IllegalStack> {
42        const LAYOUT: Layout = Layout::new::<TrapHandler>();
43        let bottom = range.start;
44        let top = range.end;
45        let ptr = (top - LAYOUT.size()) & !(LAYOUT.align() - 1);
46        if ptr >= bottom {
47            let handler = unsafe { &mut *(ptr as *mut TrapHandler) };
48            handler.range = range;
49            handler.drop = drop;
50            handler.context = context_ptr;
51            handler.fast_handler = fast_handler;
52            Ok(Self(unsafe { NonNull::new_unchecked(handler) }))
53        } else {
54            Err(IllegalStack)
55        }
56    }
57
58    /// 将这个陷入栈加载为预备陷入栈。
59    #[inline]
60    pub fn load(self) -> LoadedTrapStack {
61        let scratch = hal::exchange_scratch(self.0.as_ptr() as _);
62        forget(self);
63        LoadedTrapStack(scratch)
64    }
65}
66
67impl Drop for FreeTrapStack {
68    #[inline]
69    fn drop(&mut self) {
70        unsafe {
71            let handler = self.0.as_ref();
72            (handler.drop)(handler.range.clone());
73        }
74    }
75}
76
77impl LoadedTrapStack {
78    /// 获取从 `sscratch` 寄存器中换出的值。
79    #[inline]
80    pub const fn val(&self) -> usize {
81        self.0
82    }
83
84    /// 卸载陷入栈。
85    #[inline]
86    pub fn unload(self) -> FreeTrapStack {
87        let ans = unsafe { self.unload_unchecked() };
88        forget(self);
89        ans
90    }
91
92    /// 卸载但不消费所有权。
93    ///
94    /// # Safety
95    ///
96    /// 间接复制了所有权。用于 `Drop`。
97    #[inline]
98    unsafe fn unload_unchecked(&self) -> FreeTrapStack {
99        let ptr = hal::exchange_scratch(self.0) as *mut TrapHandler;
100        let handler = unsafe { NonNull::new_unchecked(ptr) };
101        FreeTrapStack(handler)
102    }
103}
104
105impl Drop for LoadedTrapStack {
106    #[inline]
107    fn drop(&mut self) {
108        drop(unsafe { self.unload_unchecked() })
109    }
110}
111
112/// 陷入处理器上下文。
113#[repr(C)]
114struct TrapHandler {
115    /// 指向一个陷入上下文的指针。
116    ///
117    /// # TODO
118    ///
119    /// 这个东西是怎么来的?生命周期是什么?
120    /// 似乎让它生命周期和陷入栈绑定也很合理。
121    /// 它可以交换,只是和陷入栈同时释放而已。
122    ///
123    /// - 发生陷入时,将寄存器保存到此对象。
124    /// - 离开陷入处理时,按此对象的内容设置寄存器。
125    context: NonNull<FlowContext>,
126    /// 快速路径函数。
127    ///
128    /// 必须在初始化陷入时设置好。
129    fast_handler: FastHandler,
130    /// 可在汇编使用的临时存储。
131    ///
132    /// - 在快速路径开始时暂存 a0。
133    /// - 在快速路径结束时保存完整路径函数。
134    scratch: usize,
135
136    range: Range<usize>,
137    drop: fn(Range<usize>),
138
139    /// 禁止移动标记。
140    ///
141    /// `TrapHandler` 是放在其内部定义的 `block` 块里的,这是一种自引用结构,不能移动。
142    pinned: PhantomPinned,
143}
144
145impl TrapHandler {
146    /// 如果从快速路径向完整路径转移,可以把一个对象放在栈底。
147    /// 用这个方法找到栈底的一个对齐的位置。
148    #[inline]
149    fn locate_fast_mail<T>(&mut self) -> *mut MaybeUninit<T> {
150        let top = self.range.end as *mut u8;
151        let offset = top.align_offset(align_of::<T>());
152        unsafe { &mut *top.add(offset).cast() }
153    }
154}