我正在armv8(aarch64)中编写一个简单的内核。
MMU配置:
我正在将新地址空间(从1<< 40开始)映射到某个自由物理区域。当我尝试访问地址1<< 40时,我得到一个例外(类型为“EL1使用SP1,同步”):
ESR_EL1=0x96000044
FAR_EL1=0xffff010000000000
检查其他寄存器,我有:
TTBR1_EL1=0x82000000
TTBR1_EL1[2]=0x0000000082003003
因此,基于ARMv8的ARM体系结构参考手册(ARMv8-A配置文件):
因此,翻译在0级失败,不应该在那里。
我的问题是:我做错了吗?我错过了一些可能导致翻译错误的信息吗?而且,更一般地说,如何调试转换错误?
更新
在启用MMU之前写入表格时,Everthing有效
每当我在启用MMU后写入表格(通过平面映射表区域),映射永远不会起作用。我想知道为什么会这样。
我还尝试手动写入所选表格(从我的mmapping函数中删除任何副作用):相同的结果(在MMU打开之前完成写入,它起作用;之后,它失败)。
我尝试执行tlbi
和dsb sy
指示,然后执行isb
,但没有效果。此时只有一个CPU正在运行,因此缓存不应该是一个问题 - 写入指令和MMU与同一个缓存进行通信(但我接下来会对其进行测试)。
答案 0 :(得分:3)
我忽略了单核心内的缓存问题。问题是,在打开MMU之后,CPU和表行走单元没有相同的内存视图。 “ARMv8 Cortex-A编程指南”指出,在修改表之后,必须清理/无效缓存以达到统一点(单个核心的相同视图)。
有两种可能性可以解释这种行为(我还不完全了解缓存是如何工作的):
dsb
指令只是等待所有内核具有同步状态(由于一致性网络):其他内核将知道该行必须更新,当他们尝试访问它时,它会更新到L2或从前一个核心的L1迁移到它们的L1。
MMU不会发生这种情况(没有一致性参与),所以它仍然可以看到L2中的旧值
但是,如果是这种情况,在MMU打开之前应该发生同样的事情(因为缓存是在之前激活的),除非在MMU被激活之前所有内存被认为是L1不可缓存的(这是可能的,我'我必须仔细检查)
解决问题的最小方法可能是更改表页面的缓存策略,但仍需要缓存维护来清除MMU中可能存在的旧值。 所以,我仍然不确定究竟是什么导致了这个问题,但清理/使所有更新的地址无效。