根据 pgtable-2-level.h ,ARM Linux 有两个版本的 PTE; Linux PTE 和 H/W PTE。 Linux PTE 存储在 1024 字节以下的偏移量上。

handle_pte_fault 中处理页面错误时,各种函数(如 pte_filepte_mkdirtypte_mkyoung )使用 H/W PTE 版本进行调用。

但实际上 ARM H/W 不支持其 PTE 中的脏位、访问位和文件位。

我的问题是它如何检查 H/W PTE 上页面的脏的、访问的、文件位?理想情况下,它应该检查 Linux PTE 上存储在 1024 字节偏移量以下的那些位?

最佳答案



TL;DR - 通过在初始访问时出现页面错误来模拟它们。

答案在 pgtable-2-level.h 中给出,



对于脏的情况,页面的初始 MMU 映射被标记为只读。当一个进程写入它时,会产生一个页面错误。这是引用的 handle_pte_fault ,主要代码在 fault.c as do_page_fault 中,将调用最终以 handle_mm_fault 结尾的通用 handle_pte_fault 。你可以看到代码,

if (flags & FAULT_FLAG_WRITE) {
        if (!pte_write(entry))
            return do_wp_page(mm, vma, address,
                    pte, pmd, ptl, entry);
        entry = pte_mkdirty(entry);  /** Here is the dirty emulation. **/
}

所以Linux通用代码会检查页面的权限,看它是可写的,然后调用pte_mkdirty将页面标记为脏;整个过程通过故障处理程序启动或模拟。在 Linux PTE 中将页面标记为脏后,将 ARM PTE 标记为可写,以便后续写入不会导致故障。

访问是相同的,只有读取和写入最初都会出错。文件位也完全未映射,当发生故障时,会咨询 Linux PTE 以查看它是由文件支持还是完全未映射的页面错误。

在用新的权限更新硬件表并完成簿记后,用户态程序在故障指令处重新启动,除了处理故障的时间间隔外,它不会注意到差异。

ARM Linux 使用 4k 页,而 ARM 二级页表的大小为 1k(256 个条目 * 4 字节)。来自 pgtable-2-level.h 评论,



为了使用完整的 4K 页面, PTE 条目的结构如下,
  • Linux PTE [n]
  • Linux PTE [n+1]
  • ARM PTE [n]
  • ARM PTE [n+1]

  • 完整 4k 页面的四个 1k 项目。这些页面集合必须按进程管理,以便为每个进程提供独特的内存 View ,并且共享某些信息以节省实际 RAM。函数 cpu_set_pte_ext 用于更改物理 ARM 条目。由于每个 ARM CPU 修订版使用的表结构和功能略有不同,因此 processor function table 中有一个条目指向一个汇编程序。例如, cpu_v7_set_pte_ext 是 ARMv7 或典型的原始 Cortex CPU 实现。该例程负责检查 Linux 标志并相应地更新硬件位。可以看出,r3 在这个例程结束时被写入 pte+2048(从 Linux PTE 到硬件 PTE 的偏移量)。 proc-marcos.S 中的汇编宏 armv3_set_pte_ext 被许多较旧的 CPU 变体使用。

    参见:Tim's notes on ARM MM
    Page table entry (PTE) descriptor in Linux kernel for ARM

    关于linux-kernel - ARM Linux 如何模拟 PTE 的脏位、访问位和文件位?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32943129/

    10-12 00:33