一、 实验目的
-
全面深入地理解分页式内存管理的基本方法
-
理解页表的访问、完成地址转换等的方法
-
在操作系统内核中实现一个内存管理系统
二、 实验过程
1.首先需要理解Armv8架构的地址转换:
Armv8架构中存在着几个页表基址寄存器:TTBR0_ELn,TTBR1_ELn。TTBR0指向整个虚拟空间下半部分通常用于应用程序的空间,TTBR1指向虚拟空间的上半部分通常用于内核的空间。其中TTBR0除了在EL1中存在外,也在EL2 and EL3中存在,但TTBR1只在EL1中存在。
高位是1的虚拟地址空间,使用TTBR1_ELx基地址寄存器进行页表翻译;高位是0的虚拟地址空间,使用TTBR0_ELx基地址寄存器页表翻译。所以不应该说,因为你使用了哪个寄存器(TTBR0/TTBR1),然后决定了你使用的哪套虚拟地址空间;应该说,你操作系统(或软件)使用了哪套虚拟地址空间,决定了使用哪个哪个基地址寄存器(TTBR0/TTBR1)进行翻译。
下图是一个经典的48bit 虚拟地址,4级页表,页表大小为 4Kb的地址转换示例:
页表从左到右依次为0级页表到3级页表。
比如输入虚拟地址:
四级页表的查询过程
输入va:0xFFFF FFFF F000
使用bit[47:39]作为index 从页表基地址查询下一级页表的基地址为(0x1000)
使用bit[38:30]作为index,从页表基地址(0x1000)查找下一级的页表基地址(0x2000)
使用bit[29:21]作为index,从页表基地址(0x2000)查找下一级页表基地址(0x3000)
使用bit[20:12]作为index,从页表基地址(0x3000)获取页地址(0x80000000)
物理地址结果为 页地址 + 页偏移地址 0x80000000 + 0x0000 = 0x80000000
输出pa:0x80000000
这里列出了使用4级页表的模式下,映射地址 0xFFFF FFFF F000 到物理地址 0X80000000的映射与查找过程。这里使用的了4份页表,每一个页表最多包含512个表项目。完成上述映射占用了 512 * 8 * 4 byte = 16kByte 的内存空间与一级页表相比,占用的空间数量大大减少。
2.接着分版块对本实验的核心代码mmu.c进行分析:
这个数组g_mem_map_info定义了虚拟地址到物理地址映射的参数,数组中每个元素都是一个内存映射区域,包括虚拟地址起始点、物理地址起始点、大小、最大级别和属性。
这个函数基于给定的内存映射信息 g_mem_map_info计算并构建用于配置ARM处理器的MMU(内存管理单元)的TCR(Translation Control Register,翻译控制寄存器)的值。这个函数的目的是为了设置内存管理单元的虚拟地址翻译机制,并返回构建好的TCR寄存器的值。
这里基于Armv8用户手册,对TCR的功能进行分析:
比特位 | 长度 | 解释说明 |
IPS | b001 << 32 | 36bits address space - 64GB 36位地址空间,共64GB |
TG1 | b10 << 30 | 4KB granule size for TTBR1_EL1 页大小为4KB |
SH1 | b11 << 28 | 页表所在memory: Inner shareable内部可共享 |
ORGN1 | b01 << 26 | 页表所在memory: Normal, Outer Wr.Back Rd.alloc Wr.alloc Cacheble可写回缓存 |
IRGN1 | b01 << 24 | 页表所在memory: Normal, Inner Wr.Back Rd.alloc Wr.alloc Cacheble可写回缓存 |
EPD1 | b0 << 23 | Perform translation table walk using TTBR1_EL1 |
A1 | b1 << 22 | TTBR1_EL1.ASID defined the ASID |
T1SZ | b011100 << 16 | 虚拟地址为(64-n)=(64-28)=36位 |
TG0 | b00 << 14 | 4KB granule size 页大小为4KB |
SH0 | b11 << 12 | 页表所在memory: Inner Sharebale内部可共享 |
ORGN0 | b01 << 10 | 页表所在memory: Normal, Outer Wr.Back Rd.alloc Wr.alloc Cacheble可写回缓存 |
IRGN0 | b01 << 8 | 页表所在memory: Normal, Inner Wr.Back Rd.alloc Wr.alloc Cacheble可写回缓存 |
EPD0 | b0 << 7 | Perform translation table walk using TTBR0_EL1 |
0 | b0 << 6 | Zero field (reserve) |
T0SZ | b011100 << 0 | 虚拟地址为(64-n)=(64-28)=36位 |
第一个函数返回页表项的类型,第二个函数则是根据页表的级别返回对应的位移值,以计算每个页表项表示的地址范围。
这个函数则是在页表中找到给定地址和级别的页表项地址。
这个mmu_creat_table函数根据页表粒度(4k或64k)在页表区域创建一个新的页表,由于页表刚创建时为空页表,因此所有的页表项均为PTE_TYPE_FAULT,最后返回该页表的起始位置
这其中的第一个函数设置页表项指向一个页表,用于创建多级页表,第二个函数则是根据映射指定的级别来填充对应的页表项。
这个函数向MMU中添加映射:首先通过一个循环,从起始级别开始,为给定的地址范围添加映射。在每一级别,它会尝试找到对应的页表项(通过调用 mmu_find_pte 函数),如果找不到则返回错误,对于找到的页表项,调用先前定义的mmu_add_map_pte_process函数来进行填充。这包括创建新的下一级页表(如果当前页表项无效且不是最低级页表项)或直接设置页表项的值(如果是最低级页表项或已到达设定的级别)在成功添加映射后,函数会更新虚拟地址、物理地址和已映射的大小,为下一个块做准备。循环一直重复直到整个映射的大小都被处理完毕。
这个函数嵌入式汇编指令来直接操作处理器的寄存器,用于设置TTBR、TCR和MAIR寄存器的值。这些寄存器用于配置处理器的内存管理单元(MMU),控制虚拟内存到物理内存的转换。
根据Armv8用户手册对MAIR寄存器进行分析:
MAIR 支持定义八种预设的内存属性,可以分类为 memory 类型和 device 类型,每一种类型还包含了一些细节的控制,对于 memory 类型的内存,主要进行一些cache的分配策略的配置 如write back、write through等,device 类型是不可cache的地址空间,主要用于对外设寄存器访问等。
主要包含了3种属性 G/R/E:
G 表示 Gathering,即是否允许访问合并,比如2个8bit的地址连续的访问请求、合并成为一个16bit的访问请求
R 表示 Re-ordering,即表示对地址空间的访问请求是否支持重新排序,如分别读取2个地址的数据,在访问时顺序可能与程序定义不完全一致
E 表示 Early Write Acknowledgement,即对总线发起写操作时,是否允许总线提前返回写响应,而不需要等待写数据真的写入到了最终的位置。在总线上可能会存在并经过多个节点,提前返回可以提前完成写数据指令的执行。
这个函数主要用于初始化和设置内存管理单元(MMU)的页表,从而实现在ARM架构的处理器上完成虚拟地址到物理地址的转换,首先接收一系列内存映射区域、页表的基地址和长度、以及页表粒度作为参数,并根据这些参数构建起始级别的页表,最后将内存映射添加到这些页表中。
这个函数为操作系统内核设置页表,并根据预定义的内存映射信息来初始化MMU,以便系统能够使用虚拟内存管理。
最后就是初始化函数,首先调用mmu_setup函数来设置页表,然后无效化数据和指令缓存以及TLB,最后设置系统控制寄存器(SCTLR)来启用缓存和MMU。
3.启用MMU
三、测试及分析
执行程序,可以正常运行:
通过调试发现已启用MMU:
四、 Lab8作业
启用 TTBR1 ,将地址映射到虚拟地址的高半部分,使用高地址访问串口,修改后:
1.在src/bsp目录下的print.c文件中添加宏定义:
2.在src/bsp目录下的hwi_init.c文件中添加宏定义:
此处定义了dist和cpu的基址,GIC_DIST_BASE 和 GIC_CPU_BASE 的高位多少个f与MMU的配置有关,此处设置为8个f
3.更改g_mem_map_info,使得进行映射时,将地址映射到高半部分:
4.取消mmu_set_ttbr_tcr_mair函数中的注释, 启用ttbr1_el1:
ttbr1_el1 是 ARM 架构中的一个系统寄存器,全称为 “Translation Table Base Register 1 - EL1”,用于存放转换表基址,在内存管理单元(MMU)中用来控制地址空间的转换。
5.最后,Init函数、write函数以及read函数中的基址被更改为新定义的地址:
6.最后执行程序,发现能够正常运行:
五、心得体会
-
更加清楚在具体的armv8架构中,页表是如何将虚拟地址映射到物理地址的,这其中涉及多个寄存器的相互配合。
-
能了解这多个寄存器的作用,在依托手册的基础上正确的配置寄存器以实现内存管理。
-
了解了多种页表映射方案,如块映射,多级页表映射等。