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

📄 entry.s

📁 linux内核源码
💻 S
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2000-2003 Axis Communications AB * *  Authors:	Bjorn Wesen (bjornw@axis.com) *              Tobias Anderberg (tobiasa@axis.com), CRISv32 port. * * Code for the system-call and fault low-level handling routines. * * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. * * Stack layout in 'ret_from_system_call': * 	ptrace needs to have all regs on the stack. *	if the order here is changed, it needs to be *	updated in fork.c:copy_process, signal.c:do_signal, *	ptrace.c and ptrace.h * */#include <linux/linkage.h>#include <linux/sys.h>#include <asm/unistd.h>#include <asm/errno.h>#include <asm/thread_info.h>#include <asm/asm-offsets.h>#include <asm/arch/hwregs/asm/reg_map_asm.h>#include <asm/arch/hwregs/asm/intr_vect_defs_asm.h>	;; Exported functions.	.globl system_call	.globl ret_from_intr	.globl ret_from_fork	.globl resume	.globl multiple_interrupt	.globl nmi_interrupt	.globl spurious_interrupt	.globl do_sigtrap	.globl gdb_handle_exception	.globl sys_call_table	; Check if preemptive kernel scheduling should be done.#ifdef CONFIG_PREEMPT_resume_kernel:	di	; Load current task struct.	movs.w	-8192, $r0		; THREAD_SIZE = 8192	and.d	$sp, $r0	addoq	+TI_preempt_count, $r0, $acr	move.d	[$acr], $r10		; Preemption disabled?	bne	_Rexit	nop_need_resched:	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r10	btstq	TIF_NEED_RESCHED, $r10	; Check if need_resched is set.	bpl	_Rexit	nop	; Do preemptive kernel scheduling.	jsr	preempt_schedule_irq	nop	; Load new task struct.	movs.w	-8192, $r0		; THREAD_SIZE = 8192.	and.d	$sp, $r0	; One more time with new task.	ba	_need_resched	nop#else#define _resume_kernel _Rexit#endif	; Called at exit from fork. schedule_tail must be called to drop	; spinlock if CONFIG_PREEMPT.ret_from_fork:	jsr schedule_tail	nop	ba  ret_from_sys_call	nopret_from_intr:	;; Check for resched if preemptive kernel, or if we're going back to	;; user-mode. This test matches the user_regs(regs) macro. Don't simply	;; test CCS since that doesn't necessarily reflect what mode we'll	;; return into.	addoq	+PT_ccs, $sp, $acr	move.d	[$acr], $r0	btstq	16, $r0			; User-mode flag.	bpl	_resume_kernel	; Note that di below is in delay slot._resume_userspace:	di			; So need_resched and sigpending don't change.	movs.w	-8192, $r0		; THREAD_SIZE == 8192	and.d	$sp, $r0	addoq	+TI_flags, $r0, $acr	; current->work	move.d	[$acr], $r10	and.d	_TIF_WORK_MASK, $r10	; Work to be done on return?	bne	_work_pending	nop	ba	_Rexit	nop	;; The system_call is called by a BREAK instruction, which looks pretty	;; much like any other exception.	;;	;; System calls can't be made from interrupts but we still stack ERP	;; to have a complete stack frame.	;;	;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,	;; r13,mof,srp	;;	;; This function looks on the _surface_ like spaghetti programming, but it's	;; really designed so that the fast-path does not force cache-loading of	;; non-used instructions. Only the non-common cases cause the outlined code	;; to run..system_call:	;; Stack-frame similar to the irq heads, which is reversed in	;; ret_from_sys_call.	subq	12, $sp		; Skip EXS, EDA.	move	$erp, [$sp]	subq	4, $sp	move	$srp, [$sp]	subq	4, $sp	move	$ccs, [$sp]	subq	4, $sp	ei			; Allow IRQs while handling system call	move	$spc, [$sp]	subq	4, $sp	move	$mof, [$sp]	subq	4, $sp	move	$srs, [$sp]	subq	4, $sp	move.d	$acr, [$sp]	subq	14*4, $sp	; Make room for R0-R13.	movem	$r13, [$sp]	; Push R0-R13	subq	4, $sp	move.d	$r10, [$sp]	; Push orig_r10.; Set S-bit when kernel debugging to keep hardware breakpoints active.#ifdef CONFIG_ETRAX_KGDB	move $ccs, $r0	or.d (1<<9), $r0	move $r0, $ccs#endif	movs.w	-ENOSYS, $r0	addoq	+PT_r10, $sp, $acr	move.d	$r0, [$acr]	;; Check if this process is syscall-traced.	movs.w	-8192, $r0	; THREAD_SIZE == 8192	and.d	$sp, $r0	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r0	btstq	TIF_SYSCALL_TRACE, $r0	bmi	_syscall_trace_entry	nop_syscall_traced:	;; Check for sanity in the requested syscall number.	cmpu.w	NR_syscalls, $r9	bhs	ret_from_sys_call	lslq	2, $r9		;  Multiply by 4, in the delay slot.	;; The location on the stack for the register structure is passed as a	;; seventh argument. Some system calls need this.	move.d  $sp, $r0	subq	4, $sp	move.d	$r0, [$sp]	;; The registers carrying parameters (R10-R13) are intact. The optional	;; fifth and sixth parameters is in MOF and SRP respectivly. Put them	;; back on the stack.	subq	4, $sp	move	$srp, [$sp]	subq	4, $sp	move	$mof, [$sp]	;; Actually to the system call.	addo.d	+sys_call_table, $r9, $acr	move.d	[$acr], $acr	jsr	$acr	nop	addq	3*4, $sp		; Pop the mof, srp and regs parameters.	addoq	+PT_r10, $sp, $acr	move.d	$r10, [$acr]		; Save the return value.	moveq	1, $r9			; "Parameter" to ret_from_sys_call to					; show it was a sys call.	;; Fall through into ret_from_sys_call to return.ret_from_sys_call:	;; R9 is a parameter:	;;  >= 1 from syscall	;;     0 from irq	;; Get the current task-struct pointer.	movs.w	-8192, $r0	; THREAD_SIZE == 8192	and.d	$sp, $r0	di		; Make sure need_resched and sigpending don't change.	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r1	and.d	_TIF_ALLWORK_MASK, $r1	bne	_syscall_exit_work	nop_Rexit:	;; This epilogue MUST match the prologues in multiple_interrupt, irq.h	;; and ptregs.h.	addq	4, $sp		; Skip orig_r10.	movem	[$sp+], $r13	; Registers R0-R13.	move.d	[$sp+], $acr	move	[$sp], $srs	addq	4, $sp	move	[$sp+], $mof	move	[$sp+], $spc	move	[$sp+], $ccs	move	[$sp+], $srp	move	[$sp+], $erp	addq    8, $sp		; Skip EXS, EDA.	jump	$erp	rfe			; Restore condition code stack in delay-slot.	;; We get here after doing a syscall if extra work might need to be done	;; perform syscall exit tracing if needed._syscall_exit_work:	;; R0 contains current at this point and irq's are disabled.	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r1	btstq	TIF_SYSCALL_TRACE, $r1	bpl	_work_pending	nop	ei	move.d	$r9, $r1		; Preserve R9.	jsr	do_syscall_trace	nop	move.d	$r1, $r9	ba	_resume_userspace	nop_work_pending:	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r10	btstq	TIF_NEED_RESCHED, $r10	; Need resched?	bpl	_work_notifysig		; No, must be signal/notify.	nop_work_resched:	move.d	$r9, $r1		; Preserve R9.	jsr	schedule	nop	move.d	$r1, $r9	di	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r1	and.d	_TIF_WORK_MASK, $r1	; Ignore sycall trace counter.	beq	_Rexit	nop	btstq	TIF_NEED_RESCHED, $r1	bmi	_work_resched		; current->work.need_resched.	nop_work_notifysig:	;; Deal with pending signals and notify-resume requests.	addoq	+TI_flags, $r0, $acr	move.d	[$acr], $r13		; The thread_info_flags parameter.	move.d	$r9, $r10		; do_notify_resume syscall/irq param.	moveq	0, $r11			; oldset param - 0 in this case.	move.d	$sp, $r12		; The regs param.	jsr	do_notify_resume	nop	ba _Rexit	nop	;; We get here as a sidetrack when we've entered a syscall with the	;; trace-bit set. We need to call do_syscall_trace and then continue	;; with the call._syscall_trace_entry:	;; PT_r10 in the frame contains -ENOSYS as required, at this point.	jsr	do_syscall_trace	nop	;; Now re-enter the syscall code to do the syscall itself. We need to	;; restore R9 here to contain the wanted syscall, and the other	;; parameter-bearing registers.	addoq	+PT_r9, $sp, $acr	move.d	[$acr], $r9	addoq	+PT_orig_r10, $sp, $acr	move.d	[$acr], $r10		; PT_r10 is already -ENOSYS.	addoq	+PT_r11, $sp, $acr	move.d	[$acr], $r11	addoq	+PT_r12, $sp, $acr	move.d	[$acr], $r12	addoq	+PT_r13, $sp, $acr	move.d	[$acr], $r13	addoq	+PT_mof, $sp, $acr	move	[$acr], $mof	addoq	+PT_srp, $sp, $acr	move	[$acr], $srp	ba	_syscall_traced	nop	;; Resume performs the actual task-switching, by switching stack	;; pointers. Input arguments are:	;;	;; R10 = prev	;; R11 = next	;; R12 = thread offset in task struct.	;;	;; Returns old current in R10.resume:	subq	4, $sp	move	$srp, [$sp]		; Keep old/new PC on the stack.	add.d	$r12, $r10		; R10 = current tasks tss.	addoq	+THREAD_ccs, $r10, $acr	move	$ccs, [$acr]		; Save IRQ enable state.	di	addoq	+THREAD_usp, $r10, $acr	move	$usp, [$acr]		; Save user-mode stackpointer.	;; See copy_thread for the reason why register R9 is saved.	subq	10*4, $sp	movem	$r9, [$sp]		; Save non-scratch registers and R9.	addoq	+THREAD_ksp, $r10, $acr	move.d	$sp, [$acr]		; Save kernel SP for old task.	move.d	$sp, $r10		; Return last running task in R10.	and.d   -8192, $r10		; Get thread_info from stackpointer.	addoq	+TI_task, $r10, $acr	move.d	[$acr], $r10		; Get task.	add.d	$r12, $r11		; Find the new tasks tss.	addoq	+THREAD_ksp, $r11, $acr	move.d	[$acr], $sp		; Switch to new stackframe.	movem	[$sp+], $r9		; Restore non-scratch registers and R9.	addoq	+THREAD_usp, $r11, $acr	move	[$acr], $usp		; Restore user-mode stackpointer.	addoq	+THREAD_ccs, $r11, $acr	move	[$acr], $ccs		; Restore IRQ enable status.	move.d	[$sp+], $acr	jump	$acr			; Restore PC.	nopnmi_interrupt:;; If we receive a watchdog interrupt while it is not expected, then set;; up a canonical frame and dump register contents before dying.	;; This prologue MUST match the one in irq.h and the struct in ptregs.h!	subq	12, $sp		;  Skip EXS, EDA.	move	$nrp, [$sp]	subq	4, $sp	move	$srp, [$sp]	subq	4, $sp	move	$ccs, [$sp]	subq	4, $sp	move	$spc, [$sp]	subq	4, $sp	move	$mof, [$sp]	subq	4, $sp	move	$srs, [$sp]	subq	4, $sp	move.d	$acr, [$sp]	subq	14*4, $sp		; Make room for R0-R13.	movem	$r13, [$sp]		; Push R0-R13.	subq	4, $sp	move.d	$r10, [$sp]		; Push orig_r10.	move.d  REG_ADDR(intr_vect, regi_irq, r_nmi), $r0	move.d  [$r0], $r0	btstq	REG_BIT(intr_vect, r_nmi, watchdog), $r0	bpl     1f	nop	jsr 	handle_watchdog_bite	; In time.c.        move.d	$sp, $r10		; Pointer to registers1:	btstq	REG_BIT(intr_vect, r_nmi, ext), $r0	bpl     1f	nop	jsr	handle_nmi	move.d	$sp, $r10		; Pointer to registers1:	addq    4, $sp			; Skip orig_r10	movem   [$sp+], $r13	move.d  [$sp+], $acr	move    [$sp], $srs	addq    4, $sp

⌨️ 快捷键说明

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