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/11.0/sys/mips/mips/exception.S 299118 2016-05-05 13:54:50Z br $
   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.s"
   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         wait
  594 GLOBAL(MipsWaitEnd)                     # MipsWaitStart + 16
  595         jr      ra
  596         PTR_ADDU        sp, sp, CALLFRAME_SIZ
  597 END(mips_wait)
  598         .set    pop
  599 
  600 /*----------------------------------------------------------------------------
  601  *
  602  * MipsKernIntr --
  603  *
  604  *      Handle an interrupt from kernel mode.
  605  *      Interrupts use the standard kernel stack.
  606  *      switch_exit sets up a kernel stack after exit so interrupts won't fail.
  607  *
  608  * Results:
  609  *      None.
  610  *
  611  * Side effects:
  612  *      None.
  613  *
  614  *----------------------------------------------------------------------------
  615  */
  616 
  617 NESTED_NOPROFILE(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
  618         .set    noat
  619         PTR_SUBU        sp, sp, KERN_EXC_FRAME_SIZE
  620         .mask   0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
  621 
  622 /*
  623  * Check for getting interrupts just before wait
  624  */
  625         MFC0    k0, MIPS_COP_0_EXC_PC
  626         ori     k0, 0xf
  627         xori    k0, 0xf                 # 16 byte align
  628         PTR_LA  k1, MipsWaitStart
  629         bne     k0, k1, 1f
  630         nop
  631         PTR_ADDU k1, 16                 # skip over wait
  632         MTC0    k1, MIPS_COP_0_EXC_PC
  633 1:
  634 /*
  635  *  Save CPU state, building 'frame'.
  636  */
  637         SAVE_CPU
  638 /*
  639  *  Call the interrupt handler. a0 points at the saved frame.
  640  */
  641         PTR_LA  gp, _C_LABEL(_gp)
  642 #ifdef INTRNG
  643         PTR_LA  k0, _C_LABEL(intr_irq_handler)
  644 #else
  645         PTR_LA  k0, _C_LABEL(cpu_intr)
  646 #endif
  647         jalr    k0
  648         REG_S   a3, CALLFRAME_RA + KERN_REG_SIZE(sp)            # for debugging
  649 
  650         /*
  651          * Update interrupt and CPU mask in saved status register
  652          * Some of interrupts could be disabled by
  653          * intr filters if interrupts are enabled later
  654          * in trap handler
  655          */
  656         mfc0    a0, MIPS_COP_0_STATUS
  657         and     a0, a0, (MIPS_SR_INT_MASK|MIPS_SR_COP_USABILITY)
  658         RESTORE_REG(a1, SR, sp)
  659         and     a1, a1, ~(MIPS_SR_INT_MASK|MIPS_SR_COP_USABILITY)
  660         or      a1, a1, a0
  661         SAVE_REG(a1, SR, sp)
  662         REG_L   v0, CALLFRAME_RA + KERN_REG_SIZE(sp)
  663         RESTORE_CPU                     # v0 contains the return address.
  664         sync
  665         eret
  666         .set    at
  667 END(MipsKernIntr)
  668 
  669 /*----------------------------------------------------------------------------
  670  *
  671  * MipsUserIntr --
  672  *
  673  *      Handle an interrupt from user mode.
  674  *      Note: we save minimal state in the u.u_pcb struct and use the standard
  675  *      kernel stack since there has to be a u page if we came from user mode.
  676  *      If there is a pending software interrupt, then save the remaining state
  677  *      and call softintr(). This is all because if we call switch() inside
  678  *      interrupt(), not all the user registers have been saved in u.u_pcb.
  679  *
  680  * Results:
  681  *      None.
  682  *
  683  * Side effects:
  684  *      None.
  685  *
  686  *----------------------------------------------------------------------------
  687  */
  688 NESTED_NOPROFILE(MipsUserIntr, CALLFRAME_SIZ, ra)
  689         .set    noat
  690         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  691 /*
  692  * Save the relevant user registers into the u.u_pcb struct.
  693  * We don't need to save s0 - s8 because the compiler does it for us.
  694  */
  695         GET_CPU_PCPU(k1)
  696         PTR_L   k1, PC_CURPCB(k1)
  697         SAVE_U_PCB_REG(AT, AST, k1)
  698         .set    at
  699         SAVE_U_PCB_REG(v0, V0, k1)
  700         SAVE_U_PCB_REG(v1, V1, k1)
  701         SAVE_U_PCB_REG(a0, A0, k1)
  702         SAVE_U_PCB_REG(a1, A1, k1)
  703         SAVE_U_PCB_REG(a2, A2, k1)
  704         SAVE_U_PCB_REG(a3, A3, k1)
  705         SAVE_U_PCB_REG(t0, T0, k1)
  706         SAVE_U_PCB_REG(t1, T1, k1)
  707         SAVE_U_PCB_REG(t2, T2, k1)
  708         SAVE_U_PCB_REG(t3, T3, k1)
  709         SAVE_U_PCB_REG(ta0, TA0, k1)
  710         SAVE_U_PCB_REG(ta1, TA1, k1)
  711         SAVE_U_PCB_REG(ta2, TA2, k1)
  712         SAVE_U_PCB_REG(ta3, TA3, k1)
  713         SAVE_U_PCB_REG(t8, T8, k1)
  714         SAVE_U_PCB_REG(t9, T9, k1)
  715         SAVE_U_PCB_REG(gp, GP, k1)
  716         SAVE_U_PCB_REG(sp, SP, k1)
  717         SAVE_U_PCB_REG(ra, RA, k1)
  718 /*
  719  *  save remaining user state in u.u_pcb.
  720  */
  721         SAVE_U_PCB_REG(s0, S0, k1)
  722         SAVE_U_PCB_REG(s1, S1, k1)
  723         SAVE_U_PCB_REG(s2, S2, k1)
  724         SAVE_U_PCB_REG(s3, S3, k1)
  725         SAVE_U_PCB_REG(s4, S4, k1)
  726         SAVE_U_PCB_REG(s5, S5, k1)
  727         SAVE_U_PCB_REG(s6, S6, k1)
  728         SAVE_U_PCB_REG(s7, S7, k1)
  729         SAVE_U_PCB_REG(s8, S8, k1)
  730 
  731         mflo    v0                      # get lo/hi late to avoid stall
  732         mfhi    v1
  733         mfc0    a0, MIPS_COP_0_STATUS
  734         mfc0    a1, MIPS_COP_0_CAUSE
  735         MFC0    a3, MIPS_COP_0_EXC_PC
  736         SAVE_U_PCB_REG(v0, MULLO, k1)
  737         SAVE_U_PCB_REG(v1, MULHI, k1)
  738         SAVE_U_PCB_REG(a0, SR, k1)
  739         SAVE_U_PCB_REG(a1, CAUSE, k1)
  740         SAVE_U_PCB_REG(a3, PC, k1)      # PC in a3, note used later!
  741         PTR_SUBU        sp, k1, CALLFRAME_SIZ  # switch to kernel SP
  742         PTR_LA  gp, _C_LABEL(_gp)       # switch to kernel GP
  743 
  744 # Turn off fpu, disable interrupts, set kernel mode kernel mode, clear exception level.
  745         and     t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS_SR_KSU_MASK)
  746 #ifdef CPU_CNMIPS
  747         and     t0, t0, ~(MIPS_SR_COP_2_BIT)
  748         or      t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_PX)
  749 #elif defined(CPU_RMI)  || defined(CPU_NLM)
  750         or      t0, t0, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT)
  751 #endif  
  752         mtc0    t0, MIPS_COP_0_STATUS
  753         ITLBNOPFIX
  754         PTR_ADDU a0, k1, U_PCB_REGS
  755 /*
  756  * Call the interrupt handler.
  757  */
  758 #ifdef INTRNG
  759         PTR_LA  k0, _C_LABEL(intr_irq_handler)
  760 #else
  761         PTR_LA  k0, _C_LABEL(cpu_intr)
  762 #endif
  763         jalr    k0
  764         REG_S   a3, CALLFRAME_RA(sp)    # for debugging
  765 
  766 /*
  767  * Enable interrupts before doing ast().
  768  *
  769  * On SMP kernels the AST processing might trigger IPI to other processors.
  770  * If that processor is also doing AST processing with interrupts disabled
  771  * then we may deadlock.
  772  */
  773         mfc0    a0, MIPS_COP_0_STATUS
  774         or      a0, a0, MIPS_SR_INT_IE
  775         mtc0    a0, MIPS_COP_0_STATUS
  776         ITLBNOPFIX
  777 
  778 /*
  779  * DO_AST enabled interrupts
  780  */
  781         DO_AST
  782         
  783 /*
  784  * Restore user registers and return. 
  785  */
  786         CLEAR_STATUS
  787 
  788         GET_CPU_PCPU(k1)
  789         PTR_L   k1, PC_CURPCB(k1)
  790 
  791         /*
  792          * Update interrupt mask in saved status register
  793          * Some of interrupts could be disabled by
  794          * intr filters
  795          */
  796         mfc0    a0, MIPS_COP_0_STATUS
  797         and     a0, a0, MIPS_SR_INT_MASK
  798         RESTORE_U_PCB_REG(a1, SR, k1)
  799         and     a1, a1, ~MIPS_SR_INT_MASK
  800         or      a1, a1, a0
  801         SAVE_U_PCB_REG(a1, SR, k1)
  802 
  803         RESTORE_U_PCB_REG(s0, S0, k1)
  804         RESTORE_U_PCB_REG(s1, S1, k1)
  805         RESTORE_U_PCB_REG(s2, S2, k1)
  806         RESTORE_U_PCB_REG(s3, S3, k1)
  807         RESTORE_U_PCB_REG(s4, S4, k1)
  808         RESTORE_U_PCB_REG(s5, S5, k1)
  809         RESTORE_U_PCB_REG(s6, S6, k1)
  810         RESTORE_U_PCB_REG(s7, S7, k1)
  811         RESTORE_U_PCB_REG(s8, S8, k1)
  812         RESTORE_U_PCB_REG(t0, MULLO, k1)
  813         RESTORE_U_PCB_REG(t1, MULHI, k1)
  814         RESTORE_U_PCB_REG(t2, PC, k1)
  815         mtlo    t0
  816         mthi    t1
  817         MTC0    t2, MIPS_COP_0_EXC_PC   # set return address
  818         RESTORE_U_PCB_REG(v0, V0, k1)
  819         RESTORE_U_PCB_REG(v1, V1, k1)
  820         RESTORE_U_PCB_REG(a0, A0, k1)
  821         RESTORE_U_PCB_REG(a1, A1, k1)
  822         RESTORE_U_PCB_REG(a2, A2, k1)
  823         RESTORE_U_PCB_REG(a3, A3, k1)
  824         RESTORE_U_PCB_REG(t0, T0, k1)
  825         RESTORE_U_PCB_REG(t1, T1, k1)
  826         RESTORE_U_PCB_REG(t2, T2, k1)
  827         RESTORE_U_PCB_REG(t3, T3, k1)
  828         RESTORE_U_PCB_REG(ta0, TA0, k1)
  829         RESTORE_U_PCB_REG(ta1, TA1, k1)
  830         RESTORE_U_PCB_REG(ta2, TA2, k1)
  831         RESTORE_U_PCB_REG(ta3, TA3, k1)
  832         RESTORE_U_PCB_REG(t8, T8, k1)
  833         RESTORE_U_PCB_REG(t9, T9, k1)
  834         RESTORE_U_PCB_REG(gp, GP, k1)
  835         RESTORE_U_PCB_REG(k0, SR, k1)
  836         RESTORE_U_PCB_REG(sp, SP, k1)
  837         RESTORE_U_PCB_REG(ra, RA, k1)
  838         .set    noat
  839         RESTORE_U_PCB_REG(AT, AST, k1)
  840 
  841         mtc0    k0, MIPS_COP_0_STATUS   # SR with EXL set. 
  842         ITLBNOPFIX
  843         sync
  844         eret
  845         .set    at
  846 END(MipsUserIntr)
  847 
  848 LEAF_NOPROFILE(MipsTLBInvalidException)
  849         .set push
  850         .set noat
  851         .set noreorder
  852 
  853         MFC0            k0, MIPS_COP_0_BAD_VADDR
  854         PTR_LI          k1, VM_MAXUSER_ADDRESS
  855         sltu            k1, k0, k1
  856         bnez            k1, 1f
  857         nop
  858 
  859         /* Kernel address.  */
  860         lui             k1, %hi(kernel_segmap)          # k1=hi of segbase
  861         b               2f
  862         PTR_L           k1, %lo(kernel_segmap)(k1)      # k1=segment tab base
  863 
  864 1:      /* User address.  */
  865         GET_CPU_PCPU(k1)
  866         PTR_L           k1, PC_SEGBASE(k1)
  867 
  868 2:      /* Validate page directory pointer.  */
  869         beqz            k1, 3f
  870         nop
  871 
  872         PTR_SRL         k0, SEGSHIFT - PTRSHIFT         # k0=seg offset (almost)
  873         beq             k1, zero, MipsKernGenException  # ==0 -- no seg tab
  874         andi            k0, k0, PDEPTRMASK              #06: k0=seg offset
  875         PTR_ADDU        k1, k0, k1                      # k1=seg entry address
  876         PTR_L           k1, 0(k1)                       # k1=seg entry
  877 
  878         /* Validate page table pointer.  */
  879         beqz            k1, 3f
  880         nop
  881 
  882 #ifdef __mips_n64
  883         MFC0            k0, MIPS_COP_0_BAD_VADDR
  884         PTR_SRL         k0, PDRSHIFT - PTRSHIFT         # k0=pde offset (almost)
  885         beq             k1, zero, MipsKernGenException  # ==0 -- no pde tab
  886         andi            k0, k0, PDEPTRMASK              # k0=pde offset
  887         PTR_ADDU        k1, k0, k1                      # k1=pde entry address
  888         PTR_L           k1, 0(k1)                       # k1=pde entry
  889 
  890         /* Validate pde table pointer.  */
  891         beqz            k1, 3f
  892         nop
  893 #endif
  894         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
  895         PTR_SRL         k0, PAGE_SHIFT - PTESHIFT       # k0=VPN
  896         andi            k0, k0, PTEMASK                 # k0=page tab offset
  897         PTR_ADDU        k1, k1, k0                      # k1=pte address
  898         PTE_L           k0, 0(k1)                       # k0=this PTE
  899 
  900         /* Validate page table entry.  */
  901         andi            k0, PTE_V
  902         beqz            k0, 3f
  903         nop
  904 
  905         /* Check whether this is an even or odd entry.  */
  906         andi            k0, k1, PTESIZE
  907         bnez            k0, odd_page
  908         nop
  909 
  910         PTE_L           k0, 0(k1)
  911         PTE_L           k1, PTESIZE(k1)
  912         CLEAR_PTE_SWBITS(k0)
  913         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0
  914         COP0_SYNC
  915         CLEAR_PTE_SWBITS(k1)
  916         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1
  917         COP0_SYNC
  918 
  919         b               tlb_insert_entry
  920         nop
  921 
  922 odd_page:
  923         PTE_L           k0, -PTESIZE(k1)
  924         PTE_L           k1, 0(k1)
  925         CLEAR_PTE_SWBITS(k0)
  926         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0
  927         COP0_SYNC
  928         CLEAR_PTE_SWBITS(k1)
  929         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1
  930         COP0_SYNC
  931 
  932 tlb_insert_entry:
  933         tlbp
  934         HAZARD_DELAY
  935         mfc0            k0, MIPS_COP_0_TLB_INDEX
  936         bltz            k0, tlb_insert_random
  937         nop
  938         tlbwi
  939         eret
  940         ssnop
  941 
  942 tlb_insert_random:
  943         tlbwr
  944         eret
  945         ssnop
  946 
  947 3:
  948         /*
  949          * Branch to the comprehensive exception processing.
  950          */
  951         mfc0    k1, MIPS_COP_0_STATUS
  952         andi    k1, k1, MIPS_SR_KSU_USER
  953         bnez    k1, _C_LABEL(MipsUserGenException)
  954         nop
  955 
  956         /*
  957          * Check for kernel stack overflow.
  958          */
  959         GET_CPU_PCPU(k1)
  960         PTR_L   k0, PC_CURTHREAD(k1)
  961         PTR_L   k0, TD_KSTACK(k0)
  962         sltu    k0, k0, sp
  963         bnez    k0, _C_LABEL(MipsKernGenException)
  964         nop
  965 
  966         /*
  967          * Kernel stack overflow.
  968          *
  969          * Move to a valid stack before we call panic. We use the boot stack
  970          * for this purpose.
  971          */
  972         GET_CPU_PCPU(k1)
  973         lw      k1, PC_CPUID(k1)
  974         sll     k1, k1, PAGE_SHIFT + 1
  975 
  976         PTR_LA  k0, _C_LABEL(pcpu_space)
  977         PTR_ADDU        k0, PAGE_SIZE * 2
  978         PTR_ADDU        k0, k0, k1
  979 
  980         /*
  981          * Stash the original value of 'sp' so we can update trapframe later.
  982          * We assume that SAVE_CPU does not trash 'k1'.
  983          */
  984         move    k1, sp
  985 
  986         move    sp, k0
  987         PTR_SUBU        sp, sp, KERN_EXC_FRAME_SIZE
  988 
  989         move    k0, ra
  990         move    ra, zero
  991         REG_S   ra, CALLFRAME_RA(sp)    /* stop the ddb backtrace right here */
  992         REG_S   zero, CALLFRAME_SP(sp)
  993         move    ra, k0
  994 
  995         SAVE_CPU
  996 
  997         /*
  998          * Now restore the value of 'sp' at the time of the tlb exception in
  999          * the trapframe.
 1000          */
 1001         SAVE_REG(k1, SP, sp)
 1002 
 1003         /*
 1004          * Squelch any more overflow checks by setting the stack base to 0.
 1005          */
 1006         GET_CPU_PCPU(k1)
 1007         PTR_L   k0, PC_CURTHREAD(k1)
 1008         PTR_S   zero, TD_KSTACK(k0)
 1009 
 1010         move    a1, a0
 1011         PANIC("kernel stack overflow - trapframe at %p")
 1012 
 1013         /*
 1014          * This nop is necessary so that the 'ra' remains within the bounds
 1015          * of this handler. Otherwise the ddb backtrace code will think that
 1016          * the panic() was called from MipsTLBMissException.
 1017          */
 1018         nop
 1019 
 1020         .set pop
 1021 END(MipsTLBInvalidException)
 1022 
 1023 /*----------------------------------------------------------------------------
 1024  *
 1025  * MipsTLBMissException --
 1026  *
 1027  *      Handle a TLB miss exception from kernel mode in kernel space.
 1028  *      The BaddVAddr, Context, and EntryHi registers contain the failed
 1029  *      virtual address.
 1030  *
 1031  * Results:
 1032  *      None.
 1033  *
 1034  * Side effects:
 1035  *      None.
 1036  *
 1037  *----------------------------------------------------------------------------
 1038  */
 1039 LEAF_NOPROFILE(MipsTLBMissException)
 1040         .set    noat
 1041         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address
 1042         PTR_LI          k1, VM_MAX_KERNEL_ADDRESS       # check fault address against
 1043         sltu            k1, k1, k0                      # upper bound of kernel_segmap
 1044         bnez            k1, MipsKernGenException        # out of bound
 1045         lui             k1, %hi(kernel_segmap)          # k1=hi of segbase
 1046         PTR_SRL         k0, SEGSHIFT - PTRSHIFT         # k0=seg offset (almost)
 1047         PTR_L           k1, %lo(kernel_segmap)(k1)      # k1=segment tab base
 1048         beq             k1, zero, MipsKernGenException  # ==0 -- no seg tab
 1049         andi            k0, k0, PDEPTRMASK              #06: k0=seg offset
 1050         PTR_ADDU        k1, k0, k1                      # k1=seg entry address
 1051         PTR_L           k1, 0(k1)                       # k1=seg entry
 1052         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
 1053         beq             k1, zero, MipsKernGenException  # ==0 -- no page table
 1054 #ifdef __mips_n64
 1055         PTR_SRL         k0, PDRSHIFT - PTRSHIFT         # k0=VPN
 1056         andi            k0, k0, PDEPTRMASK              # k0=pde offset
 1057         PTR_ADDU        k1, k0, k1                      # k1=pde entry address
 1058         PTR_L           k1, 0(k1)                       # k1=pde entry
 1059         MFC0            k0, MIPS_COP_0_BAD_VADDR        # k0=bad address (again)
 1060         beq             k1, zero, MipsKernGenException  # ==0 -- no page table
 1061 #endif
 1062         PTR_SRL         k0, PAGE_SHIFT - PTESHIFT       # k0=VPN
 1063         andi            k0, k0, PTE2MASK                # k0=page tab offset
 1064         PTR_ADDU        k1, k1, k0                      # k1=pte address
 1065         PTE_L           k0, 0(k1)                       # k0=lo0 pte
 1066         PTE_L           k1, PTESIZE(k1)                 # k1=lo1 pte
 1067         CLEAR_PTE_SWBITS(k0)
 1068         PTE_MTC0        k0, MIPS_COP_0_TLB_LO0          # lo0 is loaded
 1069         COP0_SYNC
 1070         CLEAR_PTE_SWBITS(k1)
 1071         PTE_MTC0        k1, MIPS_COP_0_TLB_LO1          # lo1 is loaded
 1072         COP0_SYNC
 1073         tlbwr                                   # write to tlb
 1074         HAZARD_DELAY
 1075         eret                                    # return from exception
 1076         .set    at
 1077 END(MipsTLBMissException)
 1078 
 1079 /*----------------------------------------------------------------------------
 1080  *
 1081  * MipsFPTrap --
 1082  *
 1083  *      Handle a floating point Trap.
 1084  *
 1085  *      MipsFPTrap(statusReg, causeReg, pc)
 1086  *              unsigned statusReg;
 1087  *              unsigned causeReg;
 1088  *              unsigned pc;
 1089  *
 1090  * Results:
 1091  *      None.
 1092  *
 1093  * Side effects:
 1094  *      None.
 1095  *
 1096  *----------------------------------------------------------------------------
 1097  */
 1098 NESTED(MipsFPTrap, CALLFRAME_SIZ, ra)
 1099         PTR_SUBU        sp, sp, CALLFRAME_SIZ
 1100         mfc0    t0, MIPS_COP_0_STATUS
 1101         REG_S   ra, CALLFRAME_RA(sp)
 1102         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
 1103 
 1104         or      t1, t0, MIPS_SR_COP_1_BIT
 1105         mtc0    t1, MIPS_COP_0_STATUS
 1106         ITLBNOPFIX
 1107         cfc1    t1, MIPS_FPU_CSR                # stall til FP done
 1108         cfc1    t1, MIPS_FPU_CSR                # now get status
 1109         nop
 1110         sll     t2, t1, (31 - 17)               # unimplemented operation?
 1111         bgez    t2, 3f                          # no, normal trap
 1112         nop
 1113 /*
 1114  * We got an unimplemented operation trap so
 1115  * fetch the instruction, compute the next PC and emulate the instruction.
 1116  */
 1117         bgez    a1, 1f                          # Check the branch delay bit.
 1118         nop
 1119 /*
 1120  * The instruction is in the branch delay slot so the branch will have to
 1121  * be emulated to get the resulting PC.
 1122  */
 1123         PTR_S   a2, CALLFRAME_SIZ + 8(sp)
 1124         GET_CPU_PCPU(a0)
 1125 #mips64 unsafe?
 1126         PTR_L   a0, PC_CURPCB(a0)
 1127         PTR_ADDU a0, a0, U_PCB_REGS             # first arg is ptr to CPU registers
 1128         move    a1, a2                          # second arg is instruction PC
 1129         move    a2, t1                          # third arg is floating point CSR
 1130         PTR_LA  t3, _C_LABEL(MipsEmulateBranch) # compute PC after branch
 1131         jalr    t3                              # compute PC after branch
 1132         move    a3, zero                        # fourth arg is FALSE
 1133 /*
 1134  * Now load the floating-point instruction in the branch delay slot
 1135  * to be emulated.
 1136  */
 1137         PTR_L   a2, CALLFRAME_SIZ + 8(sp)       # restore EXC pc
 1138         b       2f
 1139         lw      a0, 4(a2)                       # a0 = coproc instruction
 1140 /*
 1141  * This is not in the branch delay slot so calculate the resulting
 1142  * PC (epc + 4) into v0 and continue to MipsEmulateFP().
 1143  */
 1144 1:
 1145         lw      a0, 0(a2)                       # a0 = coproc instruction
 1146 #xxx mips64 unsafe?
 1147         PTR_ADDU        v0, a2, 4                       # v0 = next pc
 1148 2:
 1149         GET_CPU_PCPU(t2)
 1150         PTR_L   t2, PC_CURPCB(t2)
 1151         SAVE_U_PCB_REG(v0, PC, t2)              # save new pc
 1152 /*
 1153  * Check to see if the instruction to be emulated is a floating-point
 1154  * instruction.
 1155  */
 1156         srl     a3, a0, MIPS_OPCODE_SHIFT
 1157         beq     a3, MIPS_OPCODE_C1, 4f          # this should never fail
 1158         nop
 1159 /*
 1160  * Send a floating point exception signal to the current process.
 1161  */
 1162 3:
 1163         GET_CPU_PCPU(a0)
 1164         PTR_L   a0, PC_CURTHREAD(a0)            # get current thread
 1165         cfc1    a2, MIPS_FPU_CSR                # code = FP execptions
 1166         ctc1    zero, MIPS_FPU_CSR              # Clear exceptions
 1167         PTR_LA  t3, _C_LABEL(trapsignal)
 1168         jalr    t3
 1169         li      a1, SIGFPE
 1170         b       FPReturn
 1171         nop
 1172 
 1173 /*
 1174  * Finally, we can call MipsEmulateFP() where a0 is the instruction to emulate.
 1175  */
 1176 4:
 1177         PTR_LA  t3, _C_LABEL(MipsEmulateFP)
 1178         jalr    t3
 1179         nop
 1180 
 1181 /*
 1182  * Turn off the floating point coprocessor and return.
 1183  */
 1184 FPReturn:
 1185         mfc0    t0, MIPS_COP_0_STATUS
 1186         PTR_L   ra, CALLFRAME_RA(sp)
 1187         and     t0, t0, ~MIPS_SR_COP_1_BIT
 1188         mtc0    t0, MIPS_COP_0_STATUS
 1189         ITLBNOPFIX
 1190         j       ra
 1191         PTR_ADDU sp, sp, CALLFRAME_SIZ
 1192 END(MipsFPTrap)
 1193 
 1194 #ifndef INTRNG
 1195 /*
 1196  * Interrupt counters for vmstat.
 1197  */
 1198         .data
 1199         .globl intrcnt
 1200         .globl sintrcnt
 1201         .globl intrnames
 1202         .globl sintrnames
 1203 intrnames:
 1204         .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1205 sintrnames:
 1206 #ifdef __mips_n64
 1207         .quad  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1208 #else
 1209         .int  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
 1210 #endif
 1211 
 1212         .align  (_MIPS_SZLONG / 8)
 1213 intrcnt:
 1214         .space  INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
 1215 sintrcnt:
 1216 #ifdef __mips_n64
 1217         .quad  INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
 1218 #else
 1219         .int  INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
 1220 #endif
 1221 #endif /* INTRNG */
 1222 
 1223 
 1224 /*
 1225  * Vector to real handler in KSEG1.
 1226  */
 1227         .text
 1228 VECTOR(MipsCache, unknown)
 1229         PTR_LA  k0, _C_LABEL(MipsCacheException)
 1230         li      k1, MIPS_KSEG0_PHYS_MASK
 1231         and     k0, k1
 1232         PTR_LI  k1, MIPS_KSEG1_START
 1233         or      k0, k1
 1234         j       k0
 1235         nop
 1236 VECTOR_END(MipsCache)
 1237 
 1238         .set    at
 1239 
 1240 
 1241 /*
 1242  * Panic on cache errors.  A lot more could be done to recover
 1243  * from some types of errors but it is tricky.
 1244  */
 1245 NESTED_NOPROFILE(MipsCacheException, KERN_EXC_FRAME_SIZE, ra)
 1246         .set    noat
 1247         .mask   0x80000000, -4
 1248         PTR_LA  k0, _C_LABEL(panic)             # return to panic
 1249         PTR_LA  a0, 9f                          # panicstr
 1250         MFC0    a1, MIPS_COP_0_ERROR_PC
 1251         mfc0    a2, MIPS_COP_0_CACHE_ERR        # 3rd arg cache error
 1252 
 1253         MTC0    k0, MIPS_COP_0_ERROR_PC         # set return address
 1254 
 1255         mfc0    k0, MIPS_COP_0_STATUS           # restore status
 1256         li      k1, MIPS_SR_DIAG_PE             # ignore further errors
 1257         or      k0, k1
 1258         mtc0    k0, MIPS_COP_0_STATUS           # restore status
 1259         COP0_SYNC
 1260 
 1261         eret
 1262 
 1263         MSG("cache error @ EPC 0x%x CachErr 0x%x");
 1264         .set    at
 1265 END(MipsCacheException)

Cache object: 5aff03d4ba8e9be4027c2e5926c69d03


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