patch-2.4.9 linux/arch/arm/kernel/entry-common.S

Next file: linux/arch/arm/kernel/entry-header.S
Previous file: linux/arch/arm/kernel/entry-armv.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
@@ -8,70 +8,85 @@
  * published by the Free Software Foundation.
  */
 #include <linux/config.h>
+#include "entry-header.S"
 
-#define PT_TRACESYS	0x00000002
-
-@ OS version number used in SWIs
-@  RISC OS is 0
-@  RISC iX is 8
-@
-#define OS_NUMBER	9
+/* 
+ * We rely on the fact that R0 is at the bottom of the stack (due to
+ * slow/fast restore user regs).
+ */
+#if S_R0 != 0
+#error "Please fix"
+#endif
 
-/*============================================================================
- * All exits to user mode from the kernel go through this code.
+/*
+ * Our do_softirq out of line code.  See include/asm-arm/softirq.h for
+ * the calling assembly.
  */
+	.section ".text.lock","ax"
+ENTRY(__do_softirq)
+	stmfd	sp!, {r0 - r3, ip, lr}
+	bl	do_softirq
+	ldmfd	sp!, {r0 - r3, ip, pc}
+	.previous
 
-#define S_OFF		8
+	.align	5
+/*
+ * This is the fast syscall return path.  We do as little as
+ * possible here, and this includes saving r0 back into the SVC
+ * stack.
+ */
+ret_fast_syscall:
+	ldr	r1, [tsk, #TSK_NEED_RESCHED]
+	ldr	r2, [tsk, #TSK_SIGPENDING]
+	teq	r1, #0				@ need_resched || sigpending
+	teqeq	r2, #0
+	bne	slow
+	fast_restore_user_regs
 
-		.macro	get_softirq, rd
-#ifdef CONFIG_SMP
-#error SMP not supported
-#else
-		ldr	\rd, __irq_stat
-#endif
-		.endm
+/*
+ * Ok, we need to do extra processing, enter the slow path.
+ */
+slow:	str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
+	b	1f
 
-		.globl	ret_from_sys_call
+/*
+ * "slow" syscall return path.  "why" tells us if this was a real syscall.
+ */
+reschedule:
+	bl	SYMBOL_NAME(schedule)
+ENTRY(ret_to_user)
+ret_slow_syscall:
+	ldr	r1, [tsk, #TSK_NEED_RESCHED]
+	ldr	r2, [tsk, #TSK_SIGPENDING]
+1:	teq	r1, #0				@ need_resched => schedule()
+	bne	reschedule
+	teq	r2, #0				@ sigpending => do_signal()
+	blne	__do_signal
+	restore_user_regs
+
+__do_signal:
+	mov	r0, #0				@ NULL 'oldset'
+	mov	r1, sp				@ 'regs'
+	mov	r2, why				@ 'syscall'
+	b	SYMBOL_NAME(do_signal)		@ note the bl above sets lr
 
-		.align	5
-fast_syscall_return:
-		str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
-ret_from_sys_call:				@ external entry
-		get_softirq r0
-		get_current_task r5
-		ldmia	r0, {r0, r1}		@ softirq_active, softirq_mask
-		mov	r4, #1			@ flag this as being syscall return
-		tst	r0, r1
-		blne	SYMBOL_NAME(do_softirq)
-ret_with_reschedule:				@ external entry (r5 must be set) (__irq_usr)
-		ldr	r0, [r5, #TSK_NEED_RESCHED]
-		ldr	r1, [r5, #TSK_SIGPENDING]
-		teq	r0, #0
-		bne	ret_reschedule
-		teq	r1, #0			@ check for signals
-		blne	ret_signal
-
-ret_from_all:	restore_user_regs		@ internal
-
-ret_signal:	mov	r1, sp			@ internal
-		mov	r2, r4
-		b	SYMBOL_NAME(do_signal)	@ note the bl above sets lr
-
-ret_reschedule:	adrsvc	al, lr, ret_with_reschedule	@ internal
-		b	SYMBOL_NAME(schedule)
-
-		.globl	ret_from_exception
-ret_from_exception:				@ external entry
-		get_softirq r0
-		get_current_task r5
-		ldmia	r0, {r0, r1}		@ softirq_active, softirq_mask
-		mov	r4, #0
-		tst	r0, r1
-		ldr	r6, [sp, #S_PSR]
-		blne	SYMBOL_NAME(do_softirq)
-		tst	r6, #3			@ returning to user mode?
-		beq	ret_with_reschedule
-		b	ret_from_all
+/*
+ * This is how we return from a fork.  __switch_to will be calling us
+ * with r0 pointing at the previous task that was running (ready for
+ * calling schedule_tail).
+ */
+ENTRY(ret_from_fork)
+	bl	SYMBOL_NAME(schedule_tail)
+	get_current_task tsk
+	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
+	mov	why, #1
+	tst	ip, #PT_TRACESYS		@ are we tracing syscalls?
+	beq	ret_slow_syscall
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	bl	SYMBOL_NAME(syscall_trace)
+	b	ret_slow_syscall
+	
 
 #include "calls.S"
 
@@ -80,78 +95,98 @@
  *-----------------------------------------------------------------------------
  */
 
-/*
- * Create some aliases for some registers.  These should allow
- * us to have in theory up to 7 arguments to a function.
- */
-scno		.req	r9			@ syscall number
-tbl		.req	r8			@ syscall table pointer
-tip		.req	r7			@ temporary IP
-
-		.align	5
-vector_swi:	save_user_regs
-		mask_pc	lr, lr
-		zero_fp
-		ldr	scno, [lr, #-4]		@ get SWI instruction
-		arm700_bug_check scno, ip
+	/* If we're optimising for StrongARM the resulting code won't 
+	   run on an ARM7 and we can save a couple of instructions.  
+								--pb */
+#ifdef CONFIG_CPU_ARM710
+	.macro	arm710_bug_check, instr, temp
+	and	\temp, \instr, #0x0f000000	@ check for SWI
+	teq	\temp, #0x0f000000
+	bne	.Larm700bug
+	.endm
+
+.Larm700bug:
+	ldr	r0, [sp, #S_PSR]		@ Get calling cpsr
+	sub	lr, lr, #4
+	str	lr, [r8]
+	msr	spsr, r0
+	ldmia	sp, {r0 - lr}^			@ Get calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	movs	pc, lr
+#else
+	.macro	arm710_bug_check, instr, temp
+	.endm
+#endif
+
+	.align	5
+ENTRY(vector_swi)
+	save_user_regs
+	mask_pc	lr, lr
+	zero_fp
+	ldr	scno, [lr, #-4]			@ get SWI instruction
+	arm710_bug_check scno, ip
+
 #ifdef CONFIG_ALIGNMENT_TRAP
-		ldr	ip, .LCswi
-		ldr	ip, [ip]
-		mcr	p15, 0, ip, c1, c0
+	ldr	ip, __cr_alignment
+	ldr	ip, [ip]
+	mcr	p15, 0, ip, c1, c0		@ update control register
 #endif
-		enable_irqs ip
+	enable_irqs ip
+
+	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
-		str	r4, [sp, #-S_OFF]!	@ push fifth arg
-		adrsvc	al, lr, fast_syscall_return
+	get_current_task tsk
+	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
+	bic	scno, scno, #0xff000000		@ mask off SWI op-code
+	eor	scno, scno, #OS_NUMBER << 20	@ check OS number
+	adr	tbl, sys_call_table		@ load syscall table pointer
+	tst	ip, #PT_TRACESYS		@ are we tracing syscalls?
+	bne	__sys_trace
+
+	adrsvc	al, lr, ret_fast_syscall	@ return address
+	cmp	scno, #NR_syscalls		@ check upper syscall limit
+	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
+
+	add	r1, sp, #S_OFF
+2:	mov	why, #0				@ no longer a real syscall
+	cmp	scno, #ARMSWI_OFFSET
+	eor	r0, scno, #OS_NUMBER << 20	@ put OS number back
+	bcs	SYMBOL_NAME(arm_syscall)	
+	b	SYMBOL_NAME(sys_ni_syscall)	@ not private func
+
+	/*
+	 * This is the really slow path.  We're going to be doing
+	 * context switches, and waiting for our parent to respond.
+	 */
+__sys_trace:
+	add	r1, sp, #S_OFF
+	mov	r0, #0				@ trace entry [IP = 0]
+	bl	SYMBOL_NAME(syscall_trace)
+
+	adrsvc	al, lr, __sys_trace_return	@ return address
+	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	cmp	scno, #NR_syscalls		@ check upper syscall limit
+	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
+	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
+	b	2b
+
+__sys_trace_return:
+	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	bl	SYMBOL_NAME(syscall_trace)
+	b	ret_slow_syscall
 
-		bic	scno, scno, #0xff000000	@ mask off SWI op-code
-		eor	scno, scno, #OS_NUMBER<<20	@ check OS number
-		cmp	scno, #NR_syscalls	@ check upper syscall limit
-		bcs	2f
-
-		get_current_task ip
-		ldr	ip, [ip, #TSK_PTRACE]	@ check for syscall tracing
-		adr	tbl, SYMBOL_NAME(sys_call_table)
-		tst	ip, #PT_TRACESYS
-		ldreq	pc, [tbl, scno, lsl #2]	@ call sys routine
-
-		ldr	tip, [sp, #S_IP + S_OFF]	@ save old IP
-		mov	ip, #0
-		str	ip, [sp, #S_IP + S_OFF]	@ trace entry [IP = 0]
-		bl	SYMBOL_NAME(syscall_trace)
-		str	tip, [sp, #S_IP + S_OFF]
-
-		add	ip, sp, #S_OFF
-		ldmia	ip, {r0 - r3}		@ have to reload r0 - r3
-		mov	lr, pc
-		ldr	pc, [tbl, scno, lsl #2]	@ call sys routine
-		str	r0, [sp, #S_R0 + S_OFF]	@ returned r0
-
-		mov	ip, #1
-		str	ip, [sp, #S_IP + S_OFF]	@ trace exit [IP = 1]
-		bl	SYMBOL_NAME(syscall_trace)
-		str	tip, [sp, #S_IP + S_OFF]
-		add	sp, sp, #S_OFF
-		b	ret_from_sys_call
-
-2:		add	r1, sp, #S_OFF
-		tst	scno, #0x00f00000	@ is it a Unix SWI?
-		bne	3f
-		subs	r0, scno, #(KSWI_SYS_BASE - KSWI_BASE)
-		bcs	SYMBOL_NAME(arm_syscall)
-		b	SYMBOL_NAME(sys_ni_syscall) @ not private func
-
-3:		eor	r0, scno, #OS_NUMBER <<20	@ Put OS number back
-		bl	SYMBOL_NAME(deferred)
-		add	sp, sp, #S_OFF
-		b	ret_from_sys_call
-
-		.align	5
-		.type	__irq_stat, #object
-__irq_stat:
-		.word	SYMBOL_NAME(irq_stat)
+	.align	5
+#ifdef CONFIG_ALIGNMENT_TRAP
+	.type	__cr_alignment, #object
+__cr_alignment:
+	.word	SYMBOL_NAME(cr_alignment)
+#endif
 
-		.type	sys_call_table, #object
+	.type	sys_call_table, #object
 ENTRY(sys_call_table)
 #include "calls.S"
 
@@ -164,7 +199,6 @@
 SYMBOL_NAME(sys_syscall):
 		eor	scno, r0, #OS_NUMBER << 20
 		cmp	scno, #NR_syscalls	@ check range
-		add	ip, sp, #S_OFF
 		stmleia	sp, {r5, r6}		@ shuffle args
 		movle	r0, r1
 		movle	r1, r2
@@ -225,8 +259,3 @@
 		str	r5, [sp, #4]
 		b	do_mmap2
 #endif
-
-		.data
-
-ENTRY(fp_enter)
-		.word	fpe_not_present

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)