Re: [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support
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.cara...@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:
[PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support
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.cara...@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 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); +
[PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support
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.cara...@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 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); +