1. TRAMPOLINE (蹦床):模式切换的“安全屋”

在 RISC-V 中,从用户态切换到内核态(比如执行系统调用时)是一个非常惊险的动作:你需要更换页表(切换 satp 寄存器)、更换栈指针、保存所有寄存器。

  • 它的角色:它是所有进程共享的一段代码。
  • 它的特殊性:它在用户页表和内核页表中的虚拟地址是完全一样的(都在 )。
  • 为什么叫蹦床?:用户程序像“跳”上蹦床一样进入这段代码,在蹦床上完成页表切换等高难度动作,然后“弹”进内核。如果没有它,CPU 在切换页表的瞬间会因为找不到下一条指令而崩溃。

2. TRAPFRAME (陷阱帧):寄存器的“保险柜”

当 CPU 突然要从用户态跳进内核态时,用户程序正在运行。这时,用户程序的寄存器(如 a0a7rasp 等)里存满了重要数据。

  • 它的角色:它是每个进程独立拥有的一页物理内存。
  • 它的功能:当进入 TRAMPOLINE 时,代码会立刻把当前所有的寄存器值“塞”进这个 TRAPFRAME 页面里。

为什么需要它?:RISC-V 的调用约定规定 a0-a7 用于传递参数 。如果在进入内核时不把这些寄存器存起来,内核运行时的操作就会把用户程序的数据覆盖掉,用户程序就再也回不去了。


3. 为什么你在 proc_pagetable 里要映射它们?

每一个进程想要运行,都必须具备这三个基本映射。proc_pagetable 的逻辑通常是这样的:

  1. 映射 TRAMPOLINE:让进程有能力跳进内核。
  2. 映射 TRAPFRAME:让进程跳进内核时有地方存寄存器数据。
  3. 映射 USYSCALL (你加的):让进程能直接读到 PID。
  • TRAMPOLINE:位于虚拟地址最高端。它是用户态与内核态转换的代码中转站,所有进程共享同一物理页。
  • TRAPFRAME:位于 TRAMPOLINE 下方一页。用于在陷阱处理(Trap)期间保护用户的寄存器现场,每个进程拥有独立的物理页。
  • 撤销逻辑原则:在 proc_pagetable 这种初始化函数中,必须遵循 “后入先出” 的清理原则,确保映射失败时不会在页表中留下任何残留。