KVM: PPC: Add sanity checking to vcpu_run
authorAlexander Graf <agraf@suse.de>
Wed, 10 Aug 2011 11:57:08 +0000 (13:57 +0200)
committerAvi Kivity <avi@redhat.com>
Sun, 25 Sep 2011 16:52:27 +0000 (19:52 +0300)
There are multiple features in PowerPC KVM that can now be enabled
depending on the user's wishes. Some of the combinations don't make
sense or don't work though.

So this patch adds a way to check if the executing environment would
actually be able to run the guest properly. It also adds sanity
checks if PVR is set (should always be true given the current code
flow), if PAPR is only used with book3s_64 where it works and that
HV KVM is only used in PAPR mode.

Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/kvm.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/44x.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/powerpc.c

index a6a253ee81bbf65962f46f51a8dfe189f290062d..08fe69edcd103f7882a3e172b7c5a55764009550 100644 (file)
@@ -284,6 +284,11 @@ struct kvm_guest_debug_arch {
 #define KVM_INTERRUPT_UNSET    -2U
 #define KVM_INTERRUPT_SET_LEVEL        -3U
 
+#define KVM_CPU_440            1
+#define KVM_CPU_E500V2         2
+#define KVM_CPU_3S_32          3
+#define KVM_CPU_3S_64          4
+
 /* for KVM_CAP_SPAPR_TCE */
 struct kvm_create_spapr_tce {
        __u64 liobn;
index e6813021126d270edc67e37904c51937b2cb9e49..2b8284f4b4b72f4f620c912629e793d55c3de2e6 100644 (file)
@@ -390,6 +390,8 @@ struct kvm_vcpu_arch {
        u8 osi_needed;
        u8 osi_enabled;
        u8 papr_enabled;
+       u8 sane;
+       u8 cpu_type;
        u8 hcall_needed;
 
        u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
index d121f49d62b85186bc4f3eabe1af64ceab501534..46efd1a265c958775f390a4b72d53d40c8890e3a 100644 (file)
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
index da3a1225c0ac10117918f105799f8d60b20665ce..ca1f88b3dc596fb099c8fba2a9659fbe047592f5 100644 (file)
@@ -78,6 +78,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
        for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
                vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
+       vcpu->arch.cpu_type = KVM_CPU_440;
+
        return 0;
 }
 
index cc0d7f1b19ab474f62c702192f8fb44ff8ecf216..bf66ec731e8fe83001f9df0bbd8a9a9a42b93f51 100644 (file)
@@ -510,6 +510,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
        spin_unlock(&vcore->lock);
        vcpu->arch.vcore = vcore;
 
+       vcpu->arch.cpu_type = KVM_CPU_3S_64;
+       kvmppc_sanity_check(vcpu);
+
        return vcpu;
 
 free_vcpu:
@@ -800,6 +803,11 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
        int r;
 
+       if (!vcpu->arch.sane) {
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               return -EINVAL;
+       }
+
        do {
                r = kvmppc_run_vcpu(run, vcpu);
 
index 48558f6176e9fc3ca2b1b13ad0161d1e98db4558..6e3488b0951945904adb30b10898ac91811bb8dc 100644 (file)
@@ -153,6 +153,7 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
                if (!to_book3s(vcpu)->hior_sregs)
                        to_book3s(vcpu)->hior = 0xfff00000;
                to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+               vcpu->arch.cpu_type = KVM_CPU_3S_64;
        } else
 #endif
        {
@@ -160,8 +161,11 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
                if (!to_book3s(vcpu)->hior_sregs)
                        to_book3s(vcpu)->hior = 0;
                to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+               vcpu->arch.cpu_type = KVM_CPU_3S_32;
        }
 
+       kvmppc_sanity_check(vcpu);
+
        /* If we are in hypervisor level on 970, we can tell the CPU to
         * treat DCBZ as 32 bytes store */
        vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
@@ -938,6 +942,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
        ulong ext_msr;
 
+       /* Check if we can run the vcpu at all */
+       if (!vcpu->arch.sane) {
+               kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               return -EINVAL;
+       }
+
        /* No need to go into the guest when all we do is going out */
        if (signal_pending(current)) {
                kvm_run->exit_reason = KVM_EXIT_INTR;
index ee45fa01220ef11679ea081cdb5c9ccf4e1ab4d0..bb6c988f010aa29b0732d628788547456e6b577c 100644 (file)
@@ -316,6 +316,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int ret;
 
+       if (!vcpu->arch.sane) {
+               kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               return -EINVAL;
+       }
+
        local_irq_disable();
        kvm_guest_enter();
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
@@ -618,6 +623,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
        int i;
+       int r;
 
        vcpu->arch.pc = 0;
        vcpu->arch.shared->msr = 0;
@@ -634,7 +640,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 
        kvmppc_init_timing_stats(vcpu);
 
-       return kvmppc_core_vcpu_setup(vcpu);
+       r = kvmppc_core_vcpu_setup(vcpu);
+       kvmppc_sanity_check(vcpu);
+       return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
index 797a7447c268aff9f0ee603ab8c22c0546ba4d4c..26d20903f2bc5c8cce1a94637f58ea9dea73a696 100644 (file)
@@ -73,6 +73,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
        /* Since booke kvm only support one core, update all vcpus' PIR to 0 */
        vcpu->vcpu_id = 0;
 
+       vcpu->arch.cpu_type = KVM_CPU_E500V2;
+
        return 0;
 }
 
index 13bc798a44414fa0c528c36dd8e704e337ed6de5..a8000ce562b06c8c2084cf884613bd685112e2d9 100644 (file)
@@ -95,6 +95,31 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
        return r;
 }
 
+int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
+{
+       int r = false;
+
+       /* We have to know what CPU to virtualize */
+       if (!vcpu->arch.pvr)
+               goto out;
+
+       /* PAPR only works with book3s_64 */
+       if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
+               goto out;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+       /* HV KVM can only do PAPR mode for now */
+       if (!vcpu->arch.papr_enabled)
+               goto out;
+#endif
+
+       r = true;
+
+out:
+       vcpu->arch.sane = r;
+       return r ? 0 : -EINVAL;
+}
+
 int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
        enum emulation_result er;
@@ -582,6 +607,9 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
                break;
        }
 
+       if (!r)
+               r = kvmppc_sanity_check(vcpu);
+
        return r;
 }