根据 pgtable-2-level.h ,ARM Linux 有两个版本的 PTE; Linux PTE 和 H/W PTE。 Linux PTE 存储在 1024 字节以下的偏移量上。
在 handle_pte_fault
中处理页面错误时,各种函数(如 pte_file
、 pte_mkdirty
、 pte_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 条目的结构如下,
完整 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/