ARM架构中MMU的做用主要就是将CPU发出的虚拟地址转换成为物理地址,从实现内核和用户程序和用户程序之间的虚拟地址空间隔离。MMU的主要组成为两部分,其一是内部的TLBs缓存;还有就是转换表装换单元。CPU发出虚拟地址会被MMU拦截从而进行地址转换,地址装换过程优先查询MMU内部的Cacha是否有现成的转换条目。若是有则直接映射出物理地址,不然须要转换单元按配置的方式和装换表进行地址装换以获得物理地址,若是成功装换虚拟地址到物理地址则MMU还会新建这-条目。转换后的物理地址就能够被总线拿来访问物理内存了,不过在物理存储以前还须要查询对应的Cacha是否有当前地址的数据的缓存,由于真正的物理存储的访问速度相对于处理器的处理速度是十分缓慢的。若是在cacha中命中了对应的数据则省去了去访问外部存储的时间,反之则须要访问外部存储获取数据,而后更新cacha-----利用程序地址空间局限性提升cacha的命中率。缓存
在启用MMU以前必须先创建好MMU转换须要的转换表,并经过协处理器的特殊寄存器保存转换表的基址。转换表不一样的系统的实现方式不一样。MMU的映射是以页为单位的,不一样的页面size转换是的方式略有差异可是本质的原理流程通用。须要注意的是大的页size能提升TLB的命中率,可是会形成内存的浪费。小的页面能更好的控制内存访问属性和节省内存,可是TLB的命中率就会比较低。架构
TLB的结构大体以下
TAG [ASID] DESCRIPTION
VA [ASID] PA + Attributes
VA [ASID] PA + Attributes
VA [ASID] PA + Attributes
.
.
.spa
使用后SID的缘由是避免应用程序在TLB中的转换条目没法区分的问题,由于用户空间程序的虚拟地址空间都是相同的在TLB中使用ASID进行区分。TLBs中的缓存可能存在过时的状况,若是系统软件修改了装换表,此时应该经过对应的协处理器指令使对应的TLB条目无效,或者粗犷一点直接使全部的装换条目无效。进程
常见的转换过程有不少种这里说一下两级4K页的转换过程:内存
两级页面的映射须要两级页表,第一级页表的页面项保存看二级页表的基址,二级页表项加虚拟地址低12bits 描述看物理页面和页面属性。拿一个32位的4K页面的系统来讲虚拟地址将分为三个位域,其中最低12位做为业内偏移,余下的20位如何划分取决于实现可按10和10的分法分配,即最高10bits用来表示一级表项在一级页表的偏移,中间10bits则表示二级页表的目录项偏移。一级页表的基址保存在协处理器的基址寄存器中一共有两个TTBR0/1,若是按32位4G空间的映射的话,则一级页表有1024个目录项每个占四个字节,二级表项每个也有1024个表项每个也一样占4个字节。这样下来转换表总共占的内存空间是1024*4+1024*1024*4 < 4.1M的物理内存空间。因此如何安排32位虚拟地址到物理地址之间的映射讲决定装换表所占的内存空间。仔细查上面的页表大小和处理器的要,arm内核要求一级页表必须是对其在16K字节边界上,而二级页表的大小是4K天然也是对其到4K的边界上方便访问,因此一级页表项和二级页表项的低12位必定是为0的,鉴于此低12位就被用来,就被用来描述对应映射到的内存空间的属性信息,这样一级页表项的属性描述的就是4M的物理地址空间的内存属性;进而二级页表项描述的就是一个页的属性。属性主要由权限位和访问属性、缓存属性等信息。it
为何内核硬件上会实现两个装换表基址寄存器TTBR0和TTBR1呢?原理
使用两个转换表基址寄存器是为了节省内存,避免16K的L1转换表存在N个副本。由于每一个进程的装换表中都包括了部份内核的地址空间映射,一般内核区域的映射都是固定不变的因此避免每一个进程都重复创建内核部分的地址映射才出现了两个装换表基址寄存器。使用TTB控制寄存器配置虚拟地址最高N个bit都为0时使用TTBR0不然使用TTRB1,这样就能区别使用内核空间或用户空间装换转表基址。假如配置N为7则虚拟地址低32M空间使用TTBR0,如Linux就将其配置为2因此,低0-1G的内核空间使用TTBR0,用户空间使用1-4G的3G虚拟内存空间使用TTBR1。软件
这里随便一条心得:Linux 自旋锁能够采用WFE和SEV配合以下降功耗。配置