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

📄 entry.s

📁 linux 内核源代码
💻 S
📖 第 1 页 / 共 4 页
字号:
/* * arch/xtensa/kernel/entry.S * * Low-level exception handling * * 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. * * Copyright (C) 2004-2007 by Tensilica Inc. * * Chris Zankel <chris@zankel.net> * */#include <linux/linkage.h>#include <asm/asm-offsets.h>#include <asm/processor.h>#include <asm/thread_info.h>#include <asm/uaccess.h>#include <asm/unistd.h>#include <asm/ptrace.h>#include <asm/current.h>#include <asm/pgtable.h>#include <asm/page.h>#include <asm/signal.h>#include <asm/tlbflush.h>/* Unimplemented features. */#undef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION#undef KERNEL_STACK_OVERFLOW_CHECK#undef PREEMPTIBLE_KERNEL#undef ALLOCA_EXCEPTION_IN_IRAM/* Not well tested. * * - fast_coprocessor *//* * Macro to find first bit set in WINDOWBASE from the left + 1 * * 100....0 -> 1 * 010....0 -> 2 * 000....1 -> WSBITS */	.macro ffs_ws bit mask#if XCHAL_HAVE_NSA	nsau    \bit, \mask			# 32-WSBITS ... 31 (32 iff 0)	addi    \bit, \bit, WSBITS - 32 + 1   	# uppest bit set -> return 1#else	movi    \bit, WSBITS#if WSBITS > 16	_bltui  \mask, 0x10000, 99f	addi    \bit, \bit, -16	extui   \mask, \mask, 16, 16#endif#if WSBITS > 899:	_bltui  \mask, 0x100, 99f	addi    \bit, \bit, -8	srli    \mask, \mask, 8#endif99:	_bltui  \mask, 0x10, 99f	addi    \bit, \bit, -4	srli    \mask, \mask, 499:	_bltui  \mask, 0x4, 99f	addi    \bit, \bit, -2	srli    \mask, \mask, 299:	_bltui  \mask, 0x2, 99f	addi    \bit, \bit, -199:#endif	.endm/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- *//* * First-level exception handler for user exceptions. * Save some special registers, extra states and all registers in the AR * register file that were in use in the user task, and jump to the common * exception code. * We save SAR (used to calculate WMASK), and WB and WS (we don't have to * save them for kernel exceptions). * * Entry condition for user_exception: * *   a0:	trashed, original value saved on stack (PT_AREG0) *   a1:	a1 *   a2:	new stack pointer, original value in depc *   a3:	dispatch table *   depc:	a2, original value saved on stack (PT_DEPC) *   excsave1:	a3 * *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * * Entry condition for _user_exception: * *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC *   excsave has been restored, and *   stack pointer (a1) has been set. * * Note: _user_exception might be at an odd adress. Don't use call0..call12 */ENTRY(user_exception)	/* Save a2, a3, and depc, restore excsave_1 and set SP. */	xsr	a3, EXCSAVE_1	rsr	a0, DEPC	s32i	a1, a2, PT_AREG1	s32i	a0, a2, PT_AREG2	s32i	a3, a2, PT_AREG3	mov	a1, a2	.globl _user_exception_user_exception:	/* Save SAR and turn off single stepping */	movi	a2, 0	rsr	a3, SAR	xsr	a2, ICOUNTLEVEL	s32i	a3, a1, PT_SAR	s32i	a2, a1, PT_ICOUNTLEVEL	/* Rotate ws so that the current windowbase is at bit0. */	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */	rsr	a2, WINDOWBASE	rsr	a3, WINDOWSTART	ssr	a2	s32i	a2, a1, PT_WINDOWBASE	s32i	a3, a1, PT_WINDOWSTART	slli	a2, a3, 32-WSBITS	src	a2, a3, a2	srli	a2, a2, 32-WSBITS	s32i	a2, a1, PT_WMASK	# needed for restoring registers	/* Save only live registers. */	_bbsi.l	a2, 1, 1f	s32i	a4, a1, PT_AREG4	s32i	a5, a1, PT_AREG5	s32i	a6, a1, PT_AREG6	s32i	a7, a1, PT_AREG7	_bbsi.l	a2, 2, 1f	s32i	a8, a1, PT_AREG8	s32i	a9, a1, PT_AREG9	s32i	a10, a1, PT_AREG10	s32i	a11, a1, PT_AREG11	_bbsi.l	a2, 3, 1f	s32i	a12, a1, PT_AREG12	s32i	a13, a1, PT_AREG13	s32i	a14, a1, PT_AREG14	s32i	a15, a1, PT_AREG15	_bnei	a2, 1, 1f		# only one valid frame?	/* Only one valid frame, skip saving regs. */	j	2f	/* Save the remaining registers.	 * We have to save all registers up to the first '1' from	 * the right, except the current frame (bit 0).	 * Assume a2 is:  001001000110001	 * All register frames starting from the top field to the marked '1'	 * must be saved.	 */1:	addi	a3, a2, -1		# eliminate '1' in bit 0: yyyyxxww0	neg	a3, a3			# yyyyxxww0 -> YYYYXXWW1+1	and	a3, a3, a2		# max. only one bit is set	/* Find number of frames to save */	ffs_ws	a0, a3			# number of frames to the '1' from left	/* Store information into WMASK:	 * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,	 * bits 4...: number of valid 4-register frames	 */	slli	a3, a0, 4		# number of frames to save in bits 8..4	extui	a2, a2, 0, 4		# mask for the first 16 registers	or	a2, a3, a2	s32i	a2, a1, PT_WMASK	# needed when we restore the reg-file	/* Save 4 registers at a time */1:	rotw	-1	s32i	a0, a5, PT_AREG_END - 16	s32i	a1, a5, PT_AREG_END - 12	s32i	a2, a5, PT_AREG_END - 8	s32i	a3, a5, PT_AREG_END - 4	addi	a0, a4, -1	addi	a1, a5, -16	_bnez	a0, 1b	/* WINDOWBASE still in SAR! */	rsr	a2, SAR			# original WINDOWBASE	movi	a3, 1	ssl	a2	sll	a3, a3	wsr	a3, WINDOWSTART		# set corresponding WINDOWSTART bit	wsr	a2, WINDOWBASE		# and WINDOWSTART	rsync	/* We are back to the original stack pointer (a1) */2:#if XCHAL_EXTRA_SA_SIZE	/* For user exceptions, save the extra state into the user's TCB.	 * Note: We must assume that xchal_extra_store_funcbody destroys a2..a15	 */	GET_CURRENT(a2,a1)	addi	a2, a2, THREAD_CP_SAVE	xchal_extra_store_funcbody#endif	/* Now, jump to the common exception handler. */	j	common_exception/* * First-level exit handler for kernel exceptions * Save special registers and the live window frame. * Note: Even though we changes the stack pointer, we don't have to do a *	 MOVSP here, as we do that when we return from the exception. *	 (See comment in the kernel exception exit code) * * Entry condition for kernel_exception: * *   a0:	trashed, original value saved on stack (PT_AREG0) *   a1:	a1 *   a2:	new stack pointer, original in DEPC *   a3:	dispatch table *   depc:	a2, original value saved on stack (PT_DEPC) *   excsave_1:	a3 * *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * * Entry condition for _kernel_exception: * *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC *   excsave has been restored, and *   stack pointer (a1) has been set. * * Note: _kernel_exception might be at an odd adress. Don't use call0..call12 */ENTRY(kernel_exception)	/* Save a0, a2, a3, DEPC and set SP. */	xsr	a3, EXCSAVE_1		# restore a3, excsave_1	rsr	a0, DEPC		# get a2	s32i	a1, a2, PT_AREG1	s32i	a0, a2, PT_AREG2	s32i	a3, a2, PT_AREG3	mov	a1, a2	.globl _kernel_exception_kernel_exception:	/* Save SAR and turn off single stepping */	movi	a2, 0	rsr	a3, SAR	xsr	a2, ICOUNTLEVEL	s32i	a3, a1, PT_SAR	s32i	a2, a1, PT_ICOUNTLEVEL	/* Rotate ws so that the current windowbase is at bit0. */	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */	rsr	a2, WINDOWBASE		# don't need to save these, we only	rsr	a3, WINDOWSTART		# need shifted windowstart: windowmask	ssr	a2	slli	a2, a3, 32-WSBITS	src	a2, a3, a2	srli	a2, a2, 32-WSBITS	s32i	a2, a1, PT_WMASK	# needed for kernel_exception_exit	/* Save only the live window-frame */	_bbsi.l	a2, 1, 1f	s32i	a4, a1, PT_AREG4	s32i	a5, a1, PT_AREG5	s32i	a6, a1, PT_AREG6	s32i	a7, a1, PT_AREG7	_bbsi.l	a2, 2, 1f	s32i	a8, a1, PT_AREG8	s32i	a9, a1, PT_AREG9	s32i	a10, a1, PT_AREG10	s32i	a11, a1, PT_AREG11	_bbsi.l	a2, 3, 1f	s32i	a12, a1, PT_AREG12	s32i	a13, a1, PT_AREG13	s32i	a14, a1, PT_AREG14	s32i	a15, a1, PT_AREG151:#ifdef KERNEL_STACK_OVERFLOW_CHECK	/*  Stack overflow check, for debugging  */	extui	a2, a1, TASK_SIZE_BITS,XX	movi	a3, SIZE??	_bge	a2, a3, out_of_stack_panic#endif/* * This is the common exception handler. * We get here from the user exception handler or simply by falling through * from the kernel exception handler. * Save the remaining special registers, switch to kernel mode, and jump * to the second-level exception handler. * */common_exception:	/* Save some registers, disable loops and clear the syscall flag. */	rsr	a2, DEBUGCAUSE	rsr	a3, EPC_1	s32i	a2, a1, PT_DEBUGCAUSE	s32i	a3, a1, PT_PC	movi	a2, -1	rsr	a3, EXCVADDR	s32i	a2, a1, PT_SYSCALL	movi	a2, 0	s32i	a3, a1, PT_EXCVADDR	xsr	a2, LCOUNT	s32i	a2, a1, PT_LCOUNT	/* It is now save to restore the EXC_TABLE_FIXUP variable. */	rsr	a0, EXCCAUSE	movi	a3, 0	rsr	a2, EXCSAVE_1	s32i	a0, a1, PT_EXCCAUSE	s32i	a3, a2, EXC_TABLE_FIXUP	/* All unrecoverable states are saved on stack, now, and a1 is valid,	 * so we can allow exceptions and interrupts (*) again.	 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)	 *	 * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before	 *     (interrupts disabled) and if this exception is not an interrupt.	 */	rsr	a3, PS	addi	a0, a0, -4	movi	a2, 1	extui	a3, a3, 0, 1		# a3 = PS.INTLEVEL[0]	moveqz	a3, a2, a0		# a3 = 1 iff interrupt exception	movi	a2, 1 << PS_WOE_BIT	or	a3, a3, a2	rsr	a0, EXCCAUSE	xsr	a3, PS	s32i	a3, a1, PT_PS		# save ps	/* Save LBEG, LEND */	rsr	a2, LBEG	rsr	a3, LEND	s32i	a2, a1, PT_LBEG	s32i	a3, a1, PT_LEND	/* Go to second-level dispatcher. Set up parameters to pass to the	 * exception handler and call the exception handler.	 */	movi	a4, exc_table	mov	a6, a1			# pass stack frame	mov	a7, a0			# pass EXCCAUSE	addx4	a4, a0, a4	l32i	a4, a4, EXC_TABLE_DEFAULT		# load handler	/* Call the second-level handler */	callx4	a4	/* Jump here for exception exit */common_exception_return:	/* Jump if we are returning from kernel exceptions. */1:	l32i	a3, a1, PT_PS	_bbsi.l	a3, PS_UM_BIT, 2f	j	kernel_exception_exit	/* Specific to a user exception exit:	 * We need to check some flags for signal handling and rescheduling,	 * and have to restore WB and WS, extra states, and all registers	 * in the register file that were in use in the user task.	 */2:	wsr	a3, PS		/* disable interrupts */	/* Check for signals (keep interrupts disabled while we read TI_FLAGS)	 * Note: PS.INTLEVEL = 0, PS.EXCM = 1	 */	GET_THREAD_INFO(a2,a1)	l32i	a4, a2, TI_FLAGS	/* Enable interrupts again.	 * Note: When we get here, we certainly have handled any interrupts.	 *       (Hint: There is only one user exception frame on stack)	 */	movi	a3, 1 << PS_WOE_BIT	_bbsi.l	a4, TIF_NEED_RESCHED, 3f	_bbci.l	a4, TIF_SIGPENDING, 4f#ifndef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION	l32i	a4, a1, PT_DEPC	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f#endif	/* Reenable interrupts and call do_signal() */	wsr	a3, PS	movi	a4, do_signal	# int do_signal(struct pt_regs*, sigset_t*)	mov	a6, a1	movi	a7, 0	callx4	a4	j	1b3:	/* Reenable interrupts and reschedule */	wsr	a3, PS	movi	a4, schedule	# void schedule (void)	callx4	a4	j	1b	/* Restore the state of the task and return from the exception. */4:	/* a2 holds GET_CURRENT(a2,a1)  */#if XCHAL_EXTRA_SA_SIZE	/* For user exceptions, restore the extra state from the user's TCB. */	/* Note: a2 still contains GET_CURRENT(a2,a1) */	addi	a2, a2, THREAD_CP_SAVE	xchal_extra_load_funcbody	/* We must assume that xchal_extra_store_funcbody destroys	 * registers a2..a15.  FIXME, this list can eventually be	 * reduced once real register requirements of the macro are	 * finalized. */#endif /* XCHAL_EXTRA_SA_SIZE */	/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */	l32i	a2, a1, PT_WINDOWBASE	l32i	a3, a1, PT_WINDOWSTART	wsr	a1, DEPC		# use DEPC as temp storage	wsr	a3, WINDOWSTART		# restore WINDOWSTART	ssr	a2			# preserve user's WB in the SAR	wsr	a2, WINDOWBASE		# switch to user's saved WB	rsync	rsr	a1, DEPC		# restore stack pointer	l32i	a2, a1, PT_WMASK	# register frames saved (in bits 4...9)	rotw	-1			# we restore a4..a7	_bltui	a6, 16, 1f		# only have to restore current window?	/* The working registers are a0 and a3.  We are restoring to	 * a4..a7.  Be careful not to destroy what we have just restored.	 * Note: wmask has the format YYYYM:	 *       Y: number of registers saved in groups of 4	 *       M: 4 bit mask of first 16 registers	 */	mov	a2, a6	mov	a3, a52:	rotw	-1			# a0..a3 become a4..a7	addi	a3, a7, -4*4		# next iteration	addi	a2, a6, -16		# decrementing Y in WMASK	l32i	a4, a3, PT_AREG_END + 0	l32i	a5, a3, PT_AREG_END + 4	l32i	a6, a3, PT_AREG_END + 8	l32i	a7, a3, PT_AREG_END + 12	_bgeui	a2, 16, 2b	/* Clear unrestored registers (don't leak anything to user-land */1:	rsr	a0, WINDOWBASE	rsr	a3, SAR	sub	a3, a0, a3	beqz	a3, 2f	extui	a3, a3, 0, WBBITS1:	rotw	-1	addi	a3, a7, -1	movi	a4, 0	movi	a5, 0	movi	a6, 0	movi	a7, 0	bgei	a3, 1, 1b	/* We are back were we were when we started.	 * Note: a2 still contains WMASK (if we've returned to the original	 *	 frame where we had loaded a2), or at least the lower 4 bits	 *	 (if we have restored WSBITS-1 frames).	 */2:	j	common_exception_exit	/* This is the kernel exception exit.	 * We avoided to do a MOVSP when we entered the exception, but we	 * have to do it here.	 */

⌨️ 快捷键说明

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