S-Mode虚存的地址转换
(1) 读取 satp CSR
- satp.PPN 给出了L2页表基地址的 物理页号(Physical Page Number, PPN)。
- satp.MODE(4 bits):8(Sv39)、9(Sv48)、10(Sv57)。
L2页表基地址 = PPN × 4 KiB
S-Mode虚存的地址转换
(2) 解析 VPN(Virtual Page Number)
根据虚拟地址提取 VPN[2], VPN[1], VPN[0],并进行 3 级页表查询。
每个页表项(PTE,Page Table Entry)大小为 64-bit,其结构如下:
63 10 9 8 7 6 5 4 3 2 1 0
+---------------+-----+---+------------ +
| PPN (44 bits) | RSW | D | A | X W R V |
+---------------+-----+---+------------ +
- PPN(物理页号):映射到下一级页表或最终物理页。V(Valid):有效位,1 表示 PTE 有效。R/W/X(读/写/执行):页的权限。A/D(Access/Dirty):访问和修改位。
S-Mode虚存的地址转换
三级地址翻译步骤:
- VPN[2] = VA [38:30], 给出了L2页表的索引号
L2页表的页表项(L2-PTE)地址= (satp.PPN × 4 KiB) + (VPN[2] × 8)
L2-PTE.PPN = L1页表基址的物理页号
63 10 9 8 7 6 5 4 3 2 1 0
+---------------+-----+---+------------ +
| PPN (44 bits) | RSW | D | A | X W R V |
+---------------+-----+---+------------ +
S-Mode虚存的地址转换
三级地址翻译步骤:
2. VPN[1] = VA [29:21], 给出了L1页表的索引号
L1页表的页表项(L1-PTE)地址= (L2-PTE.PPN × 4 KiB) + (VPN[1] × 8)
L1-PTE.PPN = L0页表基址的物理页号
63 10 9 8 7 6 5 4 3 2 1 0
+---------------+-----+---+------------ +
| PPN (44 bits) | RSW | D | A | X W R V |
+---------------+-----+---+------------ +
S-Mode虚存的地址转换
三级地址翻译步骤:
3. VPN[0] = VA [20:12], 给出了L0页表的索引号
L0页表的页表项(L0-PTE)地址= (L1-PTE.PPN × 4 KiB) + (VPN[1] × 8)
L0-PTE.PPN = 最终物理地址的物理页号
63 10 9 8 7 6 5 4 3 2 1 0
+---------------+-----+---+------------ +
| PPN (44 bits) | RSW | D | A | X W R V |
+---------------+-----+---+------------ +
S-Mode虚存的地址转换
- 计算物理地址
虚地址对应的最终物理地址 = (L0 PTE.PPN × 4 KiB) + Page Offset
假设: satp.PPN = 0x12345,
即L2页表基地址 = 0x12345 × 4 KiB = 0x12345000。
虚拟地址: 0x1234_5678
VPN[2] = 0x091(9 bits)
VPN[1] = 0x234(9 bits)
VPN[0] = 0x567(9 bits)
Page Offset = 0x078
S-Mode虚存的地址转换
- 计算物理地址
- 经过三级页表查询:
- L2 PTE 指向 L1 页表(PPN = 0x20000)。
- L1 PTE 指向 L0 页表(PPN = 0x30000)。
- L0 PTE 指向物理页(PPN = 0x40000)。
最终 物理地址计算:
物理地址 = (0x40000 × 4 KiB) + 0x078
= 0x40000000 + 0x078
= 0x40000078
小结
- 了解 RISC-V 特权级和硬件隔离方式
- 了解 RISC-V 的 M-Mode 和 S-Mode 的基本特征
- 了解OS在 M-Mode 和 S-Mode 下如何访问控制计算机系统
- 了解不同软件如何在 M-Mode<–>S-Mode<–>U-Mode 之间进行切换
- 了解虚实地址转换
主要说明x86, arm由于兼容性,历史原因,导致设计实现复杂,riscv简洁/灵活/可扩展,便于学习掌握并用于写OS
“encoding”通常指的是指令编码(instruction encoding) 决定了指令的结构和执行方式
## RISC-V 系统模式:控制状态寄存器CSR
强制隔离以避免对整个系统的可用性/可靠性/安全影响
- mstatus/status(Machine/Supervisor Status)全局中断及其他状态
- mtvec(MachineTrapVector)保存发生异常时需要跳转到的地址
## RISC-V 系统模式:控制状态寄存器CSR
- mtvec(MachineTrapVector)保存发生异常时需要跳转到的地址。
- mepc(Machine Exception PC)指向发生异常的指令。
- mcause(Machine Exception Cause)指示发生异常的种类。
- mie(Machine Interrupt Enable)指出处理器目前能处理的中断。
- mip(Machine Interrupt Pending)列出目前正准备处理的中断。
- mtval(Machine Trap Value)保存陷入(trap)附加信息:地址例外中出错的地址、发生非法指令例外的指令本身;对于其他异常,值为0。
- mscratch(Machine Scratch)它暂时存放一个字大小的数据。
- mstatus(Machine Status)保存全局中断以及其他的状态
---
## RISC-V 系统模式:控制状态寄存器CSR
- mcause(Machine Exception Cause)它指示发生异常的种类。
- SIE控制S-Mode下全局中断,MIE控制M-Mode下全局中断。
- SPIE、MPIE记录发生中断之前MIE和SIE的值。
---
## RISC-V 系统模式:控制状态寄存器CSR
- sstatus(supervisor status)保存发生异常时需要跳转到的地址。
- stvec(supervisor trap vector)保存s模式的trap向量基址。stvec总是4字节对齐
- satp(supervisor Address Translation and Protection) S-Mode控制状态寄存器控制了分页系统。
- sscratch (supervisor Scratch Register) 保存指向hart-local supervisor上下文的指针. 在trap处理程序的开头,sscratch与用户寄存器交换,以提供初始工作寄存器。
- sepc(supervisor Exception PC)它指向发生异常的指令。
Zifencei扩展 https://www.cnblogs.com/mikewolf2002/p/11191254.html
修改页表时,修改上下文时,刷新同步
它确保在页表更新或进程切换后,CPU 不会使用过期的地址映射信息
指令缓存一致性
在执行 fence.i 指令之前,对于同一个硬件线程(hart), RISC-V 不保证用存储指令写到内存指令区的数据可以被取指令取到。使用fence.i指令后,对同一hart,可以确保指令读取是最近写到内存指令区域的数据。但是,fence.i将不保证别的riscv hart的指令读取也能够满足读写一致性。如果要使写指令内存空间对所有的hart都满足一致性要求,需要执行fence指令。
- 堆栈:保存上下文;切换页表
--- 是smode的硬件处理流程 有误,应该是m-mode的才对
##### 中断/异常的硬件响应
1. **发生中断/异常的指令PC**被存入 mepc, 且 PC 被设置为 mtvec
2. mcause 设置中断/异常**类型**,mtval被设置为出错的地址/异常**相关信息**
- 映射表:存储了系统调用或中断到其所对应的处理例程的地址
3. 把 sstatus中的 SIE 位置零,**屏蔽中断**, **SIE位之前的值**被保存在 SPIE 位中
4. **发生例外前的特权模式**被保存在 sstatus 的 SPP(previous privilege) 域,然后设置当前特权模式为S-Mode
5. **跳转**到stvec CSR设置的地址继续执行
mtval(Machine Trap Value)保存陷入(trap)附加信息:地址例外中出错的地址、发生非法指令例外的指令本身;对于其他异常,值为0。
是smode的代码 有误
---
##### M-Mode中断处理例程
```
let scause = scause::read();
let stval = stval::read();
match scause.cause() {
Trap::Exception(Exception::UserEnvCall) => {
cx.sepc += 4;
cx.x[10] = do_syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
}
_ => {
panic!(
"Unsupported trap {:?}, stval = {:#x}!",
scause.cause(),
stval
);
}
}
```
,是 mie 和 mip 的子集。这两个寄存器和 M-Mode下有相同的布局。sie 和 sip 中只有与由 mideleg 委托的中断对应的位才能读写,没有委派的中断对应位总是 0
ASID 是一个唯一标识符,用于区分不同进程的虚拟地址空间。每个进程在使用其页表进行内存访问时都会有一个对应的 ASID。
ASID 使得 TLB 能够同时缓存多个进程的地址映射,而无需在每次上下文切换时清空整个 TLB。
ASID 减少了 TLB 刷新需求
如果没有 ASID,每次进程上下文切换后,必须完全刷新 TLB,因为同一虚拟地址可能指向不同的物理地址。这是因为 TLB 缓存的是虚拟到物理地址的映射,没有额外的信息来区分不同进程的映射。
频繁的 TLB 刷新会导致显著的性能开销。这是因为新的内存访问将无法命中已缓存的 TLB 条目,导致更多时间花费在查找和加载新的映射上。
---

## RISC-V 系统编程:S-Mode下的隔离
- S-Mode比 U-Mode权限更高,但是比 M-Mode权限低
- S-Mode下运行的软件不能使用 M-Mode的 CSR 和指令,并受到 PMP 的限制
- 支持基于页面的虚拟内存