现代操作系统启动时一般会开启分页机制。由于在开启分页机制之前, 代码按照物理地址执行(PC为物理地址, 数值较小, 称为低地址), 因此在开启分页机制的同时, 需要将PC重定位至正确的虚拟地址(数值较大, 称为高地址)。
我此前学习到的做法是, 首先使得分页机制的页表将与物理地址相同的虚拟地址映射到物理地址, 同时将正确的虚拟地址也映射到物理地址。开启分页机制、加载页表后, 通过一些方法使得PC从低地址无缝转至高地址。然后, 撤销物理地址和虚拟地址相同的映射条目, 并刷新页表的TLB。至此, 开启完毕。
阅读Linux的RISC-V架构相关代码的时候, 我发现代码采用了一种巧妙的写法。代码具体在arch/riscv/kernel/head.S
, 其先将中断与异常处理函数入口点(stvec
)配置为刷新TLB指令的下一条指令的正确的虚拟地址(高地址), 然后直接配置一个页表, 只映射了正确的虚拟地址映射到物理地址, 并刷新TLB。
此时, 由于PC仍为低地址, 且页表中没有相应的映射, 处理器会产生一个缺页异常, 将PC设置为中断与异常处理函数入口点, 即刷新TLB指令的下一条指令的正确的虚拟地址。正是我们需要的效果, 任务完成!
wow!解决了一个疑问,非常感谢