[BACK]Return to tlbhandler.S CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

Annotation of sys/arch/mips64/mips64/tlbhandler.S, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: tlbhandler.S,v 1.16 2007/05/25 20:58:39 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 1995-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  *
                     27:  */
                     28:
                     29: /*
                     30:  *  This code handles TLB exceptions and updates.
                     31:  */
                     32:
                     33: #include <machine/param.h>
                     34: #include <machine/psl.h>
                     35: #include <machine/pte.h>
                     36: #include <machine/asm.h>
                     37: #include <machine/cpu.h>
                     38: #include <machine/regnum.h>
                     39: #include <machine/cpustate.h>
                     40:
                     41: #define        HAIRY_R5000_ERRATA
                     42:
                     43: #include "assym.h"
                     44:
                     45:        .set    mips3
                     46:
                     47:        .set    noreorder       /* Default reorder mode */
                     48:
                     49: /*---------------------------------------------------------------- tlb_miss
                     50:  *     Low level TLB exception handler. TLB and XTLB share some
                     51:  *     code for the moment and is copied down at the same time.
                     52:  *     This code must be PIC and not more than 64 instructions
                     53:  *     for both TLB and XTLB handling or it will overflow the
                     54:  *     available storage. If the startup code finds out that it
                     55:  *     is larger, the trampoline code is copied instead of panicing.
                     56:  */
                     57: /*****************************  Start of code copied to exception vector */
                     58:        .globl  tlb_miss        /* 0xffffffff80000000 */
                     59:        .set    noat
                     60:        .ent    tlb_miss, 0
                     61: tlb_miss:
                     62: #ifdef HAIRY_R5000_ERRATA
                     63:        /*
                     64:         * R5000 errata: edge cases can trigger a TLB miss exception
                     65:         * instead of an invalid TLB exception. Servicing the TLB miss
                     66:         * exception would cause a duplicate TLB to be inserted, which
                     67:         * causes the processor operation to become unpredictable (but
                     68:         * very bad for the kernel's health, ten times out of nine).
                     69:         *
                     70:         * More details about the problem can be found in:
                     71:         *  http://www.linux-mips.org/archives/linux-mips/2000-02/msg00040.html
                     72:         *
                     73:         * We work around the issue by checking for an existing TLB entry,
                     74:         * and handling this as an invalid TLB exception (as it was intended
                     75:         * to be), in this case.
                     76:         */
                     77:        tlbp
                     78:        mfc0    k1, COP_0_TLB_INDEX
                     79:        bltz    k1, 1f                  # missing!
                     80:         nop
                     81:        j       k_tlb_inv
                     82:         nop
                     83: 1:
                     84: #endif
                     85:        PTR_L   k1, curprocpaddr
                     86:        dmfc0   k0, COP_0_BAD_VADDR
                     87:        bltz    k0, _k_miss             # kernel address space
                     88:        PTR_SRL k0, k0, SEGSHIFT - LOGREGSZ
                     89:        PTR_L   k1, PCB_SEGTAB(k1)
                     90:        andi    k0, k0, (PMAP_SEGTABSIZE - 1) << LOGREGSZ
                     91:        PTR_ADDU k1, k1, k0
                     92:        PTR_L   k1, 0(k1)               # get pointer to page table
                     93:        dmfc0   k0, COP_0_BAD_VADDR
                     94:        PTR_SRL k0, k0, PGSHIFT - 2
                     95:        andi    k0, k0, ((NPTEPG/2) - 1) << 3
                     96:        beqz    k1, _inv_seg            # invalid segment map
                     97:        PTR_ADDU k1, k1, k0             # index into segment map
                     98:        lw      k0, 0(k1)               # get page PTE
                     99: tlb_load:
                    100:        lw      k1, 4(k1)
                    101:        dsll    k0, k0, 34
                    102:        dsrl    k0, k0, 34
                    103:        dmtc0   k0, COP_0_TLB_LO0
                    104:        dsll    k1, k1, 34
                    105:        dsrl    k1, k1, 34
                    106:        dmtc0   k1, COP_0_TLB_LO1
                    107:        nop                             # RM7000 needs 4 nops
                    108:        nop
                    109:        nop
                    110:        nop
                    111:        tlbwr                           # update TLB
                    112:        nop
                    113:        nop
                    114:        nop
                    115:        nop
                    116:        eret                            # RM7000 need 4 for JTLB usage.
                    117:        .end    tlb_miss
                    118:
                    119:        .globl  e_tlb_miss
                    120: e_tlb_miss:
                    121:
                    122: /*---------------------------------------------------------------- xtlb_miss
                    123:  *     Low level XTLB exception handler.
                    124:  */
                    125:        .globl  xtlb_miss       /* 0xffffffff80000080 */
                    126:        .set    noat
                    127:        .ent    xtlb_miss, 0
                    128: xtlb_miss:
                    129: #ifdef HAIRY_R5000_ERRATA
                    130:        /* See errata comments in tlb_miss above */
                    131:        tlbp
                    132:        mfc0    k1, COP_0_TLB_INDEX
                    133:        bltz    k1, 1f                  # missing!
                    134:         nop
                    135:        j       k_tlb_inv
                    136:         nop
                    137: 1:
                    138: #endif
                    139:        dmfc0   k0, COP_0_BAD_VADDR
                    140:        bltz    k0, _k_miss             # kernel address space
                    141:        PTR_SRL k0, k0, SEGSHIFT
                    142:        sltiu   k1, k0, PMAP_SEGTABSIZE
                    143:        beqz    k1, _inv_seg            # wrong if outside pm_segtab
                    144:        PTR_SLL k0, k0, LOGREGSZ
                    145:        PTR_L   k1, curprocpaddr
                    146:        PTR_L   k1, PCB_SEGTAB(k1)
                    147:        PTR_ADDU k1, k1, k0
                    148:        PTR_L   k1, 0(k1)               # get pointer to page table
                    149:        dmfc0   k0, COP_0_BAD_VADDR
                    150:        PTR_SRL k0, k0, PGSHIFT - 2
                    151:        andi    k0, k0, ((NPTEPG/2) - 1) << 3
                    152:        beqz    k1, _inv_seg
                    153:        PTR_ADDU k1, k1, k0
                    154:        b       tlb_load                # rest is same as 'tlb_miss'
                    155:        lw      k0, 0(k1)
                    156:
                    157: _inv_seg:
                    158:        j       tlb_miss_nopt           # No page table for this segment.
                    159:        nop
                    160:
                    161: _k_miss:
                    162:        j       k_tlb_miss              # kernel tlbmiss.
                    163:        dmfc0   k0, COP_0_BAD_VADDR     # must reload.
                    164:        .end    xtlb_miss
                    165:
                    166:        .globl  e_xtlb_miss
                    167: e_xtlb_miss:
                    168:        .set    at
                    169: /*****************************  End of code copied to exception vector */
                    170:
                    171:        .globl  tlb_miss_nopt
                    172:        .ent    tlb_miss_nopt, 0
                    173: tlb_miss_nopt:
                    174:        .set    noat
                    175:        mfc0    k0, COP_0_STATUS_REG
                    176:        andi    k0, SR_KSU_USER
                    177:        bne     k0, zero, go_u_general
                    178:        nop
                    179:        j       k_general
                    180:        nop
                    181:        .end    tlb_miss_nopt
                    182:        .set    at
                    183:
                    184: /*
                    185:  * Trampolines copied to exception vectors when code is too big.
                    186:  */
                    187:        .globl  tlb_miss_tramp
                    188:        .ent    tlb_miss_tramp, 0
                    189: tlb_miss_tramp:
                    190:        .set    noat
                    191:        LA      k0, tlb_miss
                    192:        jr      k0
                    193:        nop
                    194:        .end    tlb_miss_tramp
                    195:        .set    at
                    196:        .globl  e_tlb_miss_tramp
                    197: e_tlb_miss_tramp:
                    198:
                    199:        .globl  xtlb_miss_tramp
                    200:        .ent    xtlb_miss_tramp, 0
                    201: xtlb_miss_tramp:
                    202:        .set    noat
                    203:        LA      k0, xtlb_miss
                    204:        jr      k0
                    205:        nop
                    206:        .end    xtlb_miss_tramp
                    207:        .set    at
                    208:        .globl  e_xtlb_miss_tramp
                    209: e_xtlb_miss_tramp:
                    210:
                    211:
                    212: /*---------------------------------------------------------------- k_tlb_inv
                    213:  *     Handle a TLB invalid exception from kernel mode in kernel
                    214:  *     space. This happens when we have a TLB match but an invalid
                    215:  *     entry. Try to reload.
                    216:  */
                    217: NLEAF(k_tlb_inv, 0)
                    218:        .set    noat
                    219:        LA      k1, (VM_MIN_KERNEL_ADDRESS)     # compute index
                    220:        dmfc0   k0, COP_0_BAD_VADDR     # get the fault address
                    221:        PTR_SUBU k0, k0, k1
                    222:        lw      k1, Sysmapsize                  # index within range?
                    223:        PTR_SRL k0, k0, PGSHIFT
                    224:        sltu    k1, k0, k1
                    225:        beq     k1, zero, sys_stk_chk           # No. check for valid stack
                    226:        nop
                    227:
                    228:        PTR_L   k1, Sysmap
                    229:        PTR_SLL k0, k0, 2                       # compute offset from index
                    230:        tlbp                                    # Probe the invalid entry
                    231:        PTR_ADDU k1, k1, k0
                    232:        and     k0, k0, 4                       # check even/odd page
                    233:        bne     k0, zero, k_tlb_inv_odd
                    234:        nop
                    235:
                    236:        mfc0    k0, COP_0_TLB_INDEX
                    237:        blez    k0, sys_stk_chk                 # probe fail or index 0!
                    238:        lw      k0, 0(k1)                       # get PTE entry
                    239:
                    240:        dsll    k0, k0, 34                      # get rid of "wired" bit
                    241:        dsrl    k0, k0, 34
                    242:        dmtc0   k0, COP_0_TLB_LO0               # load PTE entry
                    243:        and     k0, k0, PG_V                    # check for valid entry
                    244:        beq     k0, zero, go_k_general  # PTE invalid
                    245:        lw      k0, 4(k1)                       # get odd PTE entry
                    246:        dsll    k0, k0, 34
                    247:        dsrl    k0, k0, 34
                    248:        dmtc0   k0, COP_0_TLB_LO1               # load PTE entry
                    249:        nop
                    250:        nop
                    251:        nop
                    252:        nop
                    253:        tlbwi                                   # write TLB
                    254:        nop
                    255:        nop
                    256:        nop
                    257:        nop
                    258:        eret
                    259:
                    260: k_tlb_inv_odd:
                    261:        mfc0    k0, COP_0_TLB_INDEX
                    262:        blez    k0, sys_stk_chk                 # probe fail or index 0!
                    263:        lw      k0, 0(k1)                       # get PTE entry
                    264:
                    265:        dsll    k0, k0, 34                      # get rid of wired bit
                    266:        dsrl    k0, k0, 34
                    267:        dmtc0   k0, COP_0_TLB_LO1               # save PTE entry
                    268:        and     k0, k0, PG_V                    # check for valid entry
                    269:        beq     k0, zero, go_k_general  # PTE invalid
                    270:        lw      k0, -4(k1)                      # get even PTE entry
                    271:        dsll    k0, k0, 34
                    272:        dsrl    k0, k0, 34
                    273:        dmtc0   k0, COP_0_TLB_LO0               # save PTE entry
                    274:        nop
                    275:        nop
                    276:        nop
                    277:        nop
                    278:        tlbwi                                   # update TLB
                    279:        nop
                    280:        nop
                    281:        nop
                    282:        nop
                    283:        eret
                    284: END(k_tlb_inv)
                    285:
                    286: /*---------------------------------------------------------------- k_tlb_miss
                    287:  *
                    288:  *     Handle a TLB miss exception from kernel mode in kernel space.
                    289:  *     We must check that this is coming from kernel mode. If not
                    290:  *     it's a bad address from user mode so handle properly.
                    291:  *     Load up the correct entry contents from the kernel map.
                    292:  *     k0 has bad address.
                    293:  */
                    294: NLEAF(k_tlb_miss, 0)
                    295:        .set    noat
                    296:        mfc0    k1, COP_0_STATUS_REG
                    297:        andi    k1, SR_KSU_USER
                    298:        bne     k1, zero, go_u_general
                    299:        LA      k1, (VM_MIN_KERNEL_ADDRESS)     # compute index
                    300:        PTR_SUBU k0, k0, k1
                    301:        lw      k1, Sysmapsize                  # index within range?
                    302:        PTR_SRL k0, k0, PGSHIFT
                    303:        sltu    k1, k0, k1
                    304:        beq     k1, zero, sys_stk_chk           # No. check for valid stack
                    305:        PTR_SRL k0, k0, 1
                    306:        PTR_L   k1, Sysmap
                    307:        PTR_SLL k0, k0, 3                       # compute offset from index
                    308:        PTR_ADDU k1, k1, k0
                    309:        lw      k0, 0(k1)                       # get PTE entry
                    310:        lw      k1, 4(k1)                       # get odd PTE entry
                    311:        dsll    k0, k0, 34                      # get rid of "wired" bit
                    312:        dsrl    k0, k0, 34
                    313:        dmtc0   k0, COP_0_TLB_LO0               # load PTE entry
                    314:        dsll    k1, k1, 34
                    315:        dsrl    k1, k1, 34
                    316:        dmtc0   k1, COP_0_TLB_LO1               # load PTE entry
                    317:        nop
                    318:        nop
                    319:        nop
                    320:        nop
                    321:        tlbwr                                   # write TLB
                    322:        nop
                    323:        nop
                    324:        nop
                    325:        nop
                    326:        eret
                    327:
                    328: sys_stk_chk:
                    329:        PTR_L   k1, curprocpaddr
                    330:        PTR_SUBU k0, sp, k1                     # check to see if we have a
                    331:        sltiu   k0, 2048                        #  valid kernel stack
                    332:        beqz    k0, go_k_general                # yes, handle.
                    333:        nop
                    334:
                    335:        LA      a0, start-FRAMESZ(CF_SZ)-4*REGSZ # set sp to a valid place
                    336: #ifdef __mips_n64
                    337:        mfc0    a4, COP_0_STATUS_REG
                    338:        mfc0    a5, COP_0_CAUSE_REG
                    339:        move    a6, sp
                    340: #else
                    341:        mfc0    a2, COP_0_STATUS_REG
                    342:        mfc0    a3, COP_0_CAUSE_REG
                    343:        REG_S   a2, CF_ARGSZ+0*REGSZ(sp)
                    344:        REG_S   a3, CF_ARGSZ+1*REGSZ(sp)
                    345:        PTR_S   sp, CF_ARGSZ+2*REGSZ(a0)
                    346: #endif
                    347:        move    sp, a0
                    348:        dmfc0   a1, COP_0_EXC_PC
                    349:        move    a2, ra
                    350:        LA      a0, 1f
                    351:        jal     printf
                    352:        dmfc0   a3, COP_0_BAD_VADDR
                    353:
                    354:        LA      sp, start-FRAMESZ(CF_SZ)        # set sp to a valid place
                    355:
                    356: #ifdef DDB
                    357:        LA      a0, 2f
                    358:        jal     trapDump
                    359:        nop
                    360: #endif
                    361:
                    362:        PANIC("kernel stack overflow")
                    363:        /*noreturn*/
                    364:
                    365: go_k_general:
                    366:        j       k_general
                    367:        nop
                    368:
                    369: go_u_general:
                    370:        j       u_general
                    371:        nop
                    372:
                    373:
                    374:        .data
                    375: 1:
                    376:        .asciiz "\rktlbmiss: PC %p RA %p ADR %p\nSR %p CR %p SP %p\n"
                    377: 2:
                    378:        .asciiz "stack ovf"
                    379:        .text
                    380:
                    381:        .set    at
                    382: END(k_tlb_miss)
                    383:
                    384: /*---------------------------------------------------------------- tlb_write_i
                    385:  *     Write the given entry into the TLB at the given index.
                    386:  */
                    387: LEAF(tlb_write_indexed, 0)
                    388:        mfc0    v1, COP_0_STATUS_REG    # Save the status register.
                    389:        ori     v0, v1, SR_INT_ENAB
                    390:        xori    v0, v0, SR_INT_ENAB
                    391:        mtc0    v0, COP_0_STATUS_REG    # Disable interrupts
                    392:        ITLBNOPFIX
                    393:        ld      a2, 16(a1)
                    394:        ld      a3, 24(a1)
                    395:        dmfc0   ta0, COP_0_TLB_HI               # Save the current PID.
                    396:
                    397:        dmtc0   a2, COP_0_TLB_LO0               # Set up entry low0.
                    398:        dmtc0   a3, COP_0_TLB_LO1               # Set up entry low1.
                    399:        ld      a2, 0(a1)
                    400:        ld      a3, 8(a1)
                    401:        mtc0    a0, COP_0_TLB_INDEX     # Set the index.
                    402:        dmtc0   a2, COP_0_TLB_PG_MASK   # Set up entry mask.
                    403:        dmtc0   a3, COP_0_TLB_HI                # Set up entry high.
                    404:        nop
                    405:        nop
                    406:        nop
                    407:        nop
                    408:        tlbwi                                   # Write the TLB
                    409:        nop
                    410:        nop                                     # Delay for effect
                    411:        nop
                    412:        nop
                    413:
                    414:        dmtc0   ta0, COP_0_TLB_HI               # Restore the PID.
                    415:        nop
                    416:        dmtc0   zero, COP_0_TLB_PG_MASK # Default mask value.
                    417:        mtc0    v1, COP_0_STATUS_REG    # Restore the status register
                    418:        ITLBNOPFIX
                    419:        j       ra
                    420:        nop
                    421: END(tlb_write_indexed)
                    422:
                    423: /*---------------------------------------------------------------- tlb_flush
                    424:  *     Flush the "random" entries from the TLB.
                    425:  *     Uses "wired" register to determine what register to start with.
                    426:  *     Arg "tlbsize" is the number of entries to flush.
                    427:  */
                    428: LEAF(tlb_flush, 0)
                    429:        mfc0    v1, COP_0_STATUS_REG    # Save the status register.
                    430:        ori     v0, v1, SR_INT_ENAB
                    431:        xori    v0, v0, SR_INT_ENAB
                    432:        mtc0    v0, COP_0_STATUS_REG    # Disable interrupts
                    433:        ITLBNOPFIX
                    434:        mfc0    ta1, COP_0_TLB_WIRED
                    435:        LA      v0, KSEG0_BASE          # invalid address
                    436:        dmfc0   ta0, COP_0_TLB_HI       # Save the PID
                    437:
                    438:        dmtc0   v0, COP_0_TLB_HI        # Mark entry high as invalid
                    439:        dmtc0   zero, COP_0_TLB_LO0     # Zero out low entry0.
                    440:        dmtc0   zero, COP_0_TLB_LO1     # Zero out low entry1.
                    441:        mtc0    zero, COP_0_TLB_PG_MASK # Zero out mask entry.
                    442: /*
                    443:  * Align the starting value (ta1) and the upper bound (a0).
                    444:  */
                    445: 1:
                    446:        mtc0    ta1, COP_0_TLB_INDEX    # Set the index register.
                    447:        addu    ta1, ta1, 1             # Increment index.
                    448:        nop
                    449:        nop
                    450:        nop
                    451:        tlbwi                           # Write the TLB entry.
                    452:        nop
                    453:        nop
                    454:        bne     ta1, a0, 1b
                    455:        nop
                    456:
                    457:        dmtc0   ta0, COP_0_TLB_HI       # Restore the PID
                    458:        mtc0    v1, COP_0_STATUS_REG    # Restore the status register
                    459:        ITLBNOPFIX
                    460:        j       ra
                    461:        nop
                    462: END(tlb_flush)
                    463:
                    464: /*--------------------------------------------------------------- tlb_flush_addr
                    465:  *     Flush any TLB entries for the given address and TLB PID.
                    466:  */
                    467: LEAF(tlb_flush_addr, 0)
                    468:        mfc0    v1, COP_0_STATUS_REG    # Save the status register.
                    469:        ori     v0, v1, SR_INT_ENAB
                    470:        xori    v0, v0, SR_INT_ENAB
                    471:        mtc0    v0, COP_0_STATUS_REG    # Disable interrupts
                    472:        ITLBNOPFIX
                    473:        li      v0, (PG_HVPN | PG_ASID)
                    474:        and     a0, a0, v0              # Make sure valid hi value.
                    475:        dmfc0   ta0, COP_0_TLB_HI       # Get current PID
                    476:        dmtc0   a0, COP_0_TLB_HI        # look for addr & PID
                    477:        nop
                    478:        nop
                    479:        nop
                    480:        nop
                    481:        tlbp                            # Probe for the entry.
                    482:        nop
                    483:        nop                             # Delay for effect
                    484:        nop
                    485:        LA      ta1, KSEG0_BASE         # Load invalid entry.
                    486:        mfc0    v0, COP_0_TLB_INDEX     # See what we got
                    487:        bltz    v0, 1f                  # index < 0 => !found
                    488:        nop
                    489:        dmtc0   ta1, COP_0_TLB_HI       # Mark entry high as invalid
                    490:
                    491:        dmtc0   zero, COP_0_TLB_LO0     # Zero out low entry.
                    492:        dmtc0   zero, COP_0_TLB_LO1     # Zero out low entry.
                    493:        nop
                    494:        nop
                    495:        nop
                    496:        nop
                    497:        tlbwi
                    498:        nop
                    499:        nop
                    500:        nop
                    501:        nop
                    502: 1:
                    503:        dmtc0   ta0, COP_0_TLB_HI       # restore PID
                    504:        mtc0    v1, COP_0_STATUS_REG    # Restore the status register
                    505:        ITLBNOPFIX
                    506:        j       ra
                    507:        nop
                    508: END(tlb_flush_addr)
                    509:
                    510: /*---------------------------------------------------------------- tlb_update
                    511:  *     Update the TLB if highreg is found; otherwise, enter the data.
                    512:  */
                    513: LEAF(tlb_update, 0)
                    514:        mfc0    v1, COP_0_STATUS_REG    # Save the status register.
                    515:        ori     v0, v1, SR_INT_ENAB
                    516:        xori    v0, v0, SR_INT_ENAB
                    517:        mtc0    v0, COP_0_STATUS_REG    # Disable interrupts
                    518:        ITLBNOPFIX
                    519:        and     ta1, a0, 0x1000         # ta1 = Even/Odd flag
                    520:        li      v0, (PG_HVPN | PG_ASID)
                    521:        and     a0, a0, v0
                    522:        dmfc0   ta0, COP_0_TLB_HI       # Save current PID
                    523:        dmtc0   a0, COP_0_TLB_HI        # Init high reg
                    524:        and     a2, a1, PG_G            # Copy global bit
                    525:        nop
                    526:        nop
                    527:        nop
                    528:        tlbp                            # Probe for the entry.
                    529:        dsll    a1, a1, 34
                    530:        dsrl    a1, a1, 34
                    531:        bne     ta1, zero, 2f           # Decide even odd
                    532:        mfc0    v0, COP_0_TLB_INDEX     # See what we got
                    533: # EVEN
                    534:        bltz    v0, 1f                  # index < 0 => !found
                    535:        nop
                    536:
                    537:        tlbr                            # update, read entry first
                    538:        nop
                    539:        nop
                    540:        nop
                    541:        dmtc0   a1, COP_0_TLB_LO0       # init low reg0.
                    542:        nop
                    543:        nop
                    544:        nop
                    545:        nop
                    546:        tlbwi                           # update slot found
                    547:        b       4f
                    548:        li      v0, 1
                    549: 1:
                    550:        mtc0    zero, COP_0_TLB_PG_MASK # init mask.
                    551:        dmtc0   a0, COP_0_TLB_HI        # init high reg.
                    552:        dmtc0   a1, COP_0_TLB_LO0       # init low reg0.
                    553:        dmtc0   a2, COP_0_TLB_LO1       # init low reg1.
                    554:        nop
                    555:        nop
                    556:        nop
                    557:        nop
                    558:        tlbwr                           # enter into a random slot
                    559:        b       4f
                    560:        li      v0, 0
                    561: # ODD
                    562: 2:
                    563:        nop
                    564:        bltz    v0, 3f                  # index < 0 => !found
                    565:        nop
                    566:
                    567:        tlbr                            # read the entry first
                    568:        nop
                    569:        nop
                    570:        nop
                    571:        dmtc0   a1, COP_0_TLB_LO1       # init low reg1.
                    572:        nop
                    573:        nop
                    574:        nop
                    575:        nop
                    576:        tlbwi                           # update slot found
                    577:        b       4f
                    578:        li      v0, 1
                    579: 3:
                    580:        mtc0    zero, COP_0_TLB_PG_MASK # init mask.
                    581:        dmtc0   a0, COP_0_TLB_HI        # init high reg.
                    582:        dmtc0   a2, COP_0_TLB_LO0       # init low reg0.
                    583:        dmtc0   a1, COP_0_TLB_LO1       # init low reg1.
                    584:        nop
                    585:        nop
                    586:        nop
                    587:        nop
                    588:        tlbwr                           # enter into a random slot
                    589:        nop
                    590:        li      v0, 0
                    591:
                    592: 4:                                     # Make sure pipeline
                    593:        nop                             # advances before we
                    594:        nop                             # use the tlb.
                    595:        dmtc0   ta0, COP_0_TLB_HI       # restore PID
                    596:        mtc0    v1, COP_0_STATUS_REG    # Restore the status register
                    597:        ITLBNOPFIX
                    598:        j       ra
                    599:        nop
                    600: END(tlb_update)
                    601:
                    602: /*---------------------------------------------------------------- tlb_read
                    603:  *     Read the TLB entry.
                    604:  */
                    605: LEAF(tlb_read, 0)
                    606:        mfc0    v1, COP_0_STATUS_REG    # Save the status register.
                    607:        ori     v0, v1, SR_INT_ENAB
                    608:        xori    v0, v0, SR_INT_ENAB
                    609:        mtc0    v0, COP_0_STATUS_REG    # Disable interrupts
                    610:        ITLBNOPFIX
                    611:        dmfc0   v0, COP_0_TLB_HI        # Get current PID
                    612:
                    613:        mtc0    a0, COP_0_TLB_INDEX     # Set the index register
                    614:        nop
                    615:        nop
                    616:        nop
                    617:        nop
                    618:        tlbr                            # Read from the TLB
                    619:        nop
                    620:        nop
                    621:        nop
                    622:        dmfc0   ta0, COP_0_TLB_PG_MASK  # fetch the hi entry
                    623:        dmfc0   ta1, COP_0_TLB_HI       # fetch the hi entry
                    624:        dmfc0   ta2, COP_0_TLB_LO0      # See what we got
                    625:        dmfc0   ta3, COP_0_TLB_LO1      # See what we got
                    626:        dmtc0   v0, COP_0_TLB_HI        # restore PID
                    627:        nop
                    628:        nop
                    629:        nop                             # wait for PID active
                    630:        mtc0    v1, COP_0_STATUS_REG    # Restore the status register
                    631:        ITLBNOPFIX
                    632:        sd      ta0, 0(a1)
                    633:        sd      ta1, 8(a1)
                    634:        sd      ta2, 16(a1)
                    635:        j       ra
                    636:        sd      ta3, 24(a1)
                    637: END(tlb_read)
                    638:
                    639: /*---------------------------------------------------------------- tlb_get_pid
                    640:  *     Read the tlb pid value.
                    641:  */
                    642: LEAF(tlb_get_pid, 0)
                    643:        dmfc0   v0, COP_0_TLB_HI        # get PID
                    644:        li      v1, VMTLB_PID           # mask off PID
                    645:        j       ra
                    646:        and     v0, v0, v1              # mask off PID
                    647: END(tlb_get_pid)
                    648:
                    649: /*---------------------------------------------------------------- tlb_set_pid
                    650:  *     Write the given pid into the TLB pid reg.
                    651:  */
                    652: LEAF(tlb_set_pid, 0)
                    653:        dmtc0   a0, COP_0_TLB_HI                # Write the hi reg value
                    654:        j       ra
                    655:        nop
                    656: END(tlb_set_pid)
                    657:
                    658: /*---------------------------------------------------------------- tlb_get_wired
                    659:  *     Get the value from the TLB wired reg.
                    660:  */
                    661: LEAF(tlb_get_wired, 0)
                    662:        mfc0    v0, COP_0_TLB_WIRED
                    663:        j       ra
                    664:        nop
                    665: END(tlb_get_wired)
                    666:
                    667: /*---------------------------------------------------------------- tlb_set_wired
                    668:  *     Write the given value into the TLB wired reg.
                    669:  */
                    670: LEAF(tlb_set_wired, 0)
                    671:        mtc0    a0, COP_0_TLB_WIRED
                    672:        j       ra
                    673:        nop
                    674: END(tlb_set_wired)

CVSweb