我对MMU如何处理内核物理和逻辑地址有些怀疑。我试着用一个例子来解释我的问题。 让我们假设我们在ARM架构上。
系统在MMU关闭时启动,因此在CPU内部传递的所有地址都是物理的。在我们启用MMU之前,我们创建了一个页表,我们说所有物理地址都映射到虚拟地址physical address + 0xC0000000
。在此之后我们打开MMU。所有这一切都很清楚。但现在问题开始了:
由于我们处于流水线架构中,所以请说后面的指令是来自地址0x8000的负载。现在据我所知,我们应该有一个页面错误,因为MMU在页面表的任何地方都找不到这个地址,所以它调用了一个页面错误来处理这种情况。但是如果我们设置了中断向量,那么它内部就会有一个分支到另一个物理地址,所以MMU找不到这个地址,我们不可避免地陷入了无限循环。我错过了什么?
答案 0 :(得分:1)
您错过了所有使用的虚拟地址都应该被映射的信息,即使它们实际上匹配相同的物理内存区域。让我们详细说明。
假设有startup
代码(用于主初始化和启用MMU)和其他main
代码(仅在启用MMU的情况下),其布局如下。
这种布局是链接器工作,而您的工作是使用正确的脚本来供稿。在此示例中,CPU入口点应该为0x4000
。差不多就是硬件专用地址。
CPU在禁用MMU且'PC = 0x4000'的情况下启动,并且在启用MMU之前一直持续到说0x4800
。
因此,在启用MMU之前,必须有0x4000-0x7FFFF
(启动)和0xC0008000-0xC000BFFF
(所有其他代码)的映射。
现在已启用MMU。 PC具有0x4804(假设32b CPU)。 0x4804
现在是虚拟地址,并且已映射到0x4804
物理地址上。 CPU继续执行0x4804
,0x4808
,0x480C
等。
在某个时候,您应该跳到main
。对于 ARM ,它类似于
ldr r0, =0xC0008000
bx r0
请注意,使用了main
条目的虚拟地址。因此,在将PC=0xC0008000
分支到物理内存中的0x8000
之后。
0x4000-0x7FFFF
之后可以删除映射。