source: src/linux/universal/linux-4.4/arch/mips/kernel/genex.S @ 31884

Last change on this file since 31884 was 31884, checked in by brainslayer, 6 weeks ago

update kernels

File size: 13.1 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, 9f
165        MTC0    k0, CP0_EPC
1669:
167        .set pop
168        .endm
169
170        .align  5
171BUILD_ROLLBACK_PROLOGUE handle_int
172NESTED(handle_int, PT_SIZE, sp)
173#ifdef CONFIG_TRACE_IRQFLAGS
174        /*
175         * Check to see if the interrupted code has just disabled
176         * interrupts and ignore this interrupt for now if so.
177         *
178         * local_irq_disable() disables interrupts and then calls
179         * trace_hardirqs_off() to track the state. If an interrupt is taken
180         * after interrupts are disabled but before the state is updated
181         * it will appear to restore_all that it is incorrectly returning with
182         * interrupts disabled
183         */
184        .set    push
185        .set    noat
186        mfc0    k0, CP0_STATUS
187#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
188        and     k0, ST0_IEP
189        bnez    k0, 1f
190
191        mfc0    k0, CP0_EPC
192        .set    noreorder
193        j       k0
194        rfe
195#else
196        and     k0, ST0_IE
197        bnez    k0, 1f
198
199        eret
200#endif
2011:
202        .set pop
203#endif
204        SAVE_ALL
205        CLI
206        TRACE_IRQS_OFF
207
208        LONG_L  s0, TI_REGS($28)
209        LONG_S  sp, TI_REGS($28)
210
211        /*
212         * SAVE_ALL ensures we are using a valid kernel stack for the thread.
213         * Check if we are already using the IRQ stack.
214         */
215        move    s1, sp # Preserve the sp
216
217        /* Get IRQ stack for this CPU */
218        ASM_CPUID_MFC0  k0, ASM_SMP_CPUID_REG
219#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
220        lui     k1, %hi(irq_stack)
221#else
222        lui     k1, %highest(irq_stack)
223        daddiu  k1, %higher(irq_stack)
224        dsll    k1, 16
225        daddiu  k1, %hi(irq_stack)
226        dsll    k1, 16
227#endif
228        LONG_SRL        k0, SMP_CPUID_PTRSHIFT
229        LONG_ADDU       k1, k0
230        LONG_L  t0, %lo(irq_stack)(k1)
231
232        # Check if already on IRQ stack
233        PTR_LI  t1, ~(_THREAD_SIZE-1)
234        and     t1, t1, sp
235        beq     t0, t1, 2f
236
237        /* Switch to IRQ stack */
238        li      t1, _IRQ_STACK_SIZE
239        PTR_ADD sp, t0, t1
240
2412:
242        jal     plat_irq_dispatch
243
244        /* Restore sp */
245        move    sp, s1
246
247        j       ret_from_irq
248#ifdef CONFIG_CPU_MICROMIPS
249        nop
250#endif
251        END(handle_int)
252
253        __INIT
254
255/*
256 * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
257 * This is a dedicated interrupt exception vector which reduces the
258 * interrupt processing overhead.  The jump instruction will be replaced
259 * at the initialization time.
260 *
261 * Be careful when changing this, it has to be at most 128 bytes
262 * to fit into space reserved for the exception handler.
263 */
264NESTED(except_vec4, 0, sp)
2651:      j       1b                      /* Dummy, will be replaced */
266        END(except_vec4)
267
268/*
269 * EJTAG debug exception handler.
270 * The EJTAG debug exception entry point is 0xbfc00480, which
271 * normally is in the boot PROM, so the boot PROM must do an
272 * unconditional jump to this vector.
273 */
274NESTED(except_vec_ejtag_debug, 0, sp)
275        j       ejtag_debug_handler
276#ifdef CONFIG_CPU_MICROMIPS
277         nop
278#endif
279        END(except_vec_ejtag_debug)
280
281        __FINIT
282
283/*
284 * Vectored interrupt handler.
285 * This prototype is copied to ebase + n*IntCtl.VS and patched
286 * to invoke the handler
287 */
288BUILD_ROLLBACK_PROLOGUE except_vec_vi
289NESTED(except_vec_vi, 0, sp)
290        SAVE_SOME
291        SAVE_AT
292        .set    push
293        .set    noreorder
294        PTR_LA  v1, except_vec_vi_handler
295FEXPORT(except_vec_vi_lui)
296        lui     v0, 0           /* Patched */
297        jr      v1
298FEXPORT(except_vec_vi_ori)
299         ori    v0, 0           /* Patched */
300        .set    pop
301        END(except_vec_vi)
302EXPORT(except_vec_vi_end)
303
304/*
305 * Common Vectored Interrupt code
306 * Complete the register saves and invoke the handler which is passed in $v0
307 */
308NESTED(except_vec_vi_handler, 0, sp)
309        SAVE_TEMP
310        SAVE_STATIC
311        CLI
312#ifdef CONFIG_TRACE_IRQFLAGS
313        move    s0, v0
314        TRACE_IRQS_OFF
315        move    v0, s0
316#endif
317
318        LONG_L  s0, TI_REGS($28)
319        LONG_S  sp, TI_REGS($28)
320
321        /*
322         * SAVE_ALL ensures we are using a valid kernel stack for the thread.
323         * Check if we are already using the IRQ stack.
324         */
325        move    s1, sp # Preserve the sp
326
327        /* Get IRQ stack for this CPU */
328        ASM_CPUID_MFC0  k0, ASM_SMP_CPUID_REG
329#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
330        lui     k1, %hi(irq_stack)
331#else
332        lui     k1, %highest(irq_stack)
333        daddiu  k1, %higher(irq_stack)
334        dsll    k1, 16
335        daddiu  k1, %hi(irq_stack)
336        dsll    k1, 16
337#endif
338        LONG_SRL        k0, SMP_CPUID_PTRSHIFT
339        LONG_ADDU       k1, k0
340        LONG_L  t0, %lo(irq_stack)(k1)
341
342        # Check if already on IRQ stack
343        PTR_LI  t1, ~(_THREAD_SIZE-1)
344        and     t1, t1, sp
345        beq     t0, t1, 2f
346
347        /* Switch to IRQ stack */
348        li      t1, _IRQ_STACK_SIZE
349        PTR_ADD sp, t0, t1
350
3512:
352        jalr    v0
353
354        /* Restore sp */
355        move    sp, s1
356
357        j       ret_from_irq
358        END(except_vec_vi_handler)
359
360/*
361 * EJTAG debug exception handler.
362 */
363NESTED(ejtag_debug_handler, PT_SIZE, sp)
364        .set    push
365        .set    noat
366        MTC0    k0, CP0_DESAVE
367        mfc0    k0, CP0_DEBUG
368
369        sll     k0, k0, 30      # Check for SDBBP.
370        bgez    k0, ejtag_return
371
372        PTR_LA  k0, ejtag_debug_buffer
373        LONG_S  k1, 0(k0)
374        SAVE_ALL
375        move    a0, sp
376        jal     ejtag_exception_handler
377        RESTORE_ALL
378        PTR_LA  k0, ejtag_debug_buffer
379        LONG_L  k1, 0(k0)
380
381ejtag_return:
382        MFC0    k0, CP0_DESAVE
383        .set    mips32
384        deret
385        .set pop
386        END(ejtag_debug_handler)
387
388/*
389 * This buffer is reserved for the use of the EJTAG debug
390 * handler.
391 */
392        .data
393EXPORT(ejtag_debug_buffer)
394        .fill   LONGSIZE
395        .previous
396
397        __INIT
398
399/*
400 * NMI debug exception handler for MIPS reference boards.
401 * The NMI debug exception entry point is 0xbfc00000, which
402 * normally is in the boot PROM, so the boot PROM must do a
403 * unconditional jump to this vector.
404 */
405NESTED(except_vec_nmi, 0, sp)
406        j       nmi_handler
407#ifdef CONFIG_CPU_MICROMIPS
408         nop
409#endif
410        END(except_vec_nmi)
411
412        __FINIT
413
414NESTED(nmi_handler, PT_SIZE, sp)
415        .set    push
416        .set    noat
417        /*
418         * Clear ERL - restore segment mapping
419         * Clear BEV - required for page fault exception handler to work
420         */
421        mfc0    k0, CP0_STATUS
422        ori     k0, k0, ST0_EXL
423        li      k1, ~(ST0_BEV | ST0_ERL)
424        and     k0, k0, k1
425        mtc0    k0, CP0_STATUS
426        _ehb
427        SAVE_ALL
428        move    a0, sp
429        jal     nmi_exception_handler
430        /* nmi_exception_handler never returns */
431        .set    pop
432        END(nmi_handler)
433
434        .macro  __build_clear_none
435        .endm
436
437        .macro  __build_clear_sti
438        TRACE_IRQS_ON
439        STI
440        .endm
441
442        .macro  __build_clear_cli
443        CLI
444        TRACE_IRQS_OFF
445        .endm
446
447        .macro  __build_clear_fpe
448        .set    push
449        /* gas fails to assemble cfc1 for some archs (octeon).*/ \
450        .set    mips1
451        SET_HARDFLOAT
452        cfc1    a1, fcr31
453        .set    pop
454        CLI
455        TRACE_IRQS_OFF
456        .endm
457
458        .macro  __build_clear_msa_fpe
459        _cfcmsa a1, MSA_CSR
460        CLI
461        TRACE_IRQS_OFF
462        .endm
463
464        .macro  __build_clear_ade
465        MFC0    t0, CP0_BADVADDR
466        PTR_S   t0, PT_BVADDR(sp)
467        KMODE
468        .endm
469
470        .macro  __BUILD_silent exception
471        .endm
472
473        /* Gas tries to parse the PRINT argument as a string containing
474           string escapes and emits bogus warnings if it believes to
475           recognize an unknown escape code.  So make the arguments
476           start with an n and gas will believe \n is ok ...  */
477        .macro  __BUILD_verbose nexception
478        LONG_L  a1, PT_EPC(sp)
479#ifdef CONFIG_32BIT
480        PRINT("Got \nexception at %08lx\012")
481#endif
482#ifdef CONFIG_64BIT
483        PRINT("Got \nexception at %016lx\012")
484#endif
485        .endm
486
487        .macro  __BUILD_count exception
488        LONG_L  t0,exception_count_\exception
489        LONG_ADDIU t0, 1
490        LONG_S  t0,exception_count_\exception
491        .comm   exception_count\exception, 8, 8
492        .endm
493
494        .macro  __BUILD_HANDLER exception handler clear verbose ext
495        .align  5
496        NESTED(handle_\exception, PT_SIZE, sp)
497        .set    noat
498        SAVE_ALL
499        FEXPORT(handle_\exception\ext)
500        __build_clear_\clear
501        .set    at
502        __BUILD_\verbose \exception
503        move    a0, sp
504        PTR_LA  ra, ret_from_exception
505        j       do_\handler
506        END(handle_\exception)
507        .endm
508
509        .macro  BUILD_HANDLER exception handler clear verbose
510        __BUILD_HANDLER \exception \handler \clear \verbose _int
511        .endm
512
513        BUILD_HANDLER adel ade ade silent               /* #4  */
514        BUILD_HANDLER ades ade ade silent               /* #5  */
515        BUILD_HANDLER ibe be cli silent                 /* #6  */
516        BUILD_HANDLER dbe be cli silent                 /* #7  */
517        BUILD_HANDLER bp bp sti silent                  /* #9  */
518        BUILD_HANDLER ri ri sti silent                  /* #10 */
519        BUILD_HANDLER cpu cpu sti silent                /* #11 */
520        BUILD_HANDLER ov ov sti silent                  /* #12 */
521        BUILD_HANDLER tr tr sti silent                  /* #13 */
522        BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent    /* #14 */
523        BUILD_HANDLER fpe fpe fpe silent                /* #15 */
524        BUILD_HANDLER ftlb ftlb none silent             /* #16 */
525        BUILD_HANDLER msa msa sti silent                /* #21 */
526        BUILD_HANDLER mdmx mdmx sti silent              /* #22 */
527#ifdef  CONFIG_HARDWARE_WATCHPOINTS
528        /*
529         * For watch, interrupts will be enabled after the watch
530         * registers are read.
531         */
532        BUILD_HANDLER watch watch cli silent            /* #23 */
533#else
534        BUILD_HANDLER watch watch sti verbose           /* #23 */
535#endif
536        BUILD_HANDLER mcheck mcheck cli verbose         /* #24 */
537        BUILD_HANDLER mt mt sti silent                  /* #25 */
538        BUILD_HANDLER dsp dsp sti silent                /* #26 */
539        BUILD_HANDLER reserved reserved sti verbose     /* others */
540
541        .align  5
542        LEAF(handle_ri_rdhwr_vivt)
543        .set    push
544        .set    noat
545        .set    noreorder
546        /* check if TLB contains a entry for EPC */
547        MFC0    k1, CP0_ENTRYHI
548        andi    k1, 0xff        /* ASID_MASK */
549        MFC0    k0, CP0_EPC
550        PTR_SRL k0, _PAGE_SHIFT + 1
551        PTR_SLL k0, _PAGE_SHIFT + 1
552        or      k1, k0
553        MTC0    k1, CP0_ENTRYHI
554        mtc0_tlbw_hazard
555        tlbp
556        tlb_probe_hazard
557        mfc0    k1, CP0_INDEX
558        .set    pop
559        bltz    k1, handle_ri   /* slow path */
560        /* fall thru */
561        END(handle_ri_rdhwr_vivt)
562
563        LEAF(handle_ri_rdhwr)
564        .set    push
565        .set    noat
566        .set    noreorder
567        /* MIPS32:    0x7c03e83b: rdhwr v1,$29 */
568        /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */
569        MFC0    k1, CP0_EPC
570#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2)
571        and     k0, k1, 1
572        beqz    k0, 1f
573        xor     k1, k0
574        lhu     k0, (k1)
575        lhu     k1, 2(k1)
576        ins     k1, k0, 16, 16
577        lui     k0, 0x007d
578        b       docheck
579        ori     k0, 0x6b3c
5801:
581        lui     k0, 0x7c03
582        lw      k1, (k1)
583        ori     k0, 0xe83b
584#else
585        andi    k0, k1, 1
586        bnez    k0, handle_ri
587        lui     k0, 0x7c03
588        lw      k1, (k1)
589        ori     k0, 0xe83b
590#endif
591        .set    reorder
592docheck:
593        bne     k0, k1, handle_ri       /* if not ours */
594
595isrdhwr:
596        /* The insn is rdhwr.  No need to check CAUSE.BD here. */
597        get_saved_sp    /* k1 := current_thread_info */
598        .set    noreorder
599        MFC0    k0, CP0_EPC
600#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
601        ori     k1, _THREAD_MASK
602        xori    k1, _THREAD_MASK
603        LONG_L  v1, TI_TP_VALUE(k1)
604        LONG_ADDIU      k0, 4
605        jr      k0
606         rfe
607#else
608#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
609        LONG_ADDIU      k0, 4           /* stall on $k0 */
610#else
611        .set    at=v1
612        LONG_ADDIU      k0, 4
613        .set    noat
614#endif
615        MTC0    k0, CP0_EPC
616        /* I hope three instructions between MTC0 and ERET are enough... */
617        ori     k1, _THREAD_MASK
618        xori    k1, _THREAD_MASK
619        LONG_L  v1, TI_TP_VALUE(k1)
620        .set    arch=r4000
621        eret
622        .set    mips0
623#endif
624        .set    pop
625        END(handle_ri_rdhwr)
626
627#ifdef CONFIG_64BIT
628/* A temporary overflow handler used by check_daddi(). */
629
630        __INIT
631
632        BUILD_HANDLER  daddi_ov daddi_ov none silent    /* #12 */
633#endif
Note: See TracBrowser for help on using the repository browser.