我的问题是它如何检查 H/W PTE 上页面的脏、已访问、文件位?
TL;DR - 它们是通过在初始访问时发生页面错误来模拟的。
答案在pgtable-2-level.h https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/pgtable-2level.h,
通过仅授予硬件写入权限来模拟“脏”位
iff 该页面在 Linux PTE 中被标记为“可写”和“脏”。这
意味着写入干净页面将导致权限错误,并且
Linux MM层将通过handle_pte_fault()将页面标记为脏页。
为了使硬件注意到权限更改,TLB 条目必须
被刷新,ptep_set_access_flags() 为我们做到了这一点。
采取dirty在这种情况下,页面的初始 MMU 映射被标记为只读。当进程写入时,会生成页面错误。这是handle_pte_fault
引用,主要代码在故障.c为do_page_fault https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/fault.c#n236并将调用泛型handle_mm_fault
最终结束于handle_pte_fault https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/mm/memory.c#n3780。你可以看到代码,
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
将页面标记为脏;整个过程是通过故障处理程序启动或模拟的。页面被标记后dirty在Linux PTE中,ARM PTE被标记为可写,因此后续写入不会导致故障。
accessed是相同的,只是读和写最初都会出错。 Afile位也完全未映射,当发生故障时,会查阅 Linux PTE 来查看它是否由文件支持或者是否完全是一个文件。unmapped页面错误。
在用新的权限更新硬件表并完成记账之后,用户模式程序在故障指令处重新启动,除了处理故障的时间间隔之外,它不会注意到差异。
ARM Linux 使用 4k 页,ARM 二级页表大小为 1k(256 个条目 * 4 字节)。来自pgtable-2-level.h评论,
因此,我们稍微调整一下实现 - 我们告诉 Linux 第一层有 2048 个条目,每个条目有 8 个字节(iow,两个指向第二层的硬件指针。)第二层包含两个连续排列的硬件 PTE 表,前面是包含 Linux 所需的状态信息的 Linux 版本。因此,我们最终得到“PTE”级别的 512 条条目。
为了使用完整的 4K 页面,PTE条目的结构如下:
- Linux PTE [n]
- Linux PTE [n+1]
- ARM PTE [n]
- ARM PTE [n+1]
四个 1k 项目组成一个完整的 4k 页面。这些页面集合必须按进程进行管理,以便为每个进程提供独特的内存视图,并且共享一些信息以节省实际 RAM。功能cpu_set_pte_ext
用于更改物理 ARM 条目。由于每个 ARM CPU 版本使用的表结构和功能略有不同,因此在处理器功能表 https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/proc-fns.h#n23它指向一个汇编程序。例如,cpu_v7_set_pte_ext https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7-2level.S#n62是 ARMv7 或典型的原始 Cortex CPU 实现。该例程负责检查 Linux 标志并相应地更新硬件位。可以看出,r3
被写入pte+2048
(从 Linux PTE 到硬件 PTE 的偏移)在此例程结束时。汇编宏armv3_set_pte_ext https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-macros.S#n193 in proc-marcos.S许多较旧的 CPU 变体都使用它。
See: Tim 关于 ARM MM 的笔记 http://elinux.org/Tims_Notes_on_ARM_memory_allocation
适用于 ARM 的 Linux 内核中的页表项 (PTE) 描述符 https://stackoverflow.com/questions/16909101/page-table-entry-pte-descriptor-in-linux-kernel-for-arm