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

Cache object: 4a204a2bfe4d99444e75c1bb9de7cc1b


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