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

转:https://www.codenong.com/32943129/

How does ARM Linux emulate the dirty, accessed, and file bits of a PTE?

根据pgtable-2-level.h,ARM Linux有两个版本的PTE;另一个是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字节偏移量以下的那些位?


My question is how does it check the dirty, accessed, file bit of a page on H/W PTE?

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

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

The"dirty" bit is emulated by only granting hardware write permission
iff the page is marked"writable" and"dirty" in the Linux PTE. This
means that a write to a clean page will cause a permission fault, and
the Linux MM layer will mark the page dirty via handle_pte_fault().
For the hardware to notice the permission change, the TLB entry must
be flushed, and ptep_set_access_flags() does that for us.

为了处理这种情况,将页面的初始MMU映射标记为只读。当进程向其写入内容时,将产生页面错误。这是引用的handle_pte_fault,并且主代码在fault.c中作为do_page_fault,并将调用通用的handle_mm_fault,该通用的handle_mm_fault最终在handle_pte_fault结尾。您可以看到代码,

1
2
3
4
5
6

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注释中,

Therefore, we tweak the implementation slightly - we tell Linux that we have 2048 entries in the first level, each of which is 8 bytes (iow, two hardware pointers to the second level.) The second level contains two hardware PTE tables arranged contiguously, preceded by Linux versions which contain the state information Linux needs. We, therefore, end up with 512 entries in the"PTE" level.

为了使用完整的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修订版使用略有不同的表结构和功能,因此处理器功能表中有一个条目指向汇编程序。例如,cpu_v7_set_pte_ext是ARMv7或典型的原始Cortex CPU实现。该例程负责检查Linux标志并相应地更新硬件位。可以看出,在该例程结束时,将r3写入pte+2048(从Linux PTE到硬件PTE的偏移量)。 proc-marcos.S中的汇编程序宏armv3_set_pte_ext被许多较旧的CPU变体使用。

请参阅:Tim关于ARM MM的说明
Linux内核中用于ARM的页表条目(PTE)描述符

  • 感谢您的宝贵答复,但我再次感到困惑和困惑的是pte_write()对于只读页面如何返回true,pte_write宏检查的哪个PTE版本是Linux PTE还是ARM PTE?以相同的方式pte_mkdirty修改了Linux PTE或ARM PTE的哪个条目?因为从handle_mm_fault从pte_offset_map获取pte,它似乎返回ARM PTE,如果我错了,请纠正我。
  • 实际上,这些似乎是新问题。我已经更新了答案。您寻求的魔力是cpu_set_pte_ext,它类似于C ++虚拟函数,并且对于可变ARM MMU位布局(新CPU类型具有扩展功能)的实现方式不同。但是,在编写Linux PTE和ARM PTE(+2048)时,它们都是通用的。
  • Linux仅在Linux PTE值上运行。仅当提交它们时,才会调用cpu_set_pte_ext函数,该函数检查Linux版本并更新硬件版本??。例如,set_pte_at和其他一些初始化PTE的地方。

你可能感兴趣的:(linux,arm,嵌入式硬件)