查看64位多核 MIPS 异常和中断内核代码分析 (1)的源代码
←
64位多核 MIPS 异常和中断内核代码分析 (1)
跳转到:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
===== Cavium Octeon ===== 这个的处理函数,在 Cavium Octeon 上位于 0xFFFF FFFF 8000 1080 处,但往往这个处理函数都会超过 0x80 字节,所以动态生成过程就使用原来 32 位的入口空间再放一部分代码,在 64 位下,这个 32 位的 TLB Refill 入口空间是不用的: <source lang=c> 0xFFFF FFFF 8000 1000: c: 07410003 bgez k0,1c <0x1c> # badvaddr >= 0,即 badvaddr 低 40 位以上有货,最高位不为 1,即在 0x0 ~ 0x7FFF FFFF FFFF FFFF (xuseg or xsseg) 中时则跳转。一句话就是去处理位于 xuseg or xsseg 的异常地址 10: 3c1b817c lui k1,0x817c # 位于延迟槽,总是被执行。0xFFFF FFFF 817c 0000 #badvaddr低 40 位以上不为 0 且不位于 xuseg 或 xsseg 中,又走 TLB,则其应为位于 xkseg,范围为 0xC000 0000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF。一句话就是去处理位于 xkseg 中的地址 14: 10000024 b a8 <0xa8> ----->@@@ k1 = 0xFFFF FFFF 817B E000, it's swapper_pg_dir, 他是内核使用的除模块以外的 PGD 基地址,内核模块使用 18: 277be000 addiu k1,k1,-8192 # 位于延迟槽,总是被执行。0xFFFF FFFF 817c 0000 - 8192 = 0xFFFF FFFF 817B E000 #badvaddr 低 40 位以上不为 0 且位于 0x0 ~ 0x7FFF FFFF FFFF FFFF ( xuseg or xsseg) 1c: 3c1b8110 lui k1,0x8110 20: 277b4e00 addiu k1,k1,19968 # k1 = 0xFFFF FFFF 8110 4E00, tlb_do_page_fault_0 24: 03600008 jr k1 # call tlb_do_page_fault_0 28: 00000000 nop ... 0xFFFF FFFF 8000 1080: 8c: 403a4000 dmfc0 k0,c0_badvaddr # 取转换失败的虚拟地址 VA,TLB Refill 异常下,cp0_badvaddr (MIPS64 下,64 位长)存放翻译失败的虚拟地址 90: 001ada3e dsrl32 k1,k0,0x8 # VA 逻辑右移 (32+8)位,置入 k1 94: 1760ffdd bnez k1,c <0xc> # k1 不为 0 则跳转到 0xc 处。即 badvaddr[63:41] 不为 0,即高于 40 位不为 0,就跳转。 </source> 对于这种高于 40 位还有有效位的虚拟地址,要不他位于 xkseg,要不就是 xuseg/xsseg 的地址。对于 xkseg 的地址,有有效的地址这是确定的(MIPS32 兼容地址空间内核是用的,高于 40 位的部分都不为 0)。 MIPS64 R2 下,segbit 默认为 40,但具体实现时,MIPS Core 的 segbit 可以超过 40,即实现的真正有效的虚拟地址可以超过 40 位 对只实现 40 位 segbit,出现位于 xuseg/xsseg 的地址且高于 40 位不为 0 的话,这个地址肯定就是用户瞎访问,其就不是一个有效地址,进 do_page_fault() 然后 segment fault 即可 但对实现超过 40 位的 segbit,像 Cavium Octeon CN38xx 实现 49 位,则需要特别对待,因为 4KB 的页大小下,Linux/MIPS 设计时规定整个虚拟地址的有效位是低 40 位,高于 40 的虚拟地址空间,内核没有为之建立页表,即没有映射!虽然你实现了 49 位虚拟地址,但我 Linux 还是用不了,最终也要进入 do_page_fault() 进行处理 <source lang=c> # badvaddr 高于 40 位为 0 98: 403b2000 dmfc0 k1,c0_context # 取 cp0_context 值入 k1 9c: 7c1bb007 dins k1,zero,0x0,0x17 # zero[22:0] 替换 k1[22:0],k1 低 23 位置 0; # 留意:cp0_context[22:4] 是硬件拷贝自 cp0_badvaddr[31:13] # cp0_context[63:23] 是 PGD 的物理地址入口 a0: 377b0540 ori k1,k1,0x540 # 0x540 置入 k1 的低位 a4: 003bdafa dror k1,k1,0xb # drotr k1, k1, 11,即 k1 的低 11 位,和 k1 的高 53 位交换;k1 = k1[10:0] | k1[63:11] 上两条指令实际上是让 0b101 0100 0000 (0x540)或上 k1 的高 11 位,相当于 0xA800 0000 0000 0000 + Phy_PGD_ADDR,其是 PGD 的基地址 @@@ k1 中是 PGD 的基地址 a8: 001ad6fa dsrl k0,k0,0x1b # k0 右移 27 位 ac: 335a1ff8 andi k0,k0,0x1ff8 # 再保留 k0[12:3],实际保留的是 cp0_badvaddr[39:30] 正好是 PGD 的索引值,此时 k0 = cp0_badvaddr[39:30] << 3,64 位下 PGD 的项大小为 2^3 = 8 字节,因此其恰是索引 PGD 的指针 b0: 037ad82d daddu k1,k1,k0 # 获取 VA 对应的 PGD 项,即 VA 对应 PMD 基址的指针 b4: 403a4000 dmfc0 k0,c0_badvaddr # 取转换失败的虚拟地址 VA b8: df7b0000 ld k1,0(k1) # 取对应 PMD 基址 bc: 001ad4ba dsrl k0,k0,0x12 # 右移 18 位 c0: 335a0ff8 andi k0,k0,0xff8 # 保留 k0[12:3],实际是 cp0_badvaddr[29:21] << 3,正好是 PMD 的索引指针,PMD 的项大小也是 2^3 = 8 字节 c4: 037ad82d daddu k1,k1,k0 # 索引 PMD,指向 VA 对应之 PT 基址 c8: 403aa000 dmfc0 k0,c0_xcontext # 取 cp0_xcontext 值,Cavium Octeon 上,BadVPN2 是 xcontext[39:4],置 badvaddr[48:13] cc: df7b0000 ld k1,0(k1) # 取 PT 基址 d0: 335a0ff0 andi k0,k0,0xff0 # 保留 xcontext 的位 11:4,实际为 cp0_badvaddr[20:13] << (3 + 1),这实际为 PT 的索引值,因为 TLB Refill 总是一起填相邻的两项,因此这索引,实际是 VA 对应的偶数项索引 d4: 037ad82d daddu k1,k1,k0 # 索引 PT,指向 VA 对应之偶数项 PTE d8: df7a0000 ld k0,0(k1) # 取 VA 对应偶数项的 PTE dc: df7b0008 ld k1,8(k1) # 取 VA 对应奇数项的 PTE e0: 001ad13a dsrl k0,k0,0x4 # 忽略 PTE 的低 4 位,那是 OS 用的,TLB 的项里没有这些位 e4: 001bd93a dsrl k1,k1,0x4 e8: 003ad0ba dror k0,k0,0x2 # drotr k0, k0, 0x2,k0 低两位和高 62 位交换,这个操作和上面的右移 4 位应该是合起来的忽略 PTE 的低 6 位,因为在 MIPS64 R2 上,写入数据到 entrylo0/1[63:62] 是始终为 0 的。 ec: 40ba1000 dmtc0 k0,c0_entrylo0 # 偶数项 PTE 入 entrylo0 f0: 003bd8ba dror k1,k1,0x2 # 同上面偶数项的分析 f4: 40bb1800 dmtc0 k1,c0_entrylo1 # 奇数项PTE 入 entrylo1 f8: 42000006 tlbwr # 把 entrylo0, entrylo1 随机写入 TLB 的一项 fc: dc1a8078 ld k0,-32648(zero) 100: 42000018 eret ... </source> <br><br>
返回到
64位多核 MIPS 异常和中断内核代码分析 (1)
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面