开启 MMU 的逻辑和物理地址?

Posted

技术标签:

【中文标题】开启 MMU 的逻辑和物理地址?【英文标题】:Logical and physical address with MMU on? 【发布时间】:2017-08-21 14:17:36 【问题描述】:

我对 MMU 如何处理内核物理和逻辑地址有一些疑问。我会试着用一个例子来解释我的问题。 让我们假设我们在 ARM 架构上。

系统在 MMU 关闭的情况下启动,因此在 CPU 内部传递的所有地址都是物理地址。在我们启用 MMU 之前,我们创建一个页表,其中我们说我们所有的物理地址都映射到虚拟地址 physical address + 0xC0000000。在此之后,我们打开 MMU。这一切都很清楚。但现在问题开始了:

由于我们处于流水线架构中,假设后面的指令是从地址 0x8000 加载的。现在据我所知,我们应该有一个页面错误,因为 MMU 在页表中的任何地方都找不到这个地址,所以它调用了一个页面错误来处理这种情况。但是如果我们设置了中断向量,在它里面会有一个分支到另一个物理地址,所以 MMU 找不到这个地址,我们不可避免地陷入了一个无限循环。我错过了什么?

【问题讨论】:

【参考方案1】:

您错过了应该映射所有使用的虚拟地址,即使它们实际上匹配相同的物理内存区域。让我们详细说明。

假设有 startup 代码(用于主要初始化和启用 MMU)和其他 main 代码(仅适用于启用 MMU)具有以下布局。

启动 - 物理:0x4000-0x7FFFF,虚拟:0x4000-0x7FFFF main - phys: 0x8000-0xBFFF, virt: 0xC0008000-0xC000BFFF

这样的布局是链接器的工作,你的工作是用正确的脚本来提供它。此示例中的 CPU 入口点应该是 0x4000。这几乎是一个特定于硬件的地址。

CPU 从禁用 MMU 和“PC=0x4000”开始,直到启用 MMU 时说0x4800

所以在启用 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 映射之后可以删除。

【讨论】:

以上是关于开启 MMU 的逻辑和物理地址?的主要内容,如果未能解决你的问题,请参考以下文章

[转帖]Linux下逻辑地址线性地址物理地址详细总结

linux下内存

解答关于内核中没开MMU之前的虚拟地址物理地址转换问题

嵌入式开发(S5PV210)——u-boot中开启MMU

地址空间和地址生成

虚拟地址与物理地址之间的关系