/* SPDX-License-Identifier: GPL-2.0 *//* arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/export.h>#include <linux/linkage.h>#include <linux/errno.h>#include <linux/pgtable.h> #include <asm/head.h>#include <asm/asi.h>#include <asm/smp.h>#include <asm/contregs.h>#include <asm/ptrace.h>#include <asm/asm-offsets.h>#include <asm/psr.h>#include <asm/vaddrs.h>#include <asm/page.h>#include <asm/winmacro.h>#include <asm/signal.h>#include <asm/obio.h>#include <asm/mxcc.h>#include <asm/thread_info.h>#include <asm/param.h>#include <asm/unistd.h> #include <asm/asmmacro.h> #define curptr g6 /* These are just handy. */#define _SV save %sp, -STACKFRAME_SZ, %sp#define _RS restore #define FLUSH_ALL_KERNEL_WINDOWS \ _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ _RS; _RS; _RS; _RS; _RS; _RS; _RS; .text #ifdef CONFIG_KGDB .align 4 .globl arch_kgdb_breakpoint .type arch_kgdb_breakpoint,#functionarch_kgdb_breakpoint: ta 0x7d retl nop .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint#endif #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) .align 4 .globl floppy_hardintfloppy_hardint: /* * This code cannot touch registers %l0 %l1 and %l2 * because SAVE_ALL depends on their values. It depends * on %l3 also, but we regenerate it before a call. * Other registers are: * %l3 -- base address of fdc registers * %l4 -- pdma_vaddr * %l5 -- scratch for ld/st address * %l6 -- pdma_size * %l7 -- scratch [floppy byte, ld/st address, aux. data] */ /* Do we have work to do? */ sethi %hi(doing_pdma), %l7 ld [%l7 + %lo(doing_pdma)], %l7 cmp %l7, 0 be floppy_dosoftint nop /* Load fdc register base */ sethi %hi(fdc_status), %l3 ld [%l3 + %lo(fdc_status)], %l3 /* Setup register addresses */ sethi %hi(pdma_vaddr), %l5 ! transfer buffer ld [%l5 + %lo(pdma_vaddr)], %l4 sethi %hi(pdma_size), %l5 ! bytes to go ld [%l5 + %lo(pdma_size)], %l6next_byte: ldub [%l3], %l7 andcc %l7, 0x80, %g0 ! Does fifo still have data bz floppy_fifo_emptied ! fifo has been emptied... andcc %l7, 0x20, %g0 ! in non-dma mode still? bz floppy_overrun ! nope, overrun andcc %l7, 0x40, %g0 ! 0=write 1=read bz floppy_write sub %l6, 0x1, %l6 /* Ok, actually read this byte */ ldub [%l3 + 1], %l7 orcc %g0, %l6, %g0 stb %l7, [%l4] bne next_byte add %l4, 0x1, %l4 b floppy_tdone nop floppy_write: /* Ok, actually write this byte */ ldub [%l4], %l7 orcc %g0, %l6, %g0 stb %l7, [%l3 + 1] bne next_byte add %l4, 0x1, %l4 /* fall through... */floppy_tdone: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l5 st %l6, [%l5 + %lo(pdma_size)] /* Flip terminal count pin */ set auxio_register, %l7 ld [%l7], %l7 ldub [%l7], %l5 or %l5, 0xc2, %l5 stb %l5, [%l7] andn %l5, 0x02, %l5 2: /* Kill some time so the bits set */ WRITE_PAUSE WRITE_PAUSE stb %l5, [%l7] /* Prevent recursion */ sethi %hi(doing_pdma), %l7 b floppy_dosoftint st %g0, [%l7 + %lo(doing_pdma)] /* We emptied the FIFO, but we haven't read everything * as of yet. Store the current transfer address and * bytes left to read so we can continue when the next * fast IRQ comes in. */floppy_fifo_emptied: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l7 st %l6, [%l7 + %lo(pdma_size)] /* Restore condition codes */ wr %l0, 0x0, %psr WRITE_PAUSE jmp %l1 rett %l2 floppy_overrun: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l5 st %l6, [%l5 + %lo(pdma_size)] /* Prevent recursion */ sethi %hi(doing_pdma), %l7 st %g0, [%l7 + %lo(doing_pdma)] /* fall through... */floppy_dosoftint: rd %wim, %l3 SAVE_ALL /* Set all IRQs off. */ or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE mov 11, %o0 ! floppy irq level (unused anyway) mov %g0, %o1 ! devid is not used in fast interrupts call sparc_floppy_irq add %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs RESTORE_ALL #endif /* (CONFIG_BLK_DEV_FD) */ /* Bad trap handler */ .globl bad_trap_handlerbad_trap_handler: SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 ! pt_regs call do_hw_interrupt mov %l7, %o1 ! trap number RESTORE_ALL /* For now all IRQ's not registered get sent here. handler_irq() will * see if a routine is registered to handle this interrupt and if not * it will say so on the console. */ .align 4 .globl real_irq_entry, patch_handler_irqreal_irq_entry: SAVE_ALL #ifdef CONFIG_SMP .globl patchme_maybe_smp_msg cmp %l7, 11patchme_maybe_smp_msg: bgu maybe_smp4m_msg nop#endif real_irq_continue: or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE mov %l7, %o0 ! irq levelpatch_handler_irq: call handler_irq add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq wr %g2, PSR_ET, %psr ! keep ET up WRITE_PAUSE RESTORE_ALL #ifdef CONFIG_SMP /* SMP per-cpu ticker interrupts are handled specially. */smp4m_ticker: bne real_irq_continue+4 or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call smp4m_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL #define GET_PROCESSOR4M_ID(reg) \ rd %tbr, %reg; \ srl %reg, 12, %reg; \ and %reg, 3, %reg; /* Here is where we check for possible SMP IPI passed to us * on some level other than 15 which is the NMI and only used * for cross calls. That has a separate entry point below. * * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*. */maybe_smp4m_msg: GET_PROCESSOR4M_ID(o3) sethi %hi(sun4m_irq_percpu), %l5 sll %o3, 2, %o3 or %l5, %lo(sun4m_irq_percpu), %o5 sethi %hi(0x70000000), %o2 ! Check all soft-IRQs ld [%o5 + %o3], %o1 ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be,a smp4m_ticker cmp %l7, 14 /* Soft-IRQ IPI */ st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000 WRITE_PAUSE ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE srl %o3, 28, %o2 ! shift for simpler checks belowmaybe_smp4m_msg_check_single: andcc %o2, 0x1, %g0 beq,a maybe_smp4m_msg_check_mask andcc %o2, 0x2, %g0 call smp_call_function_single_interrupt nop andcc %o2, 0x2, %g0maybe_smp4m_msg_check_mask: beq,a maybe_smp4m_msg_check_resched andcc %o2, 0x4, %g0 call smp_call_function_interrupt nop andcc %o2, 0x4, %g0maybe_smp4m_msg_check_resched: /* rescheduling is done in RESTORE_ALL regardless, but incr stats */ beq,a maybe_smp4m_msg_out nop call smp_resched_interrupt nopmaybe_smp4m_msg_out: RESTORE_ALL .align 4 .globl linux_trap_ipi15_sun4mlinux_trap_ipi15_sun4m: SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR4M_ID(o0) sethi %hi(sun4m_irq_percpu), %l5 or %l5, %lo(sun4m_irq_percpu), %o5 sll %o0, 2, %o0 ld [%o5 + %o0], %o5 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be sun4m_nmi_error ! Must be an NMI async memory error st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 WRITE_PAUSE ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call smp4m_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 .globl smp4d_ticker /* SMP per-cpu ticker interrupts are handled specially. */smp4d_ticker: SAVE_ALL or %l0, PSR_PIL, %g2 sethi %hi(CC_ICLR), %o0 sethi %hi(1 << 14), %o1 or %o0, %lo(CC_ICLR), %o0 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */ wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call smp4d_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL .align 4 .globl linux_trap_ipi15_sun4dlinux_trap_ipi15_sun4d: SAVE_ALL sethi %hi(CC_BASE), %o4 sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2 or %o4, (CC_EREG - CC_BASE), %o0 ldda [%o0] ASI_M_MXCC, %o0 andcc %o0, %o2, %g0 bne 1f sethi %hi(BB_STAT2), %o2 lduba [%o2] ASI_M_CTL, %o2 andcc %o2, BB_STAT2_MASK, %g0 bne 2f or %o4, (CC_ICLR - CC_BASE), %o0 sethi %hi(1 << 15), %o1 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */ or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call smp4d_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 1: /* MXCC error */2: /* BB error */ /* Disable PIL 15 */ set CC_IMSK, %l4 lduha [%l4] ASI_M_MXCC, %l5 sethi %hi(1 << 15), %l7 or %l5, %l7, %l5 stha %l5, [%l4] ASI_M_MXCC /* FIXME */1: b,a 1b .globl smpleon_ipi .extern leon_ipi_interrupt /* SMP per-cpu IPI interrupts are handled specially. */smpleon_ipi: SAVE_ALL or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call leonsmp_ipi_interrupt add %sp, STACKFRAME_SZ, %o1 ! pt_regs wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL .align 4 .globl linux_trap_ipi15_leonlinux_trap_ipi15_leon: SAVE_ALL or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call leon_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 #endif /* CONFIG_SMP */ /* This routine handles illegal instructions and privileged * instruction attempts from user code. */ .align 4 .globl bad_instructionbad_instruction: sethi %hi(0xc1f80000), %l4 ld [%l1], %l5 sethi %hi(0x81d80000), %l7 and %l5, %l4, %l5 cmp %l5, %l7 be 1f SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call do_illegal_instruction mov %l0, %o3 RESTORE_ALL 1: /* unimplemented flush - just skip */ jmpl %l2, %g0 rett %l2 + 4 .align 4 .globl priv_instructionpriv_instruction: SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call do_priv_instruction mov %l0, %o3 RESTORE_ALL /* This routine handles unaligned data accesses. */ .align 4 .globl mna_handlermna_handler: andcc %l0, PSR_PS, %g0 be mna_fromuser nop SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE ld [%l1], %o1 call kernel_unaligned_trap add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL mna_fromuser: SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE ld [%l1], %o1Lines 1–500 of 1370. Load more
/* SPDX-License-Identifier: GPL-2.0 */ /* arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/export.h> #include <linux/linkage.h> #include <linux/errno.h> #include <linux/pgtable.h> #include <asm/head.h> #include <asm/asi.h> #include <asm/smp.h> #include <asm/contregs.h> #include <asm/ptrace.h> #include <asm/asm-offsets.h> #include <asm/psr.h> #include <asm/vaddrs.h> #include <asm/page.h> #include <asm/winmacro.h> #include <asm/signal.h> #include <asm/obio.h> #include <asm/mxcc.h> #include <asm/thread_info.h> #include <asm/param.h> #include <asm/unistd.h> #include <asm/asmmacro.h> #define curptr g6 /* These are just handy. */ #define _SV save %sp, -STACKFRAME_SZ, %sp #define _RS restore #define FLUSH_ALL_KERNEL_WINDOWS \ _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ _RS; _RS; _RS; _RS; _RS; _RS; _RS; .text #ifdef CONFIG_KGDB .align 4 .globl arch_kgdb_breakpoint .type arch_kgdb_breakpoint,#function arch_kgdb_breakpoint: ta 0x7d retl nop .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint #endif #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) .align 4 .globl floppy_hardint floppy_hardint: /* * This code cannot touch registers %l0 %l1 and %l2 * because SAVE_ALL depends on their values. It depends * on %l3 also, but we regenerate it before a call. * Other registers are: * %l3 -- base address of fdc registers * %l4 -- pdma_vaddr * %l5 -- scratch for ld/st address * %l6 -- pdma_size * %l7 -- scratch [floppy byte, ld/st address, aux. data] */ /* Do we have work to do? */ sethi %hi(doing_pdma), %l7 ld [%l7 + %lo(doing_pdma)], %l7 cmp %l7, 0 be floppy_dosoftint nop /* Load fdc register base */ sethi %hi(fdc_status), %l3 ld [%l3 + %lo(fdc_status)], %l3 /* Setup register addresses */ sethi %hi(pdma_vaddr), %l5 ! transfer buffer ld [%l5 + %lo(pdma_vaddr)], %l4 sethi %hi(pdma_size), %l5 ! bytes to go ld [%l5 + %lo(pdma_size)], %l6 next_byte: ldub [%l3], %l7 andcc %l7, 0x80, %g0 ! Does fifo still have data bz floppy_fifo_emptied ! fifo has been emptied... andcc %l7, 0x20, %g0 ! in non-dma mode still? bz floppy_overrun ! nope, overrun andcc %l7, 0x40, %g0 ! 0=write 1=read bz floppy_write sub %l6, 0x1, %l6 /* Ok, actually read this byte */ ldub [%l3 + 1], %l7 orcc %g0, %l6, %g0 stb %l7, [%l4] bne next_byte add %l4, 0x1, %l4 b floppy_tdone nop floppy_write: /* Ok, actually write this byte */ ldub [%l4], %l7 orcc %g0, %l6, %g0 stb %l7, [%l3 + 1] bne next_byte add %l4, 0x1, %l4 /* fall through... */ floppy_tdone: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l5 st %l6, [%l5 + %lo(pdma_size)] /* Flip terminal count pin */ set auxio_register, %l7 ld [%l7], %l7 ldub [%l7], %l5 or %l5, 0xc2, %l5 stb %l5, [%l7] andn %l5, 0x02, %l5 2: /* Kill some time so the bits set */ WRITE_PAUSE WRITE_PAUSE stb %l5, [%l7] /* Prevent recursion */ sethi %hi(doing_pdma), %l7 b floppy_dosoftint st %g0, [%l7 + %lo(doing_pdma)] /* We emptied the FIFO, but we haven't read everything * as of yet. Store the current transfer address and * bytes left to read so we can continue when the next * fast IRQ comes in. */ floppy_fifo_emptied: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l7 st %l6, [%l7 + %lo(pdma_size)] /* Restore condition codes */ wr %l0, 0x0, %psr WRITE_PAUSE jmp %l1 rett %l2 floppy_overrun: sethi %hi(pdma_vaddr), %l5 st %l4, [%l5 + %lo(pdma_vaddr)] sethi %hi(pdma_size), %l5 st %l6, [%l5 + %lo(pdma_size)] /* Prevent recursion */ sethi %hi(doing_pdma), %l7 st %g0, [%l7 + %lo(doing_pdma)] /* fall through... */ floppy_dosoftint: rd %wim, %l3 SAVE_ALL /* Set all IRQs off. */ or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE mov 11, %o0 ! floppy irq level (unused anyway) mov %g0, %o1 ! devid is not used in fast interrupts call sparc_floppy_irq add %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs RESTORE_ALL #endif /* (CONFIG_BLK_DEV_FD) */ /* Bad trap handler */ .globl bad_trap_handler bad_trap_handler: SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 ! pt_regs call do_hw_interrupt mov %l7, %o1 ! trap number RESTORE_ALL /* For now all IRQ's not registered get sent here. handler_irq() will * see if a routine is registered to handle this interrupt and if not * it will say so on the console. */ .align 4 .globl real_irq_entry, patch_handler_irq real_irq_entry: SAVE_ALL #ifdef CONFIG_SMP .globl patchme_maybe_smp_msg cmp %l7, 11 patchme_maybe_smp_msg: bgu maybe_smp4m_msg nop #endif real_irq_continue: or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE mov %l7, %o0 ! irq level patch_handler_irq: call handler_irq add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq wr %g2, PSR_ET, %psr ! keep ET up WRITE_PAUSE RESTORE_ALL #ifdef CONFIG_SMP /* SMP per-cpu ticker interrupts are handled specially. */ smp4m_ticker: bne real_irq_continue+4 or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call smp4m_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL #define GET_PROCESSOR4M_ID(reg) \ rd %tbr, %reg; \ srl %reg, 12, %reg; \ and %reg, 3, %reg; /* Here is where we check for possible SMP IPI passed to us * on some level other than 15 which is the NMI and only used * for cross calls. That has a separate entry point below. * * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*. */ maybe_smp4m_msg: GET_PROCESSOR4M_ID(o3) sethi %hi(sun4m_irq_percpu), %l5 sll %o3, 2, %o3 or %l5, %lo(sun4m_irq_percpu), %o5 sethi %hi(0x70000000), %o2 ! Check all soft-IRQs ld [%o5 + %o3], %o1 ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be,a smp4m_ticker cmp %l7, 14 /* Soft-IRQ IPI */ st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000 WRITE_PAUSE ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE srl %o3, 28, %o2 ! shift for simpler checks below maybe_smp4m_msg_check_single: andcc %o2, 0x1, %g0 beq,a maybe_smp4m_msg_check_mask andcc %o2, 0x2, %g0 call smp_call_function_single_interrupt nop andcc %o2, 0x2, %g0 maybe_smp4m_msg_check_mask: beq,a maybe_smp4m_msg_check_resched andcc %o2, 0x4, %g0 call smp_call_function_interrupt nop andcc %o2, 0x4, %g0 maybe_smp4m_msg_check_resched: /* rescheduling is done in RESTORE_ALL regardless, but incr stats */ beq,a maybe_smp4m_msg_out nop call smp_resched_interrupt nop maybe_smp4m_msg_out: RESTORE_ALL .align 4 .globl linux_trap_ipi15_sun4m linux_trap_ipi15_sun4m: SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR4M_ID(o0) sethi %hi(sun4m_irq_percpu), %l5 or %l5, %lo(sun4m_irq_percpu), %o5 sll %o0, 2, %o0 ld [%o5 + %o0], %o5 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be sun4m_nmi_error ! Must be an NMI async memory error st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 WRITE_PAUSE ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call smp4m_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 .globl smp4d_ticker /* SMP per-cpu ticker interrupts are handled specially. */ smp4d_ticker: SAVE_ALL or %l0, PSR_PIL, %g2 sethi %hi(CC_ICLR), %o0 sethi %hi(1 << 14), %o1 or %o0, %lo(CC_ICLR), %o0 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */ wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call smp4d_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL .align 4 .globl linux_trap_ipi15_sun4d linux_trap_ipi15_sun4d: SAVE_ALL sethi %hi(CC_BASE), %o4 sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2 or %o4, (CC_EREG - CC_BASE), %o0 ldda [%o0] ASI_M_MXCC, %o0 andcc %o0, %o2, %g0 bne 1f sethi %hi(BB_STAT2), %o2 lduba [%o2] ASI_M_CTL, %o2 andcc %o2, BB_STAT2_MASK, %g0 bne 2f or %o4, (CC_ICLR - CC_BASE), %o0 sethi %hi(1 << 15), %o1 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */ or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call smp4d_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 1: /* MXCC error */ 2: /* BB error */ /* Disable PIL 15 */ set CC_IMSK, %l4 lduha [%l4] ASI_M_MXCC, %l5 sethi %hi(1 << 15), %l7 or %l5, %l7, %l5 stha %l5, [%l4] ASI_M_MXCC /* FIXME */ 1: b,a 1b .globl smpleon_ipi .extern leon_ipi_interrupt /* SMP per-cpu IPI interrupts are handled specially. */ smpleon_ipi: SAVE_ALL or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE call leonsmp_ipi_interrupt add %sp, STACKFRAME_SZ, %o1 ! pt_regs wr %l0, PSR_ET, %psr WRITE_PAUSE RESTORE_ALL .align 4 .globl linux_trap_ipi15_leon linux_trap_ipi15_leon: SAVE_ALL or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE call leon_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 #endif /* CONFIG_SMP */ /* This routine handles illegal instructions and privileged * instruction attempts from user code. */ .align 4 .globl bad_instruction bad_instruction: sethi %hi(0xc1f80000), %l4 ld [%l1], %l5 sethi %hi(0x81d80000), %l7 and %l5, %l4, %l5 cmp %l5, %l7 be 1f SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call do_illegal_instruction mov %l0, %o3 RESTORE_ALL 1: /* unimplemented flush - just skip */ jmpl %l2, %g0 rett %l2 + 4 .align 4 .globl priv_instruction priv_instruction: SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call do_priv_instruction mov %l0, %o3 RESTORE_ALL /* This routine handles unaligned data accesses. */ .align 4 .globl mna_handler mna_handler: andcc %l0, PSR_PS, %g0 be mna_fromuser nop SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE ld [%l1], %o1 call kernel_unaligned_trap add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL mna_fromuser: SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE ld [%l1], %o1