作者简介:baron (csdn:代码改变世界ctw),九年手机安全/SOC底层安全开发经验。擅长trustzone/tee安全产品的设计和开发。
在 MMU 未开启阶段,PC 操作的都是物理地址执行程序,这样看起来一切正常,没啥问题。例如:
取指(到物理地址 0x4000 处取指)、译码、执行 取指(物理地址 0x4004 处取指)、译码、执行 取指(物理地址 0x4008 处取指)、译码、执行 取指(物理地址 0x400C 处取指)、译码、执行
但是假如程序在执行的过程中,你突然打开了 MMU,那么会发生什么呢?
比如在前面的示例中,程序本来执行在 0X4000、0x4004 处,而 0x4004 正好是 enable_mmu 指令,那么接下来 PC 将取值 0x4008 处地址的指令,由于此时 MMU 已经被打开,那么 0x4008 会被当作虚拟地址,经过MMU翻译......
经过 MMU,那么就可能出现两种问题:
那么上面的程序执行就变成了如下逻辑:
取指(到到物理地址 0x4000 处取指)、译码、执行 取指(物理地址 0x4004 处取指)、译码、执行 -- 这条指令是开启 MMU 取指(到虚拟地址 0x4008 处取指,经 MMU 单元后,要么是 invalid;要么是 0xXXXX)、译码、执行 ......
为了解决上述描述的问题,你有什么想法吗?
先自己想下......
下面给出了两种解决方案:
取指(到到物理地址 0x4000 处取指)、译码、执行 取指(物理地址 0x4004 处取指)、译码、执行 -- 这条指令是开启MMU 取指(到虚拟地址 0x4008 处取指,因为是一一映射,所以经 MMU 单元后,物理地址依然是是 0x4008)、译码、执行 ......
取指(到到物理地址 0x4000 处取指)、译码、执行 取指(物理地址 0x4004 处取指)、译码、执行 -- 这条指令是开启MMU 取指,到虚拟地址 0x4008 处取指,经 MMU 单元时在页表是找不到 0x4008 这个虚拟地址的(因为没做 map),所以会产生 prefetch abort 异常、而在异常代码 ERET 返回时,正好返回到 0xXXXX 地址处,该地址是虚拟地址,正好 map 到 0x4008 物理地址,程序得到继续执行,译码、执行 ......