entry.s

来自「Linux Kernel 2.6.9 for OMAP1710」· S 代码 · 共 990 行 · 第 1/2 页

S
990
字号
/* arch/arm26/kernel/entry.S *  * Assembled from chunks of code in arch/arm * * Copyright (C) 2003 Ian Molton * */#include <linux/config.h> /* for CONFIG_ARCH_xxxx */#include <linux/linkage.h>#include <asm/assembler.h>#include <asm/asm_offsets.h>#include <asm/errno.h>#include <asm/hardware.h>#include <asm/sysirq.h>#include <asm/thread_info.h>#include <asm/page.h>#include <asm/ptrace.h>	.macro	zero_fp#ifndef CONFIG_NO_FRAME_POINTER	mov	fp, #0#endif	.endm	.text@ Bad Abort numbers@ -----------------@#define BAD_PREFETCH	0#define BAD_DATA	1#define BAD_ADDREXCPTN	2#define BAD_IRQ		3#define BAD_UNDEFINSTR	4#define PT_TRACESYS	0x00000002@ OS version number used in SWIs@  RISC OS is 0@  RISC iX is 8@#define OS_NUMBER	9#define ARMSWI_OFFSET	0x000f0000@@ Stack format (ensured by USER_* and SVC_*)@#define S_FRAME_SIZE	72   @ FIXME: Really?#define S_OLD_R0	64#define S_PSR		60#define S_PC		60#define S_LR		56#define S_SP		52#define S_IP		48#define S_FP		44#define S_R10		40#define S_R9		36#define S_R8		32#define S_R7		28#define S_R6		24#define S_R5		20#define S_R4		16#define S_R3		12#define S_R2		8#define S_R1		4#define S_R0		0#define S_OFF		8	.macro	save_user_regs	str	r0, [sp, #-4]!	str	lr, [sp, #-4]!	sub	sp, sp, #15*4	stmia	sp, {r0 - lr}^	mov	r0, r0	.endm	.macro	slow_restore_user_regs	ldmia	sp, {r0 - lr}^   @ restore the user regs	mov	r0, r0           @ no-op	ldr	lr, [sp, #15*4]  @ get user PC	add	sp, sp, #15*4+8  @ free stack	movs	pc, lr           @ return	.endm	.macro	fast_restore_user_regs	add	sp, sp, #S_OFF	ldmib	sp, {r1 - lr}^	mov	r0, r0	ldr	lr, [sp, #15*4]	add	sp, sp, #15*4+8	movs	pc, lr	.endm	.macro	mask_pc, rd, rm	bic	\rd, \rm, #PCMASK	.endm	.macro  disable_irqs, temp	mov     \temp, pc	orr     \temp, \temp, #PSR_I_BIT	teqp    \temp, #0	.endm	.macro	enable_irqs, temp	mov     \temp, pc	and     \temp, \temp, #~PSR_I_BIT	teqp	\temp, #0	.endm	.macro	initialise_traps_extra	.endm	.macro	get_thread_info, rd	mov	\rd, sp, lsr #13	mov	\rd, \rd, lsl #13	.endm	/*	 * Like adr, but force SVC mode (if required)	 */	.macro	adrsvc, cond, reg, label	adr\cond	\reg, \label	orr\cond	\reg, \reg, #PSR_I_BIT | MODE_SVC26	.endm/* * These are the registers used in the syscall handler, and allow us to * have in theory up to 7 arguments to a function - r0 to r6. * * r7 is reserved for the system call number for thumb mode. * * Note that tbl == why is intentional. * * We must set at least "tsk" and "why" when calling ret_with_reschedule. */scno	.req	r7		@ syscall numbertbl	.req	r8		@ syscall table pointerwhy	.req	r8		@ Linux syscall (!= 0)tsk	.req	r9		@ current thread_info/* * Get the system call number. */	.macro	get_scno	mask_pc	lr, lr	ldr	scno, [lr, #-4]		@ get SWI instruction	.endm/* *  ----------------------------------------------------------------------- *//*  * 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/* * Our do_softirq out of line code.  See include/asm-arm26/hardirq.h for * the calling assembly. */ENTRY(__do_softirq)	stmfd	sp!, {r0 - r3, ip, lr}	bl	do_softirq	ldmfd	sp!, {r0 - r3, ip, pc}	.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:	disable_irqs r1				@ disable interrupts	ldr	r1, [tsk, #TI_FLAGS]	tst	r1, #_TIF_WORK_MASK	bne	fast_work_pending	fast_restore_user_regs/* * Ok, we need to do extra processing, enter the slow path. */fast_work_pending:	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0work_pending:	tst	r1, #_TIF_NEED_RESCHED	bne	work_resched	tst	r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING	beq	no_work_pending	mov	r0, sp				@ 'regs'	mov	r2, why				@ 'syscall'	bl	do_notify_resume	disable_irqs r1				@ disable interrupts	b	no_work_pendingwork_resched:	bl	schedule/* * "slow" syscall return path.  "why" tells us if this was a real syscall. */ENTRY(ret_to_user)ret_slow_syscall:	disable_irqs r1				@ disable interrupts	ldr	r1, [tsk, #TI_FLAGS]	tst	r1, #_TIF_WORK_MASK	bne	work_pendingno_work_pending:	slow_restore_user_regs/* * This is how we return from a fork. */ENTRY(ret_from_fork)	bl	schedule_tail	get_thread_info tsk	ldr	r1, [tsk, #TI_FLAGS]		@ check for syscall tracing	mov	why, #1	tst	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?	beq	ret_slow_syscall	mov	r1, sp	mov	r0, #1				@ trace exit [IP = 1]	bl	syscall_trace	b	ret_slow_syscall	#include <asm/calls.h>/*============================================================================= * SWI handler *----------------------------------------------------------------------------- */	.align	5ENTRY(vector_swi)	save_user_regs	zero_fp	get_scno#ifdef CONFIG_ALIGNMENT_TRAP	ldr	ip, __cr_alignment	ldr	ip, [ip]	mcr	p15, 0, ip, c1, c0		@ update control register#endif	enable_irqs ip	str	r4, [sp, #-S_OFF]!		@ push fifth arg	get_thread_info tsk	ldr	ip, [tsk, #TI_FLAGS]		@ 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, #_TIF_SYSCALL_TRACE		@ 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_OFF2:	mov	why, #0				@ no longer a real syscall	cmp	scno, #ARMSWI_OFFSET	eor	r0, scno, #OS_NUMBER << 20	@ put OS number back	bcs	arm_syscall		b	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	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	syscall_trace	b	ret_slow_syscall	.align	5#ifdef CONFIG_ALIGNMENT_TRAP	.type	__cr_alignment, #object__cr_alignment:	.word	cr_alignment#endif	.type	sys_call_table, #objectENTRY(sys_call_table)#include <asm/calls.h>/*============================================================================ * Special system call wrappers */@ r0 = syscall number@ r5 = syscall table		.type	sys_syscall, #functionsys_syscall:		eor	scno, r0, #OS_NUMBER << 20		cmp	scno, #NR_syscalls	@ check range		stmleia	sp, {r5, r6}		@ shuffle args		movle	r0, r1		movle	r1, r2		movle	r2, r3		movle	r3, r4		ldrle	pc, [tbl, scno, lsl #2]		b	sys_ni_syscallsys_fork_wrapper:		add	r0, sp, #S_OFF		b	sys_forksys_vfork_wrapper:		add	r0, sp, #S_OFF		b	sys_vforksys_execve_wrapper:		add	r3, sp, #S_OFF		b	sys_execvesys_clone_wapper:		add	r2, sp, #S_OFF		b	sys_clonesys_sigsuspend_wrapper:		add	r3, sp, #S_OFF		b	sys_sigsuspendsys_rt_sigsuspend_wrapper:		add	r2, sp, #S_OFF		b	sys_rt_sigsuspendsys_sigreturn_wrapper:		add	r0, sp, #S_OFF		b	sys_sigreturnsys_rt_sigreturn_wrapper:		add	r0, sp, #S_OFF		b	sys_rt_sigreturnsys_sigaltstack_wrapper:		ldr	r2, [sp, #S_OFF + S_SP]		b	do_sigaltstack/* * Note: off_4k (r5) is always units of 4K.  If we can't do the requested * offset, we return EINVAL.  FIXME - this lost some stuff from arm32 to * ifdefs. check it out. */sys_mmap2:		tst	r5, #((1 << (PAGE_SHIFT - 12)) - 1)		moveq	r5, r5, lsr #PAGE_SHIFT - 12		streq	r5, [sp, #4]		beq	do_mmap2		mov	r0, #-EINVAL		RETINSTR(mov,pc, lr)/* *  Design issues: *   - We have several modes that each vector can be called from, *     each with its own set of registers.  On entry to any vector, *     we *must* save the registers used in *that* mode. * *   - This code must be as fast as possible. * *  There are a few restrictions on the vectors: *   - the SWI vector cannot be called from *any* non-user mode * *   - the FP emulator is *never* called from *any* non-user mode undefined *     instruction. * */		.text		.equ	ioc_base_high, IOC_BASE & 0xff000000		.equ	ioc_base_low, IOC_BASE & 0x00ff0000		.macro	disable_fiq		mov	r12, #ioc_base_high		.if	ioc_base_low		orr	r12, r12, #ioc_base_low		.endif		strb	r12, [r12, #0x38]	@ Disable FIQ register		.endm		.macro	get_irqnr_and_base, irqnr, base		mov	r4, #ioc_base_high		@ point at IOC		.if	ioc_base_low		orr	r4, r4, #ioc_base_low		.endif		ldrb	\irqnr, [r4, #0x24]		@ get high priority first		adr	\base, irq_prio_h		teq	\irqnr, #0		ldreqb	\irqnr, [r4, #0x14]		@ get low priority		adreq	\base, irq_prio_l		.endm/* * Interrupt table (incorporates priority) */		.macro	irq_prio_tableirq_prio_l:	.byte	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3		.byte	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7irq_prio_h:	.byte	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10		.byte	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10		.endm#if 1/* FIXME (well, ok, dont - but its easy to grep for :) *//* * Uncomment these if you wish to get more debugging into about data aborts. */#define FAULT_CODE_LDRSTRPOST	0x80#define FAULT_CODE_LDRSTRPRE	0x40#define FAULT_CODE_LDRSTRREG	0x20#define FAULT_CODE_LDMSTM	0x10#define FAULT_CODE_LDCSTC	0x08#endif#define FAULT_CODE_PREFETCH	0x04#define FAULT_CODE_WRITE	0x02#define FAULT_CODE_FORCECOW	0x01#define SVC_SAVE_ALL				\		str	sp, [sp, #-16]!		;\		str	lr, [sp, #8]		;\		str	lr, [sp, #4]		;\		stmfd	sp!, {r0 - r12}		;\		mov	r0, #-1			;\		str	r0, [sp, #S_OLD_R0]	;\		zero_fp#define SVC_IRQ_SAVE_ALL			\		str	sp, [sp, #-16]!		;\		str	lr, [sp, #4]		;\		ldr	lr, .LCirq		;\		ldr	lr, [lr]		;\		str	lr, [sp, #8]		;\		stmfd	sp!, {r0 - r12}		;\		mov	r0, #-1			;\		str	r0, [sp, #S_OLD_R0]	;\		zero_fp#define SVC_RESTORE_ALL				\		ldmfd	sp, {r0 - pc}^		/*============================================================================= * Undefined FIQs *----------------------------------------------------------------------------- */_unexp_fiq:	ldr     sp, .LCfiq		mov	r12, #IOC_BASE		strb	r12, [r12, #0x38]	@ Disable FIQ register		teqp	pc, #PSR_I_BIT | PSR_F_BIT | MODE_SVC26

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?