diff options
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
| -rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 136 | 
1 files changed, 96 insertions, 40 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index f5dfe3411f64..8057f4f6980f 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -61,19 +61,22 @@  #define EXC_HV	H  #define EXC_STD -#define EXCEPTION_PROLOG_1(area)					\ +#define __EXCEPTION_PROLOG_1(area, extra, vec)				\  	GET_PACA(r13);							\  	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\  	std	r10,area+EX_R10(r13);					\ -	std	r11,area+EX_R11(r13);					\ -	std	r12,area+EX_R12(r13);					\  	BEGIN_FTR_SECTION_NESTED(66);					\  	mfspr	r10,SPRN_CFAR;						\  	std	r10,area+EX_CFAR(r13);					\  	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		\ -	GET_SCRATCH0(r9);						\ -	std	r9,area+EX_R13(r13);					\ -	mfcr	r9 +	mfcr	r9;							\ +	extra(vec);							\ +	std	r11,area+EX_R11(r13);					\ +	std	r12,area+EX_R12(r13);					\ +	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, h)				\  	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\ @@ -85,13 +88,65 @@  	mtspr	SPRN_##h##SRR1,r10;					\  	h##rfid;							\  	b	.	/* prevent speculative execution */ -#define EXCEPTION_PROLOG_PSERIES_1(label, h) \ +#define EXCEPTION_PROLOG_PSERIES_1(label, h)				\  	__EXCEPTION_PROLOG_PSERIES_1(label, h) -#define EXCEPTION_PROLOG_PSERIES(area, label, h)			\ -	EXCEPTION_PROLOG_1(area);					\ +#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec)		\ +	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 + +#define __KVM_HANDLER(area, h, n)					\ +do_kvm_##n:								\ +	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);			\ +	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 +#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 NOTEST(n) +  /*   * The common exception prolog is used for all except a few exceptions   * such as a segment miss on a kernel address.  We have to be prepared @@ -164,57 +219,58 @@  	.globl label##_pSeries;				\  label##_pSeries:					\  	HMT_MEDIUM;					\ -	DO_KVM	vec;					\  	SET_SCRATCH0(r13);		/* save r13 */		\ -	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD) +	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\ +				 EXC_STD, KVMTEST_PR, vec)  #define STD_EXCEPTION_HV(loc, vec, label)		\  	. = loc;					\  	.globl label##_hv;				\  label##_hv:						\  	HMT_MEDIUM;					\ -	DO_KVM	vec;					\ -	SET_SCRATCH0(r13);	/* save r13 */		\ -	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV) +	SET_SCRATCH0(r13);	/* save r13 */			\ +	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\ +				 EXC_HV, KVMTEST, vec) -#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h)			\ -	HMT_MEDIUM;							\ -	DO_KVM	vec;							\ -	SET_SCRATCH0(r13);    /* save r13 */				\ -	GET_PACA(r13);							\ -	std	r9,PACA_EXGEN+EX_R9(r13);	/* save r9, r10 */	\ -	std	r10,PACA_EXGEN+EX_R10(r13);				\ +#define __SOFTEN_TEST(h)						\  	lbz	r10,PACASOFTIRQEN(r13);					\ -	mfcr	r9;							\  	cmpwi	r10,0;							\ -	beq	masked_##h##interrupt;					\ -	GET_SCRATCH0(r10);						\ -	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_##h##SRR0;	/* save SRR0 */			\ -	LOAD_HANDLER(r12,label##_common)				\ -	mtspr	SPRN_##h##SRR0,r12;					\ -	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\ -	mtspr	SPRN_##h##SRR1,r10;					\ -	h##rfid;							\ -	b	.	/* prevent speculative execution */ -#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h)			\ -	__MASKABLE_EXCEPTION_PSERIES(vec, label, h) +	beq	masked_##h##interrupt +#define _SOFTEN_TEST(h)	__SOFTEN_TEST(h) + +#define SOFTEN_TEST_PR(vec)						\ +	KVMTEST_PR(vec);						\ +	_SOFTEN_TEST(EXC_STD) + +#define SOFTEN_TEST_HV(vec)						\ +	KVMTEST(vec);							\ +	_SOFTEN_TEST(EXC_HV) + +#define SOFTEN_TEST_HV_201(vec)						\ +	KVMTEST(vec);							\ +	_SOFTEN_TEST(EXC_STD) + +#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\ +	HMT_MEDIUM;							\ +	SET_SCRATCH0(r13);    /* save r13 */				\ +	__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:							\ -	_MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD) +	_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) +	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\ +				    EXC_HV, SOFTEN_TEST_HV)  #ifdef CONFIG_PPC_ISERIES  #define DISABLE_INTS				\  |