]> bbs.cooldavid.org Git - net-next-2.6.git/blob - arch/mips/kernel/genex.S
83843a229be7f551f4e1e36cd6a043c610c1a833
[net-next-2.6.git] / arch / mips / kernel / genex.S
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8  * Copyright (C) 2001 MIPS Technologies, Inc.
9  * Copyright (C) 2002 Maciej W. Rozycki
10  */
11 #include <linux/init.h>
12
13 #include <asm/asm.h>
14 #include <asm/asmmacro.h>
15 #include <asm/cacheops.h>
16 #include <asm/irqflags.h>
17 #include <asm/regdef.h>
18 #include <asm/fpregdef.h>
19 #include <asm/mipsregs.h>
20 #include <asm/stackframe.h>
21 #include <asm/war.h>
22 #include <asm/page.h>
23
24 #define PANIC_PIC(msg)                                  \
25                 .set push;                              \
26                 .set    reorder;                        \
27                 PTR_LA  a0,8f;                          \
28                 .set    noat;                           \
29                 PTR_LA  AT, panic;                      \
30                 jr      AT;                             \
31 9:              b       9b;                             \
32                 .set    pop;                            \
33                 TEXT(msg)
34
35         __INIT
36
37 NESTED(except_vec0_generic, 0, sp)
38         PANIC_PIC("Exception vector 0 called")
39         END(except_vec0_generic)
40
41 NESTED(except_vec1_generic, 0, sp)
42         PANIC_PIC("Exception vector 1 called")
43         END(except_vec1_generic)
44
45 /*
46  * General exception vector for all other CPUs.
47  *
48  * Be careful when changing this, it has to be at most 128 bytes
49  * to fit into space reserved for the exception handler.
50  */
51 NESTED(except_vec3_generic, 0, sp)
52         .set    push
53         .set    noat
54 #if R5432_CP0_INTERRUPT_WAR
55         mfc0    k0, CP0_INDEX
56 #endif
57         mfc0    k1, CP0_CAUSE
58         andi    k1, k1, 0x7c
59 #ifdef CONFIG_64BIT
60         dsll    k1, k1, 1
61 #endif
62         PTR_L   k0, exception_handlers(k1)
63         jr      k0
64         .set    pop
65         END(except_vec3_generic)
66
67 /*
68  * General exception handler for CPUs with virtual coherency exception.
69  *
70  * Be careful when changing this, it has to be at most 256 (as a special
71  * exception) bytes to fit into space reserved for the exception handler.
72  */
73 NESTED(except_vec3_r4000, 0, sp)
74         .set    push
75         .set    mips3
76         .set    noat
77         mfc0    k1, CP0_CAUSE
78         li      k0, 31<<2
79         andi    k1, k1, 0x7c
80         .set    push
81         .set    noreorder
82         .set    nomacro
83         beq     k1, k0, handle_vced
84          li     k0, 14<<2
85         beq     k1, k0, handle_vcei
86 #ifdef CONFIG_64BIT
87          dsll   k1, k1, 1
88 #endif
89         .set    pop
90         PTR_L   k0, exception_handlers(k1)
91         jr      k0
92
93         /*
94          * Big shit, we now may have two dirty primary cache lines for the same
95          * physical address.  We can safely invalidate the line pointed to by
96          * c0_badvaddr because after return from this exception handler the
97          * load / store will be re-executed.
98          */
99 handle_vced:
100         MFC0    k0, CP0_BADVADDR
101         li      k1, -4                                  # Is this ...
102         and     k0, k1                                  # ... really needed?
103         mtc0    zero, CP0_TAGLO
104         cache   Index_Store_Tag_D, (k0)
105         cache   Hit_Writeback_Inv_SD, (k0)
106 #ifdef CONFIG_PROC_FS
107         PTR_LA  k0, vced_count
108         lw      k1, (k0)
109         addiu   k1, 1
110         sw      k1, (k0)
111 #endif
112         eret
113
114 handle_vcei:
115         MFC0    k0, CP0_BADVADDR
116         cache   Hit_Writeback_Inv_SD, (k0)              # also cleans pi
117 #ifdef CONFIG_PROC_FS
118         PTR_LA  k0, vcei_count
119         lw      k1, (k0)
120         addiu   k1, 1
121         sw      k1, (k0)
122 #endif
123         eret
124         .set    pop
125         END(except_vec3_r4000)
126
127         __FINIT
128
129         .align  5
130 NESTED(handle_int, PT_SIZE, sp)
131         SAVE_ALL
132         CLI
133         TRACE_IRQS_OFF
134
135         LONG_L  s0, TI_REGS($28)
136         LONG_S  sp, TI_REGS($28)
137         PTR_LA  ra, ret_from_irq
138         j       plat_irq_dispatch
139         END(handle_int)
140
141         __INIT
142
143 /*
144  * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
145  * This is a dedicated interrupt exception vector which reduces the
146  * interrupt processing overhead.  The jump instruction will be replaced
147  * at the initialization time.
148  *
149  * Be careful when changing this, it has to be at most 128 bytes
150  * to fit into space reserved for the exception handler.
151  */
152 NESTED(except_vec4, 0, sp)
153 1:      j       1b                      /* Dummy, will be replaced */
154         END(except_vec4)
155
156 /*
157  * EJTAG debug exception handler.
158  * The EJTAG debug exception entry point is 0xbfc00480, which
159  * normally is in the boot PROM, so the boot PROM must do a
160  * unconditional jump to this vector.
161  */
162 NESTED(except_vec_ejtag_debug, 0, sp)
163         j       ejtag_debug_handler
164         END(except_vec_ejtag_debug)
165
166         __FINIT
167
168 /*
169  * Vectored interrupt handler.
170  * This prototype is copied to ebase + n*IntCtl.VS and patched
171  * to invoke the handler
172  */
173 NESTED(except_vec_vi, 0, sp)
174         SAVE_SOME
175         SAVE_AT
176         .set    push
177         .set    noreorder
178 #ifdef CONFIG_MIPS_MT_SMTC
179         /*
180          * To keep from blindly blocking *all* interrupts
181          * during service by SMTC kernel, we also want to
182          * pass the IM value to be cleared.
183          */
184 FEXPORT(except_vec_vi_mori)
185         ori     a0, $0, 0
186 #endif /* CONFIG_MIPS_MT_SMTC */
187 FEXPORT(except_vec_vi_lui)
188         lui     v0, 0           /* Patched */
189         j       except_vec_vi_handler
190 FEXPORT(except_vec_vi_ori)
191          ori    v0, 0           /* Patched */
192         .set    pop
193         END(except_vec_vi)
194 EXPORT(except_vec_vi_end)
195
196 /*
197  * Common Vectored Interrupt code
198  * Complete the register saves and invoke the handler which is passed in $v0
199  */
200 NESTED(except_vec_vi_handler, 0, sp)
201         SAVE_TEMP
202         SAVE_STATIC
203 #ifdef CONFIG_MIPS_MT_SMTC
204         /*
205          * SMTC has an interesting problem that interrupts are level-triggered,
206          * and the CLI macro will clear EXL, potentially causing a duplicate
207          * interrupt service invocation. So we need to clear the associated
208          * IM bit of Status prior to doing CLI, and restore it after the
209          * service routine has been invoked - we must assume that the
210          * service routine will have cleared the state, and any active
211          * level represents a new or otherwised unserviced event...
212          */
213         mfc0    t1, CP0_STATUS
214         and     t0, a0, t1
215         mfc0    t2, CP0_TCCONTEXT
216         or      t0, t0, t2
217         mtc0    t0, CP0_TCCONTEXT
218         xor     t1, t1, t0
219         mtc0    t1, CP0_STATUS
220         _ehb
221 #endif /* CONFIG_MIPS_MT_SMTC */
222         CLI
223 #ifdef CONFIG_TRACE_IRQFLAGS
224         move    s0, v0
225 #ifdef CONFIG_MIPS_MT_SMTC
226         move    s1, a0
227 #endif
228         TRACE_IRQS_OFF
229 #ifdef CONFIG_MIPS_MT_SMTC
230         move    a0, s1
231 #endif
232         move    v0, s0
233 #endif
234
235         LONG_L  s0, TI_REGS($28)
236         LONG_S  sp, TI_REGS($28)
237         PTR_LA  ra, ret_from_irq
238         jr      v0
239         END(except_vec_vi_handler)
240
241 /*
242  * EJTAG debug exception handler.
243  */
244 NESTED(ejtag_debug_handler, PT_SIZE, sp)
245         .set    push
246         .set    noat
247         MTC0    k0, CP0_DESAVE
248         mfc0    k0, CP0_DEBUG
249
250         sll     k0, k0, 30      # Check for SDBBP.
251         bgez    k0, ejtag_return
252
253         PTR_LA  k0, ejtag_debug_buffer
254         LONG_S  k1, 0(k0)
255         SAVE_ALL
256         move    a0, sp
257         jal     ejtag_exception_handler
258         RESTORE_ALL
259         PTR_LA  k0, ejtag_debug_buffer
260         LONG_L  k1, 0(k0)
261
262 ejtag_return:
263         MFC0    k0, CP0_DESAVE
264         .set    mips32
265         deret
266         .set pop
267         END(ejtag_debug_handler)
268
269 /*
270  * This buffer is reserved for the use of the EJTAG debug
271  * handler.
272  */
273         .data
274 EXPORT(ejtag_debug_buffer)
275         .fill   LONGSIZE
276         .previous
277
278         __INIT
279
280 /*
281  * NMI debug exception handler for MIPS reference boards.
282  * The NMI debug exception entry point is 0xbfc00000, which
283  * normally is in the boot PROM, so the boot PROM must do a
284  * unconditional jump to this vector.
285  */
286 NESTED(except_vec_nmi, 0, sp)
287         j       nmi_handler
288         END(except_vec_nmi)
289
290         __FINIT
291
292 NESTED(nmi_handler, PT_SIZE, sp)
293         .set    push
294         .set    noat
295         SAVE_ALL
296         move    a0, sp
297         jal     nmi_exception_handler
298         RESTORE_ALL
299         .set    mips3
300         eret
301         .set    pop
302         END(nmi_handler)
303
304         .macro  __build_clear_none
305         .endm
306
307         .macro  __build_clear_sti
308         TRACE_IRQS_ON
309         STI
310         .endm
311
312         .macro  __build_clear_cli
313         CLI
314         TRACE_IRQS_OFF
315         .endm
316
317         .macro  __build_clear_fpe
318         cfc1    a1, fcr31
319         li      a2, ~(0x3f << 12)
320         and     a2, a1
321         ctc1    a2, fcr31
322         TRACE_IRQS_ON
323         STI
324         .endm
325
326         .macro  __build_clear_ade
327         MFC0    t0, CP0_BADVADDR
328         PTR_S   t0, PT_BVADDR(sp)
329         KMODE
330         .endm
331
332         .macro  __BUILD_silent exception
333         .endm
334
335         /* Gas tries to parse the PRINT argument as a string containing
336            string escapes and emits bogus warnings if it believes to
337            recognize an unknown escape code.  So make the arguments
338            start with an n and gas will believe \n is ok ...  */
339         .macro  __BUILD_verbose nexception
340         LONG_L  a1, PT_EPC(sp)
341 #ifdef CONFIG_32BIT
342         PRINT("Got \nexception at %08lx\012")
343 #endif
344 #ifdef CONFIG_64BIT
345         PRINT("Got \nexception at %016lx\012")
346 #endif
347         .endm
348
349         .macro  __BUILD_count exception
350         LONG_L  t0,exception_count_\exception
351         LONG_ADDIU t0, 1
352         LONG_S  t0,exception_count_\exception
353         .comm   exception_count\exception, 8, 8
354         .endm
355
356         .macro  __BUILD_HANDLER exception handler clear verbose ext
357         .align  5
358         NESTED(handle_\exception, PT_SIZE, sp)
359         .set    noat
360         SAVE_ALL
361         FEXPORT(handle_\exception\ext)
362         __BUILD_clear_\clear
363         .set    at
364         __BUILD_\verbose \exception
365         move    a0, sp
366         PTR_LA  ra, ret_from_exception
367         j       do_\handler
368         END(handle_\exception)
369         .endm
370
371         .macro  BUILD_HANDLER exception handler clear verbose
372         __BUILD_HANDLER \exception \handler \clear \verbose _int
373         .endm
374
375         BUILD_HANDLER adel ade ade silent               /* #4  */
376         BUILD_HANDLER ades ade ade silent               /* #5  */
377         BUILD_HANDLER ibe be cli silent                 /* #6  */
378         BUILD_HANDLER dbe be cli silent                 /* #7  */
379         BUILD_HANDLER bp bp sti silent                  /* #9  */
380         BUILD_HANDLER ri ri sti silent                  /* #10 */
381         BUILD_HANDLER cpu cpu sti silent                /* #11 */
382         BUILD_HANDLER ov ov sti silent                  /* #12 */
383         BUILD_HANDLER tr tr sti silent                  /* #13 */
384         BUILD_HANDLER fpe fpe fpe silent                /* #15 */
385         BUILD_HANDLER mdmx mdmx sti silent              /* #22 */
386         BUILD_HANDLER watch watch sti verbose           /* #23 */
387         BUILD_HANDLER mcheck mcheck cli verbose         /* #24 */
388         BUILD_HANDLER mt mt sti silent                  /* #25 */
389         BUILD_HANDLER dsp dsp sti silent                /* #26 */
390         BUILD_HANDLER reserved reserved sti verbose     /* others */
391
392         .align  5
393         LEAF(handle_ri_rdhwr_vivt)
394 #ifdef CONFIG_MIPS_MT_SMTC
395         PANIC_PIC("handle_ri_rdhwr_vivt called")
396 #else
397         .set    push
398         .set    noat
399         .set    noreorder
400         /* check if TLB contains a entry for EPC */
401         MFC0    k1, CP0_ENTRYHI
402         andi    k1, 0xff        /* ASID_MASK */
403         MFC0    k0, CP0_EPC
404         PTR_SRL k0, PAGE_SHIFT + 1
405         PTR_SLL k0, PAGE_SHIFT + 1
406         or      k1, k0
407         MTC0    k1, CP0_ENTRYHI
408         mtc0_tlbw_hazard
409         tlbp
410         tlb_probe_hazard
411         mfc0    k1, CP0_INDEX
412         .set    pop
413         bltz    k1, handle_ri   /* slow path */
414         /* fall thru */
415 #endif
416         END(handle_ri_rdhwr_vivt)
417
418         LEAF(handle_ri_rdhwr)
419         .set    push
420         .set    noat
421         .set    noreorder
422         /* 0x7c03e83b: rdhwr v1,$29 */
423         MFC0    k1, CP0_EPC
424         lui     k0, 0x7c03
425         lw      k1, (k1)
426         ori     k0, 0xe83b
427         .set    reorder
428         bne     k0, k1, handle_ri       /* if not ours */
429         /* The insn is rdhwr.  No need to check CAUSE.BD here. */
430         get_saved_sp    /* k1 := current_thread_info */
431         .set    noreorder
432         MFC0    k0, CP0_EPC
433 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
434         ori     k1, _THREAD_MASK
435         xori    k1, _THREAD_MASK
436         LONG_L  v1, TI_TP_VALUE(k1)
437         LONG_ADDIU      k0, 4
438         jr      k0
439          rfe
440 #else
441         LONG_ADDIU      k0, 4           /* stall on $k0 */
442         MTC0    k0, CP0_EPC
443         /* I hope three instructions between MTC0 and ERET are enough... */
444         ori     k1, _THREAD_MASK
445         xori    k1, _THREAD_MASK
446         LONG_L  v1, TI_TP_VALUE(k1)
447         .set    mips3
448         eret
449         .set    mips0
450 #endif
451         .set    pop
452         END(handle_ri_rdhwr)
453
454 #ifdef CONFIG_64BIT
455 /* A temporary overflow handler used by check_daddi(). */
456
457         __INIT
458
459         BUILD_HANDLER  daddi_ov daddi_ov none silent    /* #12 */
460 #endif