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 继续 0x48040x48080x480C

在某些时候你应该跳进 main。对于 ARM 这将类似于

ldr r0, =0xC0008000
bx r0

请注意,使用了 main 条目的 虚拟地址 。所以在分支 PC=0xC0008000 之后在物理内存中解析为 0x8000.

0x4000-0x7FFFF 之后可以删除映射。