跳转至

示例 · xv6 中断后栈错乱

这是一条按模板写好的真实风格示例。你的每条踩坑记录都长这样。

现象

跑 xv6 的 lab 时,开启时钟中断后偶发 panic,栈回溯(backtrace)显示返回地址是一串明显非法的值。

环境 / 触发条件

  • xv6-riscv,QEMU 7.x
  • 只在开启多核(CPUS=2 以上)时出现,单核复现不了
  • 大约每 20 次启动触发 1 次,非必现

走过的弯路

  • 一开始怀疑是自己改的调度器逻辑,回滚后仍复现 —— 排除。
  • 以为是 QEMU 版本问题,换版本无效 —— 排除。
  • 这些弯路本身值得记,免得下次又走一遍。

根因

中断处理入口没有正确切换到内核栈,在用户栈上继续压栈,遇到特定时序就踩到非法区域。本质是保存上下文的时机问题。

解法

在 trap 入口最早处先完成栈切换再做其它保存。关键改动:

# 进入 trap 后,第一件事就是换到内核栈
csrrw sp, sscratch, sp    # (1)
  1. sscratch 里事先放好了内核栈指针,csrrw 一条指令完成交换,避免在用户栈上多做任何动作。

一句话教训

中断/异常入口,换栈要趁早——任何在切换前发生的压栈都可能踩到不该碰的地方。

评论