2017-01-18

来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/120613197201571932454226

createmapping会调用到allocinitpte(), 进而调用setpte_ext()

#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)

这里qemu模拟的versatilepb ARM Versatile/PB (ARM926EJ-S) ARMv5TEJ

所以setpteext(pte, pfnpte(pfn, _pgprot(type->prot_pte)), 0);

就是

cpuarm926setpteext (pte, pfnpte(pfn, _pgprot(type->prot_pte)), 0);

/*
 * cpu_arm926_set_pte_ext(ptep, pte, ext)
 *
 * Set a PTE and flush it out
 */
    .align  5
ENTRY(cpu_arm926_set_pte_ext)
#ifdef CONFIG_MMU
    armv3_set_pte_ext
    mov r0, r0
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
    mcr p15, 0, r0, c7, c10, 1      @ clean D entry
#endif
    mcr p15, 0, r0, c7, c10, 4      @ drain WB
#endif
    mov pc, lr

其中宏armv3setpte_ext实现在 linux-2.6.35.7/arch/arm/mm/proc-macros.S

/*
 * The ARMv3, ARMv4 and ARMv5 set_pte_ext translation function,
 * covering most CPUs except Xscale and Xscale 3.
 *
 * Permission translation:
 *  YUWD   AP   SVC User
 *  0xxx  0x00  no acc  no acc
 *  100x  0x00  r/o no acc
 *  10x0  0x00  r/o no acc
 *  1011  0x55  r/w no acc
 *  110x  0xaa  r/w r/o
 *  11x0  0xaa  r/w r/o
 *  1111  0xff  r/w r/w
 */

    .macro  armv3_set_pte_ext wc_disable=1
    str r1, [r0], #-2048        @ linux version

cpuarm926setpteext(ptep, pte, ext)参数中的ptep已经指向linux版的pte了, linux版在高地址, hw版在低地址, 所以有上面的-2048.
arm hw版二级页表和linux版 在内存布局的关系如下图所示:

 高地址   +--------------+ x+1024*4
   ^     |   linux pte  | 
   |     |              |
   |     +--------------+ x+1024*3
   |     |   linux pte  | 
   |     |              |  
   |     +--------------+ x+1024*2
   |     |   hw pte     | 
   |     |              | 
   |     +--------------+ x+1024*1
         |   hw pte     |
         |              | 
  低地址  +--------------+ x+0



    eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY

    bic r2, r1, #PTE_SMALL_AP_MASK  @ keep C, B bits
    bic r2, r2, #PTE_TYPE_MASK
    orr r2, r2, #PTE_TYPE_SMALL
先清低2位,然后D1:D0写为10,也就是使用small page


    tst r3, #L_PTE_USER         @ user?
    orrne   r2, r2, #PTE_SMALL_AP_URO_SRW

将linux版本的LPTEUSER转为arm版本
这个bit(LPTEUSER)来自memtypes[]的struct memtype的成员prot_pte

static struct mem_type mem_types[] = {

    [MT_HIGH_VECTORS] = {
        .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
                L_PTE_USER | L_PTE_EXEC,
        .prot_l1   = PMD_TYPE_TABLE,
        .domain    = DOMAIN_USER,
    },

};


tst r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW

留意0x55| 0xaa==0xff, 对应本段代码前面的注释

Permission translation:
YUWD   AP   SVC User
1011  0x55  r/w no acc
110x  0xaa  r/w r/o
11x0  0xaa  r/w r/o
1111  0xff  r/w r/w

问题:AP3到AP0是?
答:If the level one descriptor defines a page-mapped access and the level two descriptor is for a large or small page, four access permission fields, ap3 to ap0, are specified, each corresponding to one quarter of the page. For small pages ap3 is selected by the top 1KB of the page and ap0 is selected by the bottom 1KB of the page.

问题:对于二级页表中small page, 当前是哪个domain呢?
答:所属的一级页表的domain决定, 见Figure3-4. D8:D5这4个bit选择16个domain中的一个.

tst r3, #L_PTE_PRESENT | L_PTE_YOUNG    @ present and young?
movne   r2, #0

对应arm的二级页表中的fault的情况, 见Figure3-9.

    .if \wc_disable
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
    tst r2, #PTE_CACHEABLE
    bicne   r2, r2, #PTE_BUFFERABLE
#endif
    .endif
    str r2, [r0]            @ hardware version
    .endm

相关资料 ARM926EJ-S Technical Reference Manual

本文地址: https://awakening-fong.github.io/posts/arm/arm_create_mapping_page_table

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus