掉进兔子洞(中断入口点)
我们已经知道,在发生中断的时候, CPU会跳到stvec.我们准备采用Direct模式,也就是只有一个中断处理程序, stvec直接跳到中断处理程序的入口点,那么需要我们对stvec寄存器做初始化.
中断的处理需要“放下当前的事情但之后还能回来接着之前往下做”,对于CPU来说,实际上只需要把原先的寄存器保存下来,做完其他事情把寄存器恢复回来就可以了。这些寄存器也被叫做CPU的context(上下文,情境)。我们要用汇编实现上下文切换(context switch)机制,这包含两步:
保存CPU的寄存器(上下文)到内存中(栈上)
从内存中(栈上)恢复CPU的寄存器
为了方便我们组织上下文的数据(几十个寄存器),我们定义一个结构体。
sscratch寄存器在处理用户态程序的中断时才起作用。在目前其实用处不大。
须知 RISCV汇编的通用寄存器别名和含义
The RISC-V Instruction Set Manual Volume I: Unprivileged ISA Document Version 20191213
Chapter 25 RISC-V Assembly Programmer’s Handbook
Register
ABI Name
Description
Saver
x0
zero
Hard-wired zero
—
x1
ra
Return address
Caller
x2
sp
Stack pointer
Callee
x3
gp
Global pointer
—
x4
tp
Thread pointer
—
x5
t0
Temporary/alternate link register
Caller
x6–7
t1–2
Temporaries
Caller
x8
s0/fp
Saved register/frame pointer
Callee
x9
s1
Saved register
Callee
x10–11
a0–1
Function arguments/return values
Caller
x12–17
a2–7
Function arguments
Caller
x18–27
s2–11
Saved registers
Callee
x28–31
t3–6
Temporaries
Caller
C语言里面的结构体,是若干个变量在内存里直线排列。也就是说,一个trapFrame结构体占据36个uintptr_t的空间(在64位RISCV架构里我们定义uintptr_t为64位无符号整数),里面依次排列通用寄存器x0到x31,然后依次排列4个和中断相关的CSR, 我们希望中断处理程序能够利用这几个CSR的数值。
首先我们定义一个汇编宏 SAVE_ALL, 用来保存所有寄存器到栈顶(实际上把一个trapFrame结构体放到了栈顶)。
然后是恢复上下文的汇编宏,恢复的顺序和当时保存的顺序反过来,先加载两个CSR, 再加载通用寄存器。
现在我们编写真正的中断入口点
我们可以看到,trapentry.S这个中断入口点的作用是保存和恢复上下文,并把上下文包装成结构体送到trap函数那里去。下面我们就去看看trap函数里面做些什么。
最后更新于
这有帮助吗?