全部博文(4)
分类: LINUX
2008-10-22 17:39:39
映射机制的本质:是一个程序能够判断出其使用的某个地址是否在自己的地址空间,并且迅速找出相对应的物理地址。
简单来说就是V ADD-〉P ADD的过程。
但是mips中,tlb不命中充填的过程不是由硬件来完成的,因此需要软件来做。
也就是当发现一个无法译码的地址的时候,就触发一个TLB重装异常,然后由程序作剩下的事情。
由此可以看出,其实转换得过程就是一个输入键值(V ADD)和一个输出值(P ADD),
而mips里有以下几个寄存器来装载这些东西。
EnrtyHi寄存器包含 V ADD的VPN,ASID,PageMask。对应键值。
EntryLo寄存器包含输出值:P ADD的PFN,N/C,D,V等控制位。用来描述和控制该物理地址的。
ASID:这个值是操作系统用来识别当前进程的地址空间,它*不会*被 *异常* 改变, 所以当发生tlb重装异常的时候,他依旧标识着当前进程的信息。??那么中断呢?
N/C: 是否被缓存, 32位的使用的是N(Noncacheable)置一表示不用缓存,0表示用。总之如果TLB匹配出的物理地址的N位表示使用缓存的时候,cpu就到cache中去找该物理地址中的数据,发现如果cache里面没有,再从内存里找,并且要留一份拷贝到cache中。
如果标志不使用缓存,那么就不跟缓存打交道。也不负责缓存的回写。
V:是否有效。如果是0, 则相应得物理地址时不能使用的。TLB初始化的时候需将v清0。
D:是否允许数据写入。 置一表示相应地址可写。
另外还有几个tlb内部的寄存器。
l Index寄存器:当使用tlb指令读写tlb入口的时候,就读取更改index对应的那个tlb入口。
Index的有效域表示了该cpu支持的最大tlb入口数。
l Random寄存器:仅在tlbwr指令时使用,目的是随机替换一个tlb。节约tlb重装的时间,仅此而已。
Index寄存器初值是最大,即tlb入口个数。然后随着每条指令的执行而递减,当到某一个值A 的时候,就重新置到最大值重复着一过程。目的是保护index为0----A-1 的tlb不会被随机替换策略换出。 在32上A的值是不能改的。 而64位增加了个wired寄存器来更改此值。
l Context寄存器:用来加速tlb的重装入。
当tlb缺失异常发生的时候,导致异常的V ADD已经被装入了BadVAddr,并且VPN都已经装入了EntryHi的相应域,这显然已经作了很多事情了, 但是Context寄存器更深一步,将常驻内存页表的基地址的高位,异常地址的VPN都放入到了context寄存其中。
l PageMask:用来支持不同页大小的tlb入口。
假设我们现在需要映射的内存体系是以16k为一页的,那么我们现在VPN即虚页号,还是忽略底12位。按照4k来,PFN也如此。 但是这是就用上PageMask 了。我们此时需要将PageMask的有域的底两位置一。 Tlb匹配的是活就直接将VPN的底两位这忽略掉直接拷贝到PFN上了。这就实现了16k页面的匹配。
MMU的控制指令:
Tlbr: (tlb read ) 会根据index来读tlb表项。
注意:此指令会覆盖整个EntryHi,所以之后还需要重新写入正确的当前ASID值。
Tlbwi: (tlb write by index) 根据index来写tlb表项。
Tlbwr: (tlb write by radom) 对radom寄存器选中的tlb表项进行写操作
注:一般tlbwr被用在tlb冲撞异常处理中写入一个新的tlb表项。 其他任何情况都是用tlbwi
Tlbp: (tlb prob) 在tlb中查找VPN, ASID 都跟EntryHi寄存器中的相应域匹配的入口,并把相应表项的索引值存入index寄存器。如果匹配失败,那么将index的P位(最高为)置一。
注:1:tlb指令不能从tlb中预取数据, 必须在其后运行tlbr才可以实现。
2:tlb内部是流水化的,因此在tlbp指令之后,不能紧跟读取和存储的操作。
完整的地址译码过程:
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的值。