RISC-V trap handler内部触发异常的重入问题该如何处理?
RISC-V机器模式嵌套trap的mscratch上下文错误问题解决方案
核心思路
利用mstatus寄存器的MPP位判断trap触发前的特权级,区分**普通trap(从S/U模式进入)和嵌套trap(从M模式的trap handler内部进入)**两种场景,分别采用不同的上下文指针寻址逻辑。
具体实现步骤
前置初始化
每个硬件线程(hart)预先分配独立的机器模式trap上下文内存块,系统初始化阶段将该内存块的首地址写入CSR_MSCRATCH寄存器。
Trap入口处理
- 第一步执行交换指令:
csrrw tp, CSR_MSCRATCH, tp,完成tp与mscratch的值互换 - 第二步读取
mstatus寄存器,提取MPP字段判断trap来源:- 若MPP不等于机器模式(普通trap场景):此时tp寄存器已经是trap上下文首地址,直接按原有逻辑通过tp访问上下文即可
- 若MPP等于机器模式(嵌套trap场景):此时tp寄存器存储的是低特权级的原始tp值,
CSR_MSCRATCH寄存器中存储的才是trap上下文首地址,执行csrr t0, CSR_MSCRATCH将上下文地址读取到临时寄存器,后续通过该寄存器访问上下文
- 第三步将当前tp值(无论哪种场景都存储的是低特权级原始tp)存入trap上下文的预留字段,避免数据丢失
Trap出口处理
- 从trap上下文预留字段读取原始tp值,写回tp寄存器
- 执行
csrw CSR_MSCRATCH, <trap上下文首地址>,将上下文指针恢复到CSR_MSCRATCH,保证下一次trap进入逻辑正常
无空闲寄存器的兼容处理
如果入口处没有空闲寄存器可以用来读取mstatus,可以预先在trap上下文的首地址位置预留一个临时存储字段:
- 执行完
csrrw tp, CSR_MSCRATCH, tp后,先将当前tp值写入CSR_MSCRATCH指向的上下文首地址预留字段 - 复用tp作为临时寄存器读取
mstatus完成MPP判断 - 从预留字段读回原始tp值,再执行后续上下文保存逻辑
内容的提问来源于stack exchange,提问作者bitsnbytes
相关产品推荐
相关产品推荐

