aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-02-19 05:00:34 -0500
committerAvi Kivity <avi@redhat.com>2010-04-25 05:34:56 -0400
commitc8c0b6f2f7db22a340f1311602182a25a2378996 (patch)
tree479571debbf03831a804a6e8cbc3ba4c986af1df /arch/powerpc/kvm/book3s.c
parentd6d549b20776c937cb4717b24ef05baec4768f99 (diff)
KVM: PPC: Combine extension interrupt handlers
When we for example get an Altivec interrupt, but our guest doesn't support altivec, we need to inject a program interrupt, not an altivec interrupt. The same goes for paired singles. When an altivec interrupt arrives, we're pretty sure we need to emulate the instruction because it's a paired single operation. So let's make all the ext handlers aware that they need to jump to the program interrupt handler when an extension interrupt arrives that was not supposed to arrive for the guest CPU. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r--arch/powerpc/kvm/book3s.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 8cb9f5a67464..b18415fc0188 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -37,6 +37,8 @@
37/* #define DEBUG_EXT */ 37/* #define DEBUG_EXT */
38 38
39static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); 39static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
40static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
41 ulong msr);
40 42
41struct kvm_stats_debugfs_item debugfs_entries[] = { 43struct kvm_stats_debugfs_item debugfs_entries[] = {
42 { "exits", VCPU_STAT(sum_exits) }, 44 { "exits", VCPU_STAT(sum_exits) },
@@ -629,6 +631,30 @@ static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
629 kvmppc_recalc_shadow_msr(vcpu); 631 kvmppc_recalc_shadow_msr(vcpu);
630} 632}
631 633
634static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
635{
636 ulong srr0 = vcpu->arch.pc;
637 int ret;
638
639 /* Need to do paired single emulation? */
640 if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
641 return EMULATE_DONE;
642
643 /* Read out the instruction */
644 ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &vcpu->arch.last_inst, false);
645 if (ret == -ENOENT) {
646 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1);
647 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0);
648 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
649 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
650 } else if(ret == EMULATE_DONE) {
651 /* Need to emulate */
652 return EMULATE_FAIL;
653 }
654
655 return EMULATE_AGAIN;
656}
657
632/* Handle external providers (FPU, Altivec, VSX) */ 658/* Handle external providers (FPU, Altivec, VSX) */
633static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, 659static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
634 ulong msr) 660 ulong msr)
@@ -773,6 +799,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
773 enum emulation_result er; 799 enum emulation_result er;
774 ulong flags; 800 ulong flags;
775 801
802program_interrupt:
776 flags = vcpu->arch.shadow_srr1 & 0x1f0000ull; 803 flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
777 804
778 if (vcpu->arch.msr & MSR_PR) { 805 if (vcpu->arch.msr & MSR_PR) {
@@ -816,14 +843,32 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
816 r = RESUME_GUEST; 843 r = RESUME_GUEST;
817 break; 844 break;
818 case BOOK3S_INTERRUPT_FP_UNAVAIL: 845 case BOOK3S_INTERRUPT_FP_UNAVAIL:
819 r = kvmppc_handle_ext(vcpu, exit_nr, MSR_FP);
820 break;
821 case BOOK3S_INTERRUPT_ALTIVEC: 846 case BOOK3S_INTERRUPT_ALTIVEC:
822 r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VEC);
823 break;
824 case BOOK3S_INTERRUPT_VSX: 847 case BOOK3S_INTERRUPT_VSX:
825 r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VSX); 848 {
849 int ext_msr = 0;
850
851 switch (exit_nr) {
852 case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break;
853 case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break;
854 case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break;
855 }
856
857 switch (kvmppc_check_ext(vcpu, exit_nr)) {
858 case EMULATE_DONE:
859 /* everything ok - let's enable the ext */
860 r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
861 break;
862 case EMULATE_FAIL:
863 /* we need to emulate this instruction */
864 goto program_interrupt;
865 break;
866 default:
867 /* nothing to worry about - go again */
868 break;
869 }
826 break; 870 break;
871 }
827 case BOOK3S_INTERRUPT_MACHINE_CHECK: 872 case BOOK3S_INTERRUPT_MACHINE_CHECK:
828 case BOOK3S_INTERRUPT_TRACE: 873 case BOOK3S_INTERRUPT_TRACE:
829 kvmppc_book3s_queue_irqprio(vcpu, exit_nr); 874 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);