64位多核 MIPS 异常和中断内核代码分析 (3)

64位多核 MIPS 异常和中断内核代码分析 (3)

 

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
    ...

你可能感兴趣的:(64位多核 MIPS 异常和中断内核代码分析 (3))