[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     ! 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