arm linux多核同时获取读写锁, 会死循环吗, 还是都得到写锁 2017-01-18

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

本篇只提问, 不解答, 祝开心.

如果读写锁是unlocked, 然后cpu 0和cpu 1都想获取写锁, 如表格所示, CPU 0在t2时刻执行的是wfene, 这时, CPU 1执行的是ldrex, 然后是否会有cpu能够获取到锁? 源码来自 linux-3.10.86/arch/arm/include/asm/spinlock.h archwritelock()

时间 CPU0 时间 CPU1
t0/t6 1: ldrex %0, [%1]
t1/t7 teq %0, #0
t2 WFE("ne") t2 1: ldrex %0, [%1]
t3 strexeq %0, %2, [%1] t3 teq %0, #0
t4 teq %0, #0 t4 WFE("ne")
t5 bne 1b t5 strexeq %0, %2, [%1]
t6 t6 teq %0, #0
t7 t7 bne 1b

qemu观察arm linux启动过程02 2017-01-18

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

1. _createpage_tables

pgtbl r4 @ page table address

其中pgtbl为宏

.macro pgtbl, rd
ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)
.endm

这里KERNELRAMPADDR和zreladdr的值相等.

1.1 identity mapping

/*
* Create identity mapping for first MB of kernel to
* cater for the MMU enable. This identity mapping
* will be removed by paging_init(). We use our current program
* counter to determine corresponding section base address.
*/
mov r6, pc
mov r6, r6, lsr #20 @ start of kernel section
orr r3, r7, r6, lsl #20 @ flags + kernel base
str r3, [r4, r6, lsl #2] @ identity mapping
@ 和arch\arm\boot\compressed\head.S类似
@ r3内容:
@ 31       20       19                 0  
@  PC高12bit       __cpu_mm_mmu_flags
@存放的地址:
@   31          14           13            2                1 0  
@  页表基址(0x4000)         页表index(pc高12bit)              00  

qemu观察arm linux启动过程01 2017-01-18

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

1. 方法

qemu-system-arm -M versatilepb -m 128M -kernel /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux -S -s

需要留意, 这里-kernel的参数不是/opt/qemu_arm/linux-2.6.35.7/vmlinux

arm-none-linux-gnueabi-gdb -tui -q /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux
Reading symbols from /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux...done.
(gdb) target extended-remote localhost:1234
Remote debugging using localhost:1234
warning: Source file is more recent than executable.
start () at arch/arm/boot/compressed/head.S:115
(gdb) b __setup_mmu
Breakpoint 1 at 0x200: file arch/arm/boot/compressed/head.S, line 409.
(gdb) c
Continuing.
Breakpoint 1, __setup_mmu () at arch/arm/boot/compressed/head.S:409
(gdb) i r r3 r4
r3 0x4000 16384
r4 0x8000 32768

从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的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