在这一章中有一个需要注意的地方,即由于任务切换是由系统决定的,因此对于上一个任务的上下文保存过程放在了trap_vector中,并且switch_to函数的返回方式变为mret(中断处理要求使用mret)。
.global trap_vector
.balign 4
trap_vector:
csrrw t6,mscratch,t6
reg_save t6
mv t5,t6
csrr t6,mscratch
STORE t6,30*SIZE_REG(t5)
csrr a0, mepc
STORE a0, 31*SIZE_REG(t5)
csrw mscratch, t5
csrr a0, mepc
csrr a1, mcause
call trap_handler
csrw mepc, a0
csrr t6, mscratch
reg_restore t6
mret
.global switch_to
.balign 4
switch_to:
csrw mscratch, a0
LOAD a1, 31*SIZE_REG(a0)
csrw mepc, a1
mv t6, a0
reg_restore t6
mret
.end
而mret会恢复之前的特权级别、程序计数器、堆栈指针等上下文信息。即调用mret时,mstatus中的MIE位会被MPIE位替换。此时需注意start.S启动代码对于mstatus寄存器的赋值,把MPIE位赋值为1即可,这样调用mret后自动开启全局中断。
csrr t0, mstatus
ori t0, t0, 0x80
csrw mstatus, t0