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