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

arm linux中通过设置CONTEXTIDR, 进而设置ASID, 相关代码为: linux-3.10.86/arch/arm/mm/proc-v7-2level.S

ENTRY(cpu_v7_switch_mm) 
... 
mcr    p15, 0, r1, c13, c0, 1        @ set context ID

调用关系为:

context_switch() ->switch_mm() -> check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) -> cpu_switch_mm() -> cpu_v7_switch_mm(pgd_t * pgd, struct mm_struct *mm)

linux把ASID存储在mm->context.id的低8位 (D7:D0).

新创建的非内核线程 (内核线程不会调用到dup_mm), 初始化ASID为0:

copy_mm -> dup_mm -> init_new_context
#define init_new_context(tsk,mm)   ({ atomic64_set(&mm->context.id, 0); 0; })

到上下文切换的时候才真正开始给ASID赋值, 并设置CONTEXTIDR寄存器.

有分配, 就该有回收, 这也是使用bitmap来管理ASID, 而不是asid++的方式的原因. ASID的分配是通过bitmap变量asidmap来记录的. set bit的操作在newcontext()中可以找到. 查找对该变量的clear bit操作, 进程退出时, 本应有该动作(清asid_map中该进程所对应的bit), 但很遗憾, 没有找到, 开发人员偷懒了?

由于ASID只有8bit, 范围为0~0xff, 当这些值分配完后, 就需要flush TLB, 同时对generation加1, 然后重新开始分配ASID. generation为mm->context.id的高24+32位(D63:D8), 这样, 后续再调度到这个进程时, 就可以通过判断generation是否变化了, 来知道 mm->context.id中的ASID是否还有效.

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

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


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


blog comments powered by Disqus