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

Next file: linux/arch/arm/kernel/head-armo.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.1.79/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
@@ -0,0 +1,283 @@
+/*
+ *=============================================================================
+ *		Low-level interface code
+ *-----------------------------------------------------------------------------
+ *		Trap initialisation
+ *-----------------------------------------------------------------------------
+ *
+ * Note - FIQ code has changed.  The default is a couple of words in 0x1c, 0x20
+ * that call _unexp_fiq.  Nowever, we now copy the FIQ routine to 0x1c (removes
+ * some excess cycles).
+ *
+ * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
+ * (the kernel).
+ * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
+ * the actuall address to jump to.
+ */
+/*
+ * these go into 0x00
+ */
+.Lbranches:	swi	SYS_ERROR0
+		ldr	pc, .Lbranches + 0xe4
+		ldr	pc, .Lbranches + 0xe8
+		ldr	pc, .Lbranches + 0xec
+		ldr	pc, .Lbranches + 0xf0
+		ldr	pc, .Lbranches + 0xf4
+		ldr	pc, .Lbranches + 0xf8
+		ldr	pc, .Lbranches + 0xfc
+/*
+ * this is put into 0xe4 and above
+ */
+.Ljump_addresses:
+		.word	vector_undefinstr	@ 0xe4
+		.word	vector_swi		@ 0xe8
+		.word	vector_prefetch		@ 0xec
+		.word	vector_data		@ 0xf0
+		.word	vector_addrexcptn	@ 0xf4
+		.word	vector_IRQ		@ 0xf8
+		.word	_unexp_fiq		@ 0xfc
+/*
+ * initialise the trap system
+ */
+ENTRY(trap_init)
+		stmfd	sp!, {r4 - r7, lr}
+		initialise_traps_extra
+		mov	r0, #0xe4
+		adr	r1, .Ljump_addresses
+		ldmia	r1, {r1 - r6}
+		stmia	r0, {r1 - r6}
+		mov	r0, #0
+		adr	r1, .Lbranches
+		ldmia	r1, {r1 - r7}
+		stmia	r0, {r1 - r7}
+		LOADREGS(fd, sp!, {r4 - r7, pc})
+
+/*=============================================================================
+ * SWI handler
+ *-----------------------------------------------------------------------------
+ *
+ * We now handle sys-call tracing, and the errno in the task structure.
+ * Still have a problem with >4 arguments for functions.  Theres only
+ * a couple of functions in the code that have 5 arguments, so Im not
+ * too worried.
+ */
+
+#include "calls.S"
+
+vector_swi:	save_user_regs
+		mov	fp, #0
+		mask_pc	lr, lr
+		ldr	r6, [lr, #-4]!		@ get SWI instruction
+		arm700_bug_check r6, r7
+		enable_irqs r7
+		
+		bic	r6, r6, #0xff000000	@ mask off SWI op-code
+		eor	r6, r6, #OS_NUMBER<<20	@ check OS number
+		cmp	r6, #NR_SYSCALLS	@ check upper syscall limit
+		bcs	2f
+
+		get_current_task r5
+		ldr	ip, [r5, #FLAGS]	@ check for syscall tracing
+		tst	ip, #PF_TRACESYS
+		bne	1f
+
+		adr	ip, SYMBOL_NAME(sys_call_table)
+		str	r4, [sp, #-4]!		@ new style: (r0 = arg1, r5 = arg5)
+		mov	lr, pc
+		ldr	pc, [ip, r6, lsl #2]	@ call sys routine
+		add	sp, sp, #4
+		str	r0, [sp, #S_R0]		@ returned r0
+		b	ret_from_sys_call
+
+1:		ldr	r7, [sp, #S_IP]		@ save old IP
+		mov	r0, #0
+		str	r7, [sp, #S_IP]		@ trace entry [IP = 0]
+		bl	SYMBOL_NAME(syscall_trace)
+		str	r7, [sp, #S_IP]
+		ldmia	sp, {r0 - r3}		@ have to reload r0 - r3
+		adr	ip, SYMBOL_NAME(sys_call_table)
+		str	r4, [sp, #-4]!		@ new style: (r0 = arg1, r5 = arg5)
+		mov	lr, pc
+		ldr	pc, [ip, r6, lsl #2]	@ call sys routine
+		add	sp, sp, #4
+		str	r0, [sp, #S_R0]		@ returned r0
+		mov	r0, #1
+		str	r0, [sp, #S_IP]		@ trace exit [IP = 1]
+		bl	SYMBOL_NAME(syscall_trace)
+		str	r7, [sp, #S_IP]
+		b	ret_from_sys_call
+
+2:		tst	r6, #0x00f00000		@ is it a Unix SWI?
+		bne	3f
+		cmp	r6, #(KSWI_SYS_BASE - KSWI_BASE)
+		bcc	4f			@ not private func
+		bic	r0, r6, #0x000f0000
+		mov	r1, sp
+		bl	SYMBOL_NAME(arm_syscall)
+		b	ret_from_sys_call
+
+3:		eor	r0, r6, #OS_NUMBER<<20	@ Put OS number back
+		mov	r1, sp
+		bl	SYMBOL_NAME(deferred)
+		ldmfd	sp, {r0 - r3}
+		b	ret_from_sys_call
+
+4:		bl	SYMBOL_NAME(sys_ni_syscall)
+		str	r0, [sp, #0]		@ returned r0
+		b	ret_from_sys_call
+
+@ r0 = syscall number
+@ r1 = syscall r0
+@ r5 = syscall r4
+@ ip = syscall table
+SYMBOL_NAME(sys_syscall):
+		mov	r6, r0
+		eor	r6, r6, #OS_NUMBER << 20
+		cmp	r6, #NR_SYSCALLS		@ check range
+		movgt	r0, #-ENOSYS
+		movgt	pc, lr
+		add	sp, sp, #4			@ take of the save of our r4
+		ldmib	sp, {r0 - r4}			@ get our args
+		str	r4, [sp, #-4]!			@ Put our arg on the stack
+		ldr	pc, [ip, r6, lsl #2]
+
+ENTRY(sys_call_table)
+#include "calls.S"
+
+/*============================================================================
+ * Special system call wrappers
+ */
+sys_fork_wrapper:
+		add	r0, sp, #4
+		b	SYMBOL_NAME(sys_fork)
+
+sys_execve_wrapper:
+		add	r3, sp, #4
+		b	SYMBOL_NAME(sys_execve)
+
+sys_mount_wrapper:
+		mov	r6, lr
+		add	r5, sp, #4
+		str	r5, [sp]
+		str	r4, [sp, #-4]!
+		bl	SYMBOL_NAME(sys_compat_mount)
+		add	sp, sp, #4
+		RETINSTR(mov,pc,r6)
+
+sys_clone_wapper:
+		add	r2, sp, #4
+		b	SYMBOL_NAME(sys_clone)
+
+sys_llseek_wrapper:
+		mov	r6, lr
+		add	r5, sp, #4
+		str	r5, [sp]
+		str	r4, [sp, #-4]!
+		bl	SYMBOL_NAME(sys_compat_llseek)
+		add	sp, sp, #4
+		RETINSTR(mov,pc,r6)
+
+sys_sigsuspend_wrapper:
+		add	r3, sp, #4
+		b	SYMBOL_NAME(sys_sigsuspend)
+
+sys_rt_sigsuspend_wrapper:
+		add	r2, sp, #4
+		b	SYMBOL_NAME(sys_rt_sigsuspend)
+
+sys_sigreturn_wrapper:
+		add	r0, sp, #4
+		b	SYMBOL_NAME(sys_sigreturn)
+
+sys_rt_sigreturn_wrapper:
+		add	r0, sp, #4
+		b	SYMBOL_NAME(sys_rt_sigreturn)
+
+/*============================================================================
+ * All exits to user mode from the kernel go through this code.
+ */
+
+		.globl	ret_from_sys_call
+
+		.globl	SYMBOL_NAME(fpreturn)
+SYMBOL_NAME(fpreturn):
+ret_from_exception:
+		adr	r0, 1f
+		ldmia	r0, {r0, r1}
+		ldr	r0, [r0]
+		ldr	r1, [r1]
+		tst	r0, r1
+		blne	SYMBOL_NAME(do_bottom_half)
+ret_from_intr:	ldr	r0, [sp, #S_PSR]
+		tst	r0, #3
+		beq	ret_with_reschedule
+		b	ret_from_all
+
+ret_signal:	mov	r1, sp
+		adrsvc	al, lr, ret_from_all
+		b	SYMBOL_NAME(do_signal)
+
+2:		bl	SYMBOL_NAME(schedule)
+
+ret_from_sys_call:
+		adr	r0, 1f
+		ldmia	r0, {r0, r1}
+		ldr	r0, [r0]
+		ldr	r1, [r1]
+		tst	r0, r1
+		adrsvc	ne, lr, ret_from_intr
+		bne	SYMBOL_NAME(do_bottom_half)
+
+ret_with_reschedule:
+		ldr	r0, 1f + 8
+		ldr	r0, [r0]
+		teq	r0, #0
+		bne	2b
+
+		get_current_task r1
+		ldr	r1, [r1, #SIGPENDING]
+		teq	r1, #0
+		bne	ret_signal
+
+ret_from_all:	restore_user_regs
+
+1:		.word	SYMBOL_NAME(bh_mask)
+		.word	SYMBOL_NAME(bh_active)
+		.word	SYMBOL_NAME(need_resched)
+
+/*============================================================================
+ * FP support
+ */
+
+1:		.word	SYMBOL_NAME(fp_save)
+		.word	SYMBOL_NAME(fp_restore)
+
+.Lfpnull:	mov	pc, lr
+
+
+/*
+ * Function to call when switching tasks to save FP state
+ */
+ENTRY(fpe_save)
+		ldr	r1, 1b
+		ldr	pc, [r1]
+
+/*
+ * Function to call when switching tasks to restore FP state
+ */
+ENTRY(fpe_restore)
+		ldr	r1, 1b + 4
+		ldr	pc, [r1]
+
+
+		.data
+
+ENTRY(fp_enter)
+		.word	SYMBOL_NAME(fpundefinstr)
+		.word	SYMBOL_NAME(fpundefinstrsvc)
+
+ENTRY(fp_save)
+		.word	.Lfpnull
+ENTRY(fp_restore)
+		.word	.Lfpnull
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov