MMU 打开时的逻辑和物理地址?
Logical and physical address with MMU on?
我对 MMU 如何处理内核物理地址和逻辑地址有一些疑问。我会尝试用一个例子来解释我的问题。
让我们假设我们在 ARM 架构上。
系统启动时MMU关闭,所以所有通过CPU的地址都是物理地址。在我们启用 MMU 之前,我们创建一个页面 table,其中我们说我们所有的物理地址都映射到虚拟地址 physical address + 0xC0000000
。在此之后,我们打开 MMU。这一切都很清楚。但现在问题开始了:
由于我们处于流水线架构中,所以假设后面的指令是从地址 0x8000 加载的。现在据我所知,我们应该有一个页面错误,因为 MMU 在页面 table 内的任何地方都找不到这个地址,所以它调用了一个页面错误来处理这种情况。但是如果我们已经设置了中断向量,它里面有一个分支到另一个物理地址,所以 MMU 找不到这个地址,我们不可避免地陷入无限循环。我错过了什么?
你错过了所有使用的虚拟地址都应该被映射,即使实际上它们匹配相同的物理内存区域。让我们详细说明。
假设有 startup
代码(用于初始初始化和启用 MMU)和其他 main
代码(仅用于启用 MMU)具有以下布局。
- 启动-物理:0x4000-0x7FFFF,虚拟:0x4000-0x7FFFF
- 主要物理:0x8000-0xBFFF,虚拟:0xC0008000-0xC000BFFF
这样的布局是链接器的工作,您的工作是为其提供正确的脚本。 CPU 本例中的入口点应该是 0x4000
。这几乎是一个硬件特定地址。
CPU 从禁用 MMU 和 'PC=0x4000' 开始,一直持续到 0x4800
启用 MMU。
因此,在启用 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
之后可以删除映射。
我对 MMU 如何处理内核物理地址和逻辑地址有一些疑问。我会尝试用一个例子来解释我的问题。 让我们假设我们在 ARM 架构上。
系统启动时MMU关闭,所以所有通过CPU的地址都是物理地址。在我们启用 MMU 之前,我们创建一个页面 table,其中我们说我们所有的物理地址都映射到虚拟地址 physical address + 0xC0000000
。在此之后,我们打开 MMU。这一切都很清楚。但现在问题开始了:
由于我们处于流水线架构中,所以假设后面的指令是从地址 0x8000 加载的。现在据我所知,我们应该有一个页面错误,因为 MMU 在页面 table 内的任何地方都找不到这个地址,所以它调用了一个页面错误来处理这种情况。但是如果我们已经设置了中断向量,它里面有一个分支到另一个物理地址,所以 MMU 找不到这个地址,我们不可避免地陷入无限循环。我错过了什么?
你错过了所有使用的虚拟地址都应该被映射,即使实际上它们匹配相同的物理内存区域。让我们详细说明。
假设有 startup
代码(用于初始初始化和启用 MMU)和其他 main
代码(仅用于启用 MMU)具有以下布局。
- 启动-物理:0x4000-0x7FFFF,虚拟:0x4000-0x7FFFF
- 主要物理:0x8000-0xBFFF,虚拟:0xC0008000-0xC000BFFF
这样的布局是链接器的工作,您的工作是为其提供正确的脚本。 CPU 本例中的入口点应该是 0x4000
。这几乎是一个硬件特定地址。
CPU 从禁用 MMU 和 'PC=0x4000' 开始,一直持续到 0x4800
启用 MMU。
因此,在启用 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
之后可以删除映射。