|
1 | 1 | use crate::TrapHandler;
|
2 | 2 | use core::alloc::Layout;
|
3 | 3 |
|
| 4 | +#[cfg(target_arch = "riscv32")] |
| 5 | +#[macro_use] |
| 6 | +mod arch { |
| 7 | + macro_rules! save { |
| 8 | + ($reg:expr => $ptr:expr; $pos:expr) => { |
| 9 | + concat!("sw ", $reg, ", 4*", $pos, "(", $ptr, ")") |
| 10 | + }; |
| 11 | + } |
| 12 | + |
| 13 | + macro_rules! load { |
| 14 | + ($ptr:expr; $pos:expr => $reg:expr) => { |
| 15 | + concat!("lw ", $reg, ", 4*", $pos, "(", $ptr, ")") |
| 16 | + }; |
| 17 | + |
| 18 | + ($ptr:expr; $pos:expr => $reg:expr, label: $label:expr) => { |
| 19 | + concat!($label, ":", load!($ptr;$pos => $reg)) |
| 20 | + }; |
| 21 | + } |
| 22 | +} |
| 23 | +#[cfg(target_arch = "riscv64")] |
| 24 | +#[macro_use] |
| 25 | +mod arch { |
| 26 | + macro_rules! save { |
| 27 | + ($reg:expr => $ptr:expr; $pos:expr) => { |
| 28 | + concat!("sd ", $reg, ", 8*", $pos, '(', $ptr, ')') |
| 29 | + }; |
| 30 | + } |
| 31 | + |
| 32 | + macro_rules! load { |
| 33 | + ($ptr:expr; $pos:expr => $reg:expr) => { |
| 34 | + concat!("ld ", $reg, ", 8*", $pos, '(', $ptr, ')') |
| 35 | + }; |
| 36 | + |
| 37 | + ($ptr:expr; $pos:expr => $reg:expr, label: $label:expr) => { |
| 38 | + concat!($label, ':', load!($ptr;$pos => $reg)) |
| 39 | + }; |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +use super::{exchange, r#return}; |
| 44 | + |
4 | 45 | /// 陷入上下文。
|
5 | 46 | ///
|
6 | 47 | /// 保存了陷入时的寄存器状态。包括所有通用寄存器和 `pc`。
|
@@ -49,3 +90,129 @@ pub unsafe extern "C" fn reuse_stack_for_trap() {
|
49 | 90 | options(noreturn)
|
50 | 91 | )
|
51 | 92 | }
|
| 93 | + |
| 94 | +/// 陷入处理例程。 |
| 95 | +/// |
| 96 | +/// # Safety |
| 97 | +/// |
| 98 | +/// 不要直接调用这个函数。暴露它仅仅是为了提供其入口的符号链接。 |
| 99 | +#[naked] |
| 100 | +pub unsafe extern "C" fn trap_entry() { |
| 101 | + core::arch::asm!( |
| 102 | + ".align 2", |
| 103 | + // 换栈 |
| 104 | + exchange!(), |
| 105 | + // 加载上下文指针 |
| 106 | + save!("a0" => "sp";2), |
| 107 | + load!("sp";0 => "a0"), |
| 108 | + // 保存尽量少的寄存器 |
| 109 | + save!("ra" => "a0";0), |
| 110 | + save!("t0" => "a0";1), |
| 111 | + save!("t1" => "a0";2), |
| 112 | + save!("t2" => "a0";3), |
| 113 | + save!("t3" => "a0";4), |
| 114 | + save!("t4" => "a0";5), |
| 115 | + save!("t5" => "a0";6), |
| 116 | + save!("t6" => "a0";7), |
| 117 | + // 调用快速路径函数 |
| 118 | + // |
| 119 | + // | reg | position |
| 120 | + // | ------ | - |
| 121 | + // | ra | `TrapHandler.context` |
| 122 | + // | t0-t6 | `TrapHandler.context` |
| 123 | + // | a0 | `TrapHandler.scratch` |
| 124 | + // | a1-a7 | 参数寄存器 |
| 125 | + // | sp | sscratch |
| 126 | + // | gp, tp | gp, tp |
| 127 | + // | s0-s11 | 不支持 |
| 128 | + // |
| 129 | + // > 若要保留陷入上下文, |
| 130 | + // > 必须在快速路径保存 a0-a7 到 `TrapHandler.context`, |
| 131 | + // > 并进入完整路径执行后续操作。 |
| 132 | + // > |
| 133 | + // > 若要切换上下文,在快速路径设置 gp/tp/sscratch/sepc 和 sstatus。 |
| 134 | + "mv a0, sp", |
| 135 | + load!("sp";1 => "ra"), |
| 136 | + "jalr ra", |
| 137 | + // 加载上下文指针 |
| 138 | + load!("sp";0 => "a1", label: 0), |
| 139 | + // 0:设置少量参数寄存器 |
| 140 | + " beqz a0, 0f", |
| 141 | + // 1:设置所有参数寄存器 |
| 142 | + " addi a0, a0, -1 |
| 143 | + beqz a0, 1f |
| 144 | + ", |
| 145 | + // 2:设置所有调用者寄存器 |
| 146 | + " addi a0, a0, -1 |
| 147 | + beqz a0, 2f |
| 148 | + ", |
| 149 | + // 3:设置所有寄存器 |
| 150 | + " addi a0, a0, -1 |
| 151 | + beqz a0, 3f |
| 152 | + ", |
| 153 | + // 4:完整路径 |
| 154 | + save!("s0" => "a1";16), |
| 155 | + save!("s1" => "a1";17), |
| 156 | + save!("s2" => "a1";18), |
| 157 | + save!("s3" => "a1";19), |
| 158 | + save!("s4" => "a1";20), |
| 159 | + save!("s5" => "a1";21), |
| 160 | + save!("s6" => "a1";22), |
| 161 | + save!("s7" => "a1";23), |
| 162 | + save!("s8" => "a1";24), |
| 163 | + save!("s9" => "a1";25), |
| 164 | + save!("s10" => "a1";26), |
| 165 | + save!("s11" => "a1";27), |
| 166 | + // 调用完整路径函数 |
| 167 | + // |
| 168 | + // | reg | position |
| 169 | + // | ------ | - |
| 170 | + // | sp | sscratch |
| 171 | + // | gp, tp | gp, tp |
| 172 | + // | else | `TrapHandler.context` |
| 173 | + // |
| 174 | + // > 若要保留陷入上下文, |
| 175 | + // > 在完整路径中保存 gp/tp/sp/pc 到 `TrapHandler.context`。 |
| 176 | + // > |
| 177 | + // > 若要切换上下文,在完整路径设置 gp/tp/sscratch/sepc 和 sstatus。 |
| 178 | + "mv a0, sp", |
| 179 | + load!("sp"; 2 => "ra"), |
| 180 | + "jalr ra", |
| 181 | + "j 0b", |
| 182 | + // 设置所有寄存器 |
| 183 | + load!("a1";16 => "s0", label: 3), |
| 184 | + load!("a1";17 => "s1"), |
| 185 | + load!("a1";18 => "s2"), |
| 186 | + load!("a1";19 => "s3"), |
| 187 | + load!("a1";20 => "s4"), |
| 188 | + load!("a1";21 => "s5"), |
| 189 | + load!("a1";22 => "s6"), |
| 190 | + load!("a1";23 => "s7"), |
| 191 | + load!("a1";24 => "s8"), |
| 192 | + load!("a1";25 => "s9"), |
| 193 | + load!("a1";26 => "s10"), |
| 194 | + load!("a1";27 => "s11"), |
| 195 | + // 设置所有调用者寄存器 |
| 196 | + load!("a1"; 0 => "ra", label: 2), |
| 197 | + load!("a1"; 1 => "t0"), |
| 198 | + load!("a1"; 2 => "t1"), |
| 199 | + load!("a1"; 3 => "t2"), |
| 200 | + load!("a1"; 4 => "t3"), |
| 201 | + load!("a1"; 5 => "t4"), |
| 202 | + load!("a1"; 6 => "t5"), |
| 203 | + load!("a1"; 7 => "t6"), |
| 204 | + // 设置所有参数寄存器 |
| 205 | + load!("a1";10 => "a2", label: 1), |
| 206 | + load!("a1";11 => "a3"), |
| 207 | + load!("a1";12 => "a4"), |
| 208 | + load!("a1";13 => "a5"), |
| 209 | + load!("a1";14 => "a6"), |
| 210 | + load!("a1";15 => "a7"), |
| 211 | + // 设置少量参数寄存器 |
| 212 | + load!("a1"; 8 => "a0", label: 0), |
| 213 | + load!("a1"; 9 => "a1"), |
| 214 | + exchange!(), |
| 215 | + r#return!(), |
| 216 | + options(noreturn), |
| 217 | + ) |
| 218 | +} |
0 commit comments