arm linux的ASID (Address Space ID) 2017-01-18

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

平台:ARM Versatile Express for Cortex-A9 (ARMv7)
# CONFIGARMLPAE is not set, 也就是使用Short-descriptor格式, ASID存储在CONTEXTIDR的低8 bit:

31                         7          0
+-------------------------+-----------+
|      PROCID             |   ASID    |
+-------------------------+-----------+

页表项中 nG == 1时, 这个页表项信息就是 non-global, 或者说 process-specific, 对应的TLB中就会有ASID信息, 执行虚拟地址到物理地址转换时, ASID也需要参与该过程.

用户地址空间的页表才会设置nG标志 (内核地址的一部分地址范围使用TLB lockdown比较合适): linux-3.10.86/arch/arm/include/asm/pgtable.h

static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 
                  pte_t *ptep, pte_t pteval) 
{ 
...
    if (addr < TASK_SIZE && pte_present_user(pteval)) { 
... 
        ext |= PTE_EXT_NG; 
    } 
... 
    set_pte_ext(ptep, pteval, ext); 
}

set_pte_at -> set_pte_ext -> cpu_v7_set_pte_ext

从create_mapping()看arm linux的页表 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

arm linux中断处理过程中寄存器的保存 2017-01-18

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

模式   usr            exception                                   svc                             
-----|----|--------------------------------|---------------------------------------------------                                                                                               
函数                 vector_\name:                             usr_entry:                         


                                                                            对应的汇编语句:                    
                  +----------------+        0  +------------------+   ------------------------    
           高地址 |spsr_<exception>|           |      r0          |      str     r1, [sp]         
                  |                |        4  +------------------+    ----------------------     
             ^    +----------------+           |      r1          |                               
             |    |                |           |                  |                               
             |    |lr_<exception>  |           |      .           |                               
             |    |                |           |      .           |      stmib   sp, {r1 - r12}   
             |    +----------------+           |      .           |                               
                  |                |           |                  |                               
           低地址 |      r0        |           |     r12          |                               
                  |                |           |                  |                               
                  +----------------+       52  +------------------+     ----------------------    
                    struct stack               |      sp_usr      |                               
                                               |                  |                               
                                           56  +------------------+     stmdb   r0, {sp, lr}^     
                                               |     lr_usr       |                               
                                               |                  |                               
                                           60  +------------------+      ---------------------    
                                               |  lr_<exception>  |                               
                                               |                  |                               
                                           64  +------------------+                                
                                               | spsr_<exception> |      stmia   r0, {r2 - r4}    
                                               |                  |                               
                                           68  +------------------+                               
                                               |      -1          |                               
                                               |                  |                               
                                           72  +------------------+     -----------------------   
                                                struct  pt_regs

arm linux的iounmap()如何处理主页表(master page table)的同步 2017-01-18

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

1. 背景

平台为qemu ARM Versatile/PB (ARM926EJ-S) ARMv5TEJ, UP

我们知道进程的内核地址空间的页表 和 swapperpgdir 进行同步, 在进程创建时, do_fork()会拷贝一级页表.

2. 问题

vmalloc() area发生异常, 由dotranslationfault()处理, 处理的是一级页表无效的情况, 处理方法: If the init_task's first level page tables contains the relevant entry, we copy the it to this task.

可以猜想, vmalloc区域的页表是 两级页表(低两位D1D0为0b01), 而不是section (D1D0为0b10)

打印vmalloc区域的对应的页表, 可以看到 D1D0 既有0b01(指向二级页表), 也有0b10(无需二级页表) 的.

从cat /proc/vmallocinfo可知, 可知0b10不是由vmalloc()引发的页表创建, 而是ioremap(). (这里并不是说ioremap创建的都是section)

虚拟地址0xc9000000开始对应的一级页表entry

关于arm linux的map_io 2017-01-18

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

1. 主要流程

平台:versatilepb ARM Versatile/PB (ARM926EJ-S) 内核版本2.6.35.7

paging_init
|--devicemaps_init
|   |--from VMALLOC_END, pmd_clear(pmd_off_k(addr))
|   |--mdesc->map_io() => versatile_map_io  
|   |   |--iotable_init
|   |   |   |--create_mapping

2. 为何是 MT_DEVICE

linux-2.6.35.7/arch/arm/mach-versatile/core.c

void __init versatile_map_io(void)
{
    iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
}

static struct map_desc versatile_io_desc[] __initdata = {
    {
        ...
        .type       = MT_DEVICE
    },
    ...