head_64.s

来自「LINUX 2.6.17.4的源码」· S 代码 · 共 2,003 行 · 第 1/4 页

S
2,003
字号
	DISABLE_INTS	bl	.save_nvgprs1:	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.unrecoverable_exception	b	1b#endif /* __DISABLED__ *//* * r13 points to the PACA, r9 contains the saved CR, * r12 contain the saved SRR1, SRR0 is still ready for return * r3 has the faulting address * r9 - r13 are saved in paca->exslb. * r3 is saved in paca->slb_r3 * We assume we aren't going to take any exceptions during this procedure. */_GLOBAL(slb_miss_realmode)	mflr	r10	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */	bl	.slb_allocate_realmode	/* All done -- return from exception. */	ld	r10,PACA_EXSLB+EX_LR(r13)	ld	r3,PACA_EXSLB+EX_R3(r13)	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */#ifdef CONFIG_PPC_ISERIES	ld	r11,PACALPPACAPTR(r13)	ld	r11,LPPACASRR0(r11)		/* get SRR0 value */#endif /* CONFIG_PPC_ISERIES */	mtlr	r10	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */	beq-	unrecov_slb.machine	push.machine	"power4"	mtcrf	0x80,r9	mtcrf	0x01,r9		/* slb_allocate uses cr0 and cr7 */.machine	pop#ifdef CONFIG_PPC_ISERIES	mtspr	SPRN_SRR0,r11	mtspr	SPRN_SRR1,r12#endif /* CONFIG_PPC_ISERIES */	ld	r9,PACA_EXSLB+EX_R9(r13)	ld	r10,PACA_EXSLB+EX_R10(r13)	ld	r11,PACA_EXSLB+EX_R11(r13)	ld	r12,PACA_EXSLB+EX_R12(r13)	ld	r13,PACA_EXSLB+EX_R13(r13)	rfid	b	.	/* prevent speculative execution */unrecov_slb:	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)	DISABLE_INTS	bl	.save_nvgprs1:	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.unrecoverable_exception	b	1b	.align	7	.globl hardware_interrupt_common	.globl hardware_interrupt_entryhardware_interrupt_common:	EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)	FINISH_NAPhardware_interrupt_entry:	DISABLE_INTS	bl	.ppc64_runlatch_on	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.do_IRQ	b	.ret_from_except_lite#ifdef CONFIG_PPC_970_NAPpower4_fixup_nap:	andc	r9,r9,r10	std	r9,TI_LOCAL_FLAGS(r11)	ld	r10,_LINK(r1)		/* make idle task do the */	std	r10,_NIP(r1)		/* equivalent of a blr */	blr#endif	.align	7	.globl alignment_commonalignment_common:	mfspr	r10,SPRN_DAR	std	r10,PACA_EXGEN+EX_DAR(r13)	mfspr	r10,SPRN_DSISR	stw	r10,PACA_EXGEN+EX_DSISR(r13)	EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)	ld	r3,PACA_EXGEN+EX_DAR(r13)	lwz	r4,PACA_EXGEN+EX_DSISR(r13)	std	r3,_DAR(r1)	std	r4,_DSISR(r1)	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	ENABLE_INTS	bl	.alignment_exception	b	.ret_from_except	.align	7	.globl program_check_commonprogram_check_common:	EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	ENABLE_INTS	bl	.program_check_exception	b	.ret_from_except	.align	7	.globl fp_unavailable_commonfp_unavailable_common:	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)	bne	.load_up_fpu		/* if from user, just load it up */	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	ENABLE_INTS	bl	.kernel_fp_unavailable_exception	BUG_OPCODE	.align	7	.globl altivec_unavailable_commonaltivec_unavailable_common:	EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)#ifdef CONFIG_ALTIVECBEGIN_FTR_SECTION	bne	.load_up_altivec	/* if from user, just load it up */END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)#endif	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	ENABLE_INTS	bl	.altivec_unavailable_exception	b	.ret_from_except#ifdef CONFIG_ALTIVEC/* * load_up_altivec(unused, unused, tsk) * Disable VMX for the task which had it previously, * and save its vector registers in its thread_struct. * Enables the VMX for use in the kernel on return. * On SMP we know the VMX is free, since we give it up every * switch (ie, no lazy save of the vector registers). * On entry: r13 == 'current' && last_task_used_altivec != 'current' */_STATIC(load_up_altivec)	mfmsr	r5			/* grab the current MSR */	oris	r5,r5,MSR_VEC@h	mtmsrd	r5			/* enable use of VMX now */	isync/* * For SMP, we don't do lazy VMX switching because it just gets too * horrendously complex, especially when a task switches from one CPU * to another.  Instead we call giveup_altvec in switch_to. * VRSAVE isn't dealt with here, that is done in the normal context * switch code. Note that we could rely on vrsave value to eventually * avoid saving all of the VREGs here... */#ifndef CONFIG_SMP	ld	r3,last_task_used_altivec@got(r2)	ld	r4,0(r3)	cmpdi	0,r4,0	beq	1f	/* Save VMX state to last_task_used_altivec's THREAD struct */	addi	r4,r4,THREAD	SAVE_32VRS(0,r5,r4)	mfvscr	vr0	li	r10,THREAD_VSCR	stvx	vr0,r10,r4	/* Disable VMX for last_task_used_altivec */	ld	r5,PT_REGS(r4)	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)	lis	r6,MSR_VEC@h	andc	r4,r4,r6	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)1:#endif /* CONFIG_SMP */	/* Hack: if we get an altivec unavailable trap with VRSAVE	 * set to all zeros, we assume this is a broken application	 * that fails to set it properly, and thus we switch it to	 * all 1's	 */	mfspr	r4,SPRN_VRSAVE	cmpdi	0,r4,0	bne+	1f	li	r4,-1	mtspr	SPRN_VRSAVE,r41:	/* enable use of VMX after return */	ld	r4,PACACURRENT(r13)	addi	r5,r4,THREAD		/* Get THREAD */	oris	r12,r12,MSR_VEC@h	std	r12,_MSR(r1)	li	r4,1	li	r10,THREAD_VSCR	stw	r4,THREAD_USED_VR(r5)	lvx	vr0,r10,r5	mtvscr	vr0	REST_32VRS(0,r4,r5)#ifndef CONFIG_SMP	/* Update last_task_used_math to 'current' */	subi	r4,r5,THREAD		/* Back to 'current' */	std	r4,0(r3)#endif /* CONFIG_SMP */	/* restore registers and return */	b	fast_exception_return#endif /* CONFIG_ALTIVEC *//* * Hash table stuff */	.align	7_GLOBAL(do_hash_page)	std	r3,_DAR(r1)	std	r4,_DSISR(r1)	andis.	r0,r4,0xa450		/* weird error? */	bne-	.handle_page_fault	/* if not, try to insert a HPTE */BEGIN_FTR_SECTION	andis.	r0,r4,0x0020		/* Is it a segment table fault? */	bne-	.do_ste_alloc		/* If so handle it */END_FTR_SECTION_IFCLR(CPU_FTR_SLB)	/*	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are	 * accessing a userspace segment (even from the kernel). We assume	 * kernel addresses always have the high bit set.	 */	rlwinm	r4,r4,32-25+9,31-9,31-9	/* DSISR_STORE -> _PAGE_RW */	rotldi	r0,r3,15		/* Move high bit into MSR_PR posn */	orc	r0,r12,r0		/* MSR_PR | ~high_bit */	rlwimi	r4,r0,32-13,30,30	/* becomes _PAGE_USER access bit */	ori	r4,r4,1			/* add _PAGE_PRESENT */	rlwimi	r4,r5,22+2,31-2,31-2	/* Set _PAGE_EXEC if trap is 0x400 */	/*	 * On iSeries, we soft-disable interrupts here, then	 * hard-enable interrupts so that the hash_page code can spin on	 * the hash_table_lock without problems on a shared processor.	 */	DISABLE_INTS	/*	 * r3 contains the faulting address	 * r4 contains the required access permissions	 * r5 contains the trap number	 *	 * at return r3 = 0 for success	 */	bl	.hash_page		/* build HPTE if possible */	cmpdi	r3,0			/* see if hash_page succeeded */#ifdef DO_SOFT_DISABLE	/*	 * If we had interrupts soft-enabled at the point where the	 * DSI/ISI occurred, and an interrupt came in during hash_page,	 * handle it now.	 * We jump to ret_from_except_lite rather than fast_exception_return	 * because ret_from_except_lite will check for and handle pending	 * interrupts if necessary.	 */	beq	.ret_from_except_lite	/* For a hash failure, we don't bother re-enabling interrupts */	ble-	12f	/*	 * hash_page couldn't handle it, set soft interrupt enable back	 * to what it was before the trap.  Note that .local_irq_restore	 * handles any interrupts pending at this point.	 */	ld	r3,SOFTE(r1)	bl	.local_irq_restore	b	11f#else	beq	fast_exception_return   /* Return from exception on success */	ble-	12f			/* Failure return from hash_page */	/* fall through */#endif/* Here we have a page fault that hash_page can't handle. */_GLOBAL(handle_page_fault)	ENABLE_INTS11:	ld	r4,_DAR(r1)	ld	r5,_DSISR(r1)	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.do_page_fault	cmpdi	r3,0	beq+	.ret_from_except_lite	bl	.save_nvgprs	mr	r5,r3	addi	r3,r1,STACK_FRAME_OVERHEAD	lwz	r4,_DAR(r1)	bl	.bad_page_fault	b	.ret_from_except/* We have a page fault that hash_page could handle but HV refused * the PTE insertion */12:	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	lwz	r4,_DAR(r1)	bl	.low_hash_fault	b	.ret_from_except	/* here we have a segment miss */_GLOBAL(do_ste_alloc)	bl	.ste_allocate		/* try to insert stab entry */	cmpdi	r3,0	beq+	fast_exception_return	b	.handle_page_fault/* * r13 points to the PACA, r9 contains the saved CR, * r11 and r12 contain the saved SRR0 and SRR1. * r9 - r13 are saved in paca->exslb. * We assume we aren't going to take any exceptions during this procedure. * We assume (DAR >> 60) == 0xc. */	.align	7_GLOBAL(do_stab_bolted)	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */	/* Hash to the primary group */	ld	r10,PACASTABVIRT(r13)	mfspr	r11,SPRN_DAR	srdi	r11,r11,28	rldimi	r10,r11,7,52	/* r10 = first ste of the group */	/* Calculate VSID */	/* This is a kernel address, so protovsid = ESID */	ASM_VSID_SCRAMBLE(r11, r9)	rldic	r9,r11,12,16	/* r9 = vsid << 12 */	/* Search the primary group for a free entry */1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/	andi.	r11,r11,0x80	beq	2f	addi	r10,r10,16	andi.	r11,r10,0x70	bne	1b	/* Stick for only searching the primary group for now.		*/	/* At least for now, we use a very simple random castout scheme */	/* Use the TB as a random number ;  OR in 1 to avoid entry 0	*/	mftb	r11	rldic	r11,r11,4,57	/* r11 = (r11 << 4) & 0x70 */	ori	r11,r11,0x10	/* r10 currently points to an ste one past the group of interest */	/* make it point to the randomly selected entry			*/	subi	r10,r10,128	or 	r10,r10,r11	/* r10 is the entry to invalidate	*/	isync			/* mark the entry invalid		*/	ld	r11,0(r10)	rldicl	r11,r11,56,1	/* clear the valid bit */	rotldi	r11,r11,8	std	r11,0(r10)	sync	clrrdi	r11,r11,28	/* Get the esid part of the ste		*/	slbie	r112:	std	r9,8(r10)	/* Store the vsid part of the ste	*/	eieio	mfspr	r11,SPRN_DAR		/* Get the new esid			*/	clrrdi	r11,r11,28	/* Permits a full 32b of ESID		*/	ori	r11,r11,0x90	/* Turn on valid and kp			*/	std	r11,0(r10)	/* Put new entry back into the stab	*/	sync	/* All done -- return from exception. */	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */	andi.	r10,r12,MSR_RI	beq-	unrecov_slb	mtcrf	0x80,r9			/* restore CR */	mfmsr	r10	clrrdi	r10,r10,2	mtmsrd	r10,1	mtspr	SPRN_SRR0,r11	mtspr	SPRN_SRR1,r12	ld	r9,PACA_EXSLB+EX_R9(r13)	ld	r10,PACA_EXSLB+EX_R10(r13)	ld	r11,PACA_EXSLB+EX_R11(r13)	ld	r12,PACA_EXSLB+EX_R12(r13)	ld	r13,PACA_EXSLB+EX_R13(r13)	rfid	b	.	/* prevent speculative execution *//* * Space for CPU0's segment table. * * On iSeries, the hypervisor must fill in at least one entry before * we get control (with relocate on).  The address is give to the hv * as a page number (see xLparMap in lpardata.c), so this must be at a * fixed address (the linker can't compute (u64)&initial_stab >> * PAGE_SHIFT). */	. = STAB0_OFFSET	/* 0x6000 */	.globl initial_stabinitial_stab:	.space	4096/* * Data area reserved for FWNMI option. * This address (0x7000) is fixed by the RPA. */	.= 0x7000	.globl fwnmi_data_areafwnmi_data_area:	/* iSeries does not use the FWNMI stuff, so it is safe to put	 * this here, even if we later allow kernels that will boot on	 * both pSeries and iSeries */#ifdef CONFIG_PPC_ISERIES        . = LPARMAP_PHYS#include "lparmap.s"/* * This ".text" is here for old compilers that generate a trailing * .note section when compiling .c files to .s */	.text#endif /* CONFIG_PPC_ISERIES */        . = 0x8000/* * On pSeries, secondary processors spin in the following code. * At entry, r3 = this processor's number (physical cpu id) */_GLOBAL(pSeries_secondary_smp_init)	mr	r24,r3		/* turn on 64-bit mode */	bl	.enable_64b_mode	isync	/* Copy some CPU settings from CPU 0 */	bl	.__restore_cpu_setup	/* Set up a paca value for this processor. Since we have the	 * physical cpu id in r24, we need to search the pacas to find	 * which logical id maps to our physical one.	 */	LOAD_REG_IMMEDIATE(r13, paca)	/* Get base vaddr of paca array	 */	li	r5,0			/* logical cpu id                */1:	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */	cmpw	r6,r24			/* Compare to our id             */	beq	2f	addi	r13,r13,PACA_SIZE	/* Loop to next PACA on miss     */	addi	r5,r5,1	cmpwi	r5,NR_CPUS	blt	1b	mr	r3,r24			/* not found, copy phys to r3	 */	b	.kexec_wait		/* next kernel might do better	 */2:	mtspr	SPRN_SPRG3,r13		/* Save vaddr of paca in SPRG3	 */	/* From now on, r24 is expected to be logical cpuid */	mr	r24,r53:	HMT_LOW	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor should */					/* start.			 */	sync	/* Create a temp kernel stack for use before relocation is on.	*/	ld	r1,PACAEMERGSP(r13)	subi	r1,r1,STACK_FRAME_OVERHEAD	cmpwi	0,r23,0#ifdef CONFIG_SMP	bne	.__secondary_start#endif	b 	3b			/* Loop until told to go	 */#ifdef CONFIG_PPC_ISERIES_STATIC(__start_initialization_iSeries)	/* Clear out the BSS */	LOAD_REG_IMMEDIATE(r11,__bss_stop)	LOAD_REG_IMMEDIATE(r8,__bss_start)	sub	r11,r11,r8		/* bss size			*/	addi	r11,r11,7		/* round up to an even double word */	rldicl. r11,r11,61,3		/* shift right by 3		*/	beq	4f

⌨️ 快捷键说明

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