查看64位多核 MIPS 异常和中断内核代码分析 (1)的源代码
←
64位多核 MIPS 异常和中断内核代码分析 (1)
跳转到:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
==== EXL=1 时 TLB Refill 的处理 ==== EXL=1 时,TLB Refill 进的是其他例外入口下 TLB Invalid 异常处理函数,TLB Invalid 分两类异常,一个是读数据引发的 (ExcCode=2, 处理函数 handle_tlbl),一个是写数据引发的 (ExcCode=3, 处理函数是 handle_tlbs)。 位于其他例外入口处的处理函数 except_vec3_generic 只是根据 ExcCode 跳转到具体例外的处理函数,TLB Load Invalid 进入 handle_tlbl;TLB Write Invalid 进入 handle_tlbs。这两个函数也是动态生成。 <br><br> ===== Cavium Octeon handle_tlbl 分析 ===== handle_tlbl (位于代码段,不受向量空间限制。从其它例外入口进入): <source lang=c> c: 403a4000 dmfc0 k0,c0_badvaddr 10: 001ada3e dsrl32 k1,k0,0x8 # 失败地址右移 40 位 14: 17600032 bnez k1,e0 <0xe0> # 40 位外不为 0 则跳转。不管CPU 具体实现了多少位的虚拟地址,对内核来讲 40 位外不为 0 都是异常地址,需要小心处理 18: 403b2000 dmfc0 k1,c0_context 1c: 7c1bb007 dins k1,zero,0x0,0x17 20: 377b0540 ori k1,k1,0x540 24: 003bdafa dror k1,k1,0xb # 以上四条指令是为:k1 = 0xA800 0000 0000 0000 + PGD_Phy,即使用一个固定映射的虚址访问 PGD 28: 001ad6fa dsrl k0,k0,0x1b # k0 里放的是 c0_badvaddr 2c: 335a1ff8 andi k0,k0,0x1ff8 # PGD offset 30: 037ad82d daddu k1,k1,k0 # PMD base addr 34: 403a4000 dmfc0 k0,c0_badvaddr 38: df7b0000 ld k1,0(k1) 3c: 001ad4ba dsrl k0,k0,0x12 40: 335a0ff8 andi k0,k0,0xff8 # PMD offset 44: 037ad82d daddu k1,k1,k0 # get PT base addr 48: 403a4000 dmfc0 k0,c0_badvaddr 4c: df7b0000 ld k1,0(k1) 50: 001ad27a dsrl k0,k0,0x9 54: 335a0ff8 andi k0,k0,0xff8 # PT offset 58: 037ad82d daddu k1,k1,k0 # index PT 5c: d37a0000 lld k0,0(k1) # get PTE 60: 42000008 tlbp # 查找失效地址 VA1 对应之 TLB 项,有则将 index 写入 cp0_index,无则将 cp0_index[31] = 1;注意所有 TLB 相关的异常 (Refill, Invalid, Modified) 出现时,CPU 都会把失效地址的高位置入 EntryHi[VPN2] 64: 335a0001 andi k0,k0,0x1 68: 13400020 beqz k0,ec <0xec> # 判断 PTE 的最低位 _PAGE_PRESENT,为 0 表示该页未分配或未在内存,则跳转到 do_page_fault() 处理。此应是 EXL=1 TLB Miss 的在此的主要路径,进入这里的 TLB Miss,多数情形是页面尚未分配,在 TLB Miss 的处理中,索引 PT 失败。经此一路,在 do_page_fault() 中,系统会为其分配页面,填充页表项,往下就不会是页面尚未分配的情形 注意,tlbp 失败只能是失效地址对应页表没有分配或不在内存(交换出去);往下 tlbp 不可能是其失败的情形,如果失效地址有页表项(有效无效皆可),其也不会在 TLB Miss 中再次 TLB Miss 另外 tlbp 失败会将 cp0_index[31] = 1,这个值远远大于现代 MIPS 实现的 TLB 项数目,随后来一条 tlbr 的话,其结果未定义! 6c: d37a0000 lld k0,0(k1) # 该页已分配,get PTE again 70: 335a0080 andi k0,k0,0x80 74: 13400008 beqz k0,98 <0x98> # 判断 PTE 的 _PAGE_VALID 位,为 0 表示该页无效,跳转。失效地址对应的页表项无效,其就不是 EXL=1 TLB Miss 引起的了,应为 TLB Invalid 异常 78: 00000000 nop # 页表项有效 7c: 42000001 tlbr # 读 TLB,cp0_Index 对应 TLB 项存入 EntryHi, EntryLo0/1, PageMask 80: 337a0008 andi k0,k1,0x8 # k1 为页表项指针,此为判断奇偶页操作 84: 13400002 beqz k0,90 <0x90> # 奇数项则跳转 88: 403a1000 dmfc0 k0,c0_entrylo0 # 延迟槽,总是被执行。取奇数页在 TLB 中的值 8c: 403a1800 dmfc0 k0,c0_entrylo1 # 偶数项 90: 335a0002 andi k0,k0,0x2 # TLB 项之 V 位 94: 17400015 bnez k0,ec <0xec> # 不为 0(有效)则跳转到 do_page_fault() 处理。这是一个奇怪的现象,能找到失效地址对应的TLB项(非 EXL=1 TLB Refill),页表项目有效(非空 PTE),且对应的 TLB 项亦有效(非 TLB Invalid),应由 do_page_fault() 进一步甄别 # 失效地址对应之页表项无效 (V=0);或者对应页表项有效,却 TLB 项无效 (V=0) 98: d37a0000 lld k0,0(k1) # 再取 PTE 9c: 375a0084 ori k0,k0,0x84 # 置 _PAGE_VALID 和 _PAGE_WRITE a0: f37a0000 scd k0,0(k1) # 更新页表项 a4: 1340ffed beqz k0,5c <0x5c> # k0=0 则事务操作失败,重做 a8: 00000000 nop ac: 377b0008 ori k1,k1,0x8 b0: 3b7b0008 xori k1,k1,0x8 # 重置页表项指针,使其重新指向失效地址对应之奇数项 b4: df7a0000 ld k0,0(k1) # 以下操作取失效地址的页表项,填充 TLB,分析同 TLB Refill b8: df7b0008 ld k1,8(k1) bc: 001ad13a dsrl k0,k0,0x4 c0: 001bd93a dsrl k1,k1,0x4 c4: 003ad0ba dror k0,k0,0x2 c8: 40ba1000 dmtc0 k0,c0_entrylo0 cc: 003bd8ba dror k1,k1,0x2 d0: 40bb1800 dmtc0 k1,c0_entrylo1 d4: 42000002 tlbwi # 写入 Index 指定的 TLB 入口中 d8: dc1a8078 ld k0,-32648(zero) dc: 42000018 eret # 40位外有货,地址异常 ,需要小心对待 e0: 3c1b817c lui k1,0x817c e4: 1000ffd0 b 28 <0x28> # k1 = 0xFFFF FFFF 817B E000, it's swapper_pg_dir e8: 277be000 addiu k1,k1,-8192 ec: 08441380 j 1104e00 <0x1104e00> # jump to tlb_do_page_fault_0, call do_page_fault(not write) f0: 00000000 nop ... </source> <br><br> ===== Cavium Octeon handle_tlbs 分析 ===== handle_tlbs (位于代码段,不受向量空间限制): <source lang=c> c: 403a4000 dmfc0 k0,c0_badvaddr 10: 001ada3e dsrl32 k1,k0,0x8 14: 17600028 bnez k1,b8 <0xb8> 18: 403b2000 dmfc0 k1,c0_context 1c: 7c1bb007 dins k1,zero,0x0,0x17 20: 377b0540 ori k1,k1,0x540 24: 003bdafa dror k1,k1,0xb 28: 001ad6fa dsrl k0,k0,0x1b 2c: 335a1ff8 andi k0,k0,0x1ff8 30: 037ad82d daddu k1,k1,k0 34: 403a4000 dmfc0 k0,c0_badvaddr 38: df7b0000 ld k1,0(k1) 3c: 001ad4ba dsrl k0,k0,0x12 40: 335a0ff8 andi k0,k0,0xff8 44: 037ad82d daddu k1,k1,k0 48: 403a4000 dmfc0 k0,c0_badvaddr 4c: df7b0000 ld k1,0(k1) 50: 001ad27a dsrl k0,k0,0x9 54: 335a0ff8 andi k0,k0,0xff8 58: 037ad82d daddu k1,k1,k0 5c: d37a0000 lld k0,0(k1) 60: 42000008 tlbp 64: 335a0003 andi k0,k0,0x3 68: 3b5a0003 xori k0,k0,0x3 6c: 17400015 bnez k0,c4 <0xc4> # 失效地址对应之页表项无效 (V=0);或者对应页表项有效,却 TLB 项无效 (V=0) 70: d37a0000 lld k0,0(k1) 74: 375a018c ori k0,k0,0x18c # 置 _PAGE_VALID, _PAGE_DIRTY, _PAGE_WRITE, _PAGE_ACCESSED 78: f37a0000 scd k0,0(k1) 7c: 1340fff7 beqz k0,5c <0x5c> # 事务失败,重做 80: 00000000 nop 84: 377b0008 ori k1,k1,0x8 88: 3b7b0008 xori k1,k1,0x8 8c: df7a0000 ld k0,0(k1) 90: df7b0008 ld k1,8(k1) 94: 001ad13a dsrl k0,k0,0x4 98: 001bd93a dsrl k1,k1,0x4 9c: 003ad0ba dror k0,k0,0x2 a0: 40ba1000 dmtc0 k0,c0_entrylo0 a4: 003bd8ba dror k1,k1,0x2 a8: 40bb1800 dmtc0 k1,c0_entrylo1 ac: 42000002 tlbwi b0: dc1a8078 ld k0,-32648(zero) b4: 42000018 eret b8: 3c1b817c lui k1,0x817c bc: 1000ffda b 28 <0x28> # k1 = 0xFFFF FFFF 817B E000, it's swapper_pg_dir c0: 277be000 addiu k1,k1,-8192 c4: 084413c8 j 1104f20 <0x1104f20> # jump to tlb_do_page_fault_1, call do_page_fault(write) c8: 00000000 nop cc: 00000000 nop </source> 除标出的外,其它与 handle_tlbl 同 <br><br> ===== RMI XLR732 handle_tlbl 分析 ===== <source lang=c> handle_tlbl: c: 403a4000 dmfc0 k0,c0_badvaddr <---- handle_tlbl start 10: 07400027 bltz k0,b0 <0xb0> # if badvaddr >= 0x80000000 00000000 branch 14: 403b2000 dmfc0 k1,c0_context 18: 001bddfa dsrl k1,k1,0x17 /* get (smp_processor_id() << 3) (26-23) */ 1c: 3c1a8396 lui k0,0x8396 /* 0xffffffff83960000 + 0x2000 = pgd_current */ 20: 037ad82d daddu k1,k1,k0 24: 403a4000 dmfc0 k0,c0_badvaddr 28: df7b2000 ld k1,8192(k1) /* pgd = pgd_current[smp_processor_id()] */ @@ 2c: 001ad6fa dsrl k0,k0,0x1b # >> 27 30: 335a1ff8 andi k0,k0,0x1ff8 /* get (vaddr[39:30] << 3), for indexing pgd */ 34: 037ad82d daddu k1,k1,k0 /* index pgd */ 38: 403a4000 dmfc0 k0,c0_badvaddr 3c: df7b0000 ld k1,0(k1) /* get pmd */ 40: 001ad4ba dsrl k0,k0,0x12 # >> 18 44: 335a0ff8 andi k0,k0,0xff8 # get (vaddr[29:21] << 3) 48: 037ad82d daddu k1,k1,k0 # index pmd 4c: 403a4000 dmfc0 k0,c0_badvaddr 50: df7b0000 ld k1,0(k1) # get p_pt 54: 001ad27a dsrl k0,k0,0x9 58: 335a0ff8 andi k0,k0,0xff8 # get (vaddr[20:12]) 5c: 037ad82d daddu k1,k1,k0 # index pt 60: d37a0000 lld k0,0(k1) # get pt entry 64: 42000008 tlbp # to distinguish TLB invalid or TLB refill exception 68: 335a0003 andi k0,k0,0x3 6c: 3b5a0003 xori k0,k0,0x3 # _PRESENT and _READ 70: 1740001a bnez k0,dc <0xdc> # low two bits is not 011, branch @@-->out 74: d37a0000 lld k0,0(k1) # get pt entry again 78: 375a0088 ori k0,k0,0x88 7c: f37a0000 scd k0,0(k1) # set pt entry's pte[7] = 1, pte[3] =1 80: 1340fff7 beqz k0,60 <0x60> 84: 00000000 nop 88: 377b0008 ori k1,k1,0x8 8c: 3b7b0008 xori k1,k1,0x8 # for getting even page 90: df7a0000 ld k0,0(k1) # get even page addr 94: df7b0008 ld k1,8(k1) # get odd page addr 98: 001ad1ba dsrl k0,k0,0x6 9c: 409a1000 mtc0 k0,c0_entrylo0 a0: 001bd9ba dsrl k1,k1,0x6 a4: 409b1800 mtc0 k1,c0_entrylo1 a8: 42000002 tlbwi ac: 42000018 eret @@ b0: 001ad8b8 dsll k1,k0,0x2 # go here, vaddr is in xkphys or xkseg (>0x8000..0000) # 0x8000..0000 ~ 0xc000..0000 is xkphys, unmapped, # so vaddr > 0xc000..0000; vaddr << 2 b4: 07610005 bgez k1,cc <0xcc> # vaddr[61] != 1 (0xc000..0000 ~ 0xdfff..ffff), branch b8: 3c1bc000 lui k1,0xc000 # vaddr, 0xe000..0000 ~ 0xffff..ffff bc: 035bd02f dsubu k0,k0,k1 # k0 = vaddr - 0xffffffffc0000000 c0: 3c1b8396 lui k1,0x8396 c4: 1000ffd9 b 2c <0x2c> c8: 277ba000 addiu k1,k1,-24576 # k1 = 0xffffffff8395a000, module_pg_dir # module_pg_dir & swapper_pg_dir don't need the smp @@ # vaddr, 0xc000..0000 ~ 0xdfff..ffff cc: 001bd83c dsll32 k1,k1,0x0 # 0xc0000000 00000000 d0: 035bd02f dsubu k0,k0,k1 # k0 = vaddr - 0xc0000000 00000000 d4: 1000ffd5 b 2c <0x2c> d8: 3c1b8396 lui k1,0x8396 # only swapper_pg_current @@-->do_page_fault dc: 08d01150 j 3404540 <0x3404540> e0: 00000000 nop ... </source> <br><br>
返回到
64位多核 MIPS 异常和中断内核代码分析 (1)
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面