RMI XLR732TLB 相关处理函数分析
0. 背景
MIPS64 下虚拟地址空间的划分:
其中内核空间是 xkphys 和 xkseg;其中 xkphys 是固定映射,不经 TLB (unmapped)
用户空间是 xuseg
1. RMI XLR732 TLB Refill handler 分析
@0xFFFF FFFF 8000 0000
c: 07610005 bgez k1,24 <0x24> /* if vaddr[61] != 1 (0xc000 0000 0000 0000 ~ 0xDFFF FFFF FFFF FFFF), branch */
10: 3c1bc000 lui k1,0xc000 -----> at delay slot, commit new value to k1 after reading k1 (bgez)
# vaddr is at 0xE000000000000000 ~ 0xFFFF FFFF FFFF FFFF,这个地址段里被 64 bit Linux 内核使用且又要经过 TLB 的就是 kseg2 了,内核的模块默认使用这个地址
14: 035bd02f dsubu k0,k0,k1 /* k0 = vaddr - 0xFFFF FFFF C0000000 */
18: 3c1b8396 lui k1,0x8396
1c: 10000023 b ac <0xac> ----> @@@
20: 277ba000 addiu k1,k1,-24576 /* 0xFFFF FFFF 8395A000 = module_pg_dir , using the module_pg_dir as the PGD entry */
# vaddr is at 0xC000000000000000 ~ 0xDFFF FFFF FFFF FFFF
24: 001bd83c dsll32 k1,k1,0x0 /* (0xFFFF FFFF C0000000 << 32) */
28: 035bd02f dsubu k0,k0,k1 /* k0 = vaddr - 0xC000000000000000 */
2c: 1000001f b ac <0xac> ----> @@@
30: 3c1b8396 lui k1,0x8396 /* 0xFFFF FFFF 83960000 = swapper_pg_current, using the swapper_pg_current as the PGD entry */
34: 00000000
38: 00000000 <repeat>
......
@0xFFFF FFFF 8000 0080 (xTLB Refill 入口)
8c: 403a4000 dmfc0 k0,c0_badvaddr
90: 0740001a bltz k0,fc <0xfc> /* if badvaddr >= 0x80000000 00000000 branch */
# vaddr is < 0x8000 0000 0000 000, so it's at kuseg
94: 403b2000 dmfc0 k1,c0_context
98: 001bddfa dsrl k1,k1,0x17 /* get (smp_processor_id() << 3) (26-23), see asm/mmu_context.h */
9c: 3c1a8396 lui k0,0x8396 /* swapper_pg_current = 0xFFFF FFFF 83960000 */
a0: 037ad82d daddu k1,k1,k0 /* k1 = swapper_pg_current[smp_processor_id()] */
a4: 403a4000 dmfc0 k0,c0_badvaddr
a8: df7b2000 ld k1,8192(k1) /*
* pgd = *((void *)(k1 + 8192), 8 bytes per pgd entry, pgd_current = 0xFFFF FFFF 8396 2000,
* 0x2000 = 8192
* actually it's pgd = pgd_current[smp_processor_id()]
*/
@@@
ac: 001ad6fa dsrl k0,k0,0x1b # >> 27
b0: 335a1ff8 andi k0,k0,0x1ff8 /* get (vaddr[39:30] << 3), for indexing pgd */
b4: 037ad82d daddu k1,k1,k0 /* index pgd */
b8: 403a4000 dmfc0 k0,c0_badvaddr
bc: df7b0000 ld k1,0(k1) /* get p_pmd */
c0: 001ad4ba dsrl k0,k0,0x12
c4: 335a0ff8 andi k0,k0,0xff8 /* get (vaddr[29:21] << 3), for indexing pmd */
c8: 037ad82d daddu k1,k1,k0 /* index pmd */
cc: 403aa000 dmfc0 k0,c0_xcontext
d0: df7b0000 ld k1,0(k1) /* get p_pt */
d4: 335a0ff0 andi k0,k0,0xff0 /* get (va[20:13] << 4), actually use va[20:12] index the pt, va[12]=0, for indexing pt */
d8: 037ad82d daddu k1,k1,k0 /* index pt */
dc: df7a0000 ld k0,0(k1) /* get even page addr */ <-------------
e0: df7b0008 ld k1,8(k1) /* get odd page addr */
e4: 001ad1ba dsrl k0,k0,0x6 /* ignore the low 6 bits, it's for os */
e8: 409a1000 mtc0 k0,c0_entrylo0 /* tlb even page entry */
ec: 001bd9ba dsrl k1,k1,0x6 /* same as above */
f0: 409b1800 mtc0 k1,c0_entrylo1 /* tlb odd page entry */
f4: 42000006 tlbwr /* random write tlb */
f8: 42000018 eret
# go here, vaddr is >=0x8000 0000 0000 0000, so it's in xkphys or xkseg; and 0x8000 0000 0000 0000 ~ 0xBFFF FFFF FFFF FFFF is xkphys, unmapped, do not index TLB, so vaddr is at 0xc000 0000 0000 0000
fc: 001ad8b8 dsll k1,k0,0x2 # vaddr << 2, will be test the vaddr[61]
100: 1000ffc2 b c <0xc>
104: 00000000 nop
108: 00000000 nop
2. RMI XLR732 handle_tlbl 分析
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
...