[MIT 6.S081] Lec 6: Isolation & system call entry/exit 笔记

Lec 6: Isolation & system call entry/exit

Trap

  • trap: 用户空间和内核空间的切换
  • 切换时机:
    • 系统调用
    • 异常 Exception, 如缺页错误(page fault), 除零错误
    • 设备触发的中断
  • 重要的寄存器:
    • STVEC(Supervisor Trap Vector Base Address Register): 指向内核中处理 trap 的指令首地址(根据来自用户或内核, 代码会有不同)
    • SEPC(Supervisor Exception Program Counter): trap 过程中保存程序计数器的值
    • SSRATCH(Supervisor Scratch Register): 用于存放 trapframe 页面虚拟地址
  • 切换时需要完成的操作:
    • 保存 32 个用户寄存器
    • 保存程序计数器 PC
    • 将模式 MODE 由用户态切换为内核态
    • 将 SATP 寄存器由用户页表指向内核页表
    • 需要一个栈来调用内核的 C 函数, 并使 SP 指向
    • 跳入内核 C 代码
  • 内核模式(supervisor mode)的特权:
    • 读写 SATP 寄存器, 对 STVEC, SEPC, SSCRATCH 等寄存器进行操作
    • 可以使用 PTE_U 标志位为 0 的 PTE

Trap 代码执行流程

  1. 系统调用通过 ECALL 指令切换到内核中(该指令不会切换页表, 此时仍未用户页表)
  2. 内核执行汇编函数 uservec, 是 trampoline.Strampoline 的一部分. 该函数会切换 SSCRATCH 和 a0 寄存器的值, 之后 a0 的值即为 trapframe 的地址, 然后将 32 个用户寄存器等寄存器的值存于 p->trapframe 中; 然后会加载内核栈帧指针(kernel_sp), 并加载内核页表地址到 SATP 寄存器完成内核页表的切换. 最后跳转至 C 代码 trap.cusertrap()
  3. usertrap() 首先将 STVEC 寄存器由 usertrap 更改为 kerneltrap(因为此时再发送中断就属于在有来自内核的 trap). 然后若为系统调用则调用 syscall() 函数从系统调用表中查找相应系统功能的函数 sys_xxx() 进行执行, 执行后返回 syscall(); 若为来自设备的中断则执行 devintr. 最后会调用 usertrapret().
  4. 执行 trap.c 中的 usertrapret(). 首先会将 p->trapframe 中和内核相关的字段的值设置好, 用于下次 trap. 设置 SSTATUS 的用户模式标志位. 最后调用汇编函数 userret.
  5. 执行 trampoline.S 中的 userret 函数. 首先切换回用户页表, 然后从 trapframe 中加载值到寄存器, 最后将 trapframe 地址存于寄存器 SSCRATCH 中.
  6. 返回用户空间.
    在这里插入图片描述
  • ECALL 作用:
    • 将代码从用户模式转为内核模式
    • 将 PC 保存与 SEPC
    • 跳转到 STVEC 寄存器指向的(处理 trap的)指令
  • 如何保存用户寄存器:
    • 内核将 trapframe 映射到了每个用户页表
    • 在进入到用户空间前(操作系统启动时是在内核模式), 内核会将 trapframe 地址保存在 SSCRATCH 寄存器, 配合 csrrw 指令进行寄存器 a0sscratch 内容的互换.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值