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

📄 entry_64.s

📁 linux-2.6.15.6
💻 S
📖 第 1 页 / 共 2 页
字号:
/* *  arch/ppc64/kernel/entry.S * *  PowerPC version  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> *  Adapted for Power Macintosh by Paul Mackerras. *  Low-level exception handlers and MMU support *  rewritten by Paul Mackerras. *    Copyright (C) 1996 Paul Mackerras. *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). * *  This file contains the system call entry code, context switch *  code, and exception/interrupt return code for PowerPC. * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version *  2 of the License, or (at your option) any later version. */#include <linux/config.h>#include <linux/errno.h>#include <asm/unistd.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/thread_info.h>#include <asm/ppc_asm.h>#include <asm/asm-offsets.h>#include <asm/cputable.h>#ifdef CONFIG_PPC_ISERIES#define DO_SOFT_DISABLE#endif/* * System calls. */	.section	".toc","aw".SYS_CALL_TABLE:	.tc .sys_call_table[TC],.sys_call_table/* This value is used to mark exception frames on the stack. */exception_marker:	.tc	ID_72656773_68657265[TC],0x7265677368657265	.section	".text"	.align 7#undef SHOW_SYSCALLS	.globl system_call_commonsystem_call_common:	andi.	r10,r12,MSR_PR	mr	r10,r1	addi	r1,r1,-INT_FRAME_SIZE	beq-	1f	ld	r1,PACAKSAVE(r13)1:	std	r10,0(r1)	std	r11,_NIP(r1)	std	r12,_MSR(r1)	std	r0,GPR0(r1)	std	r10,GPR1(r1)	std	r2,GPR2(r1)	std	r3,GPR3(r1)	std	r4,GPR4(r1)	std	r5,GPR5(r1)	std	r6,GPR6(r1)	std	r7,GPR7(r1)	std	r8,GPR8(r1)	li	r11,0	std	r11,GPR9(r1)	std	r11,GPR10(r1)	std	r11,GPR11(r1)	std	r11,GPR12(r1)	std	r9,GPR13(r1)	crclr	so	mfcr	r9	mflr	r10	li	r11,0xc01	std	r9,_CCR(r1)	std	r10,_LINK(r1)	std	r11,_TRAP(r1)	mfxer	r9	mfctr	r10	std	r9,_XER(r1)	std	r10,_CTR(r1)	std	r3,ORIG_GPR3(r1)	ld	r2,PACATOC(r13)	addi	r9,r1,STACK_FRAME_OVERHEAD	ld	r11,exception_marker@toc(r2)	std	r11,-16(r9)		/* "regshere" marker */#ifdef CONFIG_PPC_ISERIES	/* Hack for handling interrupts when soft-enabling on iSeries */	cmpdi	cr1,r0,0x5555		/* syscall 0x5555 */	andi.	r10,r12,MSR_PR		/* from kernel */	crand	4*cr0+eq,4*cr1+eq,4*cr0+eq	beq	hardware_interrupt_entry	lbz	r10,PACAPROCENABLED(r13)	std	r10,SOFTE(r1)#endif	mfmsr	r11	ori	r11,r11,MSR_EE	mtmsrd	r11,1#ifdef SHOW_SYSCALLS	bl	.do_show_syscall	REST_GPR(0,r1)	REST_4GPRS(3,r1)	REST_2GPRS(7,r1)	addi	r9,r1,STACK_FRAME_OVERHEAD#endif	clrrdi	r11,r1,THREAD_SHIFT	li	r12,0	ld	r10,TI_FLAGS(r11)	stb	r12,TI_SC_NOERR(r11)	andi.	r11,r10,_TIF_SYSCALL_T_OR_A	bne-	syscall_dotracesyscall_dotrace_cont:	cmpldi	0,r0,NR_syscalls	bge-	syscall_enosyssystem_call:			/* label this so stack traces look sane *//* * Need to vector to 32 Bit or default sys_call_table here, * based on caller's run-mode / personality. */	ld	r11,.SYS_CALL_TABLE@toc(2)	andi.	r10,r10,_TIF_32BIT	beq	15f	addi	r11,r11,8	/* use 32-bit syscall entries */	clrldi	r3,r3,32	clrldi	r4,r4,32	clrldi	r5,r5,32	clrldi	r6,r6,32	clrldi	r7,r7,32	clrldi	r8,r8,3215:	slwi	r0,r0,4	ldx	r10,r11,r0	/* Fetch system call handler [ptr] */	mtctr   r10	bctrl			/* Call handler */syscall_exit:#ifdef SHOW_SYSCALLS	std	r3,GPR3(r1)	bl	.do_show_syscall_exit	ld	r3,GPR3(r1)#endif	std	r3,RESULT(r1)	ld	r5,_CCR(r1)	li	r10,-_LAST_ERRNO	cmpld	r3,r10	clrrdi	r12,r1,THREAD_SHIFT	bge-	syscall_errorsyscall_error_cont:	/* check for syscall tracing or audit */	ld	r9,TI_FLAGS(r12)	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)	bne-	syscall_exit_tracesyscall_exit_trace_cont:	/* disable interrupts so current_thread_info()->flags can't change,	   and so that we don't get interrupted after loading SRR0/1. */	ld	r8,_MSR(r1)	andi.	r10,r8,MSR_RI	beq-	unrecov_restore	mfmsr	r10	rldicl	r10,r10,48,1	rotldi	r10,r10,16	mtmsrd	r10,1	ld	r9,TI_FLAGS(r12)	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)	bne-	syscall_exit_work	ld	r7,_NIP(r1)	stdcx.	r0,0,r1			/* to clear the reservation */	andi.	r6,r8,MSR_PR	ld	r4,_LINK(r1)	beq-	1f			/* only restore r13 if */	ld	r13,GPR13(r1)		/* returning to usermode */1:	ld	r2,GPR2(r1)	li	r12,MSR_RI	andc	r11,r10,r12	mtmsrd	r11,1			/* clear MSR.RI */	ld	r1,GPR1(r1)	mtlr	r4	mtcr	r5	mtspr	SPRN_SRR0,r7	mtspr	SPRN_SRR1,r8	rfid	b	.	/* prevent speculative execution */syscall_enosys:	li	r3,-ENOSYS	std	r3,RESULT(r1)	clrrdi	r12,r1,THREAD_SHIFT	ld	r5,_CCR(r1)syscall_error:	lbz	r11,TI_SC_NOERR(r12)	cmpwi	0,r11,0	bne-	syscall_error_cont	neg	r3,r3	oris	r5,r5,0x1000	/* Set SO bit in CR */	std	r5,_CCR(r1)	b	syscall_error_cont        /* Traced system call support */syscall_dotrace:	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.do_syscall_trace_enter	ld	r0,GPR0(r1)	/* Restore original registers */	ld	r3,GPR3(r1)	ld	r4,GPR4(r1)	ld	r5,GPR5(r1)	ld	r6,GPR6(r1)	ld	r7,GPR7(r1)	ld	r8,GPR8(r1)	addi	r9,r1,STACK_FRAME_OVERHEAD	clrrdi	r10,r1,THREAD_SHIFT	ld	r10,TI_FLAGS(r10)	b	syscall_dotrace_contsyscall_exit_trace:	std	r3,GPR3(r1)	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.do_syscall_trace_leave	REST_NVGPRS(r1)	ld	r3,GPR3(r1)	ld	r5,_CCR(r1)	clrrdi	r12,r1,THREAD_SHIFT	b	syscall_exit_trace_cont/* Stuff to do on exit from a system call. */syscall_exit_work:	std	r3,GPR3(r1)	std	r5,_CCR(r1)	b	.ret_from_except_lite/* Save non-volatile GPRs, if not already saved. */_GLOBAL(save_nvgprs)	ld	r11,_TRAP(r1)	andi.	r0,r11,1	beqlr-	SAVE_NVGPRS(r1)	clrrdi	r0,r11,1	std	r0,_TRAP(r1)	blr/* * The sigsuspend and rt_sigsuspend system calls can call do_signal * and thus put the process into the stopped state where we might * want to examine its user state with ptrace.  Therefore we need * to save all the nonvolatile registers (r14 - r31) before calling * the C code.  Similarly, fork, vfork and clone need the full * register state on the stack so that it can be copied to the child. */_GLOBAL(ppc32_sigsuspend)	bl	.save_nvgprs	bl	.compat_sys_sigsuspend	b	70f_GLOBAL(ppc64_rt_sigsuspend)	bl	.save_nvgprs	bl	.sys_rt_sigsuspend	b	70f_GLOBAL(ppc32_rt_sigsuspend)	bl	.save_nvgprs	bl	.compat_sys_rt_sigsuspend70:	cmpdi	0,r3,0	/* If it returned an error, we need to return via syscall_exit to set	   the SO bit in cr0 and potentially stop for ptrace. */	bne	syscall_exit	/* If sigsuspend() returns zero, we are going into a signal handler. We	   may need to call audit_syscall_exit() to mark the exit from sigsuspend() */#ifdef CONFIG_AUDITSYSCALL	ld	r3,PACACURRENT(r13)	ld	r4,AUDITCONTEXT(r3)	cmpdi	0,r4,0	beq	.ret_from_except	/* No audit_context: Leave immediately. */	li	r4, 2			/* AUDITSC_FAILURE */	li	r5,-4			/* It's always -EINTR */	bl	.audit_syscall_exit#endif	b	.ret_from_except_GLOBAL(ppc_fork)	bl	.save_nvgprs	bl	.sys_fork	b	syscall_exit_GLOBAL(ppc_vfork)	bl	.save_nvgprs	bl	.sys_vfork	b	syscall_exit_GLOBAL(ppc_clone)	bl	.save_nvgprs	bl	.sys_clone	b	syscall_exit_GLOBAL(ppc32_swapcontext)	bl	.save_nvgprs	bl	.compat_sys_swapcontext	b	80f	_GLOBAL(ppc64_swapcontext)	bl	.save_nvgprs	bl	.sys_swapcontext	b	80f_GLOBAL(ppc32_sigreturn)	bl	.compat_sys_sigreturn	b	80f_GLOBAL(ppc32_rt_sigreturn)	bl	.compat_sys_rt_sigreturn	b	80f_GLOBAL(ppc64_rt_sigreturn)	bl	.sys_rt_sigreturn80:	cmpdi	0,r3,0	blt	syscall_exit	clrrdi	r4,r1,THREAD_SHIFT	ld	r4,TI_FLAGS(r4)	andi.	r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)	beq+	81f	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.do_syscall_trace_leave81:	b	.ret_from_except_GLOBAL(ret_from_fork)	bl	.schedule_tail	REST_NVGPRS(r1)	li	r3,0	b	syscall_exit/* * This routine switches between two different tasks.  The process * state of one is saved on its kernel stack.  Then the state * of the other is restored from its kernel stack.  The memory * management hardware is updated to the second process's state. * Finally, we can return to the second process, via ret_from_except. * On entry, r3 points to the THREAD for the current task, r4 * points to the THREAD for the new task. * * Note: there are two ways to get to the "going out" portion * of this code; either by coming in via the entry (_switch) * or via "fork" which must set up an environment equivalent * to the "_switch" path.  If you change this you'll have to change * the fork code also. * * The code which creates the new task context is in 'copy_thread' * in arch/ppc64/kernel/process.c */	.align	7_GLOBAL(_switch)	mflr	r0	std	r0,16(r1)	stdu	r1,-SWITCH_FRAME_SIZE(r1)	/* r3-r13 are caller saved -- Cort */	SAVE_8GPRS(14, r1)	SAVE_10GPRS(22, r1)	mflr	r20		/* Return to switch caller */	mfmsr	r22	li	r0, MSR_FP#ifdef CONFIG_ALTIVECBEGIN_FTR_SECTION	oris	r0,r0,MSR_VEC@h	/* Disable altivec */	mfspr	r24,SPRN_VRSAVE	/* save vrsave register value */	std	r24,THREAD_VRSAVE(r3)END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)#endif /* CONFIG_ALTIVEC */	and.	r0,r0,r22	beq+	1f	andc	r22,r22,r0	mtmsrd	r22	isync1:	std	r20,_NIP(r1)	mfcr	r23	std	r23,_CCR(r1)	std	r1,KSP(r3)	/* Set old stack pointer */#ifdef CONFIG_SMP	/* We need a sync somewhere here to make sure that if the	 * previous task gets rescheduled on another CPU, it sees all	 * stores it has performed on this one.	 */	sync#endif /* CONFIG_SMP */	addi	r6,r4,-THREAD	/* Convert THREAD to 'current' */	std	r6,PACACURRENT(r13)	/* Set new 'current' */	ld	r8,KSP(r4)	/* new stack pointer */BEGIN_FTR_SECTION	clrrdi	r6,r8,28	/* get its ESID */	clrrdi	r9,r1,28	/* get current sp ESID */	clrldi.	r0,r6,2		/* is new ESID c00000000? */	cmpd	cr1,r6,r9	/* or is new ESID the same as current ESID? */	cror	eq,4*cr1+eq,eq	beq	2f		/* if yes, don't slbie it */	/* Bolt in the new stack SLB entry */	ld	r7,KSP_VSID(r4)	/* Get new stack's VSID */	oris	r0,r6,(SLB_ESID_V)@h	ori	r0,r0,(SLB_NUM_BOLTED-1)@l	slbie	r6	slbie	r6		/* Workaround POWER5 < DD2.1 issue */	slbmte	r7,r0	isync2:END_FTR_SECTION_IFSET(CPU_FTR_SLB)	clrrdi	r7,r8,THREAD_SHIFT	/* base of new stack */

⌨️ 快捷键说明

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