]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/mips/mips/exception.S
MFC r223364:
[FreeBSD/stable/8.git] / sys / mips / mips / exception.S
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$
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)