os/arch/riscv/trap/
trap_frame.rs

1use riscv::register::sstatus;
2
3use crate::uapi::signal::MContextT;
4
5/// 陷阱帧结构体,保存寄存器状态
6#[repr(C)] // 确保 Rust 不会重新排列字段
7#[derive(Debug, Clone, Copy)]
8pub struct TrapFrame {
9    /// 程序计数器
10    /// 在发生陷阱时,sepc 寄存器的值应保存到这里
11    pub sepc: usize, // 0(sp)
12    pub x1_ra: usize,   // 8(sp)
13    pub x2_sp: usize,   // 16(sp)
14    pub x3_gp: usize,   // 24(sp)
15    pub x4_tp: usize,   // 32(sp)
16    pub x5_t0: usize,   // 40(sp)
17    pub x6_t1: usize,   // 48(sp)
18    pub x7_t2: usize,   // 56(sp)
19    pub x8_s0: usize,   // 64(sp)
20    pub x9_s1: usize,   // 72(sp)
21    pub x10_a0: usize,  // 80(sp)
22    pub x11_a1: usize,  // 88(sp)
23    pub x12_a2: usize,  // 96(sp)
24    pub x13_a3: usize,  // 104(sp)
25    pub x14_a4: usize,  // 112(sp)
26    pub x15_a5: usize,  // 120(sp)
27    pub x16_a6: usize,  // 128(sp)
28    pub x17_a7: usize,  // 136(sp)
29    pub x18_s2: usize,  // 144(sp)
30    pub x19_s3: usize,  // 152(sp)
31    pub x20_s4: usize,  // 160(sp)
32    pub x21_s5: usize,  // 168(sp)
33    pub x22_s6: usize,  // 176(sp)
34    pub x23_s7: usize,  // 184(sp)
35    pub x24_s8: usize,  // 192(sp)
36    pub x25_s9: usize,  // 200(sp)
37    pub x26_s10: usize, // 208(sp)
38    pub x27_s11: usize, // 216(sp)
39    pub x28_t3: usize,  // 224(sp)
40    pub x29_t4: usize,  // 232(sp)
41    pub x30_t5: usize,  // 240(sp)
42    pub x31_t6: usize,  // 248(sp)
43    pub sstatus: usize, // 256(sp)
44    pub kernel_sp: usize, // 264(sp)
45                        // pub kernel_satp: usize, // 272(sp)
46                        // pub kernel_hartid: usize, // 280(sp)
47}
48
49impl TrapFrame {
50    /// 创建一个全零初始化的陷阱帧
51    pub fn zero_init() -> Self {
52        TrapFrame {
53            sepc: 0,
54            x1_ra: 0,
55            x2_sp: 0,
56            x3_gp: 0,
57            x4_tp: 0,
58            x5_t0: 0,
59            x6_t1: 0,
60            x7_t2: 0,
61            x8_s0: 0,
62            x9_s1: 0,
63            x10_a0: 0,
64            x11_a1: 0,
65            x12_a2: 0,
66            x13_a3: 0,
67            x14_a4: 0,
68            x15_a5: 0,
69            x16_a6: 0,
70            x17_a7: 0,
71            x18_s2: 0,
72            x19_s3: 0,
73            x20_s4: 0,
74            x21_s5: 0,
75            x22_s6: 0,
76            x23_s7: 0,
77            x24_s8: 0,
78            x25_s9: 0,
79            x26_s10: 0,
80            x27_s11: 0,
81            x28_t3: 0,
82            x29_t4: 0,
83            x30_t5: 0,
84            x31_t6: 0,
85            sstatus: 0,
86            kernel_sp: 0,
87            // kernel_satp: 0,
88        }
89    }
90
91    // ===== 跨架构兼容的访问方法 =====
92
93    /// 获取栈指针
94    #[inline]
95    pub fn get_sp(&self) -> usize {
96        self.x2_sp
97    }
98
99    /// 设置栈指针
100    #[inline]
101    pub fn set_sp(&mut self, val: usize) {
102        self.x2_sp = val;
103    }
104
105    /// 获取第一个参数寄存器 (a0)
106    #[inline]
107    pub fn get_a0(&self) -> usize {
108        self.x10_a0
109    }
110
111    /// 设置第一个参数寄存器 (a0)
112    #[inline]
113    pub fn set_a0(&mut self, val: usize) {
114        self.x10_a0 = val;
115    }
116
117    /// 设置程序计数器
118    #[inline]
119    pub fn set_sepc(&mut self, pc: usize) {
120        self.sepc = pc;
121    }
122
123    /// 获取程序计数器
124    #[inline]
125    pub fn get_sepc(&self) -> usize {
126        self.sepc
127    }
128
129    /// 设置内核线程的初始陷阱帧
130    /// 参数:
131    /// * `entry`: 线程入口地址
132    /// * `terminal`: 线程结束时跳转地址
133    /// * `kernel_sp`: 内核栈顶地址
134    pub fn set_kernel_trap_frame(
135        &mut self,
136        entry: usize,
137        terminal: usize,
138        kernel_sp: usize,
139        // kernel_satp: usize,
140        // kernel_hartid: usize,
141    ) {
142        let mut sstatus = sstatus::read();
143        sstatus.set_spp(sstatus::SPP::Supervisor);
144        sstatus.set_sie(false);
145        sstatus.set_spie(true);
146        self.sepc = entry;
147        self.sstatus = sstatus.bits();
148        self.kernel_sp = kernel_sp;
149        self.x1_ra = terminal;
150        self.x2_sp = kernel_sp;
151        // self.kernel_satp = kernel_satp;
152        // self.kernel_hartid = kernel_hartid;
153    }
154
155    /// 设置克隆线程的 TrapFrame
156    /// 参数:
157    /// * `parent_frame`: 父线程的 TrapFrame 引用
158    /// * `entry`: 线程入口地址
159    /// * `args`: 传递给线程函数的参数
160    /// * `kernel_sp`: 内核栈顶地址
161    /// * `user_sp`: 用户栈顶地址
162    /// # 安全性
163    /// - `parent_frame` 必须指向一个完全初始化的、有效的 `TrapFrame`
164    /// - `parent_frame` 必须在整个复制期间保持有效
165    /// - `self` 必须指向一个可写的内存区域,大小至少为 `size_of::<TrapFrame>()`
166    /// - `self` 和 `parent_frame` 不能内存重叠
167    /// - 调用后 `self` 将包含 `parent_frame` 的精确副本(除了修改的字段)
168    pub unsafe fn set_clone_trap_frame(
169        &mut self,
170        parent_frame: &TrapFrame,
171        kernel_sp: usize,
172        user_sp: usize,
173    ) {
174        // SAFETY: 调用者确保:
175        // 1. parent_frame 有效且可读
176        // 2. self 有效且可写
177        // 3. 两者不重叠
178        // 4. 两者都正确对齐
179        unsafe {
180            core::ptr::copy_nonoverlapping(
181                parent_frame as *const _ as *const u8,
182                self as *mut _ as *mut u8,
183                core::mem::size_of::<TrapFrame>(),
184            );
185        }
186        // 子进程返回 0
187        self.x10_a0 = 0;
188        self.kernel_sp = kernel_sp;
189        // 如果提供了新栈,使用新栈;否则使用父进程的栈
190        if user_sp != 0 {
191            self.x2_sp = user_sp;
192        }
193        // sepc 不变,子进程从当前位置继续执行(类似 fork)
194    }
195
196    /// 设置用户态的 TrapFrame
197    /// 用于execve新程序
198    /// 参数:
199    /// * `entry`: 用户程序入口地址
200    /// * `user_sp`: 用户栈顶地址
201    /// * `kernel_sp`: 内核栈顶地址
202    /// * `argc`: 命令行参数个数
203    /// * `argv`: 命令行参数指针数组地址
204    /// * `envp`: 环境变量指针数组地址
205    pub fn set_exec_trap_frame(
206        &mut self,
207        entry: usize,
208        user_sp: usize,
209        kernel_sp: usize,
210        argc: usize,
211        argv: usize,
212        envp: usize,
213    ) {
214        let mut sstatus = sstatus::read();
215        sstatus.set_spp(sstatus::SPP::User);
216        sstatus.set_sie(false);
217        sstatus.set_spie(true);
218
219        // Clear all registers first
220        *self = Self::zero_init();
221
222        self.sepc = entry;
223        self.sstatus = sstatus.bits();
224        self.kernel_sp = kernel_sp;
225        self.x2_sp = user_sp;
226
227        // Set arguments
228        self.x10_a0 = argc;
229        self.x11_a1 = argv;
230        self.x12_a2 = envp;
231
232        // x1_ra is 0
233    }
234
235    /// 设置 fork 后子进程的 TrapFrame
236    /// # 参数:
237    /// * `tpr`: 父进程的 TrapFrame 引用
238    /// # 安全性
239    /// - `parent_frame` 必须指向一个完全初始化的、有效的 `TrapFrame`
240    /// - `parent_frame` 必须在整个复制期间保持有效
241    /// - `self` 必须指向一个可写的内存区域,大小至少为 `size_of::<TrapFrame>()`
242    /// - `self` 和 `parent_frame` 不能内存重叠
243    /// - 调用后 `self` 将包含 `parent_frame` 的精确副本(除了修改的字段)
244    pub unsafe fn set_fork_trap_frame(&mut self, parent_frame: &TrapFrame) {
245        // SAFETY: 调用者确保:
246        // 1. parent_frame 有效且可读
247        // 2. self 有效且可写
248        // 3. 两者不重叠
249        // 4. 两者都正确对齐
250        unsafe {
251            core::ptr::copy_nonoverlapping(
252                parent_frame as *const _ as *const u8,
253                self as *mut _ as *mut u8,
254                core::mem::size_of::<TrapFrame>(),
255            );
256        }
257        // 子进程返回值为0
258        self.x10_a0 = 0;
259    }
260
261    /// 将 TrapFrame 转换为 MContextT 结构体
262    pub fn to_mcontext(&self) -> MContextT {
263        MContextT {
264            gregs: [
265                self.sepc as u64,
266                self.x1_ra as u64,
267                self.x2_sp as u64,
268                self.x3_gp as u64,
269                self.x4_tp as u64,
270                self.x5_t0 as u64,
271                self.x6_t1 as u64,
272                self.x7_t2 as u64,
273                self.x8_s0 as u64,
274                self.x9_s1 as u64,
275                self.x10_a0 as u64,
276                self.x11_a1 as u64,
277                self.x12_a2 as u64,
278                self.x13_a3 as u64,
279                self.x14_a4 as u64,
280                self.x15_a5 as u64,
281                self.x16_a6 as u64,
282                self.x17_a7 as u64,
283                self.x18_s2 as u64,
284                self.x19_s3 as u64,
285                self.x20_s4 as u64,
286                self.x21_s5 as u64,
287                self.x22_s6 as u64,
288                self.x23_s7 as u64,
289                self.x24_s8 as u64,
290                self.x25_s9 as u64,
291                self.x26_s10 as u64,
292                self.x27_s11 as u64,
293                self.x28_t3 as u64,
294                self.x29_t4 as u64,
295                self.x30_t5 as u64,
296                self.x31_t6 as u64,
297            ],
298            fpregs: [0; 66],
299        }
300    }
301
302    /// 从 MContextT 恢复 TrapFrame
303    pub fn restore_from_mcontext(&mut self, mcontext: &MContextT) {
304        self.sepc = mcontext.gregs[0] as usize;
305        self.x1_ra = mcontext.gregs[1] as usize;
306        self.x2_sp = mcontext.gregs[2] as usize;
307        self.x3_gp = mcontext.gregs[3] as usize;
308        self.x4_tp = mcontext.gregs[4] as usize;
309        self.x5_t0 = mcontext.gregs[5] as usize;
310        self.x6_t1 = mcontext.gregs[6] as usize;
311        self.x7_t2 = mcontext.gregs[7] as usize;
312        self.x8_s0 = mcontext.gregs[8] as usize;
313        self.x9_s1 = mcontext.gregs[9] as usize;
314        self.x10_a0 = mcontext.gregs[10] as usize;
315        self.x11_a1 = mcontext.gregs[11] as usize;
316        self.x12_a2 = mcontext.gregs[12] as usize;
317        self.x13_a3 = mcontext.gregs[13] as usize;
318        self.x14_a4 = mcontext.gregs[14] as usize;
319        self.x15_a5 = mcontext.gregs[15] as usize;
320        self.x16_a6 = mcontext.gregs[16] as usize;
321        self.x17_a7 = mcontext.gregs[17] as usize;
322        self.x18_s2 = mcontext.gregs[18] as usize;
323        self.x19_s3 = mcontext.gregs[19] as usize;
324        self.x20_s4 = mcontext.gregs[20] as usize;
325        self.x21_s5 = mcontext.gregs[21] as usize;
326        self.x22_s6 = mcontext.gregs[22] as usize;
327        self.x23_s7 = mcontext.gregs[23] as usize;
328        self.x24_s8 = mcontext.gregs[24] as usize;
329        self.x25_s9 = mcontext.gregs[25] as usize;
330        self.x26_s10 = mcontext.gregs[26] as usize;
331        self.x27_s11 = mcontext.gregs[27] as usize;
332        self.x28_t3 = mcontext.gregs[28] as usize;
333        self.x29_t4 = mcontext.gregs[29] as usize;
334        self.x30_t5 = mcontext.gregs[30] as usize;
335        self.x31_t6 = mcontext.gregs[31] as usize;
336    }
337}