⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 entry.s

📁 linux-2.6.15.6
💻 S
📖 第 1 页 / 共 2 页
字号:
/* arch/arm26/kernel/entry.S *  * Assembled from chunks of code in arch/arm * * Copyright (C) 2003 Ian Molton * Based on the work of RMK. * */#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@ 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_*)@ PSR and PC are comined on arm26@#define S_OFF		8#define S_OLD_R0	64#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	.macro	save_user_regs	str	r0, [sp, #-4]!   @ Store SVC r0	str	lr, [sp, #-4]!   @ Store user mode PC	sub	sp, sp, #15*4	stmia	sp, {r0 - lr}^   @ Store the other user-mode regs	mov	r0, r0	.endm	.macro	slow_restore_user_regs	ldmia	sp, {r0 - lr}^   @ restore the user regs not including PC	mov	r0, r0	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	save_svc_regs	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	.endm	.macro	save_svc_regs_irq	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	.endm	.macro	restore_svc_regs                ldmfd   sp, {r0 - pc}^	.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/* * 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. * * 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/* * 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	// FIXME - is this strictly necessary?#include "calls.S"/*============================================================================= * 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	adral	lr, ret_fast_syscall            @ set return address        orral	lr, lr, #PSR_I_BIT | MODE_SVC26 @ Force SVC mode on return	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	adral   lr, __sys_trace_return          @ set return address        orral   lr, lr, #PSR_I_BIT | MODE_SVC26 @ Force SVC mode on return	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 "calls.S"/*============================================================================ * 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		.macro handle_irq1:		mov     r4, #IOC_BASE		ldrb    r6, [r4, #0x24]            @ get high priority first		adr     r5, irq_prio_h		teq     r6, #0		ldreqb  r6, [r4, #0x14]            @ get low priority		adreq   r5, irq_prio_l                teq     r6, #0                     @ If an IRQ happened...                ldrneb  r0, [r5, r6]               @ get IRQ number                movne   r1, sp                     @ get struct pt_regs                adrne   lr, 1b                     @ Set return address to 1b                orrne   lr, lr, #PSR_I_BIT | MODE_SVC26  @ (and force SVC mode)                bne     asm_do_IRQ                 @ process IRQ (if asserted)		.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/* * Uncomment these if you wish to get more debugging into about data aborts. * FIXME - I bet we can find a way to encode these and keep performance. */#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/*============================================================================= * 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		mov	r0, r0		stmfd	sp!, {r0 - r3, ip, lr}		adr	r0, Lfiqmsg		bl	printk		ldmfd	sp!, {r0 - r3, ip, lr}		teqp	pc, #PSR_I_BIT | PSR_F_BIT | MODE_FIQ26		mov	r0, r0		movs	pc, lr

⌨️ 快捷键说明

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