The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/exception.S

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $        */
    2 /*-
    3  * Copyright (c) 1992, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * Digital Equipment Corporation and Ralph Campbell.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  * Copyright (C) 1989 Digital Equipment Corporation.
   34  * Permission to use, copy, modify, and distribute this software and
   35  * its documentation for any purpose and without fee is hereby granted,
   36  * provided that the above copyright notice appears in all copies.
   37  * Digital Equipment Corporation makes no representations about the
   38  * suitability of this software for any purpose.  It is provided "as is"
   39  * without express or implied warranty.
   40  *
   41  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
   42  *      v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
   43  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
   44  *      v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
   45  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
   46  *      v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
   47  *      from: @(#)locore.s      8.5 (Berkeley) 1/4/94
   48  *      JNPR: exception.S,v 1.5 2007/01/08 04:58:37 katta
   49  * $FreeBSD: releng/9.0/sys/mips/mips/exception.S 224612 2011-08-02 17:49:27Z attilio $
   50  */
   51 
   52 /*
   53  *      Contains code that is the first executed at boot time plus
   54  *      assembly language support routines.
   55  */
   56 
   57 #include "opt_cputype.h"
   58 #include "opt_ddb.h"
   59 #include <machine/asm.h>
   60 #include <machine/cpu.h>
   61 #include <machine/regnum.h>
   62 #include <machine/cpuregs.h>
   63 #include <machine/pte.h>
   64 
   65 #include "opt_cputype.h"
   66 
   67 #include "assym.s"
   68 
   69         .set    noreorder               # Noreorder is default style!
   70 
   71 /*
   72  * Reasonable limit
   73  */
   74 #define INTRCNT_COUNT   128
   75 
   76 
   77 /*
   78  *----------------------------------------------------------------------------
   79  *
   80  * MipsTLBMiss --
   81  *
   82  *      Vector code for the TLB-miss exception vector 0x80000000.
   83  *
   84  * This code is copied to the TLB exception vector address to
   85  * which the CPU jumps in response to an exception or a TLB miss.
   86  * NOTE: This code must be position independent!!!
   87  *
   88  *
   89  */
   90 VECTOR(MipsTLBMiss, unknown)
   91         .set push
   92         .set noat
   93         j       MipsDoTLBMiss
   94         MFC0    k0, MIPS_COP_0_BAD_VADDR        # get the fault address
   95         .set pop
   96 VECTOR_END(MipsTLBMiss)
   97 
   98 /*
   99  *----------------------------------------------------------------------------
  100  *
  101  * MipsDoTLBMiss --
  102  *
  103  * This is the real TLB Miss Handler code.
  104  * 'segbase' points to the base of the segment table for user processes.
  105  *
  106  * Don't check for invalid pte's here. We load them as well and
  107  * let the processor trap to load the correct value after service.
  108  *----------------------------------------------------------------------------
  109  */
  110         .set push
  111         .set noat
  112 MipsDoTLBMiss:
  113         bltz            k0, 1f                          #02: k0<0 -> 1f (kernel fault)
  114         PTR_SRL         k0, k0, SEGSHIFT - PTRSHIFT     #03: k0=seg offset (almost)
  115 
  116         GET_CPU_PCPU(k1)
  117         PTR_L           k1, PC_SEGBASE(k1)
  118         beqz            k1, 2f                          #05: make sure segbase is not null
  119         andi            k0, k0, PDEPTRMASK              #06: k0=seg offset
  120         PTR_ADDU        k1, k0, k1                      #07: k1=seg entry address
  121 
  122         PTR_L           k1, 0(k1)                       #08: k1=seg entry
  123         MFC0            k0, MIPS_COP_0_BAD_VADDR        #09: k0=bad address (again)
  124         beq             k1, zero, 2f                    #0a: ==0 -- no page table
  125 #ifdef __mips_n64
  126         PTR_SRL         k0, PDRSHIFT - PTRSHIFT         # k0=VPN
  127         andi            k0, k0, PDEPTRMASK              # k0=pde offset
  128         PTR_ADDU        k1, k0, k1                      # k1=pde entry address
  129         PTR_L           k1, 0(k1)                       # k1=pde entry
  130         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
  131         beq             k1, zero, 2f                    # ==0 -- no page table
  132 #endif
  133         PTR_SRL         k0, PAGE_SHIFT - PTESHIFT       #0b: k0=VPN (aka va>>10)
  134         andi            k0, k0, PTE2MASK                #0c: k0=page tab offset
  135         PTR_ADDU        k1, k1, k0                      #0d: k1=pte address
  136         PTE_L           k0, 0(k1)                       #0e: k0=lo0 pte
  137         PTE_L           k1, PTESIZE(k1)                 #0f: k1=lo0 pte
  138         CLEAR_PTE_SWBITS(k0)
  139         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0          #12: lo0 is loaded
  140         COP0_SYNC
  141         CLEAR_PTE_SWBITS(k1)
  142         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1          #15: lo1 is loaded
  143         COP0_SYNC
  144         tlbwr                                           #1a: write to tlb
  145         HAZARD_DELAY
  146         eret                                            #1f: retUrn from exception
  147 1:      j               MipsTLBMissException            #20: kernel exception
  148         nop                                             #21: branch delay slot
  149 2:      j               SlowFault                       #22: no page table present
  150         nop                                             #23: branch delay slot
  151         .set pop
  152 
  153 /*
  154  * This code is copied to the general exception vector address to
  155  * handle all execptions except RESET and TLBMiss.
  156  * NOTE: This code must be position independent!!!
  157  */
  158 VECTOR(MipsException, unknown)
  159 /*
  160  * Find out what mode we came from and jump to the proper handler.
  161  */
  162         .set    noat
  163         mfc0    k0, MIPS_COP_0_STATUS           # Get the status register
  164         mfc0    k1, MIPS_COP_0_CAUSE            # Get the cause register value.
  165         and     k0, k0, SR_KSU_USER             # test for user mode
  166                                                 # sneaky but the bits are
  167                                                 # with us........
  168         sll     k0, k0, 3                       # shift user bit for cause index
  169         and     k1, k1, MIPS3_CR_EXC_CODE       # Mask out the cause bits.
  170         or      k1, k1, k0                      # change index to user table
  171 #if defined(__mips_n64)
  172         PTR_SLL k1, k1, 1                       # shift to get 8-byte offset
  173 #endif
  174 1:
  175         PTR_LA  k0, _C_LABEL(machExceptionTable)  # get base of the jump table
  176         PTR_ADDU k0, k0, k1                     # Get the address of the
  177                                                 #  function entry.  Note that
  178                                                 #  the cause is already
  179                                                 #  shifted left by 2 bits so
  180                                                 #  we dont have to shift.
  181         PTR_L   k0, 0(k0)                       # Get the function address
  182         nop
  183         j       k0                              # Jump to the function.
  184         nop
  185         .set    at
  186 VECTOR_END(MipsException)
  187 
  188 /*
  189  * We couldn't find a TLB entry.
  190  * Find out what mode we came from and call the appropriate handler.
  191  */
  192 SlowFault:
  193         .set    noat
  194         mfc0    k0, MIPS_COP_0_STATUS
  195         nop
  196         and     k0, k0, SR_KSU_USER
  197         bne     k0, zero, _C_LABEL(MipsUserGenException)
  198         nop
  199         .set    at
  200 /*
  201  * Fall though ...
  202  */
  203 
  204 /*----------------------------------------------------------------------------
  205  *
  206  * MipsKernGenException --
  207  *
  208  *      Handle an exception from kernel mode.
  209  *
  210  * Results:
  211  *      None.
  212  *
  213  * Side effects:
  214  *      None.
  215  *
  216  *----------------------------------------------------------------------------
  217  */
  218 
  219 #define SAVE_REG(reg, offs, base) \
  220         REG_S   reg, CALLFRAME_SIZ + (SZREG * offs) (base)
  221 
  222 #if defined(CPU_CNMIPS)
  223 #define CLEAR_STATUS \
  224         mfc0    a0, MIPS_COP_0_STATUS   ;\
  225         li      a2, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX) ; \
  226         or      a0, a0, a2              ; \
  227         li      a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER)   ; \
  228         and     a0, a0, a2              ; \
  229         mtc0    a0, MIPS_COP_0_STATUS   ; \
  230         ITLBNOPFIX
  231 #elif defined(CPU_RMI) || defined(CPU_NLM)
  232 #define CLEAR_STATUS \
  233         mfc0    a0, MIPS_COP_0_STATUS   ;\
  234         li      a2, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT) ; \
  235         or      a0, a0, a2              ; \
  236         li      a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER)   ; \
  237         and     a0, a0, a2              ; \
  238         mtc0    a0, MIPS_COP_0_STATUS   ; \
  239         ITLBNOPFIX
  240 #else
  241 #define CLEAR_STATUS \
  242         mfc0    a0, MIPS_COP_0_STATUS   ;\
  243         li      a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER)   ; \
  244         and     a0, a0, a2              ; \
  245         mtc0    a0, MIPS_COP_0_STATUS   ; \
  246         ITLBNOPFIX
  247 #endif
  248 
  249 /*
  250  * Save CPU and CP0 register state.
  251  *
  252  * This is straightforward except for saving the exception program
  253  * counter. The ddb backtrace code looks for the first instruction
  254  * matching the form "sw ra, (off)sp" to figure out the address of the
  255  * calling function. So we must make sure that we save the exception
  256  * PC by staging it through 'ra' as opposed to any other register.
  257  */
  258 #define SAVE_CPU \
  259         SAVE_REG(AT, AST, sp)           ;\
  260         .set    at                      ; \
  261         SAVE_REG(v0, V0, sp)            ;\
  262         SAVE_REG(v1, V1, sp)            ;\
  263         SAVE_REG(a0, A0, sp)            ;\
  264         SAVE_REG(a1, A1, sp)            ;\
  265         SAVE_REG(a2, A2, sp)            ;\
  266         SAVE_REG(a3, A3, sp)            ;\
  267         SAVE_REG(t0, T0, sp)            ;\
  268         SAVE_REG(t1, T1, sp)            ;\
  269         SAVE_REG(t2, T2, sp)            ;\
  270         SAVE_REG(t3, T3, sp)            ;\
  271         SAVE_REG(ta0, TA0, sp)          ;\
  272         SAVE_REG(ta1, TA1, sp)          ;\
  273         SAVE_REG(ta2, TA2, sp)          ;\
  274         SAVE_REG(ta3, TA3, sp)          ;\
  275         SAVE_REG(t8, T8, sp)            ;\
  276         SAVE_REG(t9, T9, sp)            ;\
  277         SAVE_REG(gp, GP, sp)            ;\
  278         SAVE_REG(s0, S0, sp)            ;\
  279         SAVE_REG(s1, S1, sp)            ;\
  280         SAVE_REG(s2, S2, sp)            ;\
  281         SAVE_REG(s3, S3, sp)            ;\
  282         SAVE_REG(s4, S4, sp)            ;\
  283         SAVE_REG(s5, S5, sp)            ;\
  284         SAVE_REG(s6, S6, sp)            ;\
  285         SAVE_REG(s7, S7, sp)            ;\
  286         SAVE_REG(s8, S8, sp)            ;\
  287         mflo    v0                      ;\
  288         mfhi    v1                      ;\
  289         mfc0    a0, MIPS_COP_0_STATUS   ;\
  290         mfc0    a1, MIPS_COP_0_CAUSE    ;\
  291         MFC0    a2, MIPS_COP_0_BAD_VADDR;\
  292         MFC0    a3, MIPS_COP_0_EXC_PC   ;\
  293         SAVE_REG(v0, MULLO, sp)         ;\
  294         SAVE_REG(v1, MULHI, sp)         ;\
  295         SAVE_REG(a0, SR, sp)            ;\
  296         SAVE_REG(a1, CAUSE, sp)         ;\
  297         SAVE_REG(a2, BADVADDR, sp)      ;\
  298         move    t0, ra                  ;\
  299         move    ra, a3                  ;\
  300         SAVE_REG(ra, PC, sp)            ;\
  301         move    ra, t0                  ;\
  302         SAVE_REG(ra, RA, sp)            ;\
  303         PTR_ADDU v0, sp, KERN_EXC_FRAME_SIZE ;\
  304         SAVE_REG(v0, SP, sp)            ;\
  305         CLEAR_STATUS                    ;\
  306         PTR_ADDU a0, sp, CALLFRAME_SIZ  ;\
  307         ITLBNOPFIX
  308 
  309 #define RESTORE_REG(reg, offs, base) \
  310         REG_L   reg, CALLFRAME_SIZ + (SZREG * offs) (base)
  311 
  312 #define RESTORE_CPU \
  313         CLEAR_STATUS                    ;\
  314         RESTORE_REG(k0, SR, sp)         ;\
  315         RESTORE_REG(t0, MULLO, sp)      ;\
  316         RESTORE_REG(t1, MULHI, sp)      ;\
  317         mtlo    t0                      ;\
  318         mthi    t1                      ;\
  319         MTC0    v0, MIPS_COP_0_EXC_PC   ;\
  320         .set noat                       ;\
  321         RESTORE_REG(AT, AST, sp)        ;\
  322         RESTORE_REG(v0, V0, sp)         ;\
  323         RESTORE_REG(v1, V1, sp)         ;\
  324         RESTORE_REG(a0, A0, sp)         ;\
  325         RESTORE_REG(a1, A1, sp)         ;\
  326         RESTORE_REG(a2, A2, sp)         ;\
  327         RESTORE_REG(a3, A3, sp)         ;\
  328         RESTORE_REG(t0, T0, sp)         ;\
  329         RESTORE_REG(t1, T1, sp)         ;\
  330         RESTORE_REG(t2, T2, sp)         ;\
  331         RESTORE_REG(t3, T3, sp)         ;\
  332         RESTORE_REG(ta0, TA0, sp)       ;\
  333         RESTORE_REG(ta1, TA1, sp)       ;\
  334         RESTORE_REG(ta2, TA2, sp)       ;\
  335         RESTORE_REG(ta3, TA3, sp)       ;\
  336         RESTORE_REG(t8, T8, sp)         ;\
  337         RESTORE_REG(t9, T9, sp)         ;\
  338         RESTORE_REG(s0, S0, sp)         ;\
  339         RESTORE_REG(s1, S1, sp)         ;\
  340         RESTORE_REG(s2, S2, sp)         ;\
  341         RESTORE_REG(s3, S3, sp)         ;\
  342         RESTORE_REG(s4, S4, sp)         ;\
  343         RESTORE_REG(s5, S5, sp)         ;\
  344         RESTORE_REG(s6, S6, sp)         ;\
  345         RESTORE_REG(s7, S7, sp)         ;\
  346         RESTORE_REG(s8, S8, sp)         ;\
  347         RESTORE_REG(gp, GP, sp)         ;\
  348         RESTORE_REG(ra, RA, sp)         ;\
  349         PTR_ADDU sp, sp, KERN_EXC_FRAME_SIZE;\
  350         mtc0    k0, MIPS_COP_0_STATUS
  351 
  352 
  353 /*
  354  * The kernel exception stack contains 18 saved general registers,
  355  * the status register and the multiply lo and high registers.
  356  * In addition, we set this up for linkage conventions.
  357  */
  358 #define KERN_REG_SIZE           (NUMSAVEREGS * SZREG)
  359 #define KERN_EXC_FRAME_SIZE     (CALLFRAME_SIZ + KERN_REG_SIZE + 16)
  360 
  361 NNON_LEAF(MipsKernGenException, KERN_EXC_FRAME_SIZE, ra)
  362         .set    noat
  363         PTR_SUBU        sp, sp, KERN_EXC_FRAME_SIZE
  364         .mask   0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
  365 /*
  366  *  Save CPU state, building 'frame'.
  367  */
  368         SAVE_CPU
  369 /*
  370  *  Call the exception handler. a0 points at the saved frame.
  371  */
  372         PTR_LA  gp, _C_LABEL(_gp)
  373         PTR_LA  k0, _C_LABEL(trap)
  374         jalr    k0
  375         REG_S   a3, CALLFRAME_RA + KERN_REG_SIZE(sp)            # for debugging
  376 
  377         /*
  378          * Update interrupt mask in saved status register
  379          * Some of interrupts could be disabled by
  380          * intr filters if interrupts are enabled later
  381          * in trap handler
  382          */
  383         mfc0    a0, MIPS_COP_0_STATUS
  384         and     a0, a0, MIPS_SR_INT_MASK
  385         RESTORE_REG(a1, SR, sp)
  386         and     a1, a1, ~MIPS_SR_INT_MASK
  387         or      a1, a1, a0
  388         SAVE_REG(a1, SR, sp)
  389         RESTORE_CPU                     # v0 contains the return address.
  390         sync
  391         eret
  392         .set    at
  393 END(MipsKernGenException)
  394 
  395 
  396 #define SAVE_U_PCB_REG(reg, offs, base) \
  397         REG_S   reg, U_PCB_REGS + (SZREG * offs) (base)
  398 
  399 #define RESTORE_U_PCB_REG(reg, offs, base) \
  400         REG_L   reg, U_PCB_REGS + (SZREG * offs) (base)
  401 
  402 /*----------------------------------------------------------------------------
  403  *
  404  * MipsUserGenException --
  405  *
  406  *      Handle an exception from user mode.
  407  *
  408  * Results:
  409  *      None.
  410  *
  411  * Side effects:
  412  *      None.
  413  *
  414  *----------------------------------------------------------------------------
  415  */
  416 NNON_LEAF(MipsUserGenException, CALLFRAME_SIZ, ra)
  417         .set    noat
  418         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  419 /*
  420  * Save all of the registers except for the kernel temporaries in u.u_pcb.
  421  */
  422         GET_CPU_PCPU(k1)
  423         PTR_L   k1, PC_CURPCB(k1)
  424         SAVE_U_PCB_REG(AT, AST, k1)
  425         .set    at
  426         SAVE_U_PCB_REG(v0, V0, k1)
  427         SAVE_U_PCB_REG(v1, V1, k1)
  428         SAVE_U_PCB_REG(a0, A0, k1)
  429         mflo    v0
  430         SAVE_U_PCB_REG(a1, A1, k1)
  431         SAVE_U_PCB_REG(a2, A2, k1)
  432         SAVE_U_PCB_REG(a3, A3, k1)
  433         SAVE_U_PCB_REG(t0, T0, k1)
  434         mfhi    v1
  435         SAVE_U_PCB_REG(t1, T1, k1)
  436         SAVE_U_PCB_REG(t2, T2, k1)
  437         SAVE_U_PCB_REG(t3, T3, k1)
  438         SAVE_U_PCB_REG(ta0, TA0, k1)
  439         mfc0    a0, MIPS_COP_0_STATUS           # First arg is the status reg.
  440         SAVE_U_PCB_REG(ta1, TA1, k1)
  441         SAVE_U_PCB_REG(ta2, TA2, k1)
  442         SAVE_U_PCB_REG(ta3, TA3, k1)
  443         SAVE_U_PCB_REG(s0, S0, k1)
  444         mfc0    a1, MIPS_COP_0_CAUSE            # Second arg is the cause reg.
  445         SAVE_U_PCB_REG(s1, S1, k1)
  446         SAVE_U_PCB_REG(s2, S2, k1)
  447         SAVE_U_PCB_REG(s3, S3, k1)
  448         SAVE_U_PCB_REG(s4, S4, k1)
  449         MFC0    a2, MIPS_COP_0_BAD_VADDR        # Third arg is the fault addr
  450         SAVE_U_PCB_REG(s5, S5, k1)
  451         SAVE_U_PCB_REG(s6, S6, k1)
  452         SAVE_U_PCB_REG(s7, S7, k1)
  453         SAVE_U_PCB_REG(t8, T8, k1)
  454         MFC0    a3, MIPS_COP_0_EXC_PC           # Fourth arg is the pc.
  455         SAVE_U_PCB_REG(t9, T9, k1)
  456         SAVE_U_PCB_REG(gp, GP, k1)
  457         SAVE_U_PCB_REG(sp, SP, k1)
  458         SAVE_U_PCB_REG(s8, S8, k1)
  459         PTR_SUBU        sp, k1, CALLFRAME_SIZ    # switch to kernel SP
  460         SAVE_U_PCB_REG(ra, RA, k1)
  461         SAVE_U_PCB_REG(v0, MULLO, k1)
  462         SAVE_U_PCB_REG(v1, MULHI, k1)
  463         SAVE_U_PCB_REG(a0, SR, k1)
  464         SAVE_U_PCB_REG(a1, CAUSE, k1)
  465         SAVE_U_PCB_REG(a2, BADVADDR, k1)
  466         SAVE_U_PCB_REG(a3, PC, k1)
  467         REG_S   a3, CALLFRAME_RA(sp)    # for debugging
  468         PTR_LA  gp, _C_LABEL(_gp)       # switch to kernel GP
  469 # Turn off fpu and enter kernel mode
  470         and     t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS3_SR_KSU_MASK | MIPS_SR_INT_IE)
  471 #if defined(CPU_CNMIPS)
  472         or      t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_PX)
  473 #elif defined(CPU_RMI)  || defined(CPU_NLM)
  474         or      t0, t0, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT)
  475 #endif  
  476         mtc0    t0, MIPS_COP_0_STATUS
  477         PTR_ADDU a0, k1, U_PCB_REGS
  478         ITLBNOPFIX
  479 
  480 /*
  481  * Call the exception handler.
  482  */
  483         PTR_LA  k0, _C_LABEL(trap)
  484         jalr    k0
  485         nop
  486 
  487 /*
  488  * Restore user registers and return.
  489  * First disable interrupts and set exeption level.
  490  */
  491         DO_AST
  492 
  493         CLEAR_STATUS
  494 
  495 /*
  496  * The use of k1 for storing the PCB pointer must be done only
  497  * after interrupts are disabled.  Otherwise it will get overwritten
  498  * by the interrupt code.
  499  */
  500         GET_CPU_PCPU(k1)
  501         PTR_L   k1, PC_CURPCB(k1)
  502 
  503         /*
  504          * Update interrupt mask in saved status register
  505          * Some of interrupts could be enabled by ithread
  506          * scheduled by ast()
  507          */
  508         mfc0    a0, MIPS_COP_0_STATUS
  509         and     a0, a0, MIPS_SR_INT_MASK
  510         RESTORE_U_PCB_REG(a1, SR, k1)
  511         and     a1, a1, ~MIPS_SR_INT_MASK
  512         or      a1, a1, a0
  513         SAVE_U_PCB_REG(a1, SR, k1)
  514 
  515         RESTORE_U_PCB_REG(t0, MULLO, k1)
  516         RESTORE_U_PCB_REG(t1, MULHI, k1)
  517         mtlo    t0
  518         mthi    t1
  519         RESTORE_U_PCB_REG(a0, PC, k1)
  520         RESTORE_U_PCB_REG(v0, V0, k1)
  521         MTC0    a0, MIPS_COP_0_EXC_PC   # set return address
  522         RESTORE_U_PCB_REG(v1, V1, k1)
  523         RESTORE_U_PCB_REG(a0, A0, k1)
  524         RESTORE_U_PCB_REG(a1, A1, k1)
  525         RESTORE_U_PCB_REG(a2, A2, k1)
  526         RESTORE_U_PCB_REG(a3, A3, k1)
  527         RESTORE_U_PCB_REG(t0, T0, k1)
  528         RESTORE_U_PCB_REG(t1, T1, k1)
  529         RESTORE_U_PCB_REG(t2, T2, k1)
  530         RESTORE_U_PCB_REG(t3, T3, k1)
  531         RESTORE_U_PCB_REG(ta0, TA0, k1)
  532         RESTORE_U_PCB_REG(ta1, TA1, k1)
  533         RESTORE_U_PCB_REG(ta2, TA2, k1)
  534         RESTORE_U_PCB_REG(ta3, TA3, k1)
  535         RESTORE_U_PCB_REG(s0, S0, k1)
  536         RESTORE_U_PCB_REG(s1, S1, k1)
  537         RESTORE_U_PCB_REG(s2, S2, k1)
  538         RESTORE_U_PCB_REG(s3, S3, k1)
  539         RESTORE_U_PCB_REG(s4, S4, k1)
  540         RESTORE_U_PCB_REG(s5, S5, k1)
  541         RESTORE_U_PCB_REG(s6, S6, k1)
  542         RESTORE_U_PCB_REG(s7, S7, k1)
  543         RESTORE_U_PCB_REG(t8, T8, k1)
  544         RESTORE_U_PCB_REG(t9, T9, k1)
  545         RESTORE_U_PCB_REG(gp, GP, k1)
  546         RESTORE_U_PCB_REG(sp, SP, k1)
  547         RESTORE_U_PCB_REG(k0, SR, k1)
  548         RESTORE_U_PCB_REG(s8, S8, k1)
  549         RESTORE_U_PCB_REG(ra, RA, k1)
  550         .set noat
  551         RESTORE_U_PCB_REG(AT, AST, k1)
  552 
  553         mtc0    k0, MIPS_COP_0_STATUS   # still exception level
  554         ITLBNOPFIX
  555         sync
  556         eret
  557         .set    at
  558 END(MipsUserGenException)
  559 
  560 /*----------------------------------------------------------------------------
  561  *
  562  * MipsKernIntr --
  563  *
  564  *      Handle an interrupt from kernel mode.
  565  *      Interrupts use the standard kernel stack.
  566  *      switch_exit sets up a kernel stack after exit so interrupts won't fail.
  567  *
  568  * Results:
  569  *      None.
  570  *
  571  * Side effects:
  572  *      None.
  573  *
  574  *----------------------------------------------------------------------------
  575  */
  576 
  577 NNON_LEAF(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
  578         .set    noat
  579         PTR_SUBU        sp, sp, KERN_EXC_FRAME_SIZE
  580         .mask   0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
  581 /*
  582  *  Save CPU state, building 'frame'.
  583  */
  584         SAVE_CPU
  585 /*
  586  *  Call the interrupt handler. a0 points at the saved frame.
  587  */
  588         PTR_LA  gp, _C_LABEL(_gp)
  589         PTR_LA  k0, _C_LABEL(cpu_intr)
  590         jalr    k0
  591         REG_S   a3, CALLFRAME_RA + KERN_REG_SIZE(sp)            # for debugging
  592 
  593         /*
  594          * Update interrupt mask in saved status register
  595          * Some of interrupts could be disabled by
  596          * intr filters if interrupts are enabled later
  597          * in trap handler
  598          */
  599         mfc0    a0, MIPS_COP_0_STATUS
  600         and     a0, a0, MIPS_SR_INT_MASK
  601         RESTORE_REG(a1, SR, sp)
  602         and     a1, a1, ~MIPS_SR_INT_MASK
  603         or      a1, a1, a0
  604         SAVE_REG(a1, SR, sp)
  605         REG_L   v0, CALLFRAME_RA + KERN_REG_SIZE(sp)
  606         RESTORE_CPU                     # v0 contains the return address.
  607         sync
  608         eret
  609         .set    at
  610 END(MipsKernIntr)
  611 
  612 /*----------------------------------------------------------------------------
  613  *
  614  * MipsUserIntr --
  615  *
  616  *      Handle an interrupt from user mode.
  617  *      Note: we save minimal state in the u.u_pcb struct and use the standard
  618  *      kernel stack since there has to be a u page if we came from user mode.
  619  *      If there is a pending software interrupt, then save the remaining state
  620  *      and call softintr(). This is all because if we call switch() inside
  621  *      interrupt(), not all the user registers have been saved in u.u_pcb.
  622  *
  623  * Results:
  624  *      None.
  625  *
  626  * Side effects:
  627  *      None.
  628  *
  629  *----------------------------------------------------------------------------
  630  */
  631 NNON_LEAF(MipsUserIntr, CALLFRAME_SIZ, ra)
  632         .set    noat
  633         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  634 /*
  635  * Save the relevant user registers into the u.u_pcb struct.
  636  * We don't need to save s0 - s8 because the compiler does it for us.
  637  */
  638         GET_CPU_PCPU(k1)
  639         PTR_L   k1, PC_CURPCB(k1)
  640         SAVE_U_PCB_REG(AT, AST, k1)
  641         .set    at
  642         SAVE_U_PCB_REG(v0, V0, k1)
  643         SAVE_U_PCB_REG(v1, V1, k1)
  644         SAVE_U_PCB_REG(a0, A0, k1)
  645         SAVE_U_PCB_REG(a1, A1, k1)
  646         SAVE_U_PCB_REG(a2, A2, k1)
  647         SAVE_U_PCB_REG(a3, A3, k1)
  648         SAVE_U_PCB_REG(t0, T0, k1)
  649         SAVE_U_PCB_REG(t1, T1, k1)
  650         SAVE_U_PCB_REG(t2, T2, k1)
  651         SAVE_U_PCB_REG(t3, T3, k1)
  652         SAVE_U_PCB_REG(ta0, TA0, k1)
  653         SAVE_U_PCB_REG(ta1, TA1, k1)
  654         SAVE_U_PCB_REG(ta2, TA2, k1)
  655         SAVE_U_PCB_REG(ta3, TA3, k1)
  656         SAVE_U_PCB_REG(t8, T8, k1)
  657         SAVE_U_PCB_REG(t9, T9, k1)
  658         SAVE_U_PCB_REG(gp, GP, k1)
  659         SAVE_U_PCB_REG(sp, SP, k1)
  660         SAVE_U_PCB_REG(ra, RA, k1)
  661 /*
  662  *  save remaining user state in u.u_pcb.
  663  */
  664         SAVE_U_PCB_REG(s0, S0, k1)
  665         SAVE_U_PCB_REG(s1, S1, k1)
  666         SAVE_U_PCB_REG(s2, S2, k1)
  667         SAVE_U_PCB_REG(s3, S3, k1)
  668         SAVE_U_PCB_REG(s4, S4, k1)
  669         SAVE_U_PCB_REG(s5, S5, k1)
  670         SAVE_U_PCB_REG(s6, S6, k1)
  671         SAVE_U_PCB_REG(s7, S7, k1)
  672         SAVE_U_PCB_REG(s8, S8, k1)
  673 
  674         mflo    v0                      # get lo/hi late to avoid stall
  675         mfhi    v1
  676         mfc0    a0, MIPS_COP_0_STATUS
  677         mfc0    a1, MIPS_COP_0_CAUSE
  678         MFC0    a3, MIPS_COP_0_EXC_PC
  679         SAVE_U_PCB_REG(v0, MULLO, k1)
  680         SAVE_U_PCB_REG(v1, MULHI, k1)
  681         SAVE_U_PCB_REG(a0, SR, k1)
  682         SAVE_U_PCB_REG(a1, CAUSE, k1)
  683         SAVE_U_PCB_REG(a3, PC, k1)      # PC in a3, note used later!
  684         PTR_SUBU        sp, k1, CALLFRAME_SIZ  # switch to kernel SP
  685         PTR_LA  gp, _C_LABEL(_gp)       # switch to kernel GP
  686 
  687 # Turn off fpu, disable interrupts, set kernel mode kernel mode, clear exception level.
  688         and     t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS3_SR_KSU_MASK)
  689 #ifdef CPU_CNMIPS
  690         or      t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_PX)
  691 #elif defined(CPU_RMI)  || defined(CPU_NLM)
  692         or      t0, t0, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT)
  693 #endif  
  694         mtc0    t0, MIPS_COP_0_STATUS
  695         ITLBNOPFIX
  696         PTR_ADDU a0, k1, U_PCB_REGS
  697 /*
  698  * Call the interrupt handler.
  699  */
  700         PTR_LA  k0, _C_LABEL(cpu_intr)
  701         jalr    k0
  702         REG_S   a3, CALLFRAME_RA(sp)    # for debugging
  703 
  704 /*
  705  * Enable interrupts before doing ast().
  706  *
  707  * On SMP kernels the AST processing might trigger IPI to other processors.
  708  * If that processor is also doing AST processing with interrupts disabled
  709  * then we may deadlock.
  710  */
  711         mfc0    a0, MIPS_COP_0_STATUS
  712         or      a0, a0, MIPS_SR_INT_IE
  713         mtc0    a0, MIPS_COP_0_STATUS
  714         ITLBNOPFIX
  715 
  716 /*
  717  * DO_AST enabled interrupts
  718  */
  719         DO_AST
  720         
  721 /*
  722  * Restore user registers and return. 
  723  */
  724         CLEAR_STATUS
  725 
  726         GET_CPU_PCPU(k1)
  727         PTR_L   k1, PC_CURPCB(k1)
  728 
  729         /*
  730          * Update interrupt mask in saved status register
  731          * Some of interrupts could be disabled by
  732          * intr filters
  733          */
  734         mfc0    a0, MIPS_COP_0_STATUS
  735         and     a0, a0, MIPS_SR_INT_MASK
  736         RESTORE_U_PCB_REG(a1, SR, k1)
  737         and     a1, a1, ~MIPS_SR_INT_MASK
  738         or      a1, a1, a0
  739         SAVE_U_PCB_REG(a1, SR, k1)
  740 
  741         RESTORE_U_PCB_REG(s0, S0, k1)
  742         RESTORE_U_PCB_REG(s1, S1, k1)
  743         RESTORE_U_PCB_REG(s2, S2, k1)
  744         RESTORE_U_PCB_REG(s3, S3, k1)
  745         RESTORE_U_PCB_REG(s4, S4, k1)
  746         RESTORE_U_PCB_REG(s5, S5, k1)
  747         RESTORE_U_PCB_REG(s6, S6, k1)
  748         RESTORE_U_PCB_REG(s7, S7, k1)
  749         RESTORE_U_PCB_REG(s8, S8, k1)
  750         RESTORE_U_PCB_REG(t0, MULLO, k1)
  751         RESTORE_U_PCB_REG(t1, MULHI, k1)
  752         RESTORE_U_PCB_REG(t2, PC, k1)
  753         mtlo    t0
  754         mthi    t1
  755         MTC0    t2, MIPS_COP_0_EXC_PC   # set return address
  756         RESTORE_U_PCB_REG(v0, V0, k1)
  757         RESTORE_U_PCB_REG(v1, V1, k1)
  758         RESTORE_U_PCB_REG(a0, A0, k1)
  759         RESTORE_U_PCB_REG(a1, A1, k1)
  760         RESTORE_U_PCB_REG(a2, A2, k1)
  761         RESTORE_U_PCB_REG(a3, A3, k1)
  762         RESTORE_U_PCB_REG(t0, T0, k1)
  763         RESTORE_U_PCB_REG(t1, T1, k1)
  764         RESTORE_U_PCB_REG(t2, T2, k1)
  765         RESTORE_U_PCB_REG(t3, T3, k1)
  766         RESTORE_U_PCB_REG(ta0, TA0, k1)
  767         RESTORE_U_PCB_REG(ta1, TA1, k1)
  768         RESTORE_U_PCB_REG(ta2, TA2, k1)
  769         RESTORE_U_PCB_REG(ta3, TA3, k1)
  770         RESTORE_U_PCB_REG(t8, T8, k1)
  771         RESTORE_U_PCB_REG(t9, T9, k1)
  772         RESTORE_U_PCB_REG(gp, GP, k1)
  773         RESTORE_U_PCB_REG(k0, SR, k1)
  774         RESTORE_U_PCB_REG(sp, SP, k1)
  775         RESTORE_U_PCB_REG(ra, RA, k1)
  776         .set    noat
  777         RESTORE_U_PCB_REG(AT, AST, k1)
  778 
  779         mtc0    k0, MIPS_COP_0_STATUS   # SR with EXL set. 
  780         ITLBNOPFIX
  781         sync
  782         eret
  783         .set    at
  784 END(MipsUserIntr)
  785 
  786 NLEAF(MipsTLBInvalidException)
  787         .set push
  788         .set noat
  789         .set noreorder
  790 
  791         MFC0            k0, MIPS_COP_0_BAD_VADDR
  792         PTR_LI          k1, VM_MAXUSER_ADDRESS
  793         sltu            k1, k0, k1
  794         bnez            k1, 1f
  795         nop
  796 
  797         /* Kernel address.  */
  798         lui             k1, %hi(kernel_segmap)          # k1=hi of segbase
  799         b               2f
  800         PTR_L           k1, %lo(kernel_segmap)(k1)      # k1=segment tab base
  801 
  802 1:      /* User address.  */
  803         GET_CPU_PCPU(k1)
  804         PTR_L           k1, PC_SEGBASE(k1)
  805 
  806 2:      /* Validate page directory pointer.  */
  807         beqz            k1, 3f
  808         nop
  809 
  810         PTR_SRL         k0, SEGSHIFT - PTRSHIFT         # k0=seg offset (almost)
  811         beq             k1, zero, MipsKernGenException  # ==0 -- no seg tab
  812         andi            k0, k0, PDEPTRMASK              #06: k0=seg offset
  813         PTR_ADDU        k1, k0, k1                      # k1=seg entry address
  814         PTR_L           k1, 0(k1)                       # k1=seg entry
  815 
  816         /* Validate page table pointer.  */
  817         beqz            k1, 3f
  818         nop
  819 
  820 #ifdef __mips_n64
  821         MFC0            k0, MIPS_COP_0_BAD_VADDR
  822         PTR_SRL         k0, PDRSHIFT - PTRSHIFT         # k0=pde offset (almost)
  823         beq             k1, zero, MipsKernGenException  # ==0 -- no pde tab
  824         andi            k0, k0, PDEPTRMASK              # k0=pde offset
  825         PTR_ADDU        k1, k0, k1                      # k1=pde entry address
  826         PTR_L           k1, 0(k1)                       # k1=pde entry
  827 
  828         /* Validate pde table pointer.  */
  829         beqz            k1, 3f
  830         nop
  831 #endif
  832         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
  833         PTR_SRL         k0, PAGE_SHIFT - PTESHIFT       # k0=VPN
  834         andi            k0, k0, PTEMASK                 # k0=page tab offset
  835         PTR_ADDU        k1, k1, k0                      # k1=pte address
  836         PTE_L           k0, 0(k1)                       # k0=this PTE
  837 
  838         /* Validate page table entry.  */
  839         andi            k0, PTE_V
  840         beqz            k0, 3f
  841         nop
  842 
  843         /* Check whether this is an even or odd entry.  */
  844         andi            k0, k1, PTESIZE
  845         bnez            k0, odd_page
  846         nop
  847 
  848         PTE_L           k0, 0(k1)
  849         PTE_L           k1, PTESIZE(k1)
  850         CLEAR_PTE_SWBITS(k0)
  851         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0
  852         COP0_SYNC
  853         CLEAR_PTE_SWBITS(k1)
  854         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1
  855         COP0_SYNC
  856 
  857         b               tlb_insert_entry
  858         nop
  859 
  860 odd_page:
  861         PTE_L           k0, -PTESIZE(k1)
  862         PTE_L           k1, 0(k1)
  863         CLEAR_PTE_SWBITS(k0)
  864         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0
  865         COP0_SYNC
  866         CLEAR_PTE_SWBITS(k1)
  867         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1
  868         COP0_SYNC
  869 
  870 tlb_insert_entry:
  871         tlbp
  872         HAZARD_DELAY
  873         mfc0            k0, MIPS_COP_0_TLB_INDEX
  874         bltz            k0, tlb_insert_random
  875         nop
  876         tlbwi
  877         eret
  878         ssnop
  879 
  880 tlb_insert_random:
  881         tlbwr
  882         eret
  883         ssnop
  884 
  885 3:
  886         /*
  887          * Branch to the comprehensive exception processing.
  888          */
  889         mfc0    k1, MIPS_COP_0_STATUS
  890         andi    k1, k1, SR_KSU_USER
  891         bnez    k1, _C_LABEL(MipsUserGenException)
  892         nop
  893 
  894         /*
  895          * Check for kernel stack overflow.
  896          */
  897         GET_CPU_PCPU(k1)
  898         PTR_L   k0, PC_CURTHREAD(k1)
  899         PTR_L   k0, TD_KSTACK(k0)
  900         sltu    k0, k0, sp
  901         bnez    k0, _C_LABEL(MipsKernGenException)
  902         nop
  903 
  904         /*
  905          * Kernel stack overflow.
  906          *
  907          * Move to a valid stack before we call panic. We use the boot stack
  908          * for this purpose.
  909          */
  910         GET_CPU_PCPU(k1)
  911         lw      k1, PC_CPUID(k1)
  912         sll     k1, k1, PAGE_SHIFT + 1
  913 
  914         PTR_LA  k0, _C_LABEL(pcpu_space)
  915         PTR_ADDU        k0, PAGE_SIZE * 2
  916         PTR_ADDU        k0, k0, k1
  917 
  918         /*
  919          * Stash the original value of 'sp' so we can update trapframe later.
  920          * We assume that SAVE_CPU does not trash 'k1'.
  921          */
  922         move    k1, sp
  923 
  924         move    sp, k0
  925         PTR_SUBU        sp, sp, KERN_EXC_FRAME_SIZE
  926 
  927         move    k0, ra
  928         move    ra, zero
  929         REG_S   ra, CALLFRAME_RA(sp)    /* stop the ddb backtrace right here */
  930         REG_S   zero, CALLFRAME_SP(sp)
  931         move    ra, k0
  932 
  933         SAVE_CPU
  934 
  935         /*
  936          * Now restore the value of 'sp' at the time of the tlb exception in
  937          * the trapframe.
  938          */
  939         SAVE_REG(k1, SP, sp)
  940 
  941         /*
  942          * Squelch any more overflow checks by setting the stack base to 0.
  943          */
  944         GET_CPU_PCPU(k1)
  945         PTR_L   k0, PC_CURTHREAD(k1)
  946         PTR_S   zero, TD_KSTACK(k0)
  947 
  948         move    a1, a0
  949         PANIC("kernel stack overflow - trapframe at %p")
  950 
  951         /*
  952          * This nop is necessary so that the 'ra' remains within the bounds
  953          * of this handler. Otherwise the ddb backtrace code will think that
  954          * the panic() was called from MipsTLBMissException.
  955          */
  956         nop
  957 
  958         .set pop
  959 END(MipsTLBInvalidException)
  960 
  961 /*----------------------------------------------------------------------------
  962  *
  963  * MipsTLBMissException --
  964  *
  965  *      Handle a TLB miss exception from kernel mode in kernel space.
  966  *      The BaddVAddr, Context, and EntryHi registers contain the failed
  967  *      virtual address.
  968  *
  969  * Results:
  970  *      None.
  971  *
  972  * Side effects:
  973  *      None.
  974  *
  975  *----------------------------------------------------------------------------
  976  */
  977 NLEAF(MipsTLBMissException)
  978         .set    noat
  979         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address
  980         PTR_LI          k1, VM_MAX_KERNEL_ADDRESS       # check fault address against
  981         sltu            k1, k1, k0                      # upper bound of kernel_segmap
  982         bnez            k1, MipsKernGenException        # out of bound
  983         lui             k1, %hi(kernel_segmap)          # k1=hi of segbase
  984         PTR_SRL         k0, SEGSHIFT - PTRSHIFT         # k0=seg offset (almost)
  985         PTR_L           k1, %lo(kernel_segmap)(k1)      # k1=segment tab base
  986         beq             k1, zero, MipsKernGenException  # ==0 -- no seg tab
  987         andi            k0, k0, PDEPTRMASK              #06: k0=seg offset
  988         PTR_ADDU        k1, k0, k1                      # k1=seg entry address
  989         PTR_L           k1, 0(k1)                       # k1=seg entry
  990         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
  991         beq             k1, zero, MipsKernGenException  # ==0 -- no page table
  992 #ifdef __mips_n64
  993         PTR_SRL         k0, PDRSHIFT - PTRSHIFT         # k0=VPN
  994         andi            k0, k0, PDEPTRMASK              # k0=pde offset
  995         PTR_ADDU        k1, k0, k1                      # k1=pde entry address
  996         PTR_L           k1, 0(k1)                       # k1=pde entry
  997         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
  998         beq             k1, zero, MipsKernGenException  # ==0 -- no page table
  999 #endif
 1000         PTR_SRL         k0, PAGE_SHIFT - PTESHIFT       # k0=VPN
 1001         andi            k0, k0, PTE2MASK                # k0=page tab offset
 1002         PTR_ADDU        k1, k1, k0                      # k1=pte address
 1003         PTE_L           k0, 0(k1)                       # k0=lo0 pte
 1004         PTE_L           k1, PTESIZE(k1)                 # k1=lo1 pte
 1005         CLEAR_PTE_SWBITS(k0)
 1006         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0          # lo0 is loaded
 1007         COP0_SYNC
 1008         CLEAR_PTE_SWBITS(k1)
 1009         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1          # lo1 is loaded
 1010         COP0_SYNC
 1011         tlbwr                                   # write to tlb
 1012         HAZARD_DELAY
 1013         eret                                    # return from exception
 1014         .set    at
 1015 END(MipsTLBMissException)
 1016 
 1017 /*----------------------------------------------------------------------------
 1018  *
 1019  * MipsFPTrap --
 1020  *
 1021  *      Handle a floating point Trap.
 1022  *
 1023  *      MipsFPTrap(statusReg, causeReg, pc)
 1024  *              unsigned statusReg;
 1025  *              unsigned causeReg;
 1026  *              unsigned pc;
 1027  *
 1028  * Results:
 1029  *      None.
 1030  *
 1031  * Side effects:
 1032  *      None.
 1033  *
 1034  *----------------------------------------------------------------------------
 1035  */
 1036 NON_LEAF(MipsFPTrap, CALLFRAME_SIZ, ra)
 1037         PTR_SUBU        sp, sp, CALLFRAME_SIZ
 1038         mfc0    t0, MIPS_COP_0_STATUS
 1039         REG_S   ra, CALLFRAME_RA(sp)
 1040         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
 1041 
 1042         or      t1, t0, MIPS_SR_COP_1_BIT
 1043         mtc0    t1, MIPS_COP_0_STATUS
 1044         ITLBNOPFIX
 1045         cfc1    t1, MIPS_FPU_CSR                # stall til FP done
 1046         cfc1    t1, MIPS_FPU_CSR                # now get status
 1047         nop
 1048         sll     t2, t1, (31 - 17)               # unimplemented operation?
 1049         bgez    t2, 3f                          # no, normal trap
 1050         nop
 1051 /*
 1052  * We got an unimplemented operation trap so
 1053  * fetch the instruction, compute the next PC and emulate the instruction.
 1054  */
 1055         bgez    a1, 1f                          # Check the branch delay bit.
 1056         nop
 1057 /*
 1058  * The instruction is in the branch delay slot so the branch will have to
 1059  * be emulated to get the resulting PC.
 1060  */
 1061         PTR_S   a2, CALLFRAME_SIZ + 8(sp)
 1062         GET_CPU_PCPU(a0)
 1063 #mips64 unsafe?
 1064         PTR_L   a0, PC_CURPCB(a0)
 1065         PTR_ADDU a0, a0, U_PCB_REGS             # first arg is ptr to CPU registers
 1066         move    a1, a2                          # second arg is instruction PC
 1067         move    a2, t1                          # third arg is floating point CSR
 1068         PTR_LA  t3, _C_LABEL(MipsEmulateBranch) # compute PC after branch
 1069         jalr    t3                              # compute PC after branch
 1070         move    a3, zero                        # fourth arg is FALSE
 1071 /*
 1072  * Now load the floating-point instruction in the branch delay slot
 1073  * to be emulated.
 1074  */
 1075         PTR_L   a2, CALLFRAME_SIZ + 8(sp)       # restore EXC pc
 1076         b       2f
 1077         lw      a0, 4(a2)                       # a0 = coproc instruction
 1078 /*
 1079  * This is not in the branch delay slot so calculate the resulting
 1080  * PC (epc + 4) into v0 and continue to MipsEmulateFP().
 1081  */
 1082 1:
 1083         lw      a0, 0(a2)                       # a0 = coproc instruction
 1084 #xxx mips64 unsafe?
 1085         PTR_ADDU        v0, a2, 4                       # v0 = next pc
 1086 2:
 1087         GET_CPU_PCPU(t2)
 1088         PTR_L   t2, PC_CURPCB(t2)
 1089         SAVE_U_PCB_REG(v0, PC, t2)              # save new pc
 1090 /*
 1091  * Check to see if the instruction to be emulated is a floating-point
 1092  * instruction.
 1093  */
 1094         srl     a3, a0, MIPS_OPCODE_SHIFT
 1095         beq     a3, MIPS_OPCODE_C1, 4f          # this should never fail
 1096         nop
 1097 /*
 1098  * Send a floating point exception signal to the current process.
 1099  */
 1100 3:
 1101         GET_CPU_PCPU(a0)
 1102         PTR_L   a0, PC_CURTHREAD(a0)            # get current thread
 1103         cfc1    a2, MIPS_FPU_CSR                # code = FP execptions
 1104         ctc1    zero, MIPS_FPU_CSR              # Clear exceptions
 1105         PTR_LA  t3, _C_LABEL(trapsignal)
 1106         jalr    t3
 1107         li      a1, SIGFPE
 1108         b       FPReturn
 1109         nop
 1110 
 1111 /*
 1112  * Finally, we can call MipsEmulateFP() where a0 is the instruction to emulate.
 1113  */
 1114 4:
 1115         PTR_LA  t3, _C_LABEL(MipsEmulateFP)
 1116         jalr    t3
 1117         nop
 1118 
 1119 /*
 1120  * Turn off the floating point coprocessor and return.
 1121  */
 1122 FPReturn:
 1123         mfc0    t0, MIPS_COP_0_STATUS
 1124         PTR_L   ra, CALLFRAME_RA(sp)
 1125         and     t0, t0, ~MIPS_SR_COP_1_BIT
 1126         mtc0    t0, MIPS_COP_0_STATUS
 1127         ITLBNOPFIX
 1128         j       ra
 1129         PTR_ADDU sp, sp, CALLFRAME_SIZ
 1130 END(MipsFPTrap)
 1131 
 1132 /*
 1133  * Interrupt counters for vmstat.
 1134  */
 1135         .data
 1136         .globl intrcnt
 1137         .globl sintrcnt
 1138         .globl intrnames
 1139         .globl sintrnames
 1140 intrnames:
 1141         .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1142 sintrnames:
 1143 #ifdef __mips_n64
 1144         .quad  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1145 #else
 1146         .int  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1147 #endif
 1148 
 1149         .align  4
 1150 intrcnt:
 1151         .space  INTRCNT_COUNT * 4 * 2
 1152 sintrcnt:
 1153 #ifdef __mips_n64
 1154         .quad  INTRCNT_COUNT * 4 * 2
 1155 #else
 1156         .int  INTRCNT_COUNT * 4 * 2
 1157 #endif
 1158 
 1159 
 1160 /*
 1161  * Vector to real handler in KSEG1.
 1162  */
 1163         .text
 1164 VECTOR(MipsCache, unknown)
 1165         PTR_LA  k0, _C_LABEL(MipsCacheException)
 1166         li      k1, MIPS_KSEG0_PHYS_MASK
 1167         and     k0, k1
 1168         PTR_LI  k1, MIPS_KSEG1_START
 1169         or      k0, k1
 1170         j       k0
 1171         nop
 1172 VECTOR_END(MipsCache)
 1173 
 1174         .set    at
 1175 
 1176 
 1177 /*
 1178  * Panic on cache errors.  A lot more could be done to recover
 1179  * from some types of errors but it is tricky.
 1180  */
 1181 NESTED_NOPROFILE(MipsCacheException, KERN_EXC_FRAME_SIZE, ra)
 1182         .set    noat
 1183         .mask   0x80000000, -4
 1184         PTR_LA  k0, _C_LABEL(panic)             # return to panic
 1185         PTR_LA  a0, 9f                          # panicstr
 1186         MFC0    a1, MIPS_COP_0_ERROR_PC
 1187         mfc0    a2, MIPS_COP_0_CACHE_ERR        # 3rd arg cache error
 1188 
 1189         MTC0    k0, MIPS_COP_0_ERROR_PC         # set return address
 1190 
 1191         mfc0    k0, MIPS_COP_0_STATUS           # restore status
 1192         li      k1, MIPS_SR_DIAG_PE             # ignore further errors
 1193         or      k0, k1
 1194         mtc0    k0, MIPS_COP_0_STATUS           # restore status
 1195         COP0_SYNC
 1196 
 1197         eret
 1198 
 1199         MSG("cache error @ EPC 0x%x CachErr 0x%x");
 1200         .set    at
 1201 END(MipsCacheException)

Cache object: db43236d10af1387322845b30b00c67f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.