映射kernel地址空间
swapper_pg_dir其实就是swapper进程(pid等于0的那个,其实就是idle进程)的地址空间,用它来代表kernel地址空间。和恒等映射的区别是,这段空间映射没有扩展页表的需求,当然它也是使用section mapping。和前面的恒等映射一样,swapper_pg_dir也是需要3个页面。
映射kernel空间
adrp x0, swapper_pg_dir kernel页表基地址
mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) 代码段开始虚拟地址
add x5, x5, x23 // add KASLR displacement
create_pgd_entry x0, x5, x3, x6 建立各个中间level的table描述符
adrp x6, _end // runtime __pa(_end) 代码段结束物理地址
adrp x3, _text // runtime __pa(_text) 代码段开始物理地址
sub x6, x6, x3 // _end - _text 代码段长度
add x6, x6, x5 // runtime __va(_end) 代码段结束虚拟地址
create_block_map x0, x7, x3, x5, x6 创建PTE
adrp x0, idmap_pg_dir
ldr x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
dmb sy
bl __inval_dcache_area 再次清理cache
ret x28
ENDPROC(__create_page_tables)
上面调用的函数在前面都介绍过,不再次介绍了。至此内核地址空间被全部映射。
ffffff8008080000 T _text
ffffff8009175000 A _end
sharkl3 1h10 arm64的kernel使用了17,780,736字节,即不到20MB字节。
因为level2页表采用了block型描述符,每个entry管2MB,需要10个entry就够了。
左侧是内核虚拟地址分配图
cpu设置
stext--> __cpu_setup
这部分代码主要是在使能mmu前对cpu做一些设置。
ENTRY(__cpu_setup)
tlbi vmalle1 // Invalidate local TLB
dsb nsh