我正在用 armv8 (aarch64) 编写一个简单的内核。
MMU 配置:
- 48 VA 位 (T1SZ=64-48=16)
- 4K 页面大小
- 所有物理 RAM 平面映射到内核虚拟内存(在 TTBR1_EL1 上)(MMU 在 TTBR0_EL1=0 时处于活动状态,所以我只使用 0xffff<addr> 中的地址,所有平面映射到物理内存)
我正在将一个新的地址空间(从 1<<40 开始)映射到某个空闲的物理区域。当我尝试访问地址 1<<40 时,出现异常(类型为“使用 SP1 的 EL1,同步”):
ESR_EL1=0x96000044
FAR_EL1=0xffff010000000000
检查其他寄存器,我有:
TTBR1_EL1=0x82000000
TTBR1_EL1[2]=0x0000000082003003
因此,基于 ARM Architecture Reference Manual for ARMv8(ARMv8-A profile):
- ESR(异常综合症寄存器)转换为: Exception Class=100101(Data abort without a change in exception level) on page D7-1933 sq.;WnR=1(错误指令是写);第 D7-1958 页上的DFSC=0b000100(级别 0 的转换错误);
- FAR_EL1 是故障地址;它表示使用了 TTBR1_EL1(因为高位全为 1)。VA 前 9 位为 0b000000010,表示表中使用了条目 2;
- 表中的条目 2 表示物理地址 0x82003000 处的下一级表(低位 0b11)。
因此,翻译在不应该的级别 0 处失败。
我的问题是:我做错了什么吗?我是否遗漏了一些可能导致翻译错误的信息?而且,更一般地说,如何调试翻译错误?
更新:
当我在启用 MMU 之前写入表时,一切正常。
每当我在启用 MMU 之后(通过平面映射表区域)写入表时,映射永远不会起作用。我想知道为什么会这样。
我还尝试手动写入选定的表(以消除我的映射函数的任何副作用):相同的结果(在 MMU 开启之前完成写入时,它可以工作;之后,它会失败)。
我尝试了做tlbi
和dsb sy
指示,然后是isb
,没有效果。此时只有一个 CPU 正在运行,因此缓存应该不是问题 - 写入指令和 MMU 与相同的缓存通信(但我将在接下来对其进行测试)。