历史上的今天
今天是:2025年06月04日(星期三)
2020年06月04日 | ARMv8(aarch64)页表建立过程详细分析
2020-06-04 来源:elecfans
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另外几个问题
下一篇:单片机p0口的工作原理解析
史海拾趣
|
初从业,纵观行业觉甚有可为。DVR在中国的历史刚刚开始但是不久的将来必然引起一场革命,这场革命将和每一位国人密切相关. 1. 网络化。DVR不应该仅仅作为一个本地视频存储管理设备,而应该能把一个系统、一个行业、一个城市、一个地区的DVR统一管 ...… 查看全部问答> |
|
怎样减少电子医疗设备EMI解决方案: 使用基底噪声滤波器降低传导发射基底噪声滤波器被置于整体系统地和线滤波器地之间在设施接地系统内使用一个或多个基底噪声滤波器设备设计者一直要求获得具有更小封装的SMPS。更小的EMI滤波器不仅能够在电磁发射 ...… 查看全部问答> |
|
我现在在用MIPS32 4KSd内核的CPUUSIP做一个只能卡模块,用CF卡接口和WINCE5.0 的PDA相连,现在是用了usip的UART1给pda发数据,但UART1与其他三个uart不同,是一个标准的硬件控制流设备RX TX RTS CTS RI DTR DSR DCD 八个引脚 我现在只用到了RX和TX ...… 查看全部问答> |
|
不接32K晶振时,引脚XIN和XOUT可以悬空吗,如果不能悬空应该怎么接,还有,和JTAG口相连的引脚需不需要接上拉电阻到电源电压,如果不接,在不连接jtag时,会不会因为引脚是悬空的cmos口而引进干扰,谢了。… 查看全部问答> |
|
POS机套件中,TI给了一些有关电源的芯片,如TPS65910--电源管理、UCC28610--12~65W电源控制器、LMZ14203--3A易电源、TLV62130--3A降压电源、以用LI及镍氢电池充电芯片, 就其应用来说,大家讨论一下怎样利用这些芯片构建POS机的供电? … 查看全部问答> |




