ARM Linux 如何模拟 PTE 的脏位、访问位和文件位?

2024-04-11

As per pgtable-2-level.h https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/pgtable-2level.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 字节偏移以下的那些位?


我的问题是它如何检查 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条目的结构如下:

  1. Linux PTE [n]
  2. Linux PTE [n+1]
  3. ARM PTE [n]
  4. 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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM Linux 如何模拟 PTE 的脏位、访问位和文件位? 的相关文章

随机推荐