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

📄 entry.s

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 S
📖 第 1 页 / 共 3 页
字号:
/* $Id: entry.S,v 1.71 2000/03/22 13:29:33 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 */R0         =  0		/* Return value. New ABI also arg4 */R1         =  4     	/* New ABI: arg5 */R2         =  8     	/* New ABI: arg6 */R3         =  12     	/* New ABI: syscall_nr */R4         =  16     	/* New ABI: arg0 */R5         =  20     	/* New ABI: arg1 */R6         =  24     	/* New ABI: arg2 */R7         =  28     	/* New ABI: arg3 */SP	   =  (15*4)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	#0xff, $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)#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || 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	jmp	@$k0	 ldc	$k1, $ssr	.align	21:	.long	0x300000f02:	.long	CONFIG_GDB_STUB_VBR + 0x100#endif	.align	2debug_trap:	#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)	mov	#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)	bra	SYMBOL_NAME(ret_from_syscall)	 add	#4, $r15	! pop down bogus r0 (see switch_to MACRO)/* * 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	@(R4,$r15), $r4   ! arg0	mov.l	@(R5,$r15), $r5	mov.l	@(R6,$r15), $r6	mov.l	@(R7,$r15), $r7   ! arg3	mov.l	@(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, @(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()

⌨️ 快捷键说明

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