Skip to content

Commit e820c20

Browse files
authored
Merge pull request #86 from CircuitCoder/master
根据RV手册更新第三章
2 parents 8df3fbb + c231c62 commit e820c20

File tree

3 files changed

+18
-45
lines changed

3 files changed

+18
-45
lines changed

chapter3/part2.md

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -68,56 +68,32 @@ pub extern "C" fn rust_main() -> ! {
6868
}
6969
```
7070

71-
使用 `make run`构建并运行,有结果,但不是想看到的:
72-
73-
> **[danger] 非预期的显示结果**
71+
使用 `make run`构建并运行,你可能能看到以下的正确结果:
7472

73+
> **[success] trap handled**
74+
>
7575
> ```rust
7676
> ++++ setup interrupt! ++++
77-
> ++++ setup interrupt! ++++
78-
> ......
77+
> trap: cause: Exception(Breakpoint), epc: 0x0x80200022
78+
> panicked at 'trap handled!', src/interrupt.rs:20:5
7979
> ```
8080
81-
### 开启内核态中断使能
82-
83-
为何没有中断处理程序的显示,而是 qemu 模拟的 riscv 计算机不断地重新启动?仔细检查一下代码,发现在初始化阶段缺少使能中断这一步!
84-
事实上寄存器 `sstatus` 中有一控制位 `SIE`,表示 S 态全部中断的使能。如果没有设置这个`SIE`控制位,那在 S 态是不能正常接受时钟中断的。需要对下面的代码进行修改,在初始化阶段添加使能中断这一步:
85-
86-
```rust
87-
diff --git a/os/src/interrupt.rs b/os/src/interrupt.rs
88-
...
89-
@@ -2,13 +2,15 @@ use riscv::register::{
90-
scause,
91-
sepc,
92-
stvec,
93-
- sscratch
94-
+ sscratch,
95-
+ sstatus
96-
};
97-
98-
pub fn init() {
99-
unsafe {
100-
sscratch::write(0);
101-
stvec::write(trap_handler as usize, stvec::TrapMode::Direct);
102-
+ sstatus::set_sie();
103-
}
104-
println!("++++ setup interrupt! ++++");
105-
}
106-
107-
```
81+
但是很不巧,你有差不多相同的概率看到以下和我们预期不同的的结果:
10882
109-
再使用 `make run`构建并运行,有预想的结果了!
83+
> **[danger] 非预期的显示结果**
11084
111-
> **[success] trap handled**
112-
>
11385
> ```rust
11486
> ++++ setup interrupt! ++++
115-
> trap: cause: Exception(Breakpoint), epc: 0x0x80200022
116-
> panicked at 'trap handled!', src/interrupt.rs:20:5
87+
> ++++ setup interrupt! ++++
88+
> ......
11789
> ```
11890
119-
可见在进入中断处理程序之前,硬件为我们正确的设置好了 `scause,sepc` 寄存器;随后我们正确的进入了设定的中断处理程序。如果输出与预期不一致的话,可以在[这里][code]找到目前的代码进行参考。
91+
内核进入了 Boot loop?
92+
93+
### 保证异常处理入口对齐
94+
95+
为何没有异常处理程序的显示,而是 qemu 模拟的 riscv 计算机不断地重新启动?根据 RV64 ISA,异常处理入口必须按照四字节对齐,但是我们现在的代码并没有保证这一点。因此我们在设置 stvec 的时候,事实上最低两位地址被置零了,发生异常的时候可能直接跳转到了我们的异常处理程序的第一条指令中间。显然,这很大概率会导致各种各样的奇怪条件,之后跑飞。
12096
121-
到目前为止,虽然能够响应中断了,但在执行完中断处理程序后,系统还无法返回到之前中断处继续执行。如何做到?请看下一节
97+
很遗憾是,Rust 没有简单地办法保证一个符号的对齐,此外使用纯 Rust 实现 Trap handler 还有一些其他的问题:Rust 会在函数的开始和结尾加入一些额外的指令,控制栈寄存器等。因此如果要完成保存现场等工作,以便在异常处理程序完成后返回,Rust 单独是难以完成的。接下来几节中我们将通过提供使用汇编代码编写的异常处理程序来解决这些问题
12298
12399
[code]: https://github.com/rcore-os/rCore_tutorial/tree/ch3-pa2

chapter3/part4.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ OS 在正确完成中断初始化(设置中断处理程序的起始地址,
99
1010
.section .text
1111
.globl __alltraps
12+
.align 4
1213
__alltraps:
1314
SAVE_ALL
1415
mv a0, sp
@@ -20,7 +21,7 @@ __trapret:
2021
sret
2122
```
2223

23-
我们首先定义 `__alltraps` 函数作为所有中断处理程序的入口,这里我们首先通过 `SAVE_ALL` (汇编宏)来保存上下文环境,随后将当前栈顶地址 `sp` 的值给到寄存器 `a0` ,这是因为在 risc-v calling convention 中,规定 `a0` 保存函数输入的第一个参数,于是就相当于将栈顶地址传给函数 `rust_trap` 作为第一个参数。
24+
我们首先定义 `__alltraps` 函数作为所有中断处理程序的入口,这里我们首先通过 `SAVE_ALL` (汇编宏)来保存上下文环境,随后将当前栈顶地址 `sp` 的值给到寄存器 `a0` ,这是因为在 risc-v calling convention 中,规定 `a0` 保存函数输入的第一个参数,于是就相当于将栈顶地址传给函数 `rust_trap` 作为第一个参数。正如我们之前提及的,__alltraps 需要以四字节对齐。
2425

2526
随后,我们通过 `jal` 调用 `rust_trap` 函数并在返回之后跳转到调用语句的下一条指令。实际上调用返回之后进入 `__trapret` 函数,这里我们通过 `RESTORE_ALL` (汇编宏)恢复中断之前的上下文环境,并最终通过一条 `sret` 指令跳转到 `sepc`指向的地址,即回到触发中断的那条指令所在地址。这会导致触发中断的那条指令又被执行一次。
2627

@@ -181,8 +182,6 @@ pub fn init() {
181182
// 仍使用 Direct 模式
182183
// 将中断处理总入口设置为 __alltraps
183184
stvec::write(__alltraps as usize, stvec::TrapMode::Direct);
184-
// 设置 sstatus 的 SIE 位
185-
sstatus::set_sie();
186185
}
187186
println!("++++ setup interrupt! ++++");
188187
}

chapter3/part5.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,7 @@ fn super_timer() {
146146
println!("* 100 ticks *");
147147
}
148148
}
149-
// 由于一般都是在死循环内触发时钟中断
150-
// 因此我们同样的指令再执行一次也无妨
151-
// 因此不必修改 sepc
149+
// 发生外界中断时,epc 指向的指令没有完成执行,因此这里不需要修改 epc
152150
}
153151
```
154152

0 commit comments

Comments
 (0)