基础知识
MMU包括TLB和页表遍历单元(TWU)两个部件;
- TLB:是一个高速缓存,用于缓存页表转换的结果;
- TWU:页表的维护是软件进行的(这个很好理解,虚拟地址映射到哪个物理地址放给用户去设置),但是具体页表的查询是硬件完成的,这个硬件单元就是TWU;
mmu有两个职责: - 第一个:虚拟地址到物理地址的转化;
- 第二个:页表属性和内存访问权限控制等;(例如cache,读写属性等)
va->pa的查询过程
- 处理器根据虚拟地址来判断使用TTBR0还是TTBR1.当虚拟地址第63位为1时(0xFFFF_xxx),选择TTBR1;当虚拟地址第63位为0时(0x0000_xxx),选择TTBR0;TTBR存放这L0页表的基地址;
- 各个进程都有自己的页表基地址,所以进程切的时候,需要将自己的页表基地址设置进入TTBR0;
cpu_do_switch_mm:msr ttbr0_el1, x3 // now update TTBR0
- BASE地址 + index得到页表项,页表项中存放的就是下级页表的BASE地址;
- 重复2,一直到pte,pte中存放的就是实际的pfn;
set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
页面粒度
4k
构成:(9 + 9 + 9 + 9 )+ 12(4k)
16k
构成:(1 + 11 + 11 + 11)+ 14(16k)
64k
构成:(6 + 13 + 13) + 16(64k)
ttbr0,ttbr1
arm64有两套页表,分别是ttbr0、ttbr1;
- ttbr0:存放的是0x000_xxxxx开头的虚拟地址的页表基地址
- ttbr1:存放的是0xffff_xxxx开头的虚拟地址的页表基地址
当映射一个虚拟地址的时候选择ttbr0还是ttbr1由mmu硬件自动完成;
页表描述符
l0~l2
- 无效页表项:
- 块类型:存放了最终的物理地址;
- 粒度4k:存放2M连续的物理地址
- 粒度16k:存放32M连续的物理地址
- 还包括低位属性,高位属性
- 页表类型:存放了指向下一级页表的基地址;
l3
- 包含输出地址,pfn;
- 低位属性,高位属性
属性
页表描述符中提到了高位属性,和低位属性;这些属性常见的有:
1 共享性与缓存性:
缓存性就是是否带有cache属性;
那什么是共享性呢:多核处理器系统中某一个内存区域的高速缓存可以被哪些观察者看到,(类似cache中的poc,pou)
- 没有共享性:只有本地CPU能观察
- 内部共享:内部共享的CPU的观察
- 外部共享:能被外部共享的观察者观察到。比如CPU&&GPU(外部ip)&&DMA
dma-coherent就是利用这里修改的(待找代码确认)
2 访问权限
就是读写权限;
比如进程创建的缺页中断写时复制,就利用了这个特性;将页表项设置为只读属性;(确认实际的代码页表确认)
3 执行权限
4 访问标志位
5 全局和进程特有tlb
硬件管理访问与脏位
之前访问位与脏位是通过软件机制中的缺页中断进行管理;
硬件管理访问位与脏位的意思就是由硬件去自动更新;
相关寄存器
tcr
sctlr
ttbr
内存属性
1 普通内存
2 设备内存
- G:聚合
- R:指令重排
- E:提前写应答:(这个写应答的具体作用是?)
- 往设备写数据的过程是:1写入缓冲区,2往外部设备写;是能了提前写应答当达到缓冲区时就会发生写应答;
内存属性
与缓存有关,放在MMAIR寄存器中;
ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \MAIR(0x04, MT_DEVICE_nGnRE) | \MAIR(0x0c, MT_DEVICE_GRE) | \MAIR(0x44, MT_NORMAL_NC) | \MAIR(0xff, MT_NORMAL) | \MAIR(0xbb, MT_NORMAL_WT)msr mair_el1, x5
页表项中使用AttrIndx[2:0]作为索引来索引这些内存属性;
如何理解AttrIndx与MMAIR
- 如下配置的前提下:
ldr x5, =MAIR(0x44, MT_NORMAL_NC) | \MAIR(0xbb, MT_NORMAL_WT)msr mair_el1, x5
比如设置MT_NORMAL_NC,就代表使用0x44吗?
使用MT_NORMAL_WT,就代表使用0xbb吗?
- 如果是:
ldr x5, =MAIR(0xbb, MT_NORMAL_NC) | \MAIR(0x44, MT_NORMAL_WT)msr mair_el1, x5
比如设置MT_NORMAL_NC,就代表使用0xbb吗?
使用MT_NORMAL_WT,就代表使用0x44吗?
也就是说mair_el1形成了一张表,可以理解为一个数组,数组中的成员是软件可配置的;
页表属性的AttrIndx对应到这个数组的成员中
恒等映射
如何理解页表创建
首先正向看:
ttbr对应的基地址
+pgd的index
,可以得到一个地址;这个地址的内容存放的是pud的地址
;pud的地址
+pud的index
,可以得到一个地址;这个地址的内容存放的是pmd的地址
;
以这两个为例,从C语言的角度看,就是地址里面存放了一个内容,这个内容其实又是一个地址;
由于64为系统,unsigned long long
的大小就是指针
的大小,就进行了替换;
所以创建页表就是往地址的内容里面填地址;
pud_phys = alloc_pgtable(); /* 分配pud的地址,这是一个物理地址 */set_pgd(pgdp, __pgd(pud_phys | PUD_TYPE_TABLE)); /* 把pud的物理地址设置给pgd */