2017-08-18 99 views
1

我在armv8(aarch64)中编写了一个简单的内核。如何调试aarch64翻译错误?

MMU配置:

  • 48 VA位(T1SZ = 64-48 = 16)
  • 4K页大小
  • 映射到内核虚拟存储器(上TTBR1_EL1)所有物理RAM平坦 (MMU与TTBR0_EL1 = 0活性,所以我只使用在地址为0xFFFF <地址>,所有平面映射到物理存储器)

我映射新的地址空间(从1开始的< < 40)到一些自由的物理区域。当我尝试访问的地址1 < < 40,I( “使用SP1 EL1,同步” 式的)得到一个异常:

ESR_EL1=0x96000044 
FAR_EL1=0xffff010000000000 

检查其他寄存器,我有:

TTBR1_EL1=0x82000000 
TTBR1_EL1[2]=0x0000000082003003 

所以,基于ARM架构参考手册ARMv8(ARMv8-A剖面):

  • ESR(异常综合征寄存器)转化为:异常类= 100101(数据中止机智在第D7-1933页上的例外水平)发生变化。 WnR = 1(错误指令是写入); DFSC = 0b000100(级别0的翻译错误)D7-1958页;
  • FAR_EL1是错误地址;它表示使用了TTBR1_EL1(因为高位全为1)。 VA前9位为0b000000010,表示表中使用了表项2;
  • 表中的条目2表示物理地址0x82003000处的下一级表(低位0b11)。

因此,翻译失败在0级,它不应该。

我的问题是:我做错了什么?我是否错过了一些可能导致翻译错误的信息?而且,更一般地说,如何调试翻译错误?

更新:
在启用MMU之前写入表时,Everthing会起作用。
无论何时在启用MMU(通过平面映射表区域)后写入表格,映射都不会起作用。我想知道为什么发生这种情况我也尝试手动写入选定的表(以消除我的映射函数中的任何副作用):相同的结果(在MMU打开之前写入完成后,它工作;之后失败)。

我试过tlbidsb sy指令,其次是isb,没有效果。此时只有一个CPU正在运行,所以缓存不应该成为问题 - 写入指令和MMU与相同的缓存对话(但我会在下一次测试它)。

回答

1

我忽略了单个内核中的缓存问题。问题在于,打开MMU之后,CPU和表格散步单元没有相同的内存视图。ARMv8 Cortex-A编程指南指出,在修改表后,必须将缓存清理/无效化为统一点(单个内核的相同视图)。

两种可能性可以解释这种行为(我不完全理解缓存是如何工作尚未):

  1. 第一种可能性:的MMU没有在其内部的步行缓存所需的地址。
    在这种情况下,更新常规数据并使其可用于其他内核的L1时,dsb指令只是等待所有内核具有同步状态(由于一致性网络):其他内核将知道该行必须更新,当他们尝试访问它时,它会更新到L2或从前一个核心的L1迁移到L1。
    MMU(没有一致性参与)不会发生这种情况,所以它仍然会看到L2中的旧值。然而,如果是这种情况,在MMU开启之前应该发生同样的事情(因为之前激活了缓存),除非在MMU被激活之前所有内存都被认为是L1不可缓存的(这是可能的,我必须仔细检查一下)。
    解决此问题的最简单方法可能是更改表页面的缓存策略,但缓存维护仍然有必要从MMU中清除可能的旧值。
  2. 第二种可能性:在所有测试情况下,MMU已经在其内部步行高速缓存中存在与数据L1或L2不一致的错误地址。
    在这种情况下,只有一个显式的invalidate可以从MMU缓存中弹出旧行。在MMU打开之前,缓存不包含任何内容,并且永远不会获得旧值(0),只有新值。
    我仍然认为这种情况不太可能,因为我测试了很多情况,有时预先映射的内存(例如,1级表中的条目0)与新映射的内存(例如,相同级别1中的条目128表)大于缓存行大小(在这种情况下为1024字节,比任何缓存行大小都大)。

所以,我仍然不确定究竟是什么原因导致问题,但清理/无效所有更新的地址的作品。