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

📄 entry.s

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 S
📖 第 1 页 / 共 3 页
字号:
/* $Id: entry.S,v 1.71 2001/07/27 11:47:50 gniibe Exp $ * *  linux/arch/sh/entry.S * *  Copyright (C) 1999, 2000  Niibe Yutaka * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * */#include <linux/sys.h>#include <linux/linkage.h>#include <linux/config.h>/* * Define this to turn on compatibility with the previous * system call ABI.  This feature is not properly maintained. */#undef COMPAT_OLD_SYSCALL_ABI! NOTE:! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address! to be jumped is too far, but it causes illegal slot exception./*	 * entry.S contains the system-call and fault low-level handling routines. * This also contains the timer-interrupt handler, as well as all interrupts * and faults that can result in a task-switch. * * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. * * NOTE: This code uses a convention that instructions in the delay slot * of a transfer-control instruction are indented by an extra space, thus: * *    jmp	@k0	    ! control-transfer instruction *     ldc	k1, ssr     ! delay slot * * Stack layout in 'ret_from_syscall': * 	ptrace needs to have all regs on the stack. *	if the order here is changed, it needs to be *	updated in ptrace.c and ptrace.h * *	r0 *      ... *	r15 = stack pointer *	spc *	pr *	ssr *	gbr *	mach *	macl *	syscall # * *//* * These are offsets into the task-struct. */flags		=  4sigpending	=  8need_resched	= 20tsk_ptrace	= 24PT_TRACESYS  = 0x00000002PF_USEDFPU   = 0x00100000ENOSYS = 38EINVAL = 22#if defined(__sh3__)TRA     = 0xffffffd0EXPEVT  = 0xffffffd4#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)INTEVT  = 0xa4000000		! INTEVTE2(0xa4000000)#elseINTEVT  = 0xffffffd8#endifMMU_TEA = 0xfffffffc		! TLB Exception Address Register#elif defined(__SH4__)TRA     = 0xff000020EXPEVT  = 0xff000024INTEVT  = 0xff000028MMU_TEA = 0xff00000c		! TLB Exception Address Register#endif/* Offsets to the stack */OFF_R0         =  0		/* Return value. New ABI also arg4 */OFF_R1         =  4     	/* New ABI: arg5 */OFF_R2         =  8     	/* New ABI: arg6 */OFF_R3         =  12     	/* New ABI: syscall_nr */OFF_R4         =  16     	/* New ABI: arg0 */OFF_R5         =  20     	/* New ABI: arg1 */OFF_R6         =  24     	/* New ABI: arg2 */OFF_R7         =  28     	/* New ABI: arg3 */OFF_SP	   =  (15*4)OFF_SR	   =  (16*4+8)SYSCALL_NR =  (16*4+6*4)#define k0	r0#define k1	r1#define k2	r2#define k3	r3#define k4	r4#define current		r7	/* r7_bank1 */#define g_imask		r6	/* r6_bank1 */#define k_current	r7_bank	/* r7_bank1 */#define k_g_imask	r6_bank	/* r6_bank1 */#define k_ex_code	r2_bank	/* r2_bank1 *//* * Kernel mode register usage: *	k0	scratch *	k1	scratch *	k2	scratch (Exception code) *	k3	scratch (Return address) *	k4	scratch *	k5	reserved *	k6	Global Interrupt Mask (0--15 << 4) *	k7	CURRENT (pointer to current task) */!! TLB Miss / Initial Page write exception handling!			_and_! TLB hits, but the access violate the protection.! It can be valid access, such as stack grow and/or C-O-W.!!! Find the pmd/pte entry and loadtlb! If it's not found, cause address error (SEGV)!! Although this could be written in assembly language (and it'd be faster),! this first version depends *much* on C implementation.!#define STI()				\	mov.l	__INV_IMASK, r11;	\	stc	sr, r10;		\	and	r11, r10;		\	stc	k_g_imask, r11;	\	or	r11, r10;		\	ldc	r10, sr	.align	2tlb_miss_load:	bra	call_dpf	 mov	#0, r5	.align	2tlb_miss_store:	bra	call_dpf	 mov	#1, r5	.align	2initial_page_write:	bra	call_dpf	 mov	#1, r5	.align	2tlb_protection_violation_load:	bra	call_dpf	 mov	#0, r5	.align	2tlb_protection_violation_store:	bra	call_dpf	 mov	#1, r5call_dpf:	mov.l	1f, r0	mov	r5, r8	mov.l	@r0, r6	mov	r6, r9	mov.l	2f, r0	sts	pr, r10	jsr	@r0	 mov	r15, r4	!	tst	r0, r0	bf/s	0f	 lds	r10, pr	rts	 nop0:	STI()	mov.l	3f, r0	mov	r9, r6	mov	r8, r5	jmp	@r0	 mov	r15, r4	.align 21:	.long	MMU_TEA2:	.long	SYMBOL_NAME(__do_page_fault)3:	.long	SYMBOL_NAME(do_page_fault)	.align	2address_error_load:	bra	call_dae	 mov	#0,r5		! writeaccess = 0	.align	2address_error_store:	bra	call_dae	 mov	#1,r5		! writeaccess = 1call_dae:	mov.l	1f, r0	mov.l	@r0, r6		! address	mov.l	2f, r0	jmp	@r0	 mov	r15, r4		! regs	.align 21:	.long	MMU_TEA2:	.long   SYMBOL_NAME(do_address_error)#if defined(CONFIG_SH_STANDARD_BIOS)	.align	2	/* Unwind the stack and jmp to the debug entry */debug_kernel:	mov.l	@r15+, r0	mov.l	@r15+, r1	mov.l	@r15+, r2	mov.l	@r15+, r3	mov.l	@r15+, r4	mov.l	@r15+, r5	mov.l	@r15+, r6	mov.l	@r15+, r7	stc	sr, r8	mov.l	1f, r9			! BL =1, RB=1, IMASK=0x0F	or	r9, r8	ldc	r8, sr			! here, change the register bank	mov.l	@r15+, r8	mov.l	@r15+, r9	mov.l	@r15+, r10	mov.l	@r15+, r11	mov.l	@r15+, r12	mov.l	@r15+, r13	mov.l	@r15+, r14	mov.l	@r15+, k0	ldc.l	@r15+, spc	lds.l	@r15+, pr	mov.l	@r15+, k1	ldc.l	@r15+, gbr	lds.l	@r15+, mach	lds.l	@r15+, macl	mov	k0, r15	!	mov.l	2f, k0	mov.l	@k0, k0	jmp	@k0	 ldc	k1, ssr	.align	21:	.long	0x300000f02:	.long	SYMBOL_NAME(gdb_vbr_vector)#endif	.align	2debug_trap:	#if defined(CONFIG_SH_STANDARD_BIOS)	mov	#OFF_SR, r0	mov.l	@(r0,r15), r0		! get status register	shll	r0	shll	r0			! kernel space?	bt/s	debug_kernel#endif	 mov.l	@r15, r0	mov.l	1f, r8	jmp	@r8	 nop	.align	21:	.long	SYMBOL_NAME(break_point_trap_software)	.align	2error:		!	STI()	mov.l	1f, r0	jmp	@r0	 nop	.align	21:	.long	SYMBOL_NAME(do_exception_error)!!!ENTRY(ret_from_fork)	mov.l	@r15+,r0	! Call schedule_tail	mov.l	1f, r1	jsr @r1	 mov	r0, r4	! If we're being traced, return via syscall_ret_trace, otherwise	! return directly to ret_from_syscall	stc	k_current, r0	mov.l	@(tsk_ptrace,r0), r0	! Is current PTRACE_SYSCALL'd?	mov	#PT_TRACESYS, r1	tst	r1, r0	bt	ret_from_syscall	bra	syscall_ret_trace	 nop	 	.align	21:	.long	SYMBOL_NAME(schedule_tail)/* * Old syscall interface: * *	Syscall #: R0 *	Arguments #0 to #3: R4--R7 *	more arguments: On the stack *	TRA: (number of arguments on the stack) x 4 * * New syscall interface: * *	Syscall #: R3 *	Arguments #0 to #3: R4--R7 *	Arguments #4 to #6: R0, R1, R2 *	TRA: (number of arguments + 0x10) x 4 * * This code also handles delegating other traps to the BIOS/gdb stub * according to: * * Trap number * (TRA>>2) 	    Purpose * -------- 	    ------- * 0x0-0xf  	    old syscall ABI * 0x10-0x1f  	    new syscall ABI * 0x20-0xff  	    delegated through debug_trap to BIOS/gdb stub. * * Note: When we're first called, the TRA value must be shifted * right 2 bits in order to get the value that was used as the "trapa" * argument. */system_call:	mov.l	__TRA, r9	mov.l	@r9, r8	!	! Is the trap argument >= 0x20? (TRA will be >= 0x80)	mov	#0x20, r9	extu.b	r9, r9	shll2	r9	cmp/hs	r9, r8	bt	debug_trap	!	mov	#SYSCALL_NR, r14	add	r15, r14	!#ifdef COMPAT_OLD_SYSCALL_ABI	mov	#0x40, r9	cmp/hs	r9, r8	bf/s	old_abi_system_call	 nop#endif	! New Syscall ABI	add	#-0x40, r8	shlr2	r8	shll8	r8	shll8	r8 		    	! r8 = num_args<<16	mov	r3, r10	or	r8, r10	! Encode syscall # and # of arguments	mov.l	r10, @r14		! set syscall_nr	STI()	!	stc	k_current, r11	mov.l	@(tsk_ptrace,r11), r10	! Is current PTRACE_SYSCALL'd?	mov	#PT_TRACESYS, r11	tst	r11, r10	bt	5f	!                     	Yes it is traced.	mov.l	__syscall_trace, r11	! Call syscall_trace() which notifies	jsr	@r11	    	    	! superior (will chomp R[0-7])	 nop	!			Reload R0-R4 from kernel stack, where the	!   	    	    	parent may have modified them using	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are	!   	    	    	used by the system call handler directly	!   	    	    	from the kernel stack anyway, so don't need	!   	    	    	to be reloaded here.)  This allows the parent	!   	    	    	to rewrite system calls and args on the fly.	mov.l	@(OFF_R4,r15), r4   ! arg0	mov.l	@(OFF_R5,r15), r5	mov.l	@(OFF_R6,r15), r6	mov.l	@(OFF_R7,r15), r7   ! arg3	mov.l	@(OFF_R3,r15), r3   ! syscall_nr	!   	    	    Arrange for syscall_trace() to be called	!   	    	    again as the system call returns.	mov.l	__syscall_ret_trace, r10	bra	6f	 lds	r10, pr	!   	    	    No it isn't traced.	!   	    	    Arrange for normal system call return.5:	mov.l	__syscall_ret, r10	lds	r10, pr	!   	    	    Call the system call handler through the table.	!   	    	    (both normal and ptrace'd)	!   	    	    First check for bad syscall number6:	mov	r3, r9	mov.l	__n_sys, r10	cmp/hs	r10, r9	bf	2f	!   	    	    Bad syscall number	rts			! go to syscall_ret or syscall_ret_trace    	 mov	#-ENOSYS, r0	!   	    	    Good syscall number2:	shll2	r9		! x4	mov.l	__sct, r11	add	r11, r9	mov.l	@r9, r11	jmp	@r11	    	! jump to specific syscall handler	 nop	! In case of tracesyscall_ret_trace:	mov.l	r0, @(OFF_R0,r15)		! save the return value	mov.l	__syscall_trace, r1	mova	SYMBOL_NAME(ret_from_syscall), r0	jmp	@r1    	! Call syscall_trace() which notifies superior	 lds	r0, pr    	! Then return to ret_from_syscall()#ifdef COMPAT_OLD_SYSCALL_ABI! Handle old ABI system call.! Note that ptrace(SYSCALL) is not supported for the old ABI.! At this point:!   r0, r4-7 as per ABI!   r8  = value of TRA register (= num_args<<2)!   r14 = points to SYSCALL_NR in stack frame

⌨️ 快捷键说明

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