From 22c782a4b14773fab7eab3c1db54ad7ad077e9b8 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 1 Nov 2013 17:32:59 -0500 Subject: kvm/ppc/booke: Merge altivec and SPE exception handling They share exception numbers, so we can't just have separate case entries, or we'll get conflicts. This turned up during the merge because Altivec support is not yet upstream, yet some of the preparation is, which was done differently from the SDK. Signed-off-by: Scott Wood Cc: Mihai Caraman diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 6e9f858..851bac7 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -75,10 +75,6 @@ #define BOOKE_INTERRUPT_HV_SYSCALL 40 #define BOOKE_INTERRUPT_HV_PRIV 41 -/* altivec */ -#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 42 -#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 43 - /* book3s */ #define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100 diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index d2579d8..9328ee6 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -386,12 +386,10 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, case BOOKE_IRQPRIO_ITLB_MISS: case BOOKE_IRQPRIO_SYSCALL: case BOOKE_IRQPRIO_FP_UNAVAIL: - case BOOKE_IRQPRIO_SPE_UNAVAIL: - case BOOKE_IRQPRIO_SPE_FP_DATA: + case BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL: + case BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST: case BOOKE_IRQPRIO_SPE_FP_ROUND: case BOOKE_IRQPRIO_AP_UNAVAIL: - case BOOKE_IRQPRIO_ALTIVEC_UNAVAIL: - case BOOKE_IRQPRIO_ALTIVEC_ASSIST: allowed = 1; msr_mask = MSR_CE | MSR_ME | MSR_DE; int_class = INT_CLASS_NONCRIT; @@ -1099,70 +1097,51 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; break; + case BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL: #ifdef CONFIG_SPE - case BOOKE_INTERRUPT_SPE_UNAVAIL: { if (vcpu->arch.shared->msr & MSR_SPE) kvmppc_vcpu_enable_spe(vcpu); else kvmppc_booke_queue_irqprio(vcpu, - BOOKE_IRQPRIO_SPE_UNAVAIL); - r = RESUME_GUEST; - break; - } - - case BOOKE_INTERRUPT_SPE_FP_DATA: - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA); - r = RESUME_GUEST; - break; - - case BOOKE_INTERRUPT_SPE_FP_ROUND: - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); - r = RESUME_GUEST; - break; + BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL); +#elif defined(CONFIG_ALTIVEC) + kvmppc_booke_queue_irqprio(vcpu, + BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL); #else - case BOOKE_INTERRUPT_SPE_UNAVAIL: /* - * Guest wants SPE, but host kernel doesn't support it. Send - * an "unimplemented operation" program check to the guest. + * Guest wants SPE/Altivec, but host kernel doesn't support + * it. Send an "unimplemented operation" program check to + * the guest. */ kvmppc_core_queue_program(vcpu, ESR_PUO | ESR_SPV); +#endif r = RESUME_GUEST; break; - /* - * These really should never happen without CONFIG_SPE, - * as we should never enable the real MSR[SPE] in the guest. - */ - case BOOKE_INTERRUPT_SPE_FP_DATA: - case BOOKE_INTERRUPT_SPE_FP_ROUND: - printk(KERN_CRIT "%s: unexpected SPE interrupt %u at %08lx\n", + case BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST: +#if defined(CONFIG_SPE) || defined(CONFIG_ALTIVEC) + kvmppc_booke_queue_irqprio(vcpu, + BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST); + r = RESUME_GUEST; +#else + printk(KERN_CRIT "%s: unexpected SPE/Altivec interrupt %u at %08lx\n", __func__, exit_nr, vcpu->arch.pc); run->hw.hardware_exit_reason = exit_nr; r = RESUME_HOST; - break; #endif - -#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); + case BOOKE_INTERRUPT_SPE_FP_ROUND: +#ifdef CONFIG_SPE + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); r = RESUME_GUEST; - break; #else - case BOOKE_INTERRUPT_ALTIVEC_UNAVAIL: - case BOOKE_INTERRUPT_ALTIVEC_ASSIST: - printk(KERN_CRIT "%s: unexpected AltiVec interrupt %u \ - at %08lx\n", __func__, exit_nr, vcpu->arch.pc); + printk(KERN_CRIT "%s: unexpected SPE interrupt %u at %08lx\n", + __func__, exit_nr, vcpu->arch.pc); run->hw.hardware_exit_reason = exit_nr; r = RESUME_HOST; - break; #endif + break; case BOOKE_INTERRUPT_DATA_STORAGE: kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear, diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 59d1d4e..8b0861c 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -32,28 +32,26 @@ #define BOOKE_IRQPRIO_ALIGNMENT 2 #define BOOKE_IRQPRIO_PROGRAM 3 #define BOOKE_IRQPRIO_FP_UNAVAIL 4 -#define BOOKE_IRQPRIO_SPE_UNAVAIL 5 -#define BOOKE_IRQPRIO_SPE_FP_DATA 6 +#define BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL 5 +#define BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST 6 #define BOOKE_IRQPRIO_SPE_FP_ROUND 7 -#define BOOKE_IRQPRIO_ALTIVEC_UNAVAIL 8 -#define BOOKE_IRQPRIO_ALTIVEC_ASSIST 9 -#define BOOKE_IRQPRIO_SYSCALL 10 -#define BOOKE_IRQPRIO_AP_UNAVAIL 11 -#define BOOKE_IRQPRIO_DTLB_MISS 12 -#define BOOKE_IRQPRIO_ITLB_MISS 13 -#define BOOKE_IRQPRIO_MACHINE_CHECK 14 -#define BOOKE_IRQPRIO_DEBUG 15 -#define BOOKE_IRQPRIO_CRITICAL 16 -#define BOOKE_IRQPRIO_WATCHDOG 17 -#define BOOKE_IRQPRIO_EXTERNAL 18 -#define BOOKE_IRQPRIO_FIT 19 -#define BOOKE_IRQPRIO_DECREMENTER 20 -#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 21 +#define BOOKE_IRQPRIO_SYSCALL 8 +#define BOOKE_IRQPRIO_AP_UNAVAIL 9 +#define BOOKE_IRQPRIO_DTLB_MISS 10 +#define BOOKE_IRQPRIO_ITLB_MISS 11 +#define BOOKE_IRQPRIO_MACHINE_CHECK 12 +#define BOOKE_IRQPRIO_DEBUG 13 +#define BOOKE_IRQPRIO_CRITICAL 14 +#define BOOKE_IRQPRIO_WATCHDOG 15 +#define BOOKE_IRQPRIO_EXTERNAL 16 +#define BOOKE_IRQPRIO_FIT 17 +#define BOOKE_IRQPRIO_DECREMENTER 18 +#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 /* Internal pseudo-irqprio for level triggered externals */ -#define BOOKE_IRQPRIO_EXTERNAL_LEVEL 22 -#define BOOKE_IRQPRIO_DBELL 23 -#define BOOKE_IRQPRIO_DBELL_CRIT 24 -#define BOOKE_IRQPRIO_MAX 25 +#define BOOKE_IRQPRIO_EXTERNAL_LEVEL 20 +#define BOOKE_IRQPRIO_DBELL 21 +#define BOOKE_IRQPRIO_DBELL_CRIT 22 +#define BOOKE_IRQPRIO_MAX 23 #define BOOKE_IRQMASK_EE ((1 << BOOKE_IRQPRIO_EXTERNAL_LEVEL) | \ (1 << BOOKE_IRQPRIO_PERFORMANCE_MONITOR) | \ diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S index 6a10ee7..63ce811 100644 --- a/arch/powerpc/kvm/bookehv_interrupts.S +++ b/arch/powerpc/kvm/bookehv_interrupts.S @@ -253,10 +253,10 @@ 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), \ - 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_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \ + SPRN_SRR0, SPRN_SRR1, NEED_ESR +kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST, EX_PARAMS(GEN), \ + SPRN_SRR0, SPRN_SRR1, NEED_ESR kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \ SPRN_SRR0, SPRN_SRR1, 0 kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \ @@ -277,10 +277,6 @@ kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \ SPRN_DSRR0, SPRN_DSRR1, 0 kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \ SPRN_CSRR0, SPRN_CSRR1, 0 -kvm_handler BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \ - SPRN_SRR0, SPRN_SRR1, NEED_ESR -kvm_handler BOOKE_INTERRUPT_ALTIVEC_ASSIST, EX_PARAMS(GEN), \ - SPRN_SRR0, SPRN_SRR1, NEED_ESR #else /* * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h @@ -360,8 +356,8 @@ 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 -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_ALTIVEC_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0 +kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST, SPRN_SRR0, SPRN_SRR1, 0 kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0 kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, SPRN_SRR0, SPRN_SRR1, 0 kvm_handler BOOKE_INTERRUPT_DOORBELL, SPRN_SRR0, SPRN_SRR1, 0 diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index c82a89f..ed19bdd 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c @@ -380,8 +380,10 @@ void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) sregs->u.e.impl.fsl.hid0 = vcpu_e500->hid0; sregs->u.e.impl.fsl.mcar = vcpu_e500->mcar; - sregs->u.e.ivor_high[0] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; - sregs->u.e.ivor_high[1] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; + sregs->u.e.ivor_high[0] = + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL]; + sregs->u.e.ivor_high[1] = + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST]; sregs->u.e.ivor_high[2] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; sregs->u.e.ivor_high[3] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]; @@ -409,9 +411,9 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) return 0; if (sregs->u.e.features & KVM_SREGS_E_SPE) { - vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL] = sregs->u.e.ivor_high[0]; - vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST] = sregs->u.e.ivor_high[1]; vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = sregs->u.e.ivor_high[2]; diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index 1e29aa8..31b1a63 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c @@ -234,12 +234,11 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) /* extra exceptions */ case SPRN_IVOR32: - vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; - vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val; + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL] = spr_val; break; case SPRN_IVOR33: - vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val; - vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val; + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST] = + spr_val; break; case SPRN_IVOR34: vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val; @@ -358,14 +357,11 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) /* extra exceptions */ case SPRN_IVOR32: - WARN_ON_ONCE(vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] != - vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL]); - *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; + *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_ALTIVEC_UNAVAIL]; break; case SPRN_IVOR33: - WARN_ON_ONCE(vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] != - vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST]); - *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; + *spr_val = vcpu->arch.ivor[ + BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST]; break; case SPRN_IVOR34: *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; -- cgit v0.10.2