保存上下文

处理异常的时候需要保存寄存器内容(上下文的一部分),需要将这些内容保存下来。但是硬件不负责这些内容的保存,因此需要用软件代码来保存这些寄存器的值。riscv采用sw指令将各个通用寄存器以此压栈。

除了通用寄存器之外,还需要保存其他上下文内容:

  • 触发异常时的PC和处理器状态,riscv中的mepc和mstatus寄存器。异常相应机制把它们保存在相应的系统寄存器中,我们还需要将他们从系统寄存器读出,然后保存在堆栈上。
  • 异常号,riscv的mcause寄存器。我们还需要将他们保存在堆栈上。
  • 地址空间,PA4时考虑

这些内容构成了完整的上下文信息, 异常处理过程可以根据上下文来诊断并进行处理, 同时, 将来恢复上下文的时候也需要这些信息。

接下来代码会调用C函数__am_irq_handle()(在abstract-machine/am/src/$ISA/nemu/cte.c中定义), 来进行异常的处理。

学到了一个东西:函数指针

重新组织Context结构体

  • 实现这一过程的新指令(我理解为保存上下文中的新指令

  • 理解上下文形成过程,重新组织abstract-machine/am/include/arch/$ISA-nemu.h 中定义的Context结构体的成员,使得这些成员的定义顺序和 abstract-machine/am/src/$ISA/nemu/trap.S中构造的上下文保持一致。

  • 并且在重新组织Context结构体时仍然需要正确地处理地址空间信息的位置, 否则你可能会在PA4中遇到难以理解的错误.

实现之后, 你可以在__am_irq_handle()中通过printf输出上下文c的内容, 然后通过简易调试器观察触发自陷时的寄存器状态, 从而检查你的Context实现是否正确.

这里观察abstract-machine/am/src/$ISA/nemu/trap.S中的行为,先是顺序的往内存栈中压入普通寄存器的内容,然后再向其中压入csr寄存器的内容,到这里应该能猜出Context结构的成员的顺序了。

但是为什么是这种顺序呢?

我从互联网上看到有其他人的回答是这样的,结构体是一段连续存储的地址空间,而trap.S中向内存中逐个写入的操作其实就是向一段连续的地址内写入数据的操作,如果这个地址开头正好是结构体的地址,并且写入顺序和结构体的定义顺序一致,那么就相当于向一个结构体写数据。

必答题

首先要知道__am_irq_handle()是被trap.S调用的,在调用之前会执行一条指令:

mv a0, sp

这其实就是汇编函数调用时的传参。

汇编函数调用以及传参[从汇编语言的寄存器来看函数参数传递 - 金色旭光 - 博客园 (cnblogs.com)](https://www.cnblogs.com/goldsunshine/p/14560301.html#:~:text=3|5函数调用传参总结 1 传值调用 直接拷贝一份 数值,到被调用函数,被调用函数中的数值和调用函数中的数值在内存中是两份相互独立的; 2 传地址调用 是将 数值的地址 拷贝一份到被调用函数中,数值在内存中只有一份,被调用函数通过该地址还能找到数值,可以修改这个数值。)

例如

#include<stdio.h>
int main()
{
int a = 10;
return 0;
}

在汇编之后

	.file	"space.c"
.option pic
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-32
sd s0,24(sp)
addi s0,sp,32
li a5,10
sw a5,-20(s0)
li a5,0
mv a0,a5
ld s0,24(sp)
addi sp,sp,32
jr ra
.size main, .-main
.ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
.section .note.GNU-stack,"",@progbits

其中的头三条指令就是将main函数压栈,作为栈底,最后也是在main函数中退出。

传值/传地址

传值调用和传地址调用最大区别就在于调用函数处理实参的方式,传值调用,就是将数值当做实参写入寄存器,被调用函数从寄存器中取出数值;传地址调用是将数值的地址当作实参写入寄存器,被调用函数中从寄存器取出地址。

到这里就明白了,其实该指令就是函数调用传递参数的过程,只不过是用汇编语言编写的。

__am_irq_handle()函数的参数就是Context *c,那么就可以理解了,通过trap.Smv a0, sp传递进来的就是结构体指针c的地址。

事件分发

__am_irq_handle()函数会根据c中的mcause给当前的异常打包编号,编好号之后调用回调函数user_handler(ev, c),第一个参数就是异常编号,第二个参数就是上下文c。然后nanos-liteinit_irq()执行异常的具体行为。

恢复上下文

代码将会一路返回到trap.S__am_asm_trap()中, 接下来的事情就是恢复程序的上下文。

这里我漏了一个地方,riscv需要在软件层面实现PC+4。

也就是在处理具体异常的时候,根据不同异常的不同要求,分别实现是否PC+4。

这里也就出现了两个地方可以供我修改,一个是abstract-machine/am/src/riscv/nemu/cte.c,一个是/home/groot/ysyx-workbench/nanos-lite/src/irq.c。但是说了软件,就不能在abstract-machine中实现,而要在nanos-lite中实现这一功能。

实现的过程就是在do_event中处理异常的时候,根据异常的不同,决定是否将c->mepc+4。

必答题yield()的实现过程

->nanos-lite main()

---> abstact-machine yield()

--------->nemu ecall()

​ // 经过这一步之后pc值被改变, 改变为异常处理函数的入口.也就是在cte_init()中注册的地址: __am_asm_trap.

------------->nemu isa_raise_intr()

​ // 这里就是上下文保存+异常处理+恢复上下文的函数了

-----------------> abstract-machine __am_asm_trap

---------------------> abstract-machine __am_irq_handle()

------------------------->nanos-lite do_event()

---------------------> abstract-machine __am_irq_handle()

-----------------> abstract-machine __am_asm_trap

​ // 经过这一步之后pc值被还原为异常之前的pc值(或者由软件确认的是否+4的pc值)

------------->nemu mret()

---> abstact-machine yield()

->nanos-lite main()

在这里我遇见了另一个问题:如何实现DiffTest中异常行为和nemu的异常行为一致。

需要知道的一点是Spike的异常处理是一套完整的异常处理流程,而不是像nemu是一个简陋版。所以二者的行为肯定有不一样的地方,所以我应该在nemu中模仿spike的行为,将mstatus寄存器的值按照Spike中的行为处理,而不是完全按照手册处理。

一生一芯/NEMU PA3.1随笔的更多相关文章

  1. 64位的单周期 RISC-V 模拟器

    分享一个我最近完成过的小项目--64位的单周期 RISC-V 模拟器,这个项目我最近参与一生一芯计划过程中完成的一个小项目. 需要用到的相关知识:Verilog.Verilator.计算机组成原理.汇 ...

  2. 动手学TCP——CS144实验感想

    在Stanford CS144的课程实验Lab0~Lab4中,我们动手实现了一个自己的TCP协议,并且能够真的与互联网通信!此外,感谢Stanford开源本实验并提供了大量的优质测试用例,使得我们仅仅 ...

  3. Linux下学习FPGA

    声明(叠甲):鄙人水平有限,本文章仅供参考. 1.环境 推荐使用 Ubuntu20.04这是我使用多个版本中最好用的一个,相关安装教程可以自行上网搜索这不再赘述,但要补充的一点的是源推荐使用中科大的源 ...

  4. RDMA调研报告&一点随笔

    计算所科研实践随笔 被淹没在论文海里的两个星期. 早上7:10分起床,草草洗漱,7:30出发,开始漫长的1小时通勤.从地铁站的安检口起,队便排的极长,让人看得头皮发麻.下到了轨道旁稍好,但每趟呼啸而来 ...

  5. 龙芯fedora28日常生存指南

    2021-01-30 v0.0.5 从0.0.1开始改了非常多,一月余时间的花费渴望为其他人提供一点帮助,能够快速上手. 这主要是这一年来我从3B1500到3A4000再到福珑2的日常使用记录,是之前 ...

  6. <小李飞刀>系列 随笔

    1.多情剑客无情剑 古龙的作品在电视上只看过电影版的陆小凤传奇,对古龙的作品也没有过系统的了解,初读时听到了李寻欢的名字,突然感觉可惜.觉得如此早就读到这种级别的小说有些暴殄天物,不过也算是以白纸状态 ...

  7. AI人工智能系列随笔

    初探 AI人工智能系列随笔:syntaxnet 初探(1)

  8. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

  9. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  10. C++随笔:从Hello World 探秘CoreCLR的内部(1)

    紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序. 通过我的寻找,其实是一个名为TryRun的文件出了 ...

随机推荐

  1. 645仪表以JSON格式上发方法

    1.概述 之前我们已经介绍了Modbus RTU仪表实现JSON格式上发云服务器的方法,类似的现在也可以支持645协议的仪表通过JSON格式上发服务器. 卓岚实现645仪表转JSON网关的特点有: 1 ...

  2. windows failed to start

    现象 今天启动我的window11的时候,突然进不去系统了 解决办法 找一个winPe的u盘,进入. 然后找到Windows引导修复工具,这个是在winPe里都会内置的工具(比如老毛桃.大白菜.微PE ...

  3. 【6】树的DFS序、直径、重心

    前言 树上操作是 OI 重要的一环,树的 DFS 序.直径.重心这一堆东西也是树上操作的基础.树的 DFS 序可以把树上问题转化为区间问题,树的直径的性质经常是解题的关键,树的重心可以防止一些树上算法 ...

  4. Codeforces Round #706 (Div. 2) D. Let's Go Hiking 博弈 思维

    思路:A要赢的大前提就是当前x是一个波峰. 因为如果是一个直线单调的话如1 2 3 4 5(或者5 4 3 2 1),不管A选哪个位置,B直接在他下一个位置封死,A就直接GG. 现在考虑波峰的时候,那 ...

  5. 指针与地址 今天 面了一家创业公司 用C++做笔试题目 YYEJ

    int a = 20; int *b = &a; printf("%d %d %d \n",a,b,*b);// 输出的值是 20 (a的地址) 20 *b = & ...

  6. linux 安装 svn

    简介 RT 参考链接 请参阅下面的链接 https://idroot.us/install-apache-subversion-ubuntu-20-04/ ---- 下面的复制以防万一访问失效 引用步 ...

  7. POLIR-Mind-Cognition-Neural Models-NLP(Neuro-Linguistic Programming) 思维逻辑层级(logical Levels)-理解+解决问题-无敌洞察力+高维思路-{精神,身份,价值,能力,行为,环境}

    Neuro-Linguistic Programming-百知思维模型-NLP理解层次 能给你无敌洞察力+高维思路 https://v.douyin.com/iS74bMKr/ 最重要的两种能力: 目 ...

  8. POLIR-Society-Organization-Mind-真实社论: 守护好自我能量场:{气定心定,心定事顺} + 常政"平凡生活" + 不需要去应答负能量事情

    守护好自我能量场心定事顺 少在烂事上纠缠,少为不值得的人生气烦心. 守护好自己的能量场: 气定心定, 心定事顺. 不需要去应答负能量事情 凡是负能量的事情, 都不需要去应答. 凡是应答, 必将与其纠缠 ...

  9. Git-进阶1 git reset 加不加 --hard的区别 --九五小庞

    通常我们提交代码一般都是 git add ,git commit -m, git push的这么个流程.添加到暂存区,提交到git库生成版本号,push到远程仓库以供他人可以使用.这是一个完整的且非常 ...

  10. 如何本地部署Deepseek大模型

    本地部署Deepseek大模型 1.下载Ollama 去ollama官网https://ollama.com/ 下载可执行程序,可选macos.linux和Windows版本下载 下载之后如果点击直接 ...