xv6项目开源—04
理论
本章讲的是陷阱指令和系统调用
1)有三种事件会导致中央处理器搁置普通指令的执行,并强制将控制权转移到处理该事件的特殊代码上:
系统调用、异常、设备中断
2)Xv6陷阱处理分为四个阶段: RISC-V CPU采取的硬件操作、为内核C代码执行而准备的汇编程序集“向量”、决定如何处理陷阱的C陷阱处理程序以及系统调用或设备驱动程序服务例程。
3)重要的寄存器的概念:
stvec:内核在这里写入其陷阱处理程序的地址;RISC-V跳转到这里处理陷阱。sepc:当发生陷阱时,RISC-V会在这里保存程序计数器pc(因为pc会被stvec覆盖)。sret(从陷阱返回)指令会将sepc复制到pc。内核可以写入sepc来控制sret的去向。scause: RISC-V在这里放置一个描述陷阱原因的数字。sscratch:内核在这里放置了一个值,这个值在陷阱处理程序一开始就会派上用场。sstatus:其中的SIE位控制设备中断是否启用。如果内核清空SIE,RISC-V将推迟设备中断,直到内核重新设置SIE。SPP位指示陷阱是来自用户模式还是管理模式,并控制sret返回的模式
4)RISC-V有三种不同的页面错误: 加载页面错误 (当加载指令无法转换其虚拟地址时),存储页面错误 (当存储指令无法转换其虚拟地址时) 和指令页面错误 (当指令的地址无法转换时)。
5)当需要强制执行陷阱时,RISC-V硬件对所有陷阱类型(计时器中断除外)执行以下操作:
- 如果陷阱是设备中断,并且状态SIE位被清空,则不执行以下任何操作。
- 清除SIE以禁用中断。
- 将
pc复制到sepc。 - 将当前模式(用户或管理)保存在状态的SPP位中。
- 设置
scause以反映产生陷阱的原因。 - 将模式设置为管理模式。
- 将
stvec复制到pc。 - 在新的
pc上开始执行。
6)当CPU无法将虚拟地址转换为物理地址时,CPU会生成页面错误异常。Risc-v有三种不同的页面错误: 加载页面错误 (当加载指令无法转换其虚拟地址时),存储页面错误 (当存储指令无法转换其虚拟地址时) 和指令页面错误 (当指令的地址无法转换时)。scause寄存器中的值指示页面错误的类型,stval寄存器包含无法翻译的地址。
7)利用页面故障的另一个广泛使用的功能是从磁盘分页。如果应用程序需要比可用物理RAM更多的内存,内核可以换出一些页面: 将它们写入存储设备 (如磁盘),并将它们的PTE标记为无效。如果应用程序读取或写入被换出的页面,则CPU将触发页面错误。然后内核可以检查故障地址。如果该地址属于磁盘上的页面,则内核分配物理内存页面,将该页面从磁盘读取到该内存,将PTE更新为有效并引用该内存,然后恢复应用程序。为了给页面腾出空间,内核可能需要换出另一个页面。此功能不需要对应用程序进行更改,并且如果应用程序具有引用的地址 (即,它们在任何给定时间仅使用其内存的子集),则该功能可以很好地工作。
结合分页和页面错误异常的其他功能包括自动扩展栈空间和内存映射文件。
实践
1)RISC-V
阅读**call.asm*中函数g、f和main的代码。RISC-V的使用手册在参考页上。以下是您应该回答的一些问题(将答案存储在answers-traps.txt***文件中):
-
哪些寄存器保存函数的参数?例如,在
main对printf的调用中,哪个寄存器保存13?(1). 在a0-a7中存放参数,13存放在a2中
-
main的汇编代码中对函数f的调用在哪里?对g的调用在哪里(提示:编译器可能会将函数内联)(2). 在C代码中,main调用f,f调用g。而在生成的汇编中,main函数进行了内联优化处理。
从代码
li a1,12可以看出,main直接计算出了结果并储存 -
printf函数位于哪个地址?(3). 在
0x630 -
在
main中printf的jalr之后的寄存器ra中有什么值?(4).
auipc(Add Upper Immediate to PC):auipc rd imm,将高位立即数加到PC上,从下面的指令格式可以看出,该指令将20位的立即数左移12位之后(右侧补0)加上PC的值,将结果保存到dest位置 -
运行以下代码。
unsigned int i = 0x00646c72;
printf("H%x Wo%s", 57616, &i);
程序的输出是什么?这是将字节映射到字符的ASCII码表。
输出取决于RISC-V小端存储的事实。如果RISC-V是大端存储,为了得到相同的输出,你会把i设置成什么?是否需要将57616更改为其他值?
57616=0xE110,0x00646c72小端存储为72-6c-64-00,对照ASCII码表
72:r 6c:l 64:d 00:充当字符串结尾标识
因此输出为:HE110 World
若为大端存储,i应改为0x726c6400,不需改变57616
2)Backtrace
这个函数就是实现曾经调用函数地址的回溯,这个功能在日常的编程中也经常见到,编译器报错


2474

被折叠的 条评论
为什么被折叠?



