xv6 traps

Traps and System calls

什么是trap

在xv6操作系统中,"trap"是指cpu暂时跳出正常执行流程,从用户态切换到内核态的一种机制。这种切换,在xv6系统中,在这3个情况下发生:系统调用、异常、外部设备触发了中断。

系统调用就是使用了ecall指令,之前lab中增加过trace的syscall

异常的情况,包括page fault, 除0等等

外部设备触发中断,一般是磁盘完成了读写等

trap一般流程

  1. 一个trap发生时,把控制权转移到kernel
  2. 在kernel中保存寄存器,和其他一些状态,以便可以在处理完trap后恢复到正常的执行流程中去。
  3. 在kernel中执行handler代码
  4. kernel恢复保存的状态,从trap中返回,回到原本的执行代码中去。

用来处理trap的kernel代码(C或asm)通常称为handler,handler中的指令通常是用asm写的,称为vector.
我理解,handler就是trampoline.S

riscv trap机制

每个riscv cpu都有一组reg,kernel将cpu如何处理trap的信息写到这些reg中。在一个多核的芯片上,因为每个cpu有自己的一组reg,所以可以独立的处理trap

  1. stvec
    trap handler的地址写在这里
  2. sepc
    pc寄存器的值保存在这里,因为后续pc的值要被stvec中的值覆盖,sret指令会把sepc的值拷贝回pc寄存器,用来当trap结束后的返回地址。
  3. scause: 一个数字,用来描述trap的原因。
  4. sscratch: 一个值,方便handler的起始阶段使用
  5. sstatus: 这个寄存器中的SIE bit控制设备中断是否启用。SSP bit表示一个trap来自user mode还是supervisor mode,控制sret返回的mode

code: 调用 系统调用

看一下用户是如何进行exec系统调用的

initcode.S将exec的参数放在reg a0, a1中,系统调用码放在a7中. 这个系统调用码和syscalls指针数组中,exec的函数指针在数组中的索引是相同的. ecall指令立即通过trap机制进行kernel中,通过uservec -> usertrap -> syscall来进行执行

当sys_exec这个系统调用函数结束后,syscall记录了这个返回值,放在trapframe->a0,user也会得到这个返回值.

NOTE相关

  • 6.3节中

对于这里page table,有一件事情需要注意:它并没有包含任何内核部分的地址映射,这里既没有对于kernel data的映射,也没有对于kernel指令的映射。除了最后两条PTE,这个page table几乎是完全为用户代码执行而创建,所以它对于在内核执行代码并没有直接特殊的作用。

这段内容中,kernel data是什么?

  • 6.4节

这里的控制是通过STVEC寄存器完成的,这是一个只能在supervisor mode下读写的特权寄存器。在从内核空间进入到用户空间之前,内核会设置好STVEC寄存器指向内核希望trap代码运行的位置。

内核何时设置了STVEC寄存器?代码对应到哪里?

  • 6.5节

注意看学生提问

STVEC是内核在进入到用户空间之前设置好的众多数据之一,内核会将其设置成trampoline page的起始位置。

所以是在当前user mode之前的kernel mode会进行设置的操作

kernel stack和user stack区别

image

image

根据trapframe结构体的定义,起始地址偏移8字节的地址,就是kernel stack的地址。所以现在是把kernel stack的地址加载到当前进程的stack pointer,以开始执行kernel代码。

posted @ 2023-10-18 13:48  ijpq  阅读(37)  评论(0编辑  收藏  举报