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

Cache object: 7e3328ac412cd9d9a7ceab749799041f


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