source: src/linux/universal/linux-4.9/arch/mips/kernel/genex.S @ 31859

Last change on this file since 31859 was 31859, checked in by brainslayer, 11 days ago

kernel update

File size: 11.6 KB
Line 
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) 2002, 2007  Maciej W. Rozycki
9 * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
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/thread_info.h>
23
24#ifdef CONFIG_BCM47XX
25# ifdef eret
26#  undef eret
27# endif
28# define eret                                   \
29        .set push;                              \
30        .set noreorder;                         \
31         nop;                                   \
32         nop;                                   \
33         eret;                                  \
34        .set pop;
35#endif
36
37        __INIT
38
39/*
40 * General exception vector for all other CPUs.
41 *
42 * Be careful when changing this, it has to be at most 128 bytes
43 * to fit into space reserved for the exception handler.
44 */
45NESTED(except_vec3_generic, 0, sp)
46        .set    push
47        .set    noat
48#ifdef CONFIG_BCM47XX
49        nop
50#endif
51#if R5432_CP0_INTERRUPT_WAR
52        mfc0    k0, CP0_INDEX
53#endif
54        mfc0    k1, CP0_CAUSE
55        andi    k1, k1, 0x7c
56#ifdef CONFIG_64BIT
57        dsll    k1, k1, 1
58#endif
59        PTR_L   k0, exception_handlers(k1)
60        jr      k0
61        .set    pop
62        END(except_vec3_generic)
63
64/*
65 * General exception handler for CPUs with virtual coherency exception.
66 *
67 * Be careful when changing this, it has to be at most 256 (as a special
68 * exception) bytes to fit into space reserved for the exception handler.
69 */
70NESTED(except_vec3_r4000, 0, sp)
71        .set    push
72        .set    arch=r4000
73        .set    noat
74#ifdef CONFIG_BCM47XX
75        nop
76#endif
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         */
99handle_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
114handle_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       /* 32 byte rollback region */
130LEAF(__r4k_wait)
131        .set    push
132        .set    noreorder
133        /* start of rollback region */
134        LONG_L  t0, TI_FLAGS($28)
135        nop
136        andi    t0, _TIF_NEED_RESCHED
137        bnez    t0, 1f
138         nop
139        nop
140        nop
141#ifdef CONFIG_CPU_MICROMIPS
142        nop
143        nop
144        nop
145        nop
146#endif
147        .set    MIPS_ISA_ARCH_LEVEL_RAW
148        wait
149        /* end of rollback region (the region size must be power of two) */
1501:
151        jr      ra
152         nop
153        .set    pop
154        END(__r4k_wait)
155
156        .macro  BUILD_ROLLBACK_PROLOGUE handler
157        FEXPORT(rollback_\handler)
158        .set    push
159        .set    noat
160        MFC0    k0, CP0_EPC
161        PTR_LA  k1, __r4k_wait
162        ori     k0, 0x1f        /* 32 byte rollback region */
163        xori    k0, 0x1f
164        bne     k0, k1, \handler
165        MTC0    k0, CP0_EPC
166        .set pop
167        .endm
168
169        .align  5
170BUILD_ROLLBACK_PROLOGUE handle_int
171NESTED(handle_int, PT_SIZE, sp)
172#ifdef CONFIG_TRACE_IRQFLAGS
173        /*
174         * Check to see if the interrupted code has just disabled
175         * interrupts and ignore this interrupt for now if so.
176         *
177         * local_irq_disable() disables interrupts and then calls
178         * trace_hardirqs_off() to track the state. If an interrupt is taken
179         * after interrupts are disabled but before the state is updated
180         * it will appear to restore_all that it is incorrectly returning with
181         * interrupts disabled
182         */
183        .set    push
184        .set    noat
185        mfc0    k0, CP0_STATUS
186#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
187        and     k0, ST0_IEP
188        bnez    k0, 1f
189
190        mfc0    k0, CP0_EPC
191        .set    noreorder
192        j       k0
193         rfe
194#else
195        and     k0, ST0_IE
196        bnez    k0, 1f
197
198        eret
199#endif
2001:
201        .set pop
202#endif
203        SAVE_ALL
204        CLI
205        TRACE_IRQS_OFF
206
207        LONG_L  s0, TI_REGS($28)
208        LONG_S  sp, TI_REGS($28)
209        PTR_LA  ra, ret_from_irq
210        PTR_LA  v0, plat_irq_dispatch
211        jr      v0
212#ifdef CONFIG_CPU_MICROMIPS
213        nop
214#endif
215        END(handle_int)
216
217        __INIT
218
219/*
220 * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
221 * This is a dedicated interrupt exception vector which reduces the
222 * interrupt processing overhead.  The jump instruction will be replaced
223 * at the initialization time.
224 *
225 * Be careful when changing this, it has to be at most 128 bytes
226 * to fit into space reserved for the exception handler.
227 */
228NESTED(except_vec4, 0, sp)
2291:      j       1b                      /* Dummy, will be replaced */
230        END(except_vec4)
231
232/*
233 * EJTAG debug exception handler.
234 * The EJTAG debug exception entry point is 0xbfc00480, which
235 * normally is in the boot PROM, so the boot PROM must do an
236 * unconditional jump to this vector.
237 */
238NESTED(except_vec_ejtag_debug, 0, sp)
239        j       ejtag_debug_handler
240#ifdef CONFIG_CPU_MICROMIPS
241         nop
242#endif
243        END(except_vec_ejtag_debug)
244
245        __FINIT
246
247/*
248 * Vectored interrupt handler.
249 * This prototype is copied to ebase + n*IntCtl.VS and patched
250 * to invoke the handler
251 */
252BUILD_ROLLBACK_PROLOGUE except_vec_vi
253NESTED(except_vec_vi, 0, sp)
254        SAVE_SOME
255        SAVE_AT
256        .set    push
257        .set    noreorder
258        PTR_LA  v1, except_vec_vi_handler
259FEXPORT(except_vec_vi_lui)
260        lui     v0, 0           /* Patched */
261        jr      v1
262FEXPORT(except_vec_vi_ori)
263         ori    v0, 0           /* Patched */
264        .set    pop
265        END(except_vec_vi)
266EXPORT(except_vec_vi_end)
267
268/*
269 * Common Vectored Interrupt code
270 * Complete the register saves and invoke the handler which is passed in $v0
271 */
272NESTED(except_vec_vi_handler, 0, sp)
273        SAVE_TEMP
274        SAVE_STATIC
275        CLI
276#ifdef CONFIG_TRACE_IRQFLAGS
277        move    s0, v0
278        TRACE_IRQS_OFF
279        move    v0, s0
280#endif
281
282        LONG_L  s0, TI_REGS($28)
283        LONG_S  sp, TI_REGS($28)
284        PTR_LA  ra, ret_from_irq
285        jr      v0
286        END(except_vec_vi_handler)
287
288/*
289 * EJTAG debug exception handler.
290 */
291NESTED(ejtag_debug_handler, PT_SIZE, sp)
292        .set    push
293        .set    noat
294        MTC0    k0, CP0_DESAVE
295        mfc0    k0, CP0_DEBUG
296
297        sll     k0, k0, 30      # Check for SDBBP.
298        bgez    k0, ejtag_return
299
300        PTR_LA  k0, ejtag_debug_buffer
301        LONG_S  k1, 0(k0)
302        SAVE_ALL
303        move    a0, sp
304        jal     ejtag_exception_handler
305        RESTORE_ALL
306        PTR_LA  k0, ejtag_debug_buffer
307        LONG_L  k1, 0(k0)
308
309ejtag_return:
310        MFC0    k0, CP0_DESAVE
311        .set    mips32
312        deret
313        .set    pop
314        END(ejtag_debug_handler)
315
316/*
317 * This buffer is reserved for the use of the EJTAG debug
318 * handler.
319 */
320        .data
321EXPORT(ejtag_debug_buffer)
322        .fill   LONGSIZE
323        .previous
324
325        __INIT
326
327/*
328 * NMI debug exception handler for MIPS reference boards.
329 * The NMI debug exception entry point is 0xbfc00000, which
330 * normally is in the boot PROM, so the boot PROM must do a
331 * unconditional jump to this vector.
332 */
333NESTED(except_vec_nmi, 0, sp)
334        j       nmi_handler
335#ifdef CONFIG_CPU_MICROMIPS
336         nop
337#endif
338        END(except_vec_nmi)
339
340        __FINIT
341
342NESTED(nmi_handler, PT_SIZE, sp)
343        .set    push
344        .set    noat
345        /*
346         * Clear ERL - restore segment mapping
347         * Clear BEV - required for page fault exception handler to work
348         */
349        mfc0    k0, CP0_STATUS
350        ori     k0, k0, ST0_EXL
351        li      k1, ~(ST0_BEV | ST0_ERL)
352        and     k0, k0, k1
353        mtc0    k0, CP0_STATUS
354        _ehb
355        SAVE_ALL
356        move    a0, sp
357        jal     nmi_exception_handler
358        /* nmi_exception_handler never returns */
359        .set    pop
360        END(nmi_handler)
361
362        .macro  __build_clear_none
363        .endm
364
365        .macro  __build_clear_sti
366        TRACE_IRQS_ON
367        STI
368        .endm
369
370        .macro  __build_clear_cli
371        CLI
372        TRACE_IRQS_OFF
373        .endm
374
375        .macro  __build_clear_fpe
376        .set    push
377        /* gas fails to assemble cfc1 for some archs (octeon).*/ \
378        .set    mips1
379        SET_HARDFLOAT
380        cfc1    a1, fcr31
381        .set    pop
382        CLI
383        TRACE_IRQS_OFF
384        .endm
385
386        .macro  __build_clear_msa_fpe
387        _cfcmsa a1, MSA_CSR
388        CLI
389        TRACE_IRQS_OFF
390        .endm
391
392        .macro  __build_clear_ade
393        MFC0    t0, CP0_BADVADDR
394        PTR_S   t0, PT_BVADDR(sp)
395        KMODE
396        .endm
397
398        .macro  __BUILD_silent exception
399        .endm
400
401        /* Gas tries to parse the PRINT argument as a string containing
402           string escapes and emits bogus warnings if it believes to
403           recognize an unknown escape code.  So make the arguments
404           start with an n and gas will believe \n is ok ...  */
405        .macro  __BUILD_verbose nexception
406        LONG_L  a1, PT_EPC(sp)
407#ifdef CONFIG_32BIT
408        PRINT("Got \nexception at %08lx\012")
409#endif
410#ifdef CONFIG_64BIT
411        PRINT("Got \nexception at %016lx\012")
412#endif
413        .endm
414
415        .macro  __BUILD_count exception
416        LONG_L  t0,exception_count_\exception
417        LONG_ADDIU      t0, 1
418        LONG_S  t0,exception_count_\exception
419        .comm   exception_count\exception, 8, 8
420        .endm
421
422        .macro  __BUILD_HANDLER exception handler clear verbose ext
423        .align  5
424        NESTED(handle_\exception, PT_SIZE, sp)
425        .set    noat
426        SAVE_ALL
427        FEXPORT(handle_\exception\ext)
428        __build_clear_\clear
429        .set    at
430        __BUILD_\verbose \exception
431        move    a0, sp
432        PTR_LA  ra, ret_from_exception
433        j       do_\handler
434        END(handle_\exception)
435        .endm
436
437        .macro  BUILD_HANDLER exception handler clear verbose
438        __BUILD_HANDLER \exception \handler \clear \verbose _int
439        .endm
440
441        BUILD_HANDLER adel ade ade silent               /* #4  */
442        BUILD_HANDLER ades ade ade silent               /* #5  */
443        BUILD_HANDLER ibe be cli silent                 /* #6  */
444        BUILD_HANDLER dbe be cli silent                 /* #7  */
445        BUILD_HANDLER bp bp sti silent                  /* #9  */
446        BUILD_HANDLER ri ri sti silent                  /* #10 */
447        BUILD_HANDLER cpu cpu sti silent                /* #11 */
448        BUILD_HANDLER ov ov sti silent                  /* #12 */
449        BUILD_HANDLER tr tr sti silent                  /* #13 */
450        BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent    /* #14 */
451        BUILD_HANDLER fpe fpe fpe silent                /* #15 */
452        BUILD_HANDLER ftlb ftlb none silent             /* #16 */
453        BUILD_HANDLER msa msa sti silent                /* #21 */
454        BUILD_HANDLER mdmx mdmx sti silent              /* #22 */
455#ifdef  CONFIG_HARDWARE_WATCHPOINTS
456        /*
457         * For watch, interrupts will be enabled after the watch
458         * registers are read.
459         */
460        BUILD_HANDLER watch watch cli silent            /* #23 */
461#else
462        BUILD_HANDLER watch watch sti verbose           /* #23 */
463#endif
464        BUILD_HANDLER mcheck mcheck cli verbose         /* #24 */
465        BUILD_HANDLER mt mt sti silent                  /* #25 */
466        BUILD_HANDLER dsp dsp sti silent                /* #26 */
467        BUILD_HANDLER reserved reserved sti verbose     /* others */
468
469        .align  5
470        LEAF(handle_ri_rdhwr_tlbp)
471        .set    push
472        .set    noat
473        .set    noreorder
474        /* check if TLB contains a entry for EPC */
475        MFC0    k1, CP0_ENTRYHI
476        andi    k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
477        MFC0    k0, CP0_EPC
478        PTR_SRL k0, _PAGE_SHIFT + 1
479        PTR_SLL k0, _PAGE_SHIFT + 1
480        or      k1, k0
481        MTC0    k1, CP0_ENTRYHI
482        mtc0_tlbw_hazard
483        tlbp
484        tlb_probe_hazard
485        mfc0    k1, CP0_INDEX
486        .set    pop
487        bltz    k1, handle_ri   /* slow path */
488        /* fall thru */
489        END(handle_ri_rdhwr_tlbp)
490
491        LEAF(handle_ri_rdhwr)
492        .set    push
493        .set    noat
494        .set    noreorder
495        /* MIPS32:    0x7c03e83b: rdhwr v1,$29 */
496        /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */
497        MFC0    k1, CP0_EPC
498#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2)
499        and     k0, k1, 1
500        beqz    k0, 1f
501         xor    k1, k0
502        lhu     k0, (k1)
503        lhu     k1, 2(k1)
504        ins     k1, k0, 16, 16
505        lui     k0, 0x007d
506        b       docheck
507         ori    k0, 0x6b3c
5081:
509        lui     k0, 0x7c03
510        lw      k1, (k1)
511        ori     k0, 0xe83b
512#else
513        andi    k0, k1, 1
514        bnez    k0, handle_ri
515         lui    k0, 0x7c03
516        lw      k1, (k1)
517        ori     k0, 0xe83b
518#endif
519        .set    reorder
520docheck:
521        bne     k0, k1, handle_ri       /* if not ours */
522
523isrdhwr:
524        /* The insn is rdhwr.  No need to check CAUSE.BD here. */
525        get_saved_sp    /* k1 := current_thread_info */
526        .set    noreorder
527        MFC0    k0, CP0_EPC
528#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
529        ori     k1, _THREAD_MASK
530        xori    k1, _THREAD_MASK
531        LONG_L  v1, TI_TP_VALUE(k1)
532        LONG_ADDIU      k0, 4
533        jr      k0
534         rfe
535#else
536#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
537        LONG_ADDIU      k0, 4           /* stall on $k0 */
538#else
539        .set    at=v1
540        LONG_ADDIU      k0, 4
541        .set    noat
542#endif
543        MTC0    k0, CP0_EPC
544        /* I hope three instructions between MTC0 and ERET are enough... */
545        ori     k1, _THREAD_MASK
546        xori    k1, _THREAD_MASK
547        LONG_L  v1, TI_TP_VALUE(k1)
548        .set    arch=r4000
549        eret
550        .set    mips0
551#endif
552        .set    pop
553        END(handle_ri_rdhwr)
554
555#ifdef CONFIG_64BIT
556/* A temporary overflow handler used by check_daddi(). */
557
558        __INIT
559
560        BUILD_HANDLER  daddi_ov daddi_ov none silent    /* #12 */
561#endif
Note: See TracBrowser for help on using the repository browser.