1370 lines · 28.3 KB · Assembly
RawDownload
/* 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], %o1

Lines 1–500 of 1370.