patch-1.3.93 linux/arch/sparc/kernel/entry.S

Next file: linux/arch/sparc/kernel/etrap.S
Previous file: linux/arch/sparc/kernel/devices.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.92/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.79 1996/03/01 07:15:54 davem Exp $
+/* $Id: entry.S,v 1.90 1996/04/18 01:00:37 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -9,6 +9,7 @@
 
 #include <asm/head.h>
 #include <asm/asi.h>
+#include <asm/smp.h>
 #include <asm/kgdb.h>
 #include <asm/contregs.h>
 #include <asm/ptrace.h>
@@ -20,25 +21,9 @@
 #include <asm/winmacro.h>
 #include <asm/signal.h>
 
-#define NR_SYSCALLS 255      /* Each OS is different... */
+#include <asm/asmmacro.h>
 
-/* All trap entry points _must_ begin with this macro or else you
- * lose.  It makes sure the kernel has a proper window so that
- * c-code can be called.  Some day for SMP we'll grab klock here.
- */
-#define SAVE_ALL \
-	sethi	%hi(trap_setup), %l4; \
-	jmpl	%l4 + %lo(trap_setup), %l6; \
-	 nop;
-
-/* All traps low-level code here must end with this macro.
- * For SMP configurations the ret_trap_entry routine will
- * have to appropriate code to actually release the kernel
- * entry lock.
- */
-#define RESTORE_ALL \
-	b	ret_trap_entry; \
-	 nop;
+#define NR_SYSCALLS 255      /* Each OS is different... */
 
 /* First, KGDB low level things.  This is a rewrite
  * of the routines found in the sparc-stub.c asm() statement
@@ -63,6 +48,7 @@
 C_LABEL(trap_low):
 	rd	%wim, %l3
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	sethi	%hi(in_trap_handler), %l4
 	ld	[%lo(in_trap_handler) + %l4], %l5
@@ -228,18 +214,30 @@
 	/* Flip terminal count pin */
 	set	C_LABEL(auxio_register), %l4
 	ld	[%l4], %l4
-	ldub	[%l4], %l5
-	or	%l5, 0xf4, %l5
+
+	set	C_LABEL(sparc_cpu_model), %l5
+	ld	[%l5], %l5
+	subcc   %l5, 1, %g0		/* enum { sun4c = 1 }; */
+	be	1f
+	 ldub	[%l4], %l5
+
+	or	%l5, 0xc2, %l5
 	stb	%l5, [%l4]
+	andn    %l5, 0x02, %l5
+	b	2f
+	 nop
+
+1:
+	or      %l5, 0xf4, %l5
+	stb     %l5, [%l4]
+	andn    %l5, 0x04, %l5
 
+2:
 	/* Kill some time so the bits set */
 	WRITE_PAUSE
 	WRITE_PAUSE
 
-	ldub	[%l4], %l5
-	andn	%l5, 0x04, %l5
-	or	%l5, 0xf0, %l5
-	stb	%l5, [%l4]
+	stb     %l5, [%l4]
 
 	/* Prevent recursion */
 	sethi	%hi(C_LABEL(doing_pdma)), %l4
@@ -277,6 +275,7 @@
 floppy_dosoftint:
 	rd	%wim, %l3
 	SAVE_ALL
+	ENTER_IRQ
 
 	/* Set all IRQs off. */
 	or	%l0, PSR_PIL, %l4
@@ -288,6 +287,7 @@
 	call	C_LABEL(floppy_interrupt)
 	 add	%sp, REGWIN_SZ, %o1	! struct pt_regs *regs
 
+	LEAVE_IRQ
 	RESTORE_ALL
 	
 #endif /* (CONFIG_BLK_DEV_FD) */
@@ -296,6 +296,7 @@
 	.globl	bad_trap_handler
 bad_trap_handler:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -316,6 +317,52 @@
 	.globl	real_irq_entry
 real_irq_entry:
 	SAVE_ALL
+#ifdef __SMP__
+	cmp	%l7, 9
+	bne	1f
+	 nop
+
+	GET_PROCESSOR_MID(l4, l5)
+	set	C_LABEL(sun4m_interrupts), %l5
+	ld	[%l5], %l5
+	sethi	%hi(0x02000000), %l6
+	sll	%l4, 12, %l4
+	add	%l5, %l4, %l5
+	ld	[%l5], %l4
+	andcc	%l4, %l6, %g0
+	be	1f
+	 nop
+
+	b	linux_trap_ipi9_sun4m
+	 nop
+
+1:
+#endif
+	ENTER_IRQ
+
+#ifdef __SMP__
+	cmp	%l7, 13
+	bne	1f
+	 nop
+
+	/* This is where we catch the level 13 reschedule soft-IRQ. */
+	GET_PROCESSOR_MID(o3, o2)
+	set	C_LABEL(sun4m_interrupts), %l5
+	ld	[%l5], %o5
+	sethi	%hi(0x20000000), %o4
+	sll	%o3, 12, %o3
+	add	%o5, %o3, %o5
+	ld	[%o5], %o1		! read processor irq pending reg
+	andcc	%o1, %o4, %g0
+	be	1f
+	 nop
+
+	b	linux_trap_ipi13_sun4m
+	 nop
+
+1:	
+
+#endif
 
 	/* start atomic operation with respect to software interrupts */
 	sethi	%hi(C_LABEL(intr_count)), %l4
@@ -328,7 +375,9 @@
 	 * to work around a MicroSPARC bug of sorts.
 	 */
 	or	%l0, PSR_PIL, %l4
+
 	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
 	wr	%l4, PSR_ET, %psr
 	WRITE_PAUSE
 
@@ -351,13 +400,6 @@
 	be	2f
 	 nop
 
-	/* do_bottom_half must run at normal kernel priority, ie. all
-	 * IRQ's on.
-	 */
-	rd	%psr, %g4
-	andn	%g4, PSR_PIL, %g4
-	wr	%g4, 0x0, %psr
-	WRITE_PAUSE
 	call	C_LABEL(do_bottom_half)	
 	 nop
 
@@ -368,15 +410,17 @@
 2:
 	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
 
+	LEAVE_IRQ
 	RESTORE_ALL
 
-	/* This routine handles illegal instructions and privileged
+	/* This routine handles illegal isntructions and privileged
 	 * instruction attempts from user code.
 	 */
 	.align	4
 	.globl	bad_instruction
 bad_instruction:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -386,12 +430,14 @@
 	mov	%l2, %o2
 	call	C_LABEL(do_illegal_instruction)
 	 mov	%l0, %o3
+
 	RESTORE_ALL
 
 	.align	4
 	.globl	priv_instruction
 priv_instruction:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -410,6 +456,7 @@
 	.globl	mna_handler
 mna_handler:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -427,6 +474,7 @@
 	.globl	fpd_trap_handler
 fpd_trap_handler:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -445,16 +493,28 @@
 fpe_trap_handler:
 	set	fpsave_magic, %l5
 	cmp	%l1, %l5
-	bne	1f
-	 sethi	%hi(fpsave_catch), %l5
+	be	1f
+	 sethi	%hi(C_LABEL(fpsave)), %l5
+	or	%l5, %lo(C_LABEL(fpsave)), %l5
+	cmp	%l1, %l5
+	bne	2f
+	 sethi	%hi(fpsave_catch2), %l5
+	or	%l5, %lo(fpsave_catch2), %l5
+	wr	%l0, 0x0, %psr
+	WRITE_PAUSE
+	jmp	%l5
+	 rett	%l5 + 4
+1:	
+	sethi	%hi(fpsave_catch), %l5
 	or	%l5, %lo(fpsave_catch), %l5
 	wr	%l0, 0x0, %psr
 	WRITE_PAUSE
 	jmp	%l5
 	 rett	%l5 + 4
 
-1:
+2:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -472,6 +532,7 @@
 	.globl	do_tag_overflow
 do_tag_overflow:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -489,6 +550,7 @@
 	.globl	do_watchpoint
 do_watchpoint:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -506,6 +568,7 @@
 	.globl	do_reg_access
 do_reg_access:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -523,6 +586,7 @@
 	.globl	do_cp_disabled
 do_cp_disabled:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -540,6 +604,7 @@
 	.globl	do_bad_flush
 do_bad_flush:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -557,6 +622,7 @@
 	.globl	do_cp_exception
 do_cp_exception:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -574,6 +640,7 @@
 	.globl	do_hw_divzero
 do_hw_divzero:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
@@ -590,6 +657,7 @@
 	.globl	do_flush_windows
 do_flush_windows:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -612,6 +680,13 @@
 	/* We get these for debugging routines using __builtin_return_address() */
 dfw_kernel:
 	FLUSH_ALL_KERNEL_WINDOWS
+
+	/* Advance over the trap instruction. */
+	ld	[%sp + REGWIN_SZ + PT_NPC], %l1
+	add	%l1, 0x4, %l2
+	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+
 	RESTORE_ALL
 
 	/* The getcc software trap.  The user wants the condition codes from
@@ -650,9 +725,10 @@
 	.globl	linux_trap_nmi_sun4c
 linux_trap_nmi_sun4c:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	/* Ugh, we need to clear the IRQ line.  This is now
-	 * a very sun4c specific trap handler...
+	 * a very sun4c specific trap hanler...
 	 */
 	sethi	%hi(C_LABEL(interrupt_enable)), %l5
 	ld	[%l5 + %lo(C_LABEL(interrupt_enable))], %l5
@@ -683,57 +759,153 @@
 
 	RESTORE_ALL
 
-#if 0 /* WIP */
-	/* Inter-Processor Interrupts on the Sun4m. */
+#ifdef __SMP__
+
 	.align	4
-	.globl	sun4m_ipi
-sun4m_ipi:
-	SAVE_ALL_IPI4M
-
-	set	MAILBOX_ADDRESS, %l4
-	ldub	[%l4], %l5
-	subcc	%l5, MBOX_STOPCPU, %g0
-	bne,a	1f
-	 subcc	%l5, MBOX_STOPCPU2, %g0
-
-	call	C_LABEL(prom_stopcpu)
-	 mov	0, %o0
-	ba,a	2f	
+	.globl	linux_trap_ipi9_sun4m
+linux_trap_ipi9_sun4m:
+	sethi	%hi(0x02000000), %o2
+	GET_PROCESSOR_MID(o0, o1)
+	set	C_LABEL(sun4m_interrupts), %l5
+	ld	[%l5], %o5
+	sll	%o0, 12, %o0
+	add	%o5, %o0, %o5
+	st	%o2, [%o5 + 4]
+	WRITE_PAUSE
 
-1:
-	bne,a	1f
-	 subcc	%l5, MBOX_IDLECPU, %g0
+	ld	[%o5], %g0
+	WRITE_PAUSE
 
-	call	C_LABEL(prom_stopcpu)
-	 mov	0, %o0
-	ba,a	2f	
+	/* IRQ's off else we deadlock. */
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
 
-1:
-	bne,a	1f
-	 subcc	%l5, MBOX_IDLECPU2, %g0
+	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
+
+	call	C_LABEL(smp_message_irq)
+	 nop
 
-	call	C_LABEL(prom_idlecpu)
-	 mov	0, %o0
-	ba,a	2f	
+	RESTORE_ALL_FASTIRQ
 
-1:
-	bne,a	2f
+	.align	4
+	.globl	linux_trap_ipi13_sun4m
+linux_trap_ipi13_sun4m:
+	/* NOTE: real_irq_entry saved state and grabbed klock already. */
+
+	/* start atomic operation with respect to software interrupts */
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	add	%l5, 0x1, %l5
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
+
+	sethi	%hi(0x20000000), %o2
+	GET_PROCESSOR_MID(o0, o1)
+	set	C_LABEL(sun4m_interrupts), %l5
+	ld	[%l5], %o5
+	sll	%o0, 12, %o0
+	add	%o5, %o0, %o5
+	st	%o2, [%o5 + 4]
+	WRITE_PAUSE
+
+	ld	[%o5], %g0
+	WRITE_PAUSE
+
+	/* IRQ's off else we deadlock. */
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
+
+	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
+
+	call	C_LABEL(smp_reschedule_irq)
 	 nop
 
-	call	C_LABEL(prom_idlecpu)
-	 mov	0, %o0
-	ba,a	2f	
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	sub	%l5, 0x1, %l5
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
 
-2:
-	call	C_LABEL(smp_callin)
+	LEAVE_IRQ
+	RESTORE_ALL
+
+	.align	4
+	.globl	linux_trap_ipi15_sun4m
+linux_trap_ipi15_sun4m:
+	SAVE_ALL
+
+	/* First check for hard NMI memory error. */
+	sethi	%hi(0xf0000000), %o2
+	set	C_LABEL(sun4m_interrupts), %l5
+	set	0x4000, %o3
+	ld	[%l5], %l5
+	add	%l5, %o3, %l5
+	ld	[%l5], %l6
+	andcc	%o2, %l6, %o2
+	be	1f
+	 nop
+
+	/* Asyncronous fault, why you little ?!#&%@... */
+	sethi	%hi(0x80000000), %o2
+	st	%o2, [%l5 + 0xc]
+	WRITE_PAUSE
+	ld	[%l5], %g0
+	WRITE_PAUSE
+
+	/* All interrupts are off... now safe to enable traps
+	 * and call C-code.
+	 */	
+	or	%l0, PSR_PIL, %l4	! I am very paranoid...
+	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
+	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
+	call	C_LABEL(sun4m_nmi)
+	 nop
+
+	sethi	%hi(0x80000000), %o2
+	st	%o2, [%l5 + 0x8]
+	WRITE_PAUSE
+	ld	[%l5], %g0
+	WRITE_PAUSE
+
+	RESTORE_ALL_FASTIRQ
+
+1:
+	sethi	%hi(0x80000000), %o2
+	GET_PROCESSOR_MID(o0, o1)
+	set	C_LABEL(sun4m_interrupts), %l5
+	ld	[%l5], %o5
+	sll	%o0, 12, %o0
+	add	%o5, %o0, %o5
+	st	%o2, [%o5 + 4]
+	WRITE_PAUSE
+
+	ld	[%o5], %g0
+	WRITE_PAUSE
+
+	/* IRQ's off else we deadlock. */
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr
+	WRITE_PAUSE
+
+	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
+
+	call	C_LABEL(smp_message_irq)
+	 nop
+
+	RESTORE_ALL_FASTIRQ
 
-	RESTORE_ALL_IPI4M
 #endif
 
 	.align	4
 	.globl	sun4c_fault
 sun4c_fault:
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	/* XXX This needs to be scheduled better */
 	sethi	%hi(AC_SYNC_ERR), %l4
@@ -755,26 +927,22 @@
 	.align	4
 	.globl	C_LABEL(srmmu_fault)
 C_LABEL(srmmu_fault):
-	/* Slot 1 */
 	mov	0x400, %l5
 	mov	0x300, %l4
 
-	/* Slot 2 */
 	lda	[%l5] ASI_M_MMUREGS, %l6	! read sfar first
 	lda	[%l4] ASI_M_MMUREGS, %l5	! read sfsr last
 
-	/* Slot 3 */
 	andn	%l6, 0xfff, %l6
 	srl	%l5, 6, %l5			! and encode all info into l7
 
-	/* Slot 4 */
 	and	%l5, 2, %l5
 	or	%l5, %l6, %l6
 
-	/* Slot 5 */
 	or	%l6, %l7, %l7			! l7 = [addr,write,txtfault]
 
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	mov	%l7, %o1
 	mov	%l7, %o2
@@ -814,11 +982,12 @@
 	ld	[%sp + REGWIN_SZ + PT_I1], %o0
 	ld	[%sp + REGWIN_SZ + PT_I2], %o1
 	ld	[%sp + REGWIN_SZ + PT_I3], %o2
+	mov	%o7, %l5
 	ld	[%sp + REGWIN_SZ + PT_I4], %o3
 	call	%l6
 	 ld	[%sp + REGWIN_SZ + PT_I5], %o4
 
-	b	scall_store_args		/* so stupid... */
+	jmp	%l5 + 0x8		/* so stupid... */
 	 nop
 
 #if 0 /* work in progress */
@@ -834,19 +1003,22 @@
 	.align	4
 	.globl	C_LABEL(sys_execve)
 C_LABEL(sys_execve):
+	mov	%o7, %l5
 	call	C_LABEL(sparc_execve)
 	 add	%sp, REGWIN_SZ, %o0		! pt_regs *regs arg
 
-	b	scall_store_args
+	jmp	%l5 + 0x8
 	 nop
 
 	.align	4
 	.globl	C_LABEL(sys_pipe)
 C_LABEL(sys_pipe):
+	mov	%o7, %l5
+
 	call	C_LABEL(sparc_pipe)
 	 add	%sp, REGWIN_SZ, %o0		! pt_regs *regs arg
 
-	b	C_LABEL(ret_sys_call)
+	jmp	%l5 + 0x8
 	 nop
 
 	.align	4
@@ -857,18 +1029,15 @@
 	 add	%sp, REGWIN_SZ, %o1
 
 	/* We are returning to a signal handler. */
-
 	RESTORE_ALL
 
 	.align	4
 	.globl	C_LABEL(sys_sigsuspend)
 C_LABEL(sys_sigsuspend):
-	ld	[%sp + REGWIN_SZ + PT_I0], %o0
 	call	C_LABEL(do_sigsuspend)
-	 add	%sp, REGWIN_SZ, %o1
+	 add	%sp, REGWIN_SZ, %o0
 
 	/* We are returning to a signal handler. */
-
 	RESTORE_ALL
 
 	.align	4
@@ -890,6 +1059,8 @@
 	.globl	C_LABEL(sys_fork), C_LABEL(sys_vfork)
 C_LABEL(sys_vfork):
 C_LABEL(sys_fork):
+	mov	%o7, %l5
+
 	/* Save the kernel state as of now. */
 	FLUSH_ALL_KERNEL_WINDOWS;
 	STORE_WINDOW(sp)
@@ -903,12 +1074,14 @@
 	call	C_LABEL(do_fork)
 	 add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
 
-	b	scall_store_args
+	jmp	%l5 + 0x8
 	 nop
 	
 	/* Whee, kernel threads! */
 	.globl	C_LABEL(sys_clone)
 C_LABEL(sys_clone):
+	mov	%o7, %l5
+
 	/* Save the kernel state as of now. */
 	FLUSH_ALL_KERNEL_WINDOWS;
 	STORE_WINDOW(sp)
@@ -925,10 +1098,10 @@
 	call	C_LABEL(do_fork)
 	 add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
 
-	b	scall_store_args
+	jmp	%l5 + 0x8
 	 nop
 
-	/* All system calls enter here... */
+	/* Linux native and SunOS system calls enter here... */
 	.align	4
 	.globl	linux_sparc_syscall
 linux_sparc_syscall:
@@ -953,8 +1126,9 @@
 	blu,a	1f
 	 sll	%g1, 2, %l4
 
+	set	C_LABEL(sys_ni_syscall), %l7
 	b	syscall_is_too_hard
-	 set	C_LABEL(sys_ni_syscall), %l7
+	 nop
 
 1:
 	ld	[%l7 + %l4], %l7
@@ -974,6 +1148,7 @@
 syscall_is_too_hard:
 	rd	%wim, %l3
 	SAVE_ALL
+	ENTER_SYSCALL
 
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -985,7 +1160,6 @@
 	call	%l7
 	 ldd	[%sp + REGWIN_SZ + PT_I4], %o4
 
-scall_store_args:
 	st	%o0, [%sp + REGWIN_SZ + PT_I0]
 
 	.globl	C_LABEL(ret_sys_call)
@@ -1019,6 +1193,192 @@
 
 	RESTORE_ALL
 
+	/* Solaris system calls enter here... */
+	.align	4
+	.globl	solaris_syscall
+solaris_syscall:
+	/* While we are here trying to optimize our lives
+	 * away, handle the easy bogus cases like a
+	 * ni_syscall or sysnum > NR_SYSCALLS etc.
+	 * In the cases where we cannot optimize the
+	 * call inline we don't really lose anything
+	 * performance wise because we are doing here
+	 * things which we did anyway in the original
+	 * routine.  The only added complexity is a
+	 * bit test, compare, and branch to decide
+	 * if we need to save process state or not.
+	 */
+
+	/* XXX TODO: When we have ptrace working test
+	 * XXX       test for PF_TRACESYS in task flags.
+	 */
+
+	/* Direct access to user regs, must faster. */
+	cmp	%g1, NR_SYSCALLS
+	blu,a	1f
+	 sll	%g1, 2, %l4
+
+	set	C_LABEL(sys_ni_syscall), %l7
+	b	solaris_is_too_hard
+	 nop
+
+1:
+	ld	[%l7 + %l4], %l7
+
+	/* If bit-1 is set, this is a "fast" syscall.
+	 * This is the _complete_ overhead of this optimization,
+	 * and we save ourselves a load, so it evens out to nothing.
+	 */
+	andcc	%l7, 0x1, %g0
+	be	solaris_is_too_hard
+	 andn	%l7, 0x1, %l7
+
+	jmpl	%l7, %g0
+	 nop
+
+	.globl	solaris_is_too_hard
+solaris_is_too_hard:
+	rd	%wim, %l3
+	SAVE_ALL
+	ENTER_SYSCALL
+
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
+
+2:
+	ldd	[%sp + REGWIN_SZ + PT_I0], %o0
+	st	%o0, [%sp + REGWIN_SZ + PT_G0]	! for restarting syscalls
+	ldd	[%sp + REGWIN_SZ + PT_I2], %o2
+	call	%l7
+	 ldd	[%sp + REGWIN_SZ + PT_I4], %o4
+
+	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	set	PSR_C, %l6
+	cmp	%o0, -ENOIOCTLCMD
+	bgeu	1f
+	 ld	[%sp + REGWIN_SZ + PT_PSR], %l5
+
+	/* System call success, clear Carry condition code. */		
+	andn	%l5, %l6, %l5
+	b	2f
+	 st	%l5, [%sp + REGWIN_SZ + PT_PSR]	
+
+1:
+	/* System call failure, set Carry condition code.
+	 * Also, get abs(errno) to return to the process.
+	 */
+	sub	%g0, %o0, %o0
+	sethi	%hi(C_LABEL(solaris_xlatb_rorl)), %o3
+	or	%o3, %lo(C_LABEL(solaris_xlatb_rorl)), %o3
+	sll	%o0, 2, %o0
+	ld	[%o3 + %o0], %o0
+	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	or	%l5, %l6, %l5
+	st	%l5, [%sp + REGWIN_SZ + PT_PSR]
+
+	/* Advance the pc and npc over the trap instruction. */
+2:
+	ld	[%sp + REGWIN_SZ + PT_NPC], %l1	/* pc  = npc   */
+	add	%l1, 0x4, %l2			/* npc = npc+4 */
+	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+
+	RESTORE_ALL
+
+	/* {net, open}bsd system calls enter here... */
+	.align	4
+	.globl	bsd_syscall
+bsd_syscall:
+	/* While we are here trying to optimize our lives
+	 * away, handle the easy bogus cases like a
+	 * ni_syscall or sysnum > NR_SYSCALLS etc.
+	 * In the cases where we cannot optimize the
+	 * call inline we don't really lose anything
+	 * performance wise because we are doing here
+	 * things which we did anyway in the original
+	 * routine.  The only added complexity is a
+	 * bit test, compare, and branch to decide
+	 * if we need to save process state or not.
+	 */
+
+	/* XXX TODO: When we have ptrace working test
+	 * XXX       test for PF_TRACESYS in task flags.
+	 */
+
+	/* Direct access to user regs, must faster. */
+	cmp	%g1, NR_SYSCALLS
+	blu,a	1f
+	 sll	%g1, 2, %l4
+
+	set	C_LABEL(sys_ni_syscall), %l7
+	b	bsd_is_too_hard
+	 nop
+
+1:
+	ld	[%l7 + %l4], %l7
+
+	/* If bit-1 is set, this is a "fast" syscall.
+	 * This is the _complete_ overhead of this optimization,
+	 * and we save ourselves a load, so it evens out to nothing.
+	 */
+	andcc	%l7, 0x1, %g0
+	be	bsd_is_too_hard
+	 andn	%l7, 0x1, %l7
+
+	jmpl	%l7, %g0
+	 nop
+
+	.globl	bsd_is_too_hard
+bsd_is_too_hard:
+	rd	%wim, %l3
+	SAVE_ALL
+	ENTER_SYSCALL
+
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
+
+2:
+	ldd	[%sp + REGWIN_SZ + PT_I0], %o0
+	st	%o0, [%sp + REGWIN_SZ + PT_G0]	! for restarting syscalls
+	ldd	[%sp + REGWIN_SZ + PT_I2], %o2
+	call	%l7
+	 ldd	[%sp + REGWIN_SZ + PT_I4], %o4
+
+	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	set	PSR_C, %l6
+	cmp	%o0, -ENOIOCTLCMD
+	bgeu	1f
+	 ld	[%sp + REGWIN_SZ + PT_PSR], %l5
+
+	/* System call success, clear Carry condition code. */		
+	andn	%l5, %l6, %l5
+	b	2f
+	 st	%l5, [%sp + REGWIN_SZ + PT_PSR]	
+
+1:
+	/* System call failure, set Carry condition code.
+	 * Also, get abs(errno) to return to the process.
+	 */
+	sub	%g0, %o0, %o0
+#if 0 /* XXX todo XXX */
+	sethi	%hi(C_LABEL(bsd_xlatb_rorl), %o3
+	or	%o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3
+	sll	%o0, 2, %o0
+	ld	[%o3 + %o0], %o0
+#endif
+	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	or	%l5, %l6, %l5
+	st	%l5, [%sp + REGWIN_SZ + PT_PSR]
+
+	/* Advance the pc and npc over the trap instruction. */
+2:
+	ld	[%sp + REGWIN_SZ + PT_NPC], %l1	/* pc  = npc   */
+	add	%l1, 0x4, %l2			/* npc = npc+4 */
+	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+
+	RESTORE_ALL
+
 /* Saving and restoring the FPU state is best done from lowlevel code.
  *
  * void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -1027,7 +1387,7 @@
 
 	.globl	C_LABEL(fpsave)
 C_LABEL(fpsave):
-	st	%fsr, [%o1]
+	st	%fsr, [%o1]	! this can trap on us if fpu is in bogon state
 	ld	[%o1], %g1
 	set	0x2000, %g4
 	andcc	%g1, %g4, %g0
@@ -1075,6 +1435,10 @@
 	b	fpsave_magic + 4
 	 st	%fsr, [%o1]
 
+fpsave_catch2:
+	b	C_LABEL(fpsave) + 4
+	 st	%fsr, [%o1]
+
 	/* void fpload(unsigned long *fpregs, unsigned long *fsr); */
 
 	.globl	C_LABEL(fpload)
@@ -1106,9 +1470,16 @@
 	sethi	%hi(0x10c6), %o1
 	call	.umul
 	 or	%o1, %lo(0x10c6), %o1
+#ifndef __SMP__
 	sethi	%hi(C_LABEL(loops_per_sec)), %o3
 	call	.umul
 	 ld	[%o3 + %lo(C_LABEL(loops_per_sec))], %o1
+#else
+	GET_PROCESSOR_OFFSET(o4)
+	set	C_LABEL(cpu_data), %o3
+	call	.umul
+	 ld	[%o3 + %o4], %o1
+#endif
 
 	cmp	%o1, 0x0
 1:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this