买了本SEE MIPS RUN LINUX 的中文版,翻译的句子狗屁不通,什么玩意儿。第一章就看不下去,越到关键的地方越读不通。
http://hi.baidu.com/comcat/blog/item/c6f4f909cf551bc53ac76359.html
1. 概述
分支延迟槽 (Branch delay slot),简单地说就是位于分支指令后面的一条指令,不管分支发生与否其总是被执行,而且位于分支延迟槽中的指令先于分支指令提交 (commit)。
看这个代码片段 (MIPS Linux kernel 2.6.17):
801ea9d4: 02202021 move a0,s1
801ea9d8: 27a50014 addiu a1,sp,20
801ea9dc: 0c0ce551 jal 80339544 <pcibios_resource_to_bus>
801ea9e0: 02403021 move a2,s2
801ea9e4: 8e240010 lw a0,16(s1)
…
MIPS ABI 规定,a0, a1, a2, a3 用于过程调用的前四个参数,则 move a2, s2 是置第 3 个参数,但是其位于函数调用指令 jal 80339544(分支指令)之后,这个 move a2, s2 所在地即为一个分支延迟槽。
分支延迟槽在 DSP 和历史较悠久的 RISC 上比较常见,如 MIPS, SPARC 等。PowerPC 和 ARM 上则没有这个概念。x86 亦没有。
2. 缘起
引入分支延迟槽的目的主要是为了提高流水线的效率。
流水线中,分支指令执行时因为确定下一条指令的目标地址(紧随其后 or 跳转目标处?)一般要到第 2 级以后,在目标确定前流水线的取指级是不能工作的,即整个流水线就“浪费”(阻塞)了一个时间片,为了利用这个时间片,在体系结构的层面上规定跳转指令后面的一个时间片为分支延迟槽(branch delay slot)。位于分支延迟槽中的指令总是被执行,与分支发生与否没有关系。这样就有效利用了一个时间片,消除了流水线的一个“气泡”。
这种技术手段主要用在早期没有分支预测的流水线 RISC 上,现代 RISC 实现早就可以在流水线的第 2 级利用分支预测确定跳转的目标,分支延迟槽也就失去了原来的价值,但为了软件上的兼容性 MIPS 和 PowerPC 还是作了保留。
===============================
Q2:为什么延迟槽异常返回地址是上一条指令的地址
A2:
简单说,一般CPU的分支跳转指令流是:分支跳转指令->目标跳转地址的指令。
但MIPS的分支跳转指令流是:分支跳转指令 -> 延时槽指令 -> 目标跳转地址的指令,在中间操作插入了延时槽指令。
如果PC在延时槽地址中断后,中断返回时返回延时槽指令地址的话,重新执行的指令流为:延时槽指令 -> (延时槽指令地址 + 4)地址的指令,没有跳转了!
这样完全不是原来被打断的指令流,为了恢复原来的指令流需要将延时槽前面的跳转指令重新装入流水线。
所以在延时槽中断后返回的地址是前面跳转指令的地址。
Q4:ASID是否真的全部有效,虚拟地址是如何进行地址翻译的
A4:
1) 当G位为1时,不再检查ASID字段即是ASID字段无效。进程间共享内存实现应该是靠这个G位。
2) 虚拟地址翻译过程:
将虚地址页号和进程的ASID给MMU
MMU查找所有TLB项是否有匹配项,匹配过程如下(假设PageMark):
先匹配EntryHi,若VPN2相等而且ASID相等或G位为1,匹配则根据页表的最低位取出EntryL0(LSB位为0)或EntryL1(LSB位为1),不匹配则抛出TLB缺失异常。
接着匹配EntryLx,如果v位为零抛出TLB无效异常,如果d位为零而且是写操作则抛出TLB修改异常,OS应该是利用这个实现写是拷贝。
最后将EntryLx中的PFN和虚地址的页内偏移组合成实际的物理地址。
Q5:如何把虚拟地址连续但物理地址不连续的两个页放到到同一个TLB项中
A5:
当进程申请两个连续的虚拟页时,其对应的物理页可能是连续的也可能是不连续的。同时在内存中新建一个页表项。
当在有这段虚拟地址范围的地址需要翻译时,将该页表项从内存调入TLB中。
对于Linux kenerl由于采用写时拷贝策略,申请虚拟页面时并没有即可分配对应的物理页面,如前面QA4所述。
Q6:TLB项中的C字段有什么作用
A6:
根据See MIPS Run 2nd的描述,应该是用于处理多处理器Cache同步问题,原文如下
A 3-bit field originally defined for cache-coherent multiprocessor
systems to set the “cache algorithm”
Q7:影子寄存器堆作用
A7:
一般的CPU在中断处理程序开始之前需要保存CPU的上下文及CPU的寄存器。
MIPS提供了硬件的寄存器组堆栈,可以设置CPU在进入中断时使用新的寄存器组,节省了一般CPU将寄存器组保存在软件堆栈的过程,缩短中断处理程序的时间。
Q8:EXL和ERL的不同
A8:
个人理解,EXL主要是逻辑上引起的,比如:各种TLB异常等。
ERL主要是物理错误引起的,比如cache检验错误等。