ARMv8 数据中止异常子类型 "Not in translation table" 和 "Translation table fault at level" 之间的区别?

Difference between ARMv8 Data Abort exception subtypes "Not in translation table" and "Translation table fault at level"?

制作页面 tables 后,我已经获得了在 ARMv8 上工作的虚拟内存。奇怪的是,大多数 我的翻译工作(身份映射)除了位于物理地址零的闪存。我使用编辑页面 tables 的单一功能,所以 some 工作而 some 不工作的事实对我来说很奇怪.具体来说,我只映射了几个范围:

Flash       [0x00000000, len = 0x08000000]
UART        [0x09000000, len = 0x1000    ]
RAM         [0x40000000, len = 0x0fe00000]
Secure RAM  [0x4fe00000, len = 0x00200000]

而且,它们所有 都可以工作,但 Flash 除外。我的映射函数也适用于非身份映射。 Flash 范围有些奇怪。

我有一个异常处理程序用于分析问题。在捕获 Data Abort 异常时,我发现了两个有趣的案例。根据访问的内存类型,我遇到了两种数据中止子类型:

    - [1] Flash address range (e.g. 0x00000000)
            - ESR.ISS = 0x10 (ISS.DFSC = 0x10)
                - Synchronous External abort, not on translation table walk 

    - [2] An expected unmapped address (e.g. 0x50000000)
            - ESR.ISS = 0x06 (ISS.DFSC = 0x06)
                - Synchronous External abort, on translation table walk, level 2

当尝试处理访问地址的异常时,我 不希望 出现在 table 中,我得到 [2](2 级错误,因为映射了一些附近的地址)。

当我尝试处理访问 Flash 的异常时,我 期望 在 table 中,我得到 [1](不在 table 走)。

所以,我对这两个案例代表什么感到困惑。 [1] 和 [2] 有什么区别?他们似乎代表着同一件事。 [1] 是否以某种方式表示翻译在尝试之前就失败了?如果是这种情况,我希望处理定义的 0 级故障。我期待 "Not in table" 错误的地址,我不希望在 table 中,而是收到另一个地址。

事实证明,我看到的问题是由于 Flash 被映射为仅 安全 设备,因此只有安全访问才能通过 MMU(即table 条目上的 NSTable=0,块条目上的 NS=0。

在意识到这一点之后,在@artlessnoise 关于 "External Aborts" 的评论的帮助下,我得出了数据中止的两个子类型之间的以下区别:

"Not on translation table walk"

并不意味着,正如我正在阅读的那样,"The exception occurred because the requested memory address was not found 'on the translation table walk'"。而是表示异常发生在 "not on the translation table walk" 期间(即在操作之前或之后)。在这种情况下,Flash PA 被映射到 tables 但我的访问是不安全的,所以设备没有响应(MMU 没有将它们路由到设备)。这种缺乏响应导致了外部中止。因此,ARM 可能更简洁地定义了此异常,例如:

"Not on translation table walk" -> "Not as a result of translation table walk"

其他亚型:

"On translation table walk, level 2"

是人们在 page fault 期间应该期望收到的东西。换句话说,试图读取在翻译 tables 中没有 VA->PA 映射的内存。观察到的水平反映了 MMU 在停止前走了 tables 的距离。


请注意,我删除了定义的 "Synchronous External abort" 部分。两者都被认为是外部中止,因为两者都是由于 CPU 之外的操作而引发的,同时试图读取内存或直接从 MMU。