1 ARMv8存儲管理
1.1 Aarch64 Linux中的內存布局
ARMv8架構可以支持48位虛擬地址,并配置成4級頁表(4K頁),或者3級頁表(64K頁)。而本Linux系統只使用39位虛擬地址(512G內核,512G用戶),配置成3級頁表(4K頁)或者2級頁表(64K頁)
用戶空間的地址63:39位都置零,內核空間地址63:39都置一,虛擬地址的第63位可以用來選擇TTBRx。swapper_pg_dir只包含內核全局映射,用戶的pgd包含用戶(非全局)映射。swapper_pg_dir地址在TTBR1中,不會寫入TTBR0中。
AArch64Linux內存布局:
Start End Size Use
--------------------------------------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user
ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc
ffffffbbfffd0000 ffffffbcfffdffff 64KB [guardpage]
ffffffbbfffe0000 ffffffbcfffeffff 64KB PCII/O space
ffffffbbffff0000 ffffffbcffffffff 64KB [guard page]
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
ffffffbe00000000 ffffffbffbffffff ~8GB [guard,future vmmemap]
ffffffbffc000000 ffffffbfffffffff 64MB modules
ffffffc000000000 ffffffffffffffff 256GB memory
1.2 AArch64的虛擬地址格式
1.2.1 4K頁時的虛擬地址
1.2.2 64K頁時的虛擬地址
2 head.S頁表建立過程分析
2.1 頁表建立函數__create_page_tables
該函數用于在內核啟動時,為FDT(設備樹)、內核鏡像創建啟動所必須的頁表。等內核正常運行后,還需運行create_mapping為所有的物理內存創建頁表,這將覆蓋__create_page_tables所創建的頁表。
內核開始運行時創建頁表源文件:arm64/kernel/head.Sline345
/*
* Setup the initial page tables. We only setup the barest amount which is
* required to get the kernel running. The following sections are required:
* -identity mapping to enable the MMU (low address, TTBR0)
* -first few MB of the kernel linear mapping to jump to once the MMU has
* been enabled, including the FDT blob (TTBR1)
*/
__create_page_tables:
pgtbl x25, x26,x24 //idmap_pg_dir and swapper_pg_dir addresses
/*
* 清空新建的兩個頁表TTBR0,TTBR1
*/
mov x0,x25
add x6,x26, #SWAPPER_DIR_SIZE
1: stp xzr,xzr, [x0], #16
stp xzr,xzr, [x0], #16
stp xzr,xzr, [x0], #16
stp xzr,xzr, [x0], #16
cmp x0,x6
b.lo 1b
ldr x7,=MM_MMUFLAGS
/*
* Create the identity mapping.
*/
add x0, x25,#PAGE_SIZE // sectiontable address
adr x3, __turn_mmu_on // virtual/physical address
create_pgd_entry x25, x0, x3, x5, x6 //展開見1.1.3
create_block_map x0, x7, x3, x5, x5, idmap=1
/*
* Map the kernel image (starting withPHYS_OFFSET).
*/
add x0,x26, #PAGE_SIZE //section table address
mov x5,#PAGE_OFFSET
create_pgd_entry x26, x0, x5, x3, x6
ldr x6,=KERNEL_END - 1
mov x3,x24 // physoffset
create_block_map x0, x7, x3, x5, x6
/*
* Map the FDT blob (maximum 2MB; must bewithin 512MB of
* PHYS_OFFSET).
*/
mov x3,x21 // FDTphys address
and x3,x3, #~((1 << 21) - 1) // 2MBaligned
mov x6,#PAGE_OFFSET
sub x5,x3, x24 //subtract PHYS_OFFSET
tst x5,#~((1 << 29) - 1) //within 512MB?
csel x21,xzr, x21, ne // zero the FDTpointer
b.ne 1f
add x5,x5, x6 // __va(FDTblob)
add x6,x5, #1 << 21 // 2MB forthe FDT blob
sub x6,x6, #1 //inclusive range
create_block_map x0, x7, x3, x5, x6
1:
ret
ENDPROC(__create_page_tables)
2.1.1 pgtbl x25, x26, x24分析
pgtbl是個宏,定義如下:
arm64/kernel/head.S line55
.macro pgtbl,ttb0, ttb1, phys
add ttb1,phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE
sub ttb0,ttb1, #IDMAP_DIR_SIZE
.endm
pgtbl x25,x26, x24 //展開后如下
add x26,x24, #TEXT_OFFSET -SWAPPER_DIR_SIZE
sub x25,x26,#IDMAP_DIR_SIZE
其中各變量定義如下:
#defineSWAPPER_DIR_SIZE (3 * PAGE_SIZE)
#defineIDMAP_DIR_SIZE (2 *PAGE_SIZE)
說明:
1、關于TTBR0、TTBR1的介紹見ARM ARM 手冊的Page B4-1708
2、x25中存TTBR0(TTBR0 holds the base address of translation table 0)的地址;
3、X26存TTBR1(TTBR1 holds the base address of translation table 1)地址;
4、X24 存PHYS_OFFSET,/* PHYS_OFFSET- the physical address of the start of memory. */
#definePHYS_OFFSET ({ memstart_addr; })
5、TEXT_OFFSET是Bootloader啟動時傳進來的參數,是內核Image加載時相對于RAM起始地址的偏移量
6、PAGE_OFFSEST:the virtual address of the start of the kernel image.
圖1 pgtbl宏分析
2.1.2 MM_MMUFLAGS解釋
在文件arm64/kernel/head.S line71:
/*
* Initial memory map attributes.
*/
#ifndefCONFIG_SMP
#definePTE_FLAGS PTE_TYPE_PAGE | PTE_AF
#definePMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF
#else
#definePTE_FLAGS PTE_TYPE_PAGE | PTE_AF |PTE_SHARED
#definePMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF| PMD_SECT_S
#endif
#ifdefCONFIG_ARM64_64K_PAGES
#defineMM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) |PTE_FLAGS
#defineIO_MMUFLAGS PTE_ATTRINDX(MT_DEVICE_nGnRE)| PTE_XN | PTE_FLAGS
#else
#defineMM_MMUFLAGS PMD_ATTRINDX(MT_NORMAL) |PMD_FLAGS
#defineIO_MMUFLAGS PMD_ATTRINDX(MT_DEVICE_nGnRE)| PMD_SECT_XN | PMD_FLAGS
#endif
根據以上宏定義能明確,MM_MMUFLAGS就是根據你編譯內核時選定的頁大小(64K or 4K),設置MMU。
2.1.3 create_pgd_entry/create_block_map宏解釋
1、create_pgd_entry
/*
* Macro to populate the PGD for thecorresponding block entry in the next
* level (tbl) for the given virtual address.
*
* Preserves: pgd,tbl, virt
* Corrupts: tmp1,tmp2
*/
.macro create_pgd_entry,pgd, tbl, virt, tmp1, tmp2
lsr tmp1,virt, #PGDIR_SHIFT
上一篇:關于ARMv8另外幾個問題
下一篇:最后一頁
推薦閱讀
史海拾趣