PA3报告

PA3.1

  1. 特殊的原因? (建议二周目思考)

​ 这些程序状态(x86的eflags, cs, eip; mips32的epc, status, cause; riscv32的mepc, mstatus, mcause)必须由硬件来保存吗? 能否通过软件来保存? 为什么?

还不知道

  1. 异常号的保存

    ​ x86通过软件来保存异常号, 没有类似cause的寄存器. mips32和riscv32也可以这样吗? 为什么?

还不知道

  1. 对比异常处理与函数调用

    ​ 我们知道进行函数调用的时候也需要保存调用者的状态: 返回地址, 以及calling convention中需要调用者保存的寄存器. 而CTE在保存上下文的时候却要保存更多的信息. 尝试对比它们, 并思考两者保存信息不同是什么原因造成的.

保存上下文除了通用寄存器信息和PC等,还要CSR寄存器的信息,包括异常原因、异常状态等

  1. 理解上下文结构体的前世今生

    你会在__am_irq_handle()中看到有一个上下文结构指针c, c指向的上下文结构究竟在哪里? 这个上下文结构又是怎么来的? 具体地, 这个上下文结构有很多成员, 每一个成员究竟在哪里赋值的? $ISA-nemu.h, trap.S, 上述讲义文字, 以及你刚刚在NEMU中实现的新指令, 这四部分内容又有什么联系?

    • c指向的上下文结构在 trap.S__am_asm_trap

    • 开辟CONTEXT_SIZE大小的栈空间,把通用寄存器压入栈,然后读出mcause、mstatus、mepc到通用寄存器暂存,然后压入一定偏移的内存中。然后设置mstatus.MPRV to pass difftest,然后跳转到__am_irq_handle,然后再取出CSR和通用寄存器恢复。

  2. 理解穿越时空的旅程

  • 主函数如下,进入之前通过asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));定义好异常入口。并把simple_trap作为异常后执行的函数。

    image-20231227212916884

  • 首先进入yield(),该函数由内敛汇编指令组成,并调用ecall指令.

asm volatile("li a5, -1; ecall");,在RV32E中,把a5置为-1(RV32是a7),记录原因,也就是mcause;ecall会发起自陷,即调用isa_raise_intr,这里有一点需要注意,ecall的异常码固定为11(0xb),因此这里直接传入11而不是保存原因的寄存器。

image-20240113150007688

image-20240113145609002
  • 进入isa_raise_intr,记录mcausemepc,跳转到trap.s定义的异常入口__am_asm_trap

    image-20240113150346407

  • 保存现场后,执行回调函数__am_irq_handle,借助mcause识别异常的类型并处理(这里是yield,0x0b),另外用软件的方式把mepc+4;指向自陷指令PC的下一条;然后调起user_handler,测试中为simple_trap,会执行相应的命令,这里是输出字符"y"。

    image-20240113201605853

  • 执行完成后,回到trap.s进行现场复原,即把之前保存到栈里的csr和通用寄存器弹出,通过mret返回,也就是yield的下一条指令。

image-20240113203312289
posted @   HiDark  阅读(163)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
主题色彩
点击右上角即可分享
微信分享提示