QEMU模拟MIPS Malta时异常地址与文档不符的问题咨询
嘿,这个问题我之前帮朋友排查过,核心原因和QEMU模拟Malta的硬件逻辑、MIPS架构的异常向量规则直接相关,咱们一步步理清楚:
为什么QEMU里异常跳转到
0xbfc00384而非文档里的0x80000080? 1. MIPS异常向量的两种“档位”
MIPS架构的异常向量地址本来就有两种配置:
- 常规内核态异常:正常情况下,异常发生时CPU会跳转到
0x80000080(属于KSEG0区域,带缓存映射),这也是大部分文档里提到的地址。 - BootROM主导的启动阶段:Malta开发板的BootROM(启动固件)是映射在
0xbfc00000开头的KSEG1区域(非缓存映射),QEMU模拟的Malta默认从这个BootROM启动,而BootROM里把异常处理的入口设置成了0xbfc00384——这就是你调试时看到的跳转地址。
2. QEMU模拟的BootROM在搞什么?
QEMU给Malta模拟的BootROM会帮你做硬件初始化、设置基础的异常处理链。简单说:
当异常触发时,CPU先进入BootROM的0xbfc00384入口,这里的代码会先保存上下文、判断异常类型,然后再决定下一步跳去哪里。如果你还没替换掉BootROM的向量表,自然就会走到这个地址。
3. 怎么让异常跳转到你自己的0x80000080?
要把异常控制权拿到你自己的内核里,需要两步操作:
- 关掉Boot异常向量(BEV)位:修改CP0的Status寄存器,把第22位(BEV位)设为0。这样CPU就会使用KSEG0的
0x80000080作为异常向量,而非BootROM的KSEG1地址。 - 替换异常向量表:在
0x80000080位置放上你的异常处理入口代码,比如一条跳转指令:
记得在你的链接脚本里把.section .vectors, "ax" .globl exception_entry exception_entry: j handle_exception # 跳转到你的实际异常处理函数 nop # MIPS延迟槽指令.vectors段明确映射到0x80000080地址。
4. 用GDB快速验证
调试时可以先查看CP0的Status寄存器,确认BEV位状态:
info registers cp0_status
如果BEV位是1(表示启用BootROM向量),执行这条命令关掉它:
set $cp0_status = $cp0_status & ~(1<<22)
之后再触发异常,就能看到CPU跳转到你设置的0x80000080了。
内容的提问来源于stack exchange,提问作者ulfsigvardsson
相关产品推荐
相关产品推荐

