Traps from kernel space
Two kinds of traps can occur from kernel:
exceptions
device interrupts
What happened during trap?
Save all registers
Call kerneltrap() trap handler
Restore registers
Return by calling
sret, which copiessepcto program counter and resumes the interrupted kernel code.
Implementation Details
Kernel points stvec register to kernelvec assmebly code. kernelvec save registers on the same interrupted kernel thread, since all registers belong to that thread.
kernelvec:
// make room to save registers.
addi sp, sp, -256
// save the registers.
sd ra, 0(sp)
sd sp, 8(sp)
sd gp, 16(sp)
sd tp, 24(sp)
sd t0, 32(sp)
sd t1, 40(sp)
sd t2, 48(sp)
sd s0, 56(sp)
sd s1, 64(sp)
sd a0, 72(sp)
sd a1, 80(sp)
sd a2, 88(sp)
sd a3, 96(sp)
sd a4, 104(sp)
sd a5, 112(sp)
sd a6, 120(sp)
sd a7, 128(sp)
sd s2, 136(sp)
sd s3, 144(sp)
sd s4, 152(sp)
sd s5, 160(sp)
sd s6, 168(sp)
sd s7, 176(sp)
sd s8, 184(sp)
sd s9, 192(sp)
sd s10, 200(sp)
sd s11, 208(sp)
sd t3, 216(sp)
sd t4, 224(sp)
sd t5, 232(sp)
sd t6, 240(sp)
// call the C trap handler in trap.c
call kerneltrap
// restore registers.
ld ra, 0(sp)
ld sp, 8(sp)
ld gp, 16(sp)
// not this, in case we moved CPUs: ld tp, 24(sp)
ld t0, 32(sp)
ld t1, 40(sp)
ld t2, 48(sp)
ld s0, 56(sp)
ld s1, 64(sp)
ld a0, 72(sp)
ld a1, 80(sp)
ld a2, 88(sp)
ld a3, 96(sp)
ld a4, 104(sp)
ld a5, 112(sp)
ld a6, 120(sp)
ld a7, 128(sp)
ld s2, 136(sp)
ld s3, 144(sp)
ld s4, 152(sp)
ld s5, 160(sp)
ld s6, 168(sp)
ld s7, 176(sp)
ld s8, 184(sp)
ld s9, 192(sp)
ld s10, 200(sp)
ld s11, 208(sp)
ld t3, 216(sp)
ld t4, 224(sp)
ld t5, 232(sp)
ld t6, 240(sp)
addi sp, sp, 256
// return to whatever we were doing in the kernel.
sretKernel trap handler
Xv6 sets a CPU’s stvec to kernelvec when that CPU enters the kernel from user space.
Disable Interrupt
There is a small windows, that stvec hasn’t been set. It is critical that no device interrupt happen during that time.
RISC-V always disables interrupts when it starts to take a trap, and xv6 doesn’t enable them again until after it sets stvec.
Note: 在设置好kernel trap vector to stvec之后 我们再enable interrupt,这是为了确保stvec的正确性。否则我们的stvec register在中断发生的时候 存的内容不正确可能会导致严重问题。
Set up to take exceptions and traps while in the kernel.
在正常情况下 从用户空间转到内核空间的时候 需要把Kernel handler 的地址写入存储器stvec
When and where do we set up stvec if trap is from user?
stvec if trap is from user?其实在usertrap handler的c代码里 一开始就存了kernel trap handler进stvec register
这样其实只要在kernel mode, stvec都是一直指向kernel trap handler. 保证的逻辑的正确性!
Last updated
Was this helpful?