本次实验,需要使用arm提供的寄存器实现页表,地址转换功能。

使用字典树的思想逐级建立3级页表,VA达到48位,使用TTBR_EL0、TTBR_EL1寄存器将UART串口设备的虚拟地址和进程的虚拟地址分开映射,使得低异常级别的程序在硬件上无法越权访问高异常级别的系统地址空间

大家在做这个实验的时候记得调试的时候看一下自己的TTBR_EL0、TTBR_EL1是否真的有一个的值是高地址,之前很多同学都没有注意调试。

注意,每一个叶子节点的大小是4kb,虽然每个节点定义的是512entry但是512*9bit是4096b,注意考虑每个条目本身存储所占用的大小,每一级9位是arm的官方手册定的,不能乱改呀

推荐完成时间 60分钟 理解比较困难,可以借助ai理解一下

目录

1     实验项目一... 3

1.1      项目名称... 3

1.2      实验目的... 3

1.3      实验资源... 4

2     实验任务... 5

2.1      Armv8的地址转换... 5

2.2      前置知识... 5

2.2.1        粒度granule. 6

2.2.2     Gathering Reordering EarlyWriteAcknowledgement 7

2.3      Mmu管理... 9

2.3.1     src/bsp/mmu.c. 9

2.3.2     src/bsp/mmu.h. 10

2.3.3     src/bsp/cache_asm.S. 11

2.4      启用MMU.. 12

2.5      成品展示... 13

2.6      拆解代码原理... 14

2.6.1        定义映射区域... 15

2.6.2        设置映射的地址和页表大小... 16

2.6.3        设置粒度... 16

2.6.4        新建页表... 17

2.6.5        查找页表... 18

2.6.6        清除cache和buffer的数据... 19

2.6.7        重新置位... 20

2.7      Lab8作业... 20

3     总结... 23

3.1      实验中出现的问题... 23

3.2      真实感受... 23

  1. 实验项目一
    1. 项目名称

分页内存管理

    1. 实验目的

实现分页Page

    1. 实验资源

  1. 实验任务
    1. Armv8的地址转换

TTBR0指向整个虚拟空间下半部分通常用于应用程序的空间,TTBR1指向虚拟空间的上半部分通常用于内核的空间。其中TTBR0除了在EL1中存在外,也在EL2 and EL3中存在,但TTBR1只在EL1中存在。

这个分隔意味着OS不必为每个任务重新分配转换表了。

先选择基址寄存器,再进入每个条目,翻译成对应的PTE

    1. 前置知识

EL0是应用层,EL1是OS层

      1. 粒度granule

其实就是偏移offset范围,一页的大小

      1. Gathering Reordering EarlyWriteAcknowledgement

可以看出4kb粒度,启用写回写分配缓存机制

这里启用了之前已经算好的东西,那么重要的东西就有table,tcr,attr

    1. Mmu管理
      1. src/bsp/mmu.c

      1. src/bsp/mmu.h

      1. src/bsp/cache_asm.S

    1. 启用MMU

    1. 成品展示

可以看到确实在启用MMU

    1. 拆解代码原理

整个代码运作机制如图所示,我们整个程序的主要目的就是在主存内生成完整的页表给TTBR0用,然后做好粒度之类的设置(TCR)。

页表其实就像一棵树,只不过是按位来存储的,使用VPN查询页表的PTE,实际上VPN算是句柄,PTE算是一个节点,节点内存储了到达下一个节点的地址,也就是PFN。

现在我们的树是扁平化地存储在内存中的,DFS深度优先建树,从0级节点内的512个条目中的其中一个条目构建,然后再继续,直到最终指向物理空间的块(3级)。

      1. 定义映射区域

设备区域被定义的特别严格,根据这样的起始地址定义两个映射

      1. 设置映射的地址和页表大小

这里看链接文件的定义,以当前位置.分配了页表起始位置,然后长度就是以一个地址之间的差值定义的这个大小可以在链接文件里面修改。

      1. 设置粒度

MMU的粒度

      1. 新建页表

这里有512个条目,然后全部初始化为0

      1. 查找页表

这里和书上写的差不多

      1. 清除cache和buffer的数据

这里让这些东西无效化是害怕有未定义数据被写回内存里面,所以每次启动都要无效化一次

      1. 重新置位

这里重新置位了CMI位

    1. Lab8作业

第一次运行造成错误。

溢出了,需要把U32换成U64

Ld位置定义了这个符号表
ttbr1_el1没有被启用

  1. 总结
    1. 实验中出现的问题
  1. 几乎做完之前要崩溃了,有种思考乏力的感觉,像是缺乏休息,没有力气,这种状态,很难走出来
  2. 多出去走走吧,拓宽思路
  3. 找不到英文文档的重点,之前对页表的理解有偏差

    1. 真实感受
  1. 感谢某同学在北辰三角洲陪我走了一段路,我才能回过神来,不再踌躇
  2. 这实验弄懂了简单,没弄懂就难
  3. 数据结构真的很重要
  4. 头一次看到扁平化建512叉树,上一次看DFS深度优先建树,深度为3层还是在设备树那里

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐