sel4源碼解析(七) - vspace

sel4 vspace指的是進程的虛擬地址空間。armv8 64位版本的sel4 對應的頁表劃分分爲四級,分別是:pgd(page global directory)、pud(page upper directory)、pd(page directory)和pt(page table)。

本文主要介紹了sel4關於頁表的基本數據結構體、sel4爲初始進程創建頁表的過程解析以及簡要的描述了AArch64架構虛擬地址到物理地址的轉換流程。

基本數據結構

pgd

pgd結構體:

  • pud_base_address:指向pud基地址的指針(指向的pud大小爲4K);
block pgde_pud {
    padding                         16
    field_high pud_base_address     36
    padding                         10
    field pgde_type                 2 -- must be 0b11
}

pgd cap結構體:

  • capPGDMappedASID:進程的ASID(address space Identifiers);
  • capPGDBasePtr:指向pgd結構體的指針。
block page_global_directory_cap {
    field capPGDMappedASID           16
    field_high capPGDBasePtr         48  

    field capType                    5
    field capPGDIsMapped             1
    padding                          58
}

pud

pud結構體:

  • pd_base_address:指向pd基地址的指針(指向的pd大小爲4K);
block pude_pd {
    padding                         16
    field_high pd_base_address      36
    padding                         10
    field pude_type                 2
}

pud cap結構體:

  • capPUDMappedASID:進程的ASID(address space Identifiers);
  • capPUDBasePtr:指向pud結構體的指針;
  • capPUDMappedAddress:指向映射的虛擬地址。
block page_upper_directory_cap {
    field capPUDMappedASID           16
    field_high capPUDBasePtr         48

    field capType                    5
    field capPUDIsMapped             1
    field_high capPUDMappedAddress   10
    padding                          48
}

pd

pd結構體:

  • pt_base_address:指向pt基地址的指針(指向的pt大小爲4K);
block pde_small {
    padding                         16
    field_high pt_base_address      36
    padding                         10
    field pde_type                  2
}

pd cap結構體:

  • capPDMappedASID:進程的ASID(address space Identifiers);
  • capPDBasePtr:指向pd結構體的指針;
  • capPDMappedAddress:指向映射的虛擬地址。
block page_directory_cap {
    field capPDMappedASID            16
    field_high capPDBasePtr          48

    field capType                    5
    padding                          10
    field capPDIsMapped              1
    field_high capPDMappedAddress    19
    padding                          29
}

pt

pte結構體:

  • 描述頁面屬性;
block pte {
    padding                         9
    field UXN                       1
    padding                         6
    field_high page_base_address    36
    field nG                        1
    field AF                        1
    field SH                        2
    field AP                        2
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
    field AttrIndx                  4
#else
    padding                         1
    field AttrIndx                  3
#endif
    field reserved                  2 -- must be 0b11
}

page_table_cap結構體:

  • capPTMappedASID:進程的ASID(address space Identifiers);
  • capPTBasePtr:指向pt結構體的指針;
  • capPTMappedAddress:指向映射的虛擬地址。
block page_table_cap {
    field capPTMappedASID            16
    field_high capPTBasePtr          48

    field capType                    5
    padding                          10
    field capPTIsMapped              1
    field_high capPTMappedAddress    28
    padding                          20
}

sel4進程分配地址空間

這裏以初始進程爲例,初始進程的頁表建立過程大致分爲三步:創建內存、建立映射、填充頁表項屬性。具體如下所示:

create_rootserver_objects函數

  • 爲vspace分配內存空間,大小爲4k。這片內存用於存放pgd的地址映射關係;

  • 爲rootserver.paging分配內存空間,大小爲存放初始進程的鏡像尺寸。這片內存用於存放pud、pd、pt的地址映射關係;

BOOT_CODE void create_rootserver_objects(pptr_t start, v_region_t v_reg, word_t extra_bi_size_bits)
{
	...
    rootserver.vspace = alloc_rootserver_obj(seL4_VSpaceBits, 1);
    /* paging structures are 4k on every arch except aarch32 (1k) */
    word_t n = arch_get_n_paging(v_reg);
    rootserver.paging.start = alloc_rootserver_obj(seL4_PageTableBits, n);
    rootserver.paging.end = rootserver.paging.start + n * BIT(seL4_PageTableBits);
	...
}

create_it_address_space函數

  • 創建vspace_cap即page_global_directory_cap,他的成員capPGDBasePtr指向create_rootserver_objects爲vspace分配的4k內存首地址,包含292^9個pud表項;

  • 爲pud的映射關係表分配內存,其大小爲4K,包含了292^9個pd表項(從rootserver.paging中取出)。capPUDBasePtr指向pud的基地址,capPUDMappedAddress指向映射的虛擬地址。在pgd裏插入該pud表項;

  • 爲pd的映射關係表分配內存,其大小爲4K,包含了292^9個pt表項(從rootserver.paging中取出)。capPDBasePtr指向pd的基地址,capPDMappedAddress指向映射的虛擬地址。在pud裏插入該pd表項;

  • 爲pt的映射關係表分配內存,其大小爲4K,包含了292^9個表項(從rootserver.paging中取出)。capPTBasePtr指向pt的基地址,capPTMappedAddress指向映射的虛擬地址。在pd裏插入該pT表項;

BOOT_CODE cap_t create_it_address_space(cap_t root_cnode_cap, v_region_t it_v_reg)
{
    cap_t      vspace_cap;
    vptr_t     vptr;
    seL4_SlotPos slot_pos_before;
    seL4_SlotPos slot_pos_after;

    /* create the PGD */
    vspace_cap = cap_vtable_cap_new(
                     IT_ASID,        /* capPGDMappedASID */
                     rootserver.vspace, /* capPGDBasePtr   */
                     1               /* capPGDIsMapped   */
                 );
    slot_pos_before = ndks_boot.slot_pos_cur;
    write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapInitThreadVSpace), vspace_cap);
    /* Create any PUDs needed for the user land image */
    for (vptr = ROUND_DOWN(it_v_reg.start, PGD_INDEX_OFFSET);
         vptr < it_v_reg.end;
         vptr += BIT(PGD_INDEX_OFFSET)) {
        if (!provide_cap(root_cnode_cap, create_it_pud_cap(vspace_cap, it_alloc_paging(), vptr, IT_ASID))) {
            return cap_null_cap_new();
        }
    }
    /* Create any PDs needed for the user land image */
    for (vptr = ROUND_DOWN(it_v_reg.start, PUD_INDEX_OFFSET);
         vptr < it_v_reg.end;
         vptr += BIT(PUD_INDEX_OFFSET)) {
        if (!provide_cap(root_cnode_cap, create_it_pd_cap(vspace_cap, it_alloc_paging(), vptr, IT_ASID))) {
            return cap_null_cap_new();
        }
    }
    /* Create any PTs needed for the user land image */
    for (vptr = ROUND_DOWN(it_v_reg.start, PD_INDEX_OFFSET);
         vptr < it_v_reg.end;
         vptr += BIT(PD_INDEX_OFFSET)) {
        if (!provide_cap(root_cnode_cap, create_it_pt_cap(vspace_cap, it_alloc_paging(), vptr, IT_ASID))) {
            return cap_null_cap_new();
        }
    }
    slot_pos_after = ndks_boot.slot_pos_cur;
    ndks_boot.bi_frame->userImagePaging = (seL4_SlotRegion) {
        slot_pos_before, slot_pos_after
    };
    return vspace_cap;
}
  1. 最後由函數create_frames_of_region填充頁表的頁表項,具體可以參看pt的結構體;

AArch64架構虛擬地址轉換的簡要過程

虛擬地址轉換成物理地址流程:

  1. 取虛擬地址高九位結合TTBR_ELx寄存器找到pgd的首地址;
  2. 再取虛擬地址九位得到pgde,裏面包含pud的首地址;
  3. 再取九位得到pude,裏面包含pd的首地址;
  4. 再取九位得到pde,裏面包含pt的首地址;
  5. 剩餘的低十二位爲頁內地址。

相關鏈接

sel4源碼解析(一) - sel4內核對象
sel4源碼解析(二) - CSpace
sel4源碼解析(三) - sel4系統調用處理流程
sel4源碼解析(四) - ipc
sel4源碼解析(五) - Notification
sel4源碼解析(六) - 進程
sel4源碼解析(七) - vspace

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章