diff options
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
| -rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 565 | 
1 files changed, 426 insertions, 139 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 7778d6f0c87..8f35cd7d59c 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -46,6 +46,41 @@  #define EX_CCR		60  #define EX_R3		64  #define EX_LR		72 +#define EX_CFAR		80 +#define EX_PPR		88	/* SMT thread status register (priority) */ +#define EX_CTR		96 + +#ifdef CONFIG_RELOCATABLE +#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\ +	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\ +	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\ +	LOAD_HANDLER(r12,label);					\ +	mtctr	r12;							\ +	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\ +	li	r10,MSR_RI;						\ +	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\ +	bctr; +#else +/* If not relocatable, we can jump directly -- and save messing with LR */ +#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\ +	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\ +	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\ +	li	r10,MSR_RI;						\ +	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\ +	b	label; +#endif +#define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\ +	__EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\ + +/* + * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on + * so no need to rfid.  Save lr in case we're CONFIG_RELOCATABLE, in which + * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. + */ +#define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec)	\ +	EXCEPTION_PROLOG_0(area);					\ +	EXCEPTION_PROLOG_1(area, extra, vec);				\ +	EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)  /*   * We're short on space and time in the exception prolog, so we can't @@ -54,32 +89,192 @@   * word.   */  #define LOAD_HANDLER(reg, label)					\ -	addi	reg,reg,(label)-_stext;	/* virt addr of handler ... */ +	/* Handlers must be within 64K of kbase, which must be 64k aligned */ \ +	ori	reg,reg,(label)-_stext;	/* virt addr of handler ... */ + +/* Exception register prefixes */ +#define EXC_HV	H +#define EXC_STD + +#if defined(CONFIG_RELOCATABLE) +/* + * If we support interrupts with relocation on AND we're a relocatable kernel, + * we need to use CTR to get to the 2nd level handler.  So, save/restore it + * when required. + */ +#define SAVE_CTR(reg, area)	mfctr	reg ; 	std	reg,area+EX_CTR(r13) +#define GET_CTR(reg, area) 			ld	reg,area+EX_CTR(r13) +#define RESTORE_CTR(reg, area)	ld	reg,area+EX_CTR(r13) ; mtctr reg +#else +/* ...else CTR is unused and in register. */ +#define SAVE_CTR(reg, area) +#define GET_CTR(reg, area) 	mfctr	reg +#define RESTORE_CTR(reg, area) +#endif + +/* + * PPR save/restore macros used in exceptions_64s.S   + * Used for P7 or later processors + */ +#define SAVE_PPR(area, ra, rb)						\ +BEGIN_FTR_SECTION_NESTED(940)						\ +	ld	ra,PACACURRENT(r13);					\ +	ld	rb,area+EX_PPR(r13);	/* Read PPR from paca */	\ +	std	rb,TASKTHREADPPR(ra);					\ +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) + +#define RESTORE_PPR_PACA(area, ra)					\ +BEGIN_FTR_SECTION_NESTED(941)						\ +	ld	ra,area+EX_PPR(r13);					\ +	mtspr	SPRN_PPR,ra;						\ +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,941) + +/* + * Increase the priority on systems where PPR save/restore is not + * implemented/ supported. + */ +#define HMT_MEDIUM_PPR_DISCARD						\ +BEGIN_FTR_SECTION_NESTED(942)						\ +	HMT_MEDIUM;							\ +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,0,942)  /*non P7*/		 + +/* + * Get an SPR into a register if the CPU has the given feature + */ +#define OPT_GET_SPR(ra, spr, ftr)					\ +BEGIN_FTR_SECTION_NESTED(943)						\ +	mfspr	ra,spr;							\ +END_FTR_SECTION_NESTED(ftr,ftr,943) + +/* + * Set an SPR from a register if the CPU has the given feature + */ +#define OPT_SET_SPR(ra, spr, ftr)					\ +BEGIN_FTR_SECTION_NESTED(943)						\ +	mtspr	spr,ra;							\ +END_FTR_SECTION_NESTED(ftr,ftr,943) + +/* + * Save a register to the PACA if the CPU has the given feature + */ +#define OPT_SAVE_REG_TO_PACA(offset, ra, ftr)				\ +BEGIN_FTR_SECTION_NESTED(943)						\ +	std	ra,offset(r13);						\ +END_FTR_SECTION_NESTED(ftr,ftr,943) + +#define EXCEPTION_PROLOG_0(area)					\ +	GET_PACA(r13);							\ +	std	r9,area+EX_R9(r13);	/* save r9 */			\ +	OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);			\ +	HMT_MEDIUM;							\ +	std	r10,area+EX_R10(r13);	/* save r10 - r12 */		\ +	OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR) -#define EXCEPTION_PROLOG_1(area)				\ -	mfspr	r13,SPRN_SPRG_PACA;	/* get paca address into r13 */	\ -	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\ -	std	r10,area+EX_R10(r13);					\ +#define __EXCEPTION_PROLOG_1(area, extra, vec)				\ +	OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR);		\ +	OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR);		\ +	SAVE_CTR(r10, area);						\ +	mfcr	r9;							\ +	extra(vec);							\  	std	r11,area+EX_R11(r13);					\  	std	r12,area+EX_R12(r13);					\ -	mfspr	r9,SPRN_SPRG_SCRATCH0;					\ -	std	r9,area+EX_R13(r13);					\ -	mfcr	r9 +	GET_SCRATCH0(r10);						\ +	std	r10,area+EX_R13(r13) +#define EXCEPTION_PROLOG_1(area, extra, vec)				\ +	__EXCEPTION_PROLOG_1(area, extra, vec) -#define EXCEPTION_PROLOG_PSERIES_1(label)				\ +#define __EXCEPTION_PROLOG_PSERIES_1(label, h)				\  	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\  	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\ -	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\ +	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\  	LOAD_HANDLER(r12,label)						\ -	mtspr	SPRN_SRR0,r12;						\ -	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\ -	mtspr	SPRN_SRR1,r10;						\ -	rfid;								\ +	mtspr	SPRN_##h##SRR0,r12;					\ +	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\ +	mtspr	SPRN_##h##SRR1,r10;					\ +	h##rfid;							\  	b	.	/* prevent speculative execution */ +#define EXCEPTION_PROLOG_PSERIES_1(label, h)				\ +	__EXCEPTION_PROLOG_PSERIES_1(label, h) + +#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec)		\ +	EXCEPTION_PROLOG_0(area);					\ +	EXCEPTION_PROLOG_1(area, extra, vec);				\ +	EXCEPTION_PROLOG_PSERIES_1(label, h); + +#define __KVMTEST(n)							\ +	lbz	r10,HSTATE_IN_GUEST(r13);			\ +	cmpwi	r10,0;							\ +	bne	do_kvm_##n + +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +/* + * If hv is possible, interrupts come into to the hv version + * of the kvmppc_interrupt code, which then jumps to the PR handler, + * kvmppc_interrupt_pr, if the guest is a PR guest. + */ +#define kvmppc_interrupt kvmppc_interrupt_hv +#else +#define kvmppc_interrupt kvmppc_interrupt_pr +#endif + +#define __KVM_HANDLER(area, h, n)					\ +do_kvm_##n:								\ +	BEGIN_FTR_SECTION_NESTED(947)					\ +	ld	r10,area+EX_CFAR(r13);					\ +	std	r10,HSTATE_CFAR(r13);					\ +	END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947);		\ +	BEGIN_FTR_SECTION_NESTED(948)					\ +	ld	r10,area+EX_PPR(r13);					\ +	std	r10,HSTATE_PPR(r13);					\ +	END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948);	\ +	ld	r10,area+EX_R10(r13);					\ +	stw	r9,HSTATE_SCRATCH1(r13);				\ +	ld	r9,area+EX_R9(r13);					\ +	std	r12,HSTATE_SCRATCH0(r13);				\ +	li	r12,n;							\ +	b	kvmppc_interrupt + +#define __KVM_HANDLER_SKIP(area, h, n)					\ +do_kvm_##n:								\ +	cmpwi	r10,KVM_GUEST_MODE_SKIP;				\ +	ld	r10,area+EX_R10(r13);					\ +	beq	89f;							\ +	stw	r9,HSTATE_SCRATCH1(r13);			\ +	BEGIN_FTR_SECTION_NESTED(948)					\ +	ld	r9,area+EX_PPR(r13);					\ +	std	r9,HSTATE_PPR(r13);					\ +	END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948);	\ +	ld	r9,area+EX_R9(r13);					\ +	std	r12,HSTATE_SCRATCH0(r13);			\ +	li	r12,n;							\ +	b	kvmppc_interrupt;					\ +89:	mtocrf	0x80,r9;						\ +	ld	r9,area+EX_R9(r13);					\ +	b	kvmppc_skip_##h##interrupt + +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER +#define KVMTEST(n)			__KVMTEST(n) +#define KVM_HANDLER(area, h, n)		__KVM_HANDLER(area, h, n) +#define KVM_HANDLER_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n) + +#else +#define KVMTEST(n) +#define KVM_HANDLER(area, h, n) +#define KVM_HANDLER_SKIP(area, h, n) +#endif + +#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE +#define KVMTEST_PR(n)			__KVMTEST(n) +#define KVM_HANDLER_PR(area, h, n)	__KVM_HANDLER(area, h, n) +#define KVM_HANDLER_PR_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n) + +#else +#define KVMTEST_PR(n) +#define KVM_HANDLER_PR(area, h, n) +#define KVM_HANDLER_PR_SKIP(area, h, n) +#endif -#define EXCEPTION_PROLOG_PSERIES(area, label)				\ -	EXCEPTION_PROLOG_1(area);					\ -	EXCEPTION_PROLOG_PSERIES_1(label); +#define NOTEST(n)  /*   * The common exception prolog is used for all except a few exceptions @@ -97,11 +292,13 @@  	subi	r1,r1,INT_FRAME_SIZE;	/* alloc frame on kernel stack	*/ \  	beq-	1f;							   \  	ld	r1,PACAKSAVE(r13);	/* kernel stack to use		*/ \ -1:	cmpdi	cr1,r1,0;		/* check if r1 is in userspace	*/ \ -	bge-	cr1,2f;			/* abort if it is		*/ \ -	b	3f;							   \ -2:	li	r1,(n);			/* will be reloaded later	*/ \ +1:	cmpdi	cr1,r1,-INT_FRAME_SIZE;	/* check if r1 is in userspace	*/ \ +	blt+	cr1,3f;			/* abort if it is		*/ \ +	li	r1,(n);			/* will be reloaded later	*/ \  	sth	r1,PACA_TRAP_SAVE(r13);					   \ +	std	r3,area+EX_R3(r13);					   \ +	addi	r3,r13,area;		/* r3 -> where regs are saved*/	   \ +	RESTORE_CTR(r1, area);						   \  	b	bad_stack;						   \  3:	std	r9,_CCR(r1);		/* save CR in stackframe	*/ \  	std	r11,_NIP(r1);		/* save SRR0 in stackframe	*/ \ @@ -109,10 +306,15 @@  	std	r10,0(r1);		/* make stack chain pointer	*/ \  	std	r0,GPR0(r1);		/* save r0 in stackframe	*/ \  	std	r10,GPR1(r1);		/* save r1 in stackframe	*/ \ +	beq	4f;			/* if from kernel mode		*/ \  	ACCOUNT_CPU_USER_ENTRY(r9, r10);				   \ -	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \ -	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe	*/ \ -	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \ +	SAVE_PPR(area, r9, r10);					   \ +4:	EXCEPTION_PROLOG_COMMON_2(area)					   \ +	EXCEPTION_PROLOG_COMMON_3(n)					   \ +	ACCOUNT_STOLEN_TIME + +/* Save original regs values from save area to stack frame. */ +#define EXCEPTION_PROLOG_COMMON_2(area)					   \  	ld	r9,area+EX_R9(r13);	/* move r9, r10 to stackframe	*/ \  	ld	r10,area+EX_R10(r13);					   \  	std	r9,GPR9(r1);						   \ @@ -123,11 +325,20 @@  	std	r9,GPR11(r1);						   \  	std	r10,GPR12(r1);						   \  	std	r11,GPR13(r1);						   \ +	BEGIN_FTR_SECTION_NESTED(66);					   \ +	ld	r10,area+EX_CFAR(r13);					   \ +	std	r10,ORIG_GPR3(r1);					   \ +	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		   \ +	GET_CTR(r10, area);						   \ +	std	r10,_CTR(r1); + +#define EXCEPTION_PROLOG_COMMON_3(n)					   \ +	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \ +	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe   */ \ +	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \ +	mflr	r9;			/* Get LR, later save to stack	*/ \  	ld	r2,PACATOC(r13);	/* get kernel TOC into r2	*/ \ -	mflr	r9;			/* save LR in stackframe	*/ \  	std	r9,_LINK(r1);						   \ -	mfctr	r10;			/* save CTR in stackframe	*/ \ -	std	r10,_CTR(r1);						   \  	lbz	r10,PACASOFTIRQEN(r13);				   \  	mfspr	r11,SPRN_XER;		/* save XER in stackframe	*/ \  	std	r10,SOFTE(r1);						   \ @@ -137,131 +348,207 @@  	li	r10,0;							   \  	ld	r11,exception_marker@toc(r2);				   \  	std	r10,RESULT(r1);		/* clear regs->result		*/ \ -	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/ \ -	ACCOUNT_STOLEN_TIME +	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/  /*   * Exception vectors.   */ -#define STD_EXCEPTION_PSERIES(n, label)			\ -	. = n;						\ +#define STD_EXCEPTION_PSERIES(loc, vec, label)		\ +	. = loc;					\  	.globl label##_pSeries;				\  label##_pSeries:					\ -	HMT_MEDIUM;					\ -	DO_KVM	n;					\ -	mtspr	SPRN_SPRG_SCRATCH0,r13;		/* save r13 */	\ -	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) +	HMT_MEDIUM_PPR_DISCARD;				\ +	SET_SCRATCH0(r13);		/* save r13 */		\ +	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\ +				 EXC_STD, KVMTEST_PR, vec) -#define HSTD_EXCEPTION_PSERIES(n, label)		\ -	. = n;						\ -	.globl label##_pSeries;				\ -label##_pSeries:					\ -	HMT_MEDIUM;					\ -	mtspr	SPRN_SPRG_SCRATCH0,r20;	/* save r20 */	\ -	mfspr	r20,SPRN_HSRR0;		/* copy HSRR0 to SRR0 */ \ -	mtspr	SPRN_SRR0,r20;				\ -	mfspr	r20,SPRN_HSRR1;		/* copy HSRR0 to SRR0 */ \ -	mtspr	SPRN_SRR1,r20;				\ -	mfspr	r20,SPRN_SPRG_SCRATCH0;	/* restore r20 */ \ -	mtspr	SPRN_SPRG_SCRATCH0,r13;		/* save r13 */	\ -	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) - - -#define MASKABLE_EXCEPTION_PSERIES(n, label)				\ -	. = n;								\ -	.globl label##_pSeries;						\ -label##_pSeries:							\ -	HMT_MEDIUM;							\ -	DO_KVM	n;							\ -	mtspr	SPRN_SPRG_SCRATCH0,r13;	/* save r13 */			\ -	mfspr	r13,SPRN_SPRG_PACA;	/* get paca address into r13 */	\ -	std	r9,PACA_EXGEN+EX_R9(r13);	/* save r9, r10 */	\ -	std	r10,PACA_EXGEN+EX_R10(r13);				\ +/* Version of above for when we have to branch out-of-line */ +#define STD_EXCEPTION_PSERIES_OOL(vec, label)			\ +	.globl label##_pSeries;					\ +label##_pSeries:						\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec);	\ +	EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD) + +#define STD_EXCEPTION_HV(loc, vec, label)		\ +	. = loc;					\ +	.globl label##_hv;				\ +label##_hv:						\ +	HMT_MEDIUM_PPR_DISCARD;				\ +	SET_SCRATCH0(r13);	/* save r13 */			\ +	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\ +				 EXC_HV, KVMTEST, vec) + +/* Version of above for when we have to branch out-of-line */ +#define STD_EXCEPTION_HV_OOL(vec, label)		\ +	.globl label##_hv;				\ +label##_hv:						\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec);	\ +	EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV) + +#define STD_RELON_EXCEPTION_PSERIES(loc, vec, label)	\ +	. = loc;					\ +	.globl label##_relon_pSeries;			\ +label##_relon_pSeries:					\ +	HMT_MEDIUM_PPR_DISCARD;				\ +	/* No guest interrupts come through here */	\ +	SET_SCRATCH0(r13);		/* save r13 */	\ +	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ +				       EXC_STD, NOTEST, vec) + +#define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label)		\ +	.globl label##_relon_pSeries;				\ +label##_relon_pSeries:						\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\ +	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD) + +#define STD_RELON_EXCEPTION_HV(loc, vec, label)		\ +	. = loc;					\ +	.globl label##_relon_hv;			\ +label##_relon_hv:					\ +	HMT_MEDIUM_PPR_DISCARD;				\ +	/* No guest interrupts come through here */	\ +	SET_SCRATCH0(r13);	/* save r13 */		\ +	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ +				       EXC_HV, NOTEST, vec) + +#define STD_RELON_EXCEPTION_HV_OOL(vec, label)			\ +	.globl label##_relon_hv;				\ +label##_relon_hv:						\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\ +	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV) + +/* This associate vector numbers with bits in paca->irq_happened */ +#define SOFTEN_VALUE_0x500	PACA_IRQ_EE +#define SOFTEN_VALUE_0x502	PACA_IRQ_EE +#define SOFTEN_VALUE_0x900	PACA_IRQ_DEC +#define SOFTEN_VALUE_0x982	PACA_IRQ_DEC +#define SOFTEN_VALUE_0xa00	PACA_IRQ_DBELL +#define SOFTEN_VALUE_0xe80	PACA_IRQ_DBELL +#define SOFTEN_VALUE_0xe82	PACA_IRQ_DBELL + +#define __SOFTEN_TEST(h, vec)						\  	lbz	r10,PACASOFTIRQEN(r13);					\ -	mfcr	r9;							\  	cmpwi	r10,0;							\ -	beq	masked_interrupt;					\ -	mfspr	r10,SPRN_SPRG_SCRATCH0;					\ -	std	r10,PACA_EXGEN+EX_R13(r13);				\ -	std	r11,PACA_EXGEN+EX_R11(r13);				\ -	std	r12,PACA_EXGEN+EX_R12(r13);				\ -	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\ -	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\ -	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\ -	LOAD_HANDLER(r12,label##_common)				\ -	mtspr	SPRN_SRR0,r12;						\ -	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\ -	mtspr	SPRN_SRR1,r10;						\ -	rfid;								\ -	b	.	/* prevent speculative execution */ +	li	r10,SOFTEN_VALUE_##vec;					\ +	beq	masked_##h##interrupt +#define _SOFTEN_TEST(h, vec)	__SOFTEN_TEST(h, vec) -#ifdef CONFIG_PPC_ISERIES -#define DISABLE_INTS				\ -	li	r11,0;				\ -	stb	r11,PACASOFTIRQEN(r13);		\ -BEGIN_FW_FTR_SECTION;				\ -	stb	r11,PACAHARDIRQEN(r13);		\ -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES);	\ -	TRACE_DISABLE_INTS;			\ -BEGIN_FW_FTR_SECTION;				\ -	mfmsr	r10;				\ -	ori	r10,r10,MSR_EE;			\ -	mtmsrd	r10,1;				\ -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) -#else -#define DISABLE_INTS				\ -	li	r11,0;				\ -	stb	r11,PACASOFTIRQEN(r13);		\ -	stb	r11,PACAHARDIRQEN(r13);		\ -	TRACE_DISABLE_INTS -#endif /* CONFIG_PPC_ISERIES */ - -#define ENABLE_INTS				\ -	ld	r12,_MSR(r1);			\ -	mfmsr	r11;				\ -	rlwimi	r11,r12,0,MSR_EE;		\ -	mtmsrd	r11,1 - -#define STD_EXCEPTION_COMMON(trap, label, hdlr)		\ -	.align	7;					\ -	.globl label##_common;				\ -label##_common:						\ -	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\ -	DISABLE_INTS;					\ -	bl	.save_nvgprs;				\ -	addi	r3,r1,STACK_FRAME_OVERHEAD;		\ -	bl	hdlr;					\ -	b	.ret_from_except +#define SOFTEN_TEST_PR(vec)						\ +	KVMTEST_PR(vec);						\ +	_SOFTEN_TEST(EXC_STD, vec) + +#define SOFTEN_TEST_HV(vec)						\ +	KVMTEST(vec);							\ +	_SOFTEN_TEST(EXC_HV, vec) + +#define SOFTEN_TEST_HV_201(vec)						\ +	KVMTEST(vec);							\ +	_SOFTEN_TEST(EXC_STD, vec) + +#define SOFTEN_NOTEST_PR(vec)		_SOFTEN_TEST(EXC_STD, vec) +#define SOFTEN_NOTEST_HV(vec)		_SOFTEN_TEST(EXC_HV, vec) + +#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\ +	SET_SCRATCH0(r13);    /* save r13 */				\ +	EXCEPTION_PROLOG_0(PACA_EXGEN);					\ +	__EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);			\ +	EXCEPTION_PROLOG_PSERIES_1(label##_common, h); + +#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\ +	__MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) + +#define MASKABLE_EXCEPTION_PSERIES(loc, vec, label)			\ +	. = loc;							\ +	.globl label##_pSeries;						\ +label##_pSeries:							\ +	HMT_MEDIUM_PPR_DISCARD;						\ +	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\ +				    EXC_STD, SOFTEN_TEST_PR) + +#define MASKABLE_EXCEPTION_HV(loc, vec, label)				\ +	. = loc;							\ +	.globl label##_hv;						\ +label##_hv:								\ +	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\ +				    EXC_HV, SOFTEN_TEST_HV) + +#define MASKABLE_EXCEPTION_HV_OOL(vec, label)				\ +	.globl label##_hv;						\ +label##_hv:								\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec);		\ +	EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); + +#define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra)	\ +	HMT_MEDIUM_PPR_DISCARD;						\ +	SET_SCRATCH0(r13);    /* save r13 */				\ +	EXCEPTION_PROLOG_0(PACA_EXGEN);					\ +	__EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);		\ +	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); +#define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra)	\ +	__MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) + +#define MASKABLE_RELON_EXCEPTION_PSERIES(loc, vec, label)		\ +	. = loc;							\ +	.globl label##_relon_pSeries;					\ +label##_relon_pSeries:							\ +	_MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,			\ +					  EXC_STD, SOFTEN_NOTEST_PR) + +#define MASKABLE_RELON_EXCEPTION_HV(loc, vec, label)			\ +	. = loc;							\ +	.globl label##_relon_hv;					\ +label##_relon_hv:							\ +	_MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,			\ +					  EXC_HV, SOFTEN_NOTEST_HV) + +#define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label)			\ +	.globl label##_relon_hv;					\ +label##_relon_hv:							\ +	EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec);		\ +	EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); + +/* + * Our exception common code can be passed various "additions" + * to specify the behaviour of interrupts, whether to kick the + * runlatch, etc... + */ + +/* Exception addition: Hard disable interrupts */ +#define DISABLE_INTS	RECONCILE_IRQ_STATE(r10,r11) + +#define ADD_NVGPRS				\ +	bl	save_nvgprs + +#define RUNLATCH_ON				\ +BEGIN_FTR_SECTION				\ +	CURRENT_THREAD_INFO(r3, r1);		\ +	ld	r4,TI_LOCAL_FLAGS(r3);		\ +	andi.	r0,r4,_TLF_RUNLATCH;		\ +	beql	ppc64_runlatch_on_trampoline;	\ +END_FTR_SECTION_IFSET(CPU_FTR_CTRL) + +#define EXCEPTION_COMMON(trap, label, hdlr, ret, additions)	\ +	.align	7;						\ +	.globl label##_common;					\ +label##_common:							\ +	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);		\ +	additions;						\ +	addi	r3,r1,STACK_FRAME_OVERHEAD;			\ +	bl	hdlr;						\ +	b	ret + +#define STD_EXCEPTION_COMMON(trap, label, hdlr)			\ +	EXCEPTION_COMMON(trap, label, hdlr, ret_from_except,	\ +			 ADD_NVGPRS;DISABLE_INTS)  /*   * Like STD_EXCEPTION_COMMON, but for exceptions that can occur - * in the idle task and therefore need the special idle handling. + * in the idle task and therefore need the special idle handling + * (finish nap and runlatch)   */ -#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr)	\ -	.align	7;					\ -	.globl label##_common;				\ -label##_common:						\ -	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\ -	FINISH_NAP;					\ -	DISABLE_INTS;					\ -	bl	.save_nvgprs;				\ -	addi	r3,r1,STACK_FRAME_OVERHEAD;		\ -	bl	hdlr;					\ -	b	.ret_from_except - -#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)	\ -	.align	7;					\ -	.globl label##_common;				\ -label##_common:						\ -	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\ -	FINISH_NAP;					\ -	DISABLE_INTS;					\ -BEGIN_FTR_SECTION					\ -	bl	.ppc64_runlatch_on;			\ -END_FTR_SECTION_IFSET(CPU_FTR_CTRL)			\ -	addi	r3,r1,STACK_FRAME_OVERHEAD;		\ -	bl	hdlr;					\ -	b	.ret_from_except_lite +#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)		  \ +	EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ +			 FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)  /*   * When the idle code in power4_idle puts the CPU into NAP mode, @@ -273,7 +560,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)			\  #ifdef CONFIG_PPC_970_NAP  #define FINISH_NAP				\  BEGIN_FTR_SECTION				\ -	clrrdi	r11,r1,THREAD_SHIFT;		\ +	CURRENT_THREAD_INFO(r11, r1);		\  	ld	r9,TI_LOCAL_FLAGS(r11);		\  	andi.	r10,r9,_TLF_NAPPING;		\  	bnel	power4_fixup_nap;		\  | 
