@@ -68,56 +68,32 @@ pub extern "C" fn rust_main() -> ! {
68
68
}
69
69
```
70
70
71
- 使用 ` make run ` 构建并运行,有结果,但不是想看到的:
72
-
73
- > ** [ danger] 非预期的显示结果**
71
+ 使用 ` make run ` 构建并运行,你可能能看到以下的正确结果:
74
72
73
+ > ** [ success] trap handled**
74
+ >
75
75
> ``` rust
76
76
> ++++ setup interrupt! ++++
77
- > ++++ setup interrupt! ++++
78
- > ......
77
+ > trap : cause : Exception ( Breakpoint ), epc : 0x0x80200022
78
+ > panicked at ' trap handled! ', src/interrupt.rs:20:5
79
79
> ```
80
80
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
+ 但是很不巧,你有差不多相同的概率看到以下和我们预期不同的的结果:
108
82
109
- 再使用 ` make run ` 构建并运行,有预想的结果了!
83
+ > **[danger] 非预期的显示结果**
110
84
111
- > ** [ success] trap handled**
112
- >
113
85
> ```rust
114
86
> ++++ setup interrupt! ++++
115
- > trap : cause : Exception ( Breakpoint ), epc : 0x0x80200022
116
- > panicked at ' trap handled! ', src/interrupt.rs:20:5
87
+ > ++++ setup interrupt! ++++
88
+ > ......
117
89
> ```
118
90
119
- 可见在进入中断处理程序之前,硬件为我们正确的设置好了 `scause,sepc` 寄存器;随后我们正确的进入了设定的中断处理程序。如果输出与预期不一致的话,可以在[这里][code]找到目前的代码进行参考。
91
+ 内核进入了 Boot loop?
92
+
93
+ ### 保证异常处理入口对齐
94
+
95
+ 为何没有异常处理程序的显示,而是 qemu 模拟的 riscv 计算机不断地重新启动?根据 RV64 ISA,异常处理入口必须按照四字节对齐,但是我们现在的代码并没有保证这一点。因此我们在设置 stvec 的时候,事实上最低两位地址被置零了,发生异常的时候可能直接跳转到了我们的异常处理程序的第一条指令中间。显然,这很大概率会导致各种各样的奇怪条件,之后跑飞。
120
96
121
- 到目前为止,虽然能够响应中断了,但在执行完中断处理程序后,系统还无法返回到之前中断处继续执行。如何做到?请看下一节 。
97
+ 很遗憾是,Rust 没有简单地办法保证一个符号的对齐,此外使用纯 Rust 实现 Trap handler 还有一些其他的问题:Rust 会在函数的开始和结尾加入一些额外的指令,控制栈寄存器等。因此如果要完成保存现场等工作,以便在异常处理程序完成后返回,Rust 单独是难以完成的。接下来几节中我们将通过提供使用汇编代码编写的异常处理程序来解决这些问题 。
122
98
123
99
[code]: https://github.com/rcore-os/rCore_tutorial/tree/ch3-pa2
0 commit comments