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

Cache object: 37045dd8afe678ef53803f5c08368f55


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