diff mbox

[v3,2/5] KVM: PPC: Book3e: Add AltiVec support

Message ID 1407235175-30994-3-git-send-email-mihai.caraman@freescale.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mihai Caraman Aug. 5, 2014, 10:39 a.m. UTC
Add KVM Book3e AltiVec support. KVM Book3e FPU support gracefully reuse host
infrastructure so follow the same approach for AltiVec.

Keep SPE/AltiVec exception handlers distinct using CONFIG_KVM_E500V2.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
 - use distinct SPE/AltiVec exception handlers

v2:
 - integrate Paul's FP/VMX/VSX changes

 arch/powerpc/kvm/booke.c              | 73 +++++++++++++++++++++++++++++++++++
 arch/powerpc/kvm/booke.h              |  5 +++
 arch/powerpc/kvm/bookehv_interrupts.S | 10 +++--
 arch/powerpc/kvm/e500_emulate.c       | 18 +++++++++
 4 files changed, 102 insertions(+), 4 deletions(-)

Comments

Alexander Graf Aug. 12, 2014, 11:45 a.m. UTC | #1
On 05.08.14 12:39, Mihai Caraman wrote:
> Add KVM Book3e AltiVec support. KVM Book3e FPU support gracefully reuse host
> infrastructure so follow the same approach for AltiVec.
>
> Keep SPE/AltiVec exception handlers distinct using CONFIG_KVM_E500V2.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> v3:
>   - use distinct SPE/AltiVec exception handlers
>
> v2:
>   - integrate Paul's FP/VMX/VSX changes
>
>   arch/powerpc/kvm/booke.c              | 73 +++++++++++++++++++++++++++++++++++
>   arch/powerpc/kvm/booke.h              |  5 +++
>   arch/powerpc/kvm/bookehv_interrupts.S | 10 +++--
>   arch/powerpc/kvm/e500_emulate.c       | 18 +++++++++
>   4 files changed, 102 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 0c6f616..c5cca09 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -168,6 +168,40 @@ static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
>   #endif
>   }
>   
> +/*
> + * Simulate AltiVec unavailable fault to load guest state
> + * from thread to AltiVec unit.
> + * It requires to be called with preemption disabled.
> + */
> +static inline void kvmppc_load_guest_altivec(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_ALTIVEC
> +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
> +		if (!(current->thread.regs->msr & MSR_VEC)) {
> +			enable_kernel_altivec();
> +			load_vr_state(&vcpu->arch.vr);
> +			current->thread.vr_save_area = &vcpu->arch.vr;
> +			current->thread.regs->msr |= MSR_VEC;
> +		}
> +	}
> +#endif
> +}
> +
> +/*
> + * Save guest vcpu AltiVec state into thread.
> + * It requires to be called with preemption disabled.
> + */
> +static inline void kvmppc_save_guest_altivec(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_ALTIVEC
> +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
> +		if (current->thread.regs->msr & MSR_VEC)
> +			giveup_altivec(current);
> +		current->thread.vr_save_area = NULL;
> +	}
> +#endif
> +}
> +
>   static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu)
>   {
>   	/* Synchronize guest's desire to get debug interrupts into shadow MSR */
> @@ -375,9 +409,14 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
>   	case BOOKE_IRQPRIO_ITLB_MISS:
>   	case BOOKE_IRQPRIO_SYSCALL:
>   	case BOOKE_IRQPRIO_FP_UNAVAIL:
> +#ifdef CONFIG_KVM_E500V2

Why not use your new SPE_POSSIBLE define?

>   	case BOOKE_IRQPRIO_SPE_UNAVAIL:
>   	case BOOKE_IRQPRIO_SPE_FP_DATA:
>   	case BOOKE_IRQPRIO_SPE_FP_ROUND:
> +#else

We only ever support altivec capable CPUs with CONFIG_ALTIVEC, no? So 
just make this a new #ifdef CONFIG_ALTIVEC

> +	case BOOKE_IRQPRIO_ALTIVEC_UNAVAIL:
> +	case BOOKE_IRQPRIO_ALTIVEC_ASSIST:
> +#endif
>   	case BOOKE_IRQPRIO_AP_UNAVAIL:
>   		allowed = 1;
>   		msr_mask = MSR_CE | MSR_ME | MSR_DE;
> @@ -693,6 +732,17 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
>   	kvmppc_load_guest_fp(vcpu);
>   #endif
>   
> +#ifdef CONFIG_ALTIVEC
> +	/* Save userspace AltiVec state in stack */
> +	if (cpu_has_feature(CPU_FTR_ALTIVEC))
> +		enable_kernel_altivec();
> +	/*
> +	 * Since we can't trap on MSR_VEC in GS-mode, we consider the guest
> +	 * as always using the AltiVec.
> +	 */
> +	kvmppc_load_guest_altivec(vcpu);
> +#endif
> +
>   	/* Switch to guest debug context */
>   	debug = vcpu->arch.shadow_dbg_reg;
>   	switch_booke_debug_regs(&debug);
> @@ -715,6 +765,10 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
>   	kvmppc_save_guest_fp(vcpu);
>   #endif
>   
> +#ifdef CONFIG_ALTIVEC
> +	kvmppc_save_guest_altivec(vcpu);
> +#endif
> +
>   out:
>   	vcpu->mode = OUTSIDE_GUEST_MODE;
>   	return ret;
> @@ -999,6 +1053,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
>   		r = RESUME_GUEST;
>   		break;
>   
> +#ifdef CONFIG_KVM_E500V2

Why? We're already guarded by CONFIG_SPE

>   #ifdef CONFIG_SPE
>   	case BOOKE_INTERRUPT_SPE_UNAVAIL: {
>   		if (vcpu->arch.shared->msr & MSR_SPE)
> @@ -1040,7 +1095,24 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
>   		run->hw.hardware_exit_reason = exit_nr;
>   		r = RESUME_HOST;
>   		break;
> +#endif /* !CONFIG_SPE */
> +#else
> +/*
> + * On cores with Vector category, KVM is loaded only if CONFIG_ALTIVEC,
> + * see kvmppc_core_check_processor_compat().
> + */
> +#ifdef CONFIG_ALTIVEC

... and CONFIG_ALTIVEC

> +	case BOOKE_INTERRUPT_ALTIVEC_UNAVAIL:
> +		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_UNAVAIL);
> +		r = RESUME_GUEST;
> +		break;
> +
> +	case BOOKE_INTERRUPT_ALTIVEC_ASSIST:
> +		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_ASSIST);
> +		r = RESUME_GUEST;
> +		break;
>   #endif
> +#endif /* !CONFIG_KVM_E500V2 */
>   
>   	case BOOKE_INTERRUPT_DATA_STORAGE:
>   		kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
> @@ -1217,6 +1289,7 @@ out:
>   			/* interrupts now hard-disabled */
>   			kvmppc_fix_ee_before_entry();
>   			kvmppc_load_guest_fp(vcpu);
> +			kvmppc_load_guest_altivec(vcpu);
>   		}
>   	}
>   
> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> index e73d513..ce5b543 100644
> --- a/arch/powerpc/kvm/booke.h
> +++ b/arch/powerpc/kvm/booke.h
> @@ -32,9 +32,14 @@
>   #define BOOKE_IRQPRIO_ALIGNMENT 2
>   #define BOOKE_IRQPRIO_PROGRAM 3
>   #define BOOKE_IRQPRIO_FP_UNAVAIL 4
> +#ifdef CONFIG_KVM_E500V2

Same comments as above

>   #define BOOKE_IRQPRIO_SPE_UNAVAIL 5
>   #define BOOKE_IRQPRIO_SPE_FP_DATA 6
>   #define BOOKE_IRQPRIO_SPE_FP_ROUND 7
> +#else
> +#define BOOKE_IRQPRIO_ALTIVEC_UNAVAIL 5
> +#define BOOKE_IRQPRIO_ALTIVEC_ASSIST 6
> +#endif
>   #define BOOKE_IRQPRIO_SYSCALL 8
>   #define BOOKE_IRQPRIO_AP_UNAVAIL 9
>   #define BOOKE_IRQPRIO_DTLB_MISS 10
> diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
> index e9fa56a..1d7c4d6 100644
> --- a/arch/powerpc/kvm/bookehv_interrupts.S
> +++ b/arch/powerpc/kvm/bookehv_interrupts.S
> @@ -256,11 +256,9 @@ kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
>   	SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
>   kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
>   	SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
> +kvm_handler BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \
>   	SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
> -	SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
> +kvm_handler BOOKE_INTERRUPT_ALTIVEC_ASSIST, EX_PARAMS(GEN), \
>   	SPRN_SRR0, SPRN_SRR1, 0
>   kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
>   	SPRN_SRR0, SPRN_SRR1, 0
> @@ -361,6 +359,10 @@ kvm_lvl_handler BOOKE_INTERRUPT_WATCHDOG, \
>   kvm_handler BOOKE_INTERRUPT_DTLB_MISS, \
>   	SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
>   kvm_handler BOOKE_INTERRUPT_ITLB_MISS, SPRN_SRR0, SPRN_SRR1, 0
> +/*
> + * TODO: SPE handlers should be available only for e500v2 cores.
> + * HV does not target e500v2 so remove them after kernel cleanup.
> + */

Let's do the cleanup first, then apply these patches.

>   kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
>   kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, SPRN_SRR0, SPRN_SRR1, 0
>   kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0
> diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
> index c99c40e..e6e0429 100644
> --- a/arch/powerpc/kvm/e500_emulate.c
> +++ b/arch/powerpc/kvm/e500_emulate.c
> @@ -259,6 +259,7 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
>   		break;
>   
>   	/* extra exceptions */
> +#ifdef CONFIG_KVM_E500V2

Same comments as above

>   	case SPRN_IVOR32:
>   		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
>   		break;
> @@ -268,6 +269,14 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
>   	case SPRN_IVOR34:
>   		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
>   		break;
> +#else
> +	case SPRN_IVOR32:
> +		vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val;
> +		break;
> +	case SPRN_IVOR33:
> +		vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val;
> +		break;
> +#endif
>   	case SPRN_IVOR35:
>   		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
>   		break;
> @@ -381,6 +390,7 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
>   		break;
>   
>   	/* extra exceptions */
> +#ifdef CONFIG_KVM_E500V2

Here too.


Alex

>   	case SPRN_IVOR32:
>   		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
>   		break;
> @@ -390,6 +400,14 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
>   	case SPRN_IVOR34:
>   		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
>   		break;
> +#else
> +	case SPRN_IVOR32:
> +		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL];
> +		break;
> +	case SPRN_IVOR33:
> +		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST];
> +		break;
> +#endif
>   	case SPRN_IVOR35:
>   		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
>   		break;

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 0c6f616..c5cca09 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -168,6 +168,40 @@  static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
 #endif
 }
 
+/*
+ * Simulate AltiVec unavailable fault to load guest state
+ * from thread to AltiVec unit.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
+		if (!(current->thread.regs->msr & MSR_VEC)) {
+			enable_kernel_altivec();
+			load_vr_state(&vcpu->arch.vr);
+			current->thread.vr_save_area = &vcpu->arch.vr;
+			current->thread.regs->msr |= MSR_VEC;
+		}
+	}
+#endif
+}
+
+/*
+ * Save guest vcpu AltiVec state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
+		if (current->thread.regs->msr & MSR_VEC)
+			giveup_altivec(current);
+		current->thread.vr_save_area = NULL;
+	}
+#endif
+}
+
 static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu)
 {
 	/* Synchronize guest's desire to get debug interrupts into shadow MSR */
@@ -375,9 +409,14 @@  static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 	case BOOKE_IRQPRIO_ITLB_MISS:
 	case BOOKE_IRQPRIO_SYSCALL:
 	case BOOKE_IRQPRIO_FP_UNAVAIL:
+#ifdef CONFIG_KVM_E500V2
 	case BOOKE_IRQPRIO_SPE_UNAVAIL:
 	case BOOKE_IRQPRIO_SPE_FP_DATA:
 	case BOOKE_IRQPRIO_SPE_FP_ROUND:
+#else
+	case BOOKE_IRQPRIO_ALTIVEC_UNAVAIL:
+	case BOOKE_IRQPRIO_ALTIVEC_ASSIST:
+#endif
 	case BOOKE_IRQPRIO_AP_UNAVAIL:
 		allowed = 1;
 		msr_mask = MSR_CE | MSR_ME | MSR_DE;
@@ -693,6 +732,17 @@  int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	kvmppc_load_guest_fp(vcpu);
 #endif
 
+#ifdef CONFIG_ALTIVEC
+	/* Save userspace AltiVec state in stack */
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		enable_kernel_altivec();
+	/*
+	 * Since we can't trap on MSR_VEC in GS-mode, we consider the guest
+	 * as always using the AltiVec.
+	 */
+	kvmppc_load_guest_altivec(vcpu);
+#endif
+
 	/* Switch to guest debug context */
 	debug = vcpu->arch.shadow_dbg_reg;
 	switch_booke_debug_regs(&debug);
@@ -715,6 +765,10 @@  int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	kvmppc_save_guest_fp(vcpu);
 #endif
 
+#ifdef CONFIG_ALTIVEC
+	kvmppc_save_guest_altivec(vcpu);
+#endif
+
 out:
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
@@ -999,6 +1053,7 @@  int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		r = RESUME_GUEST;
 		break;
 
+#ifdef CONFIG_KVM_E500V2
 #ifdef CONFIG_SPE
 	case BOOKE_INTERRUPT_SPE_UNAVAIL: {
 		if (vcpu->arch.shared->msr & MSR_SPE)
@@ -1040,7 +1095,24 @@  int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		run->hw.hardware_exit_reason = exit_nr;
 		r = RESUME_HOST;
 		break;
+#endif /* !CONFIG_SPE */
+#else
+/*
+ * On cores with Vector category, KVM is loaded only if CONFIG_ALTIVEC,
+ * see kvmppc_core_check_processor_compat().
+ */
+#ifdef CONFIG_ALTIVEC
+	case BOOKE_INTERRUPT_ALTIVEC_UNAVAIL:
+		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_UNAVAIL);
+		r = RESUME_GUEST;
+		break;
+
+	case BOOKE_INTERRUPT_ALTIVEC_ASSIST:
+		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_ASSIST);
+		r = RESUME_GUEST;
+		break;
 #endif
+#endif /* !CONFIG_KVM_E500V2 */
 
 	case BOOKE_INTERRUPT_DATA_STORAGE:
 		kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
@@ -1217,6 +1289,7 @@  out:
 			/* interrupts now hard-disabled */
 			kvmppc_fix_ee_before_entry();
 			kvmppc_load_guest_fp(vcpu);
+			kvmppc_load_guest_altivec(vcpu);
 		}
 	}
 
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index e73d513..ce5b543 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -32,9 +32,14 @@ 
 #define BOOKE_IRQPRIO_ALIGNMENT 2
 #define BOOKE_IRQPRIO_PROGRAM 3
 #define BOOKE_IRQPRIO_FP_UNAVAIL 4
+#ifdef CONFIG_KVM_E500V2
 #define BOOKE_IRQPRIO_SPE_UNAVAIL 5
 #define BOOKE_IRQPRIO_SPE_FP_DATA 6
 #define BOOKE_IRQPRIO_SPE_FP_ROUND 7
+#else
+#define BOOKE_IRQPRIO_ALTIVEC_UNAVAIL 5
+#define BOOKE_IRQPRIO_ALTIVEC_ASSIST 6
+#endif
 #define BOOKE_IRQPRIO_SYSCALL 8
 #define BOOKE_IRQPRIO_AP_UNAVAIL 9
 #define BOOKE_IRQPRIO_DTLB_MISS 10
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index e9fa56a..1d7c4d6 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -256,11 +256,9 @@  kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
 	SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
 kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
 	SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
+kvm_handler BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \
 	SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
-	SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
+kvm_handler BOOKE_INTERRUPT_ALTIVEC_ASSIST, EX_PARAMS(GEN), \
 	SPRN_SRR0, SPRN_SRR1, 0
 kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
 	SPRN_SRR0, SPRN_SRR1, 0
@@ -361,6 +359,10 @@  kvm_lvl_handler BOOKE_INTERRUPT_WATCHDOG, \
 kvm_handler BOOKE_INTERRUPT_DTLB_MISS, \
 	SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
 kvm_handler BOOKE_INTERRUPT_ITLB_MISS, SPRN_SRR0, SPRN_SRR1, 0
+/*
+ * TODO: SPE handlers should be available only for e500v2 cores.
+ * HV does not target e500v2 so remove them after kernel cleanup.
+ */
 kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
 kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, SPRN_SRR0, SPRN_SRR1, 0
 kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index c99c40e..e6e0429 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -259,6 +259,7 @@  int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
 		break;
 
 	/* extra exceptions */
+#ifdef CONFIG_KVM_E500V2
 	case SPRN_IVOR32:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
 		break;
@@ -268,6 +269,14 @@  int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
 	case SPRN_IVOR34:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
 		break;
+#else
+	case SPRN_IVOR32:
+		vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val;
+		break;
+	case SPRN_IVOR33:
+		vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val;
+		break;
+#endif
 	case SPRN_IVOR35:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
 		break;
@@ -381,6 +390,7 @@  int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
 		break;
 
 	/* extra exceptions */
+#ifdef CONFIG_KVM_E500V2
 	case SPRN_IVOR32:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
 		break;
@@ -390,6 +400,14 @@  int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
 	case SPRN_IVOR34:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
 		break;
+#else
+	case SPRN_IVOR32:
+		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL];
+		break;
+	case SPRN_IVOR33:
+		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST];
+		break;
+#endif
 	case SPRN_IVOR35:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
 		break;