"); //-->
前面主要讲解了MIPS MMU的一些作用以及一些基本概念,现在具体讲解一下MMU的地址转换,先说一下可能提到的几个寄存器,暂且以4K经典的Page Size为例(下面的图片部分来自See MIPS Run):
1、MMU的输入是8K的虚拟空见(4K为例,如何是16K Page Size,就是32K),输出是一对物理页面。
2、VPN2(虚拟页面号除2):代表2个页。Tag比较时,VPN<31:25>总是参加比较,VPN<24:13>是否参加比较由PageMask寄存器决定。
3、G:全局位决定ASID是否参加比较。G=1,ASID不参加比较;G=0,ASID参加比较。G位是CP0寄存器EntryLoO和Entryl_ol逻辑与的结果。
4、PageMask寄存器是一个用来读或写TLB的读/写寄存器。它通过按项比较的屏蔽,实现可变的页长
应该明白如何Get到虚拟页号,MMU实际最主要就是地址转换,现在看看是如何转换的:
上面提到了一个TLB概念,小插曲讲解一下TLB东西:
TLB就是一个表连接VPN和PFN,一端是VPN,一端是PFN,可以由VPN找到PFN然后重新填写,就是页表的子集,一般可以存放32-64条。
TLB的读和写操作使用这一寄存器作为源或者目标。当虚拟地址进行转换时,根据页面大小(4K),由TLB中相应位指定虚拟地址<24:13>中的那些位来参加比较
ITLB全相联TLB,用来产生指令流的物理地址,它的页面是固定的4K。ITLB是通过硬件来管理的,对软件而言是透明的。当计算出一个指令地址时,将这个虚拟地址和ITLB的内容进行比较,如果没有在ITLB中找到该地址,我们称之为ITLB缺失,将在下一个时钟周期到JTLB中去查找,如果该地址在JTLB中找到,我们称之为命中,那么就会对ITLB进行回写,这时会重新在ITLB中进行比较,产生物理地址。由此可见,ITLB缺失至少花费2个时钟周期,如果此时JTLB忙(或者不命中),那么将花费更多的时间。
DTLB全相联TLB。能够比JTLB更快的产生LOAD/STORE类的地址。和ITLB类似,DTLB的页面也是固定的4K;也是通过硬件来管理,对软件是透明的,和ITLB不同的是,当转换LOAD/STORE类地址时,是在DTLB和JTLB中同时查找,如果DTLB缺失而JTLB命中,那么在当前这个周期,数据就会回写进DTLB。DTLB命中,就会产生物理地址,这种并行处理的方式,将会缩短DTLB缺失的时间损失
中间有几个与TLB相关的寄存器说明一些:
Index 寄存器用来挑选一个具体的TLB表项,取值从0到TLBSIZE-1, 当有意要读写那一条具体的数据项的时候,需要设置Index,当你用tlnp搜索一个TLB表项时Index会自动设置,Index的低位保存TLB的索引
Random寄存器存储着一个计数CPU执行每条指令的的TLB索引,主要是使用tlbwr指令时候可以随机替换
Wried寄存器是一个边界值,就是保护多少条TLB表项不被使用随机替换,如果它里面的保存的是10,就说明如果随机替换时仅仅替换1 --- (TLBSIZE - 1)
现在可以说一下VA到PA的转换:
VA以页表大小取余,得到PA的低位,关键是PA的高位(PFN)如何得到。内存中存放着页表,页表记录的是VPN到PFN的对应关系(一般可能会分为多级页表),以VPN查询页表即可获得PFN。
为了加速这个查询,引入了TLB,TLB记录的是一个内存页表的一个子集,相当于是内存页表的缓存。所以MMU在以VPN索引先在TLB中查找页表,如果查询TLB miss则会产生异常,由异常处理程序进行地址转换。
虚拟地址转换为物理地址过程为:
虚拟地址的高位(VPN)和当前程序的ASID送给TLB,与TLB中的所有entry表项进行匹配,匹配过程中如果有如下都满足的TLB表项,从中读取PFN, V, D域
1.当前程序(进程)的ASID等于TLB表项中的ASID(EntryHi的G bit置位的话,不比较ASID)
2.虚拟地址的bit63~62与TLB表项的R字段相同
3.虚拟地址的相应位域和TLB的VPN2相同,相应位域取决于PageMask寄存器设置的页表大小
注意最终转换是否成功取决于V, D域。如果V无效,该entry无效,产生TLB无效异常;如果D指示不可写,而有写操作会产生TLB修改异常。
如果没有上述异常,即是TLB命中,命中entry的PFN和虚拟地址低位(1KB page是低10bit,4KB page低12bit)构成最终的物理地址。
完整的地址译码过程(4KB page):
1:将cpu访问的地址去掉底12位,生成VPN,然后加上ASID一起组成一个TLB入口键值。
2:TLB内部进行匹配,匹配成功,将输出值的PFN和地址的底12位组合构成完成的物理地址。
3:判断该物理地址的特性,验证V,D项,如果V= 0,或者D=0 (不可写)并且操作是写操作的时候会引发其他的异常, BadVaddr会将该地址装入。
4:判断该物理地址是否被缓存,如果缓存了,可以从cache中读取,但如果cache不明中,到内存中读完之后,还要留一份拷贝给cache;如果没有被缓存,那么跟cache不沾边。
但是当TLB缺失异常的时候,需要做一下事情:
1:根据Context寄存器中内容指的也表项去看是否存在一个有效的转换。如果还不存在,就表示发生了嵌套的TLB异常,那么则转入到通用的异常处理函数中。
2:如果存在正确的地址转换,那么在TLB内部创建一个实现此译码的TLB入口。
3:选择一个可以丢弃的TLB入口,一般用tlbwr 即可。
注:发生双重异常的时候,不会改变异常返回寄存器EPC的值。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。