aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2011-08-10 07:57:08 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:52:27 -0400
commitaf8f38b3499f0d4a3c354df2435f0fb2dded250a (patch)
tree129cf6f362fb623c80f8c2aa89c6fb3030b04c8d /arch/powerpc
parent930b412a005bde2ea3f05911eaaeeb10f11d79ab (diff)
KVM: PPC: Add sanity checking to vcpu_run
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm.h5
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h1
-rw-r--r--arch/powerpc/kvm/44x.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv.c8
-rw-r--r--arch/powerpc/kvm/book3s_pr.c10
-rw-r--r--arch/powerpc/kvm/booke.c10
-rw-r--r--arch/powerpc/kvm/e500.c2
-rw-r--r--arch/powerpc/kvm/powerpc.c28
9 files changed, 67 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index a6a253ee81bb..08fe69edcd10 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -284,6 +284,11 @@ struct kvm_guest_debug_arch {
284#define KVM_INTERRUPT_UNSET -2U 284#define KVM_INTERRUPT_UNSET -2U
285#define KVM_INTERRUPT_SET_LEVEL -3U 285#define KVM_INTERRUPT_SET_LEVEL -3U
286 286
287#define KVM_CPU_440 1
288#define KVM_CPU_E500V2 2
289#define KVM_CPU_3S_32 3
290#define KVM_CPU_3S_64 4
291
287/* for KVM_CAP_SPAPR_TCE */ 292/* for KVM_CAP_SPAPR_TCE */
288struct kvm_create_spapr_tce { 293struct kvm_create_spapr_tce {
289 __u64 liobn; 294 __u64 liobn;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index e6813021126d..2b8284f4b4b7 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -390,6 +390,8 @@ struct kvm_vcpu_arch {
390 u8 osi_needed; 390 u8 osi_needed;
391 u8 osi_enabled; 391 u8 osi_enabled;
392 u8 papr_enabled; 392 u8 papr_enabled;
393 u8 sane;
394 u8 cpu_type;
393 u8 hcall_needed; 395 u8 hcall_needed;
394 396
395 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ 397 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index d121f49d62b8..46efd1a265c9 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
66extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu); 66extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
67extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); 67extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
68extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb); 68extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
69extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
69 70
70/* Core-specific hooks */ 71/* Core-specific hooks */
71 72
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index da3a1225c0ac..ca1f88b3dc59 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -78,6 +78,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
78 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) 78 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
79 vcpu_44x->shadow_refs[i].gtlb_index = -1; 79 vcpu_44x->shadow_refs[i].gtlb_index = -1;
80 80
81 vcpu->arch.cpu_type = KVM_CPU_440;
82
81 return 0; 83 return 0;
82} 84}
83 85
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cc0d7f1b19ab..bf66ec731e8f 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -510,6 +510,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
510 spin_unlock(&vcore->lock); 510 spin_unlock(&vcore->lock);
511 vcpu->arch.vcore = vcore; 511 vcpu->arch.vcore = vcore;
512 512
513 vcpu->arch.cpu_type = KVM_CPU_3S_64;
514 kvmppc_sanity_check(vcpu);
515
513 return vcpu; 516 return vcpu;
514 517
515free_vcpu: 518free_vcpu:
@@ -800,6 +803,11 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
800{ 803{
801 int r; 804 int r;
802 805
806 if (!vcpu->arch.sane) {
807 run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
808 return -EINVAL;
809 }
810
803 do { 811 do {
804 r = kvmppc_run_vcpu(run, vcpu); 812 r = kvmppc_run_vcpu(run, vcpu);
805 813
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 48558f6176e9..6e3488b09519 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -153,6 +153,7 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
153 if (!to_book3s(vcpu)->hior_sregs) 153 if (!to_book3s(vcpu)->hior_sregs)
154 to_book3s(vcpu)->hior = 0xfff00000; 154 to_book3s(vcpu)->hior = 0xfff00000;
155 to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL; 155 to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
156 vcpu->arch.cpu_type = KVM_CPU_3S_64;
156 } else 157 } else
157#endif 158#endif
158 { 159 {
@@ -160,8 +161,11 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
160 if (!to_book3s(vcpu)->hior_sregs) 161 if (!to_book3s(vcpu)->hior_sregs)
161 to_book3s(vcpu)->hior = 0; 162 to_book3s(vcpu)->hior = 0;
162 to_book3s(vcpu)->msr_mask = 0xffffffffULL; 163 to_book3s(vcpu)->msr_mask = 0xffffffffULL;
164 vcpu->arch.cpu_type = KVM_CPU_3S_32;
163 } 165 }
164 166
167 kvmppc_sanity_check(vcpu);
168
165 /* If we are in hypervisor level on 970, we can tell the CPU to 169 /* If we are in hypervisor level on 970, we can tell the CPU to
166 * treat DCBZ as 32 bytes store */ 170 * treat DCBZ as 32 bytes store */
167 vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32; 171 vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
@@ -938,6 +942,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
938#endif 942#endif
939 ulong ext_msr; 943 ulong ext_msr;
940 944
945 /* Check if we can run the vcpu at all */
946 if (!vcpu->arch.sane) {
947 kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
948 return -EINVAL;
949 }
950
941 /* No need to go into the guest when all we do is going out */ 951 /* No need to go into the guest when all we do is going out */
942 if (signal_pending(current)) { 952 if (signal_pending(current)) {
943 kvm_run->exit_reason = KVM_EXIT_INTR; 953 kvm_run->exit_reason = KVM_EXIT_INTR;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ee45fa01220e..bb6c988f010a 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -316,6 +316,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
316{ 316{
317 int ret; 317 int ret;
318 318
319 if (!vcpu->arch.sane) {
320 kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
321 return -EINVAL;
322 }
323
319 local_irq_disable(); 324 local_irq_disable();
320 kvm_guest_enter(); 325 kvm_guest_enter();
321 ret = __kvmppc_vcpu_run(kvm_run, vcpu); 326 ret = __kvmppc_vcpu_run(kvm_run, vcpu);
@@ -618,6 +623,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
618int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) 623int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
619{ 624{
620 int i; 625 int i;
626 int r;
621 627
622 vcpu->arch.pc = 0; 628 vcpu->arch.pc = 0;
623 vcpu->arch.shared->msr = 0; 629 vcpu->arch.shared->msr = 0;
@@ -634,7 +640,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
634 640
635 kvmppc_init_timing_stats(vcpu); 641 kvmppc_init_timing_stats(vcpu);
636 642
637 return kvmppc_core_vcpu_setup(vcpu); 643 r = kvmppc_core_vcpu_setup(vcpu);
644 kvmppc_sanity_check(vcpu);
645 return r;
638} 646}
639 647
640int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 648int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 797a7447c268..26d20903f2bc 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -73,6 +73,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
73 /* Since booke kvm only support one core, update all vcpus' PIR to 0 */ 73 /* Since booke kvm only support one core, update all vcpus' PIR to 0 */
74 vcpu->vcpu_id = 0; 74 vcpu->vcpu_id = 0;
75 75
76 vcpu->arch.cpu_type = KVM_CPU_E500V2;
77
76 return 0; 78 return 0;
77} 79}
78 80
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 13bc798a4441..a8000ce562b0 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -95,6 +95,31 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
95 return r; 95 return r;
96} 96}
97 97
98int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
99{
100 int r = false;
101
102 /* We have to know what CPU to virtualize */
103 if (!vcpu->arch.pvr)
104 goto out;
105
106 /* PAPR only works with book3s_64 */
107 if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
108 goto out;
109
110#ifdef CONFIG_KVM_BOOK3S_64_HV
111 /* HV KVM can only do PAPR mode for now */
112 if (!vcpu->arch.papr_enabled)
113 goto out;
114#endif
115
116 r = true;
117
118out:
119 vcpu->arch.sane = r;
120 return r ? 0 : -EINVAL;
121}
122
98int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) 123int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
99{ 124{
100 enum emulation_result er; 125 enum emulation_result er;
@@ -582,6 +607,9 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
582 break; 607 break;
583 } 608 }
584 609
610 if (!r)
611 r = kvmppc_sanity_check(vcpu);
612
585 return r; 613 return r;
586} 614}
587 615