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

Cache object: 2a2c63436eb2c50205ab105b10e3ca0c


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