博文

目前显示的是 六月, 2012的博文

认识ASID

图片
注:以下讨论的前提是针对于 ARM V7 中 Cache 属性为 PIPT 的情况。 ASID 是 ARM 提供的 Context ID register 寄存器的低 8 位。它的全称是 Address Space Identifier 也叫 Application Space Identifier. 这两个名称在 ARM Reference 中都提到了。 为什么要引入 ASID 呢? To reduce the software overhead of TLB maintenance, the VMSA distinguishes between Global pages and Process specific pages. The Address Space Identifier (ASID) identifies pages associated with a specific process and provides a mechanism for changing process specific tables without having to perform maintenance on the TLB structures. [1] 在 Kernel 中,对 ASID 的注释写的言简意赅: The ASID is used to tag entries in the CPU caches and TLBs. [2] 所以:由于每一个进程对应一个 ASID ,并且 TLB 的每一个 Entry 使用 ASID 来进行 tag ,那么就不必在每一次在做进程切换的时候,都需要刷新 TLB 。 不过,这只是一个粗浅的理解。对于 ASID 的理解,需要和 Pagetable 中的 nG 位放在一起讨论。下图是 ARM V7 的 mapping entry format 的 first-level descriptor formats [3] 和 second-level descriptor formats [4] 。 红色标注的地方是 nG 位。 nG 位的作用: nG == 0  The translation is global.

ARM Linux 如何模拟X86 PTE中的Present Young和Dirty标志位

图片
注:本文是参考Kernel的代码并加上个人揣测,欢迎指正 在 X86 MMU Page table entry 中,有三个标志位在ARM 的MMU硬件所规定的Page table entry中不提供。这三个标志位的作用如下: PTE_DIRTY的作用:CPU在写操作的时候,处理器会将改位置位。说明对应的页被写过,是脏的。 PTE_YOUNG 的作用是:MMU 寻址是将该标志置位(在换出的时候,如果此标志位被置位,说明该地址刚刚被使用过,暂时不换出此 pte 对应的页,同时清除该标志位)。 PTE_PRESENT 的作用是: MMU 在访问 PTE 的时候,若 PTE_PRESENT 为 0 ,则将地址放在CR2寄存器中,同时触发Pagefault异常。 下图抓自:《Linux内核情景分析》 由于 Linux 最早是 build 在 X86 平台上的,因此移植到 ARM 后,也需要遵从 X86 的内存管理框架,模拟 ARM MMU 没有提供的 PTE_PRESENT , PTE_YOUNG 和 PTE_WRITE 。 下面的分析,参考了arch/arm/include/asm/pgtable-2level.h中的注释 Q: 如何模拟 PTE_ DIRTY  ? A: ARM Linux 是通过 dirty 去标识某个页是否是可以 PTE_WRITE 的。 对于新分配的页,如果 Linux 版本的 PTE 没有 dirty 标识,对其进行写操作,会触发 MMU 异常。该异常会被 handle_pte_fault 处理 。 Q: 如何模拟 PTE_YOUNG? A: 这个 PTE_YOUNG 在内存被分配的时候置上,当解除映射的时候,将清掉该位。如果 Linux 版本的 PTE 的 young 位被清除了, MMU 使用的 PTE 版本的value是要清除的,但 TLB 并不刷新。 Q: 如何模拟 present : A: ARM 的 MMU 在访问的时候,不像 X86 的 MMU 那样 ( 只要看到 *pte 为 0 ,就判断该页压根没有被加载到内存中;若 *pte 不为 0 , PTE_PRESENT 位为 0 ,就能判断该被 swap out 了 ), 那么 ARM MM

Linux/ARM Page Table Entry 属性设置分析

图片
注:该博文写的比较凌乱,需要以后再修改。 Linux 的页表项总体可以划分为两部分,一部分是物理映射地址,另一部分是对物理地址对应的访问属性。在Linux/ARM的Kernel中,为各式各样的内存属性与定义了一下条目 :   198 static struct mem_type mem_types[] = {  199         [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */  200                 .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |  201                                   L_PTE_SHARED,  202                 .prot_l1        = PMD_TYPE_TABLE,  203                 .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_S,  204                 .domain         = DOMAIN_IO,  205         },  206         [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */  207                 .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,  208                 .prot_l1        = PMD_TYPE_TABLE,  209                 .prot_sect      = PROT_SECT_DEVICE,  210                 .domain         = DOMAIN_IO,  211         },  212         [MT_DEVICE_CACHED] = {    /* iorem