如何ARM Linux的模拟脏,访问和文件PTE的位? [英] How does ARM Linux emulate the dirty, accessed, and file bits of a PTE?

查看:837
本文介绍了如何ARM Linux的模拟脏,访问和文件PTE的位?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为每个<一href=\"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/pgtable-2level.h\"相对=nofollow> 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?理想情况下,应该检查哪些存储低于1024字节偏移在Linux PTE那些位?


解决方案

  

我的问题是它如何检查脏,访问文件页面上的H / W PTE?


TL; DR - 他们通过采取缺页初始访问仿真

问题的答案在<给定href=\"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/pgtable-2level.h\"相对=nofollow> pgtable -2- level.h ,


  

脏位仅由硬件授予写权限效仿
  当且仅当该页面被标记为可写,并在Linux PTE脏。这个
  也就是说,到一个干净的页面写入将导致权限错,
  Linux的MM层将迎来页面通过handle_pte_fault脏()。
  对于硬件注意权限更改,TLB项必须
  被刷新,并ptep_set_access_flags()会替我们。


要采取的的情况下,初始MMU映射页面被标记为只读。当一个进程写入它,则产生页面错误。这是 handle_pte_fault 引用和主code为的 fault.c为 do_page_fault 和意志调用通用 handle_mm_fault 最终在的 handle_pte_fault 。你可以看到code,

  IF(标志和安培; FAULT_FLAG_WRITE){
        如果(!pte_write(入门))
            返回do_wp_page(毫米,VMA,地址,
                    私人,PMD,PTL,输入);
        进入= pte_mkdirty(输入); / **这里是脏仿真。 ** /
}

所以Linux的通用code将检查网页的权限,看到它被假设是可写的,并调用 pte_mkdirty 来标记页面为脏;整个过程拉开序幕,或通过故障处理程序效仿。该页面被标记后的的在Linux PTE,ARM的PTE被标记为可写因此后续写入不会引起故障。

访问的是相同的只有读写最初将故障。 A 文件的位也完全未映射,当故障发生时,Linux的PTE被咨询,看它是否是由一个文件的支持还是一个完全的未映射的页面错误。

硬件表是用新的权限和簿记更新

在完成后,用户模式程序的错误指令重新启动,它不会注意到其中的差别,除了时间间隔来处理故障。


ARM Linux使用4K页和ARM二级页表是1K的大小(256个* 4字节)。从 pgtable -2- level.h 注释


  

因此​​,我们小幅调整的实现 - 我们告诉Linux的,我们已经在第一级2048项,其中每个8个字节(IOW,两个硬件指针到第二级),第二级包括两个硬件PTE表相邻排列,$ p $所包含的状态信息Linux需要Linux版本pceded。因此,我们有512项最终在PTE的水平。


为了使用完整的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修订使用稍有不同的表的结构和特征,有在<一个条目href=\"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/proc-fns.h#n23\"相对=nofollow> 处理器的指向汇编程序函数表。例如,<一href=\"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7-2level.S#n71\"相对=nofollow> cpu_v7_set_pte_ext 是ARMv7的或典型原来的Cortex CPU实现。这个程序是负责审查Linux的标志并相应地更新硬件位。可以看出,在在 R3 写入私人+ 2048 (从Linux的PTE偏移硬件PTE)这个程序的结束。汇编程序宏<一个href=\"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-macros.S#n178\"相对=nofollow> armv3_set_pte_ext PROC-marcos.S 被许多旧的CPU变种。

请参阅: Tim的ARM的MM
笔记
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; <一href=\"http://stackoverflow.com/questions/16909101/page-table-entry-pte-descriptor-in-linux-kernel-for-arm\">Page Linux内核为ARM表项(PTE)描述

As per pgtable-2-level.h, ARM Linux has two version of PTE; The Linux PTE and H/W PTE. Linux PTE are stored on below a offset of 1024 bytes.

When handling page fault in handle_pte_fault various function like pte_file, pte_mkdirty, pte_mkyoung, get invoke with the version H/W PTE.

But actually ARM H/W does not support the dirty, accessed and file bit in its PTE.

My question is how does it check the dirty, accessed, file bit of a page on H/W PTE? Ideally it should check those bit on Linux PTE which are stored below an offset of 1024 bytes?

解决方案

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

TL;DR - they are emulated by taking a page fault on initial accesses.

The answers are given in 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.

To take the dirty case, the initial MMU mappings for page are marked read-only. When a process writes to it, a page fault is generated. This is the handle_pte_fault referenced and the main code is in fault.c as do_page_fault and will call the generic handle_mm_fault which eventually ends at handle_pte_fault. You can see the code,

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. **/
}

So the Linux generic code will examine the permission of the page, see it is suppose to be writeable and call the pte_mkdirty to mark the page as dirty; the whole process is kicked off or emulated through the fault handler. After the page is marked dirty in the Linux PTE, the ARM PTE is marked as writeable so subsequent writes do not cause a fault.

accessed is identical only both read and write will initially fault. A file bit is also completely unmapped and when a fault occurs, the Linux PTE is consulted to see if it is backed by a file or is it a completely unmapped page fault.

After the hardware table is updated with new permissions and book keeping is done, the user mode program is restarted at the faulting instruction and it would not notice the difference, besides the time interval to handle the fault.


ARM Linux uses 4k pages and the ARM 2nd level page tables are 1k in size (256 entries * 4bytes). From the pgtable-2-level.h comments,

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.

In order to use the full 4K page, the PTE entries are structured like,

  1. Linux PTE [n]
  2. Linux PTE [n+1]
  3. ARM PTE [n]
  4. ARM PTE [n+1]

Four 1k items for a full 4k page. These collections of pages must be managed per process to give each a unique view of memory and some information is shared in order to conserve real RAM. The function cpu_set_pte_ext is used to change the physical ARM entries. As each ARM CPU revision uses slightly different tables structures and features, there is an entry in the processor function table that points to an assembler routine. For instance, cpu_v7_set_pte_ext is the ARMv7 or typical original Cortex CPU implementation. This routine is responsible for examining the Linux flags and updating the hardware bits accordingly. As can be seen, the r3 is written to pte+2048 (offset from Linux PTE to hardware PTE) at the end of this routine. The assembler macro armv3_set_pte_ext in proc-marcos.S is used by many of the older CPU variants.

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

这篇关于如何ARM Linux的模拟脏,访问和文件PTE的位?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆