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

📄 entry.s

📁 microwindows移植到S3C44B0的源码
💻 S
📖 第 1 页 / 共 3 页
字号:
/* * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers, *	and context-switching * *  Copyright (C) 2001,2002  NEC Corporation *  Copyright (C) 2001,2002  Miles Bader <miles@gnu.org> * * 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. * * Written by Miles Bader <miles@gnu.org> */#include <linux/sys.h>#include <asm/entry.h>#include <asm/current.h>#include <asm/clinkage.h>#include <asm/processor.h>#include <asm/irq.h>#include "v850_defs.h"/* Make a slightly more convenient alias for C_SYMBOL_NAME.  */#define CSYM	C_SYMBOL_NAME/* The offset of the struct pt_regs in a `state save frame' on the stack.  */#define PTO	STATE_SAVE_PT_OFFSET/* Save argument registers to the struct pt_regs pointed to by EP.  */#define SAVE_ARG_REGS							      \	sst.w	r6, PTO+PT_GPR(6)[ep];					      \	sst.w	r7, PTO+PT_GPR(7)[ep];					      \	sst.w	r8, PTO+PT_GPR(8)[ep];					      \	sst.w	r9, PTO+PT_GPR(9)[ep];/* Restore argument registers from the struct pt_regs pointed to by EP.  */#define RESTORE_ARG_REGS						      \	sld.w	PTO+PT_GPR(6)[ep], r6;					      \	sld.w	PTO+PT_GPR(7)[ep], r7;					      \	sld.w	PTO+PT_GPR(8)[ep], r8;					      \	sld.w	PTO+PT_GPR(9)[ep], r9;/* Save value return registers to the struct pt_regs pointed to by EP.  */#define SAVE_RVAL_REGS							      \	sst.w	r10, PTO+PT_GPR(10)[ep];				      \	sst.w	r11, PTO+PT_GPR(11)[ep];/* Restore value return registers from the struct pt_regs pointed to by EP.  */#define RESTORE_RVAL_REGS						      \	sld.w	PTO+PT_GPR(10)[ep], r10;				      \	sld.w	PTO+PT_GPR(11)[ep], r11;#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS				      \	sst.w	r1, PTO+PT_GPR(1)[ep];					      \	sst.w	r5, PTO+PT_GPR(5)[ep];#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL				      \	sst.w	r12, PTO+PT_GPR(12)[ep];				      \	sst.w	r13, PTO+PT_GPR(13)[ep];				      \	sst.w	r14, PTO+PT_GPR(14)[ep];				      \	sst.w	r15, PTO+PT_GPR(15)[ep];				      \	sst.w	r16, PTO+PT_GPR(16)[ep];				      \	sst.w	r17, PTO+PT_GPR(17)[ep];				      \	sst.w	r18, PTO+PT_GPR(18)[ep];				      \	sst.w	r19, PTO+PT_GPR(19)[ep];#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS				      \	sld.w	PTO+PT_GPR(1)[ep], r1;					      \	sld.w	PTO+PT_GPR(5)[ep], r5;#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL				      \	sld.w	PTO+PT_GPR(12)[ep], r12;				      \	sld.w	PTO+PT_GPR(13)[ep], r13;				      \	sld.w	PTO+PT_GPR(14)[ep], r14;				      \	sld.w	PTO+PT_GPR(15)[ep], r15;				      \	sld.w	PTO+PT_GPR(16)[ep], r16;				      \	sld.w	PTO+PT_GPR(17)[ep], r17;				      \	sld.w	PTO+PT_GPR(18)[ep], r18;				      \	sld.w	PTO+PT_GPR(19)[ep], r19;/* Save `call clobbered' registers to the struct pt_regs pointed to by EP.  */#define SAVE_CALL_CLOBBERED_REGS					      \	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \	SAVE_ARG_REGS;							      \	SAVE_RVAL_REGS;							      \	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;/* Restore `call clobbered' registers from the struct pt_regs pointed to   by EP.  */#define RESTORE_CALL_CLOBBERED_REGS					      \	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \	RESTORE_ARG_REGS;						      \	RESTORE_RVAL_REGS;						      \	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;/* Save `call clobbered' registers except for the return-value registers   to the struct pt_regs pointed to by EP.  */#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL				      \	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \	SAVE_ARG_REGS;							      \	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;/* Restore `call clobbered' registers except for the return-value registers   from the struct pt_regs pointed to by EP.  */#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL				      \	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \	RESTORE_ARG_REGS;						      \	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;/* Zero `call clobbered' registers except for the return-value registers.  */#define ZERO_CALL_CLOBBERED_REGS_NO_RVAL				      \	mov	r0, r1;   mov	r0, r5;					      \	mov	r0, r12;  mov	r0, r13;  mov	r0, r14;  mov	r0, r15;      \	mov	r0, r16;  mov	r0, r17;  mov	r0, r18;  mov	r0, r19;/* Save `call saved' registers to the struct pt_regs pointed to by EP.  */#define SAVE_CALL_SAVED_REGS						      \	sst.w	r2, PTO+PT_GPR(2)[ep];					      \	sst.w	r20, PTO+PT_GPR(20)[ep];				      \	sst.w	r21, PTO+PT_GPR(21)[ep];				      \	sst.w	r22, PTO+PT_GPR(22)[ep];				      \	sst.w	r23, PTO+PT_GPR(23)[ep];				      \	sst.w	r24, PTO+PT_GPR(24)[ep];				      \	sst.w	r25, PTO+PT_GPR(25)[ep];				      \	sst.w	r26, PTO+PT_GPR(26)[ep];				      \	sst.w	r27, PTO+PT_GPR(27)[ep];				      \	sst.w	r28, PTO+PT_GPR(28)[ep];				      \	sst.w	r29, PTO+PT_GPR(29)[ep];/* Restore `call saved' registers from the struct pt_regs pointed to by EP.  */#define RESTORE_CALL_SAVED_REGS						      \	sld.w	PTO+PT_GPR(2)[ep], r2;					      \	sld.w	PTO+PT_GPR(20)[ep], r20;				      \	sld.w	PTO+PT_GPR(21)[ep], r21;				      \	sld.w	PTO+PT_GPR(22)[ep], r22;				      \	sld.w	PTO+PT_GPR(23)[ep], r23;				      \	sld.w	PTO+PT_GPR(24)[ep], r24;				      \	sld.w	PTO+PT_GPR(25)[ep], r25;				      \	sld.w	PTO+PT_GPR(26)[ep], r26;				      \	sld.w	PTO+PT_GPR(27)[ep], r27;				      \	sld.w	PTO+PT_GPR(28)[ep], r28;				      \	sld.w	PTO+PT_GPR(29)[ep], r29;/* Save system registers to the struct pt_regs pointed to by REG.     r19 is clobbered.  */#define SAVE_SYS_REGS							      \	stsr	SR_EIPC, r19;	/* user's PC, before interrupt */	      \	sst.w	r19, PTO+PT_PC[ep];					      \	stsr	SR_EIPSW, r19;	/* & PSW (XXX save this?) */		      \	sst.w	r19, PTO+PT_PSW[ep];					      \	stsr	SR_CTPC, r19;	/* (XXX maybe not used in kernel?) */	      \	sst.w	r19, PTO+PT_CTPC[ep];					      \	stsr	SR_CTPSW, r19;	/* " */					      \	sst.w	r19, PTO+PT_CTPSW[ep];					      \	stsr	SR_CTBP, r19;	/* " */					      \	sst.w	r19, PTO+PT_CTBP[ep];/* Restore system registers from the struct pt_regs pointed to by EP.     LP is clobbered (it is used as a scratch register because the POP_STATE   macro restores it, and this macro is usually used inside POP_STATE).  */#define RESTORE_SYS_REGS						      \	sld.w	PTO+PT_PC[ep], lp;					      \	ldsr	lp, SR_EIPC;	/* user's PC, before interrupt */	      \	sld.w	PTO+PT_PSW[ep], lp;					      \	ldsr	lp, SR_EIPSW;	/* & PSW (XXX save this?) */		      \	sld.w	PTO+PT_CTPC[ep], lp;					      \	ldsr	lp, SR_CTPC;	/* (XXX maybe not used in kernel?) */	      \	sld.w	PTO+PT_CTPSW[ep], lp;					      \	ldsr	lp, SR_CTPSW;	/* " */					      \	sld.w	PTO+PT_CTBP[ep], lp;					      \	ldsr	lp, SR_CTBP;	/* " *//* Save system registers to the struct pt_regs pointed to by REG.  This is a   NMI-specific version, because NMIs save the PC/PSW in a different place   than other interrupt requests.  r19 is clobbered.  */#define SAVE_SYS_REGS_FOR_NMI						      \	stsr	SR_FEPC, r19;	/* user's PC, before NMI */		      \	sst.w	r19, PTO+PT_PC[ep];					      \	stsr	SR_FEPSW, r19;	/* & PSW (XXX save this?) */		      \	sst.w	r19, PTO+PT_PSW[ep];					      \	stsr	SR_CTPC, r19;	/* (XXX maybe not used in kernel?) */	      \	sst.w	r19, PTO+PT_CTPC[ep];					      \	stsr	SR_CTPSW, r19;	/* " */					      \	sst.w	r19, PTO+PT_CTPSW[ep];					      \	stsr	SR_CTBP, r19;	/* " */					      \	sst.w	r19, PTO+PT_CTBP[ep];/* Restore system registers from the struct pt_regs pointed to by EP.  This is   a NMI-specific version, because NMIs save the PC/PSW in a different place   than other interrupt requests.  LP is clobbered (it is used as a scratch   register because the POP_STATE macro restores it, and this macro is usually   used inside POP_STATE).  */#define RESTORE_SYS_REGS_FOR_NMI					      \	ldsr	lp, SR_FEPC;	/* user's PC, before NMI */		      \	sld.w	PTO+PT_PC[ep], lp;					      \	ldsr	lp, SR_FEPSW;	/* & PSW (XXX save this?) */		      \	sld.w	PTO+PT_PSW[ep], lp;					      \	ldsr	lp, SR_CTPC;	/* (XXX maybe not used in kernel?) */	      \	sld.w	PTO+PT_CTPC[ep], lp;					      \	ldsr	lp, SR_CTPSW;	/* " */					      \	sld.w	PTO+PT_CTPSW[ep], lp;					      \	ldsr	lp, SR_CTBP;	/* " */					      \	sld.w	PTO+PT_CTBP[ep], lp;/* Push register state, except for the stack pointer, on the stack in the form   of a struct pt_regs, in preparation for a system call.  This macro makes   sure that `special' registers, system registers; TYPE identifies the set of   extra registers to be saved as well.  EP is clobbered.  */#define PUSH_STATE(type)						      \	addi	-STATE_SAVE_SIZE, sp, sp; /* Make room on the stack.  */      \	st.w	ep, PTO+PT_GPR(GPR_EP)[sp];				      \	mov	sp, ep;							      \	sst.w	gp, PTO+PT_GPR(GPR_GP)[ep];				      \	sst.w	lp, PTO+PT_GPR(GPR_LP)[ep];				      \	type ## _STATE_SAVER;/* Pop a register state, except for the stack pointer, from the struct pt_regs   on the stack.  */#define POP_STATE(type)							      \	mov	sp, ep;							      \	type ## _STATE_RESTORER;					      \	sld.w	PTO+PT_GPR(GPR_GP)[ep], gp;				      \	sld.w	PTO+PT_GPR(GPR_LP)[ep], lp;				      \	sld.w	PTO+PT_GPR(GPR_EP)[ep], ep;				      \	addi	STATE_SAVE_SIZE, sp, sp; /* Clean up our stack space.  *//* Switch to the kernel stack if necessary, and push register state on   the stack in the form of a struct pt_regs.  Also load the current   task pointer if switching from user mode.  The stack-pointer (r3)   should have already been saved to the memory location SP_SAVE_LOC   (the reason for this is that the interrupt vectors may be beyond a   22-bit signed offset jump from the actual interrupt handler, and this   allows them to save the stack-pointer and use that register to do an   indirect jump).  This macro makes sure that `special' registers,   system registers, and the stack pointer are saved; TYPE identifies   the set of extra registers to be saved as well.  SYSCALL_NUM is the   register in which the system-call number this state is for is stored   (r0 if this isn't a system call).  Interrupts should already be   disabled when calling this.  */#define SAVE_STATE(type, syscall_num, sp_save_loc)			      \        tst1	0, KM;			/* See if already in kernel mode.  */ \	bz	1f;							      \        /* Kernel-mode state save.  */					      \	ld.w	sp_save_loc, sp;	/* Reload kernel stack-pointer.  */   \	st.w	sp, (PT_GPR(GPR_SP)-PT_SIZE)[sp]; /* Save original SP. */     \        PUSH_STATE(type);						      \	mov	1, r19;			/* Was in kernel-mode.  */	      \        sst.w	r19, PTO+PT_KERNEL_MODE[ep]; /* [ep is set by PUSH_STATE] */  \        br	2f;							      \1:      /* User-mode state save.  */					      \        ld.w    KSP, sp;		/* Switch to kernel stack.  */	      \        PUSH_STATE(type);						      \        sst.w	r0, PTO+PT_KERNEL_MODE[ep]; /* Was in user-mode.  */	      \        ld.w    sp_save_loc, r19;				              \	sst.w	r19, PTO+PT_GPR(GPR_SP)[ep]; /* Store user SP.  */	      \	mov	1, r19;							      \	st.b	r19, KM;		/* Now we're in kernel-mode.  */      \	GET_CURRENT_TASK(CURRENT_TASK);	/* Fetch the current task pointer. */ \2:      /* Save away the syscall number.  */				      \        sst.w	syscall_num, PTO+PT_SYSCALL[ep]/* Save register state not normally saved by PUSH_STATE for TYPE.  */#define SAVE_EXTRA_STATE(type)						      \        mov	sp, ep;							      \	type ## _EXTRA_STATE_SAVER;/* Restore register state not normally restored by POP_STATE for TYPE.  */#define RESTORE_EXTRA_STATE(type)					      \        mov	sp, ep;							      \	type ## _EXTRA_STATE_RESTORER;/* Save any call-clobbered registers not normally saved by PUSH_STATE   for TYPE.  */#define SAVE_EXTRA_STATE_FOR_FUNCALL(type)				      \        mov	sp, ep;							      \	type ## _FUNCALL_EXTRA_STATE_SAVER;/* Restore any call-clobbered registers not normally restored by POP_STATE for   TYPE.  */#define RESTORE_EXTRA_STATE_FOR_FUNCALL(type)				      \        mov	sp, ep;							      \	type ## _FUNCALL_EXTRA_STATE_RESTORER;/* These are extra_state_saver/restorer values for a user trap.  Note that we   save the argument registers so that restarted syscalls will function   properly (otherwise it wouldn't be necessary), and we must _not_ restore   the return-value registers (so that traps can return a value!), but there   are various options for what happens to other call-clobbered registers,   selected by preprocessor conditionals.  */#if TRAPS_PRESERVE_CALL_CLOBBERED_REGS   /* Traps save/restore all call-clobbered registers (except for rval regs).  */#define TRAP_STATE_SAVER						      \     SAVE_CALL_CLOBBERED_REGS_NO_RVAL;					      \     SAVE_SYS_REGS#define TRAP_STATE_RESTORER						      \     RESTORE_CALL_CLOBBERED_REGS_NO_RVAL;				      \     RESTORE_SYS_REGS#else /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS *//* Traps don't save call-clobbered registers (but do still save arg regs).  */#define TRAP_STATE_SAVER						      \     SAVE_ARG_REGS;							      \     SAVE_SYS_REGS#if TRAPS_ZERO_CALL_CLOBBERED_REGS   /* Traps zero call-clobbered registers (except for arg/rval regs) before   returning from a system call, to avoid any internal values from leaking out   of the kernel.  */#define TRAP_STATE_RESTORER						      \     ZERO_CALL_CLOBBERED_REGS_NO_ARGS_NO_RVAL;				      \     RESTORE_ARG_REGS;							      \     RESTORE_SYS_REGS#else /* !TRAPS_ZERO_CALL_CLOBBERED_REGS */   /* When traps return, they just leave call-clobbered registers (except for arg   regs) with whatever value they have from the kernel.  */#define TRAP_STATE_RESTORER						      \     RESTORE_ARG_REGS;							      \     RESTORE_SYS_REGS#endif /* TRAPS_ZERO_CALL_CLOBBERED_REGS */#endif /* TRAPS_PRESERVE_CALL_CLOBBERED_REGS *//* Save registers not normally saved by traps.  */#define TRAP_EXTRA_STATE_SAVER						      \   SAVE_RVAL_REGS;							      \   SAVE_CALL_SAVED_REGS#define TRAP_EXTRA_STATE_RESTORER					      \   RESTORE_RVAL_REGS;							      \   RESTORE_CALL_SAVED_REGS#define TRAP_FUNCALL_EXTRA_STATE_SAVER					      \   SAVE_RVAL_REGS#define TRAP_FUNCALL_EXTRA_STATE_RESTORER				      \   RESTORE_RVAL_REGS/* Register saving/restoring for maskable interrupts.  */#define IRQ_STATE_SAVER							      \   SAVE_CALL_CLOBBERED_REGS;						      \   SAVE_SYS_REGS

⌨️ 快捷键说明

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