aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-12-12 07:26:50 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:41 -0500
commit31f3438eca2fc90dc892e0e9963ba4b93a2c8383 (patch)
tree21f3b35bf1941c3429299987564bdca3b1dd64e7 /arch/powerpc
parent1022fc3d3bfaca09d5d6bfcc93a168de16840814 (diff)
KVM: PPC: Move kvm_vcpu_ioctl_[gs]et_one_reg down to platform-specific code
This moves the get/set_one_reg implementation down from powerpc.c into booke.c, book3s_pr.c and book3s_hv.c. This avoids #ifdefs in C code, but more importantly, it fixes a bug on Book3s HV where we were accessing beyond the end of the kvm_vcpu struct (via the to_book3s() macro) and corrupting memory, causing random crashes and file corruption. On Book3s HV we only accept setting the HIOR to zero, since the guest runs in supervisor mode and its vectors are never offset from zero. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de> [agraf update to apply on top of changed ONE_REG patches] Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h3
-rw-r--r--arch/powerpc/kvm/book3s_hv.c36
-rw-r--r--arch/powerpc/kvm/book3s_pr.c32
-rw-r--r--arch/powerpc/kvm/booke.c10
-rw-r--r--arch/powerpc/kvm/powerpc.c38
5 files changed, 81 insertions, 38 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index fb70414db90c..a61b5b5047d6 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -176,6 +176,9 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
176void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 176void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
177int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 177int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
178 178
179int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
180int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
181
179void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid); 182void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
180 183
181#ifdef CONFIG_KVM_BOOK3S_64_HV 184#ifdef CONFIG_KVM_BOOK3S_64_HV
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index fdc804c83938..3580db8a2326 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -398,6 +398,42 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
398 return 0; 398 return 0;
399} 399}
400 400
401int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
402{
403 int r = -EINVAL;
404
405 switch (reg->id) {
406 case KVM_REG_PPC_HIOR:
407 r = put_user(0, (u64 __user *)reg->addr);
408 break;
409 default:
410 break;
411 }
412
413 return r;
414}
415
416int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
417{
418 int r = -EINVAL;
419
420 switch (reg->id) {
421 case KVM_REG_PPC_HIOR:
422 {
423 u64 hior;
424 /* Only allow this to be set to zero */
425 r = get_user(hior, (u64 __user *)reg->addr);
426 if (!r && (hior != 0))
427 r = -EINVAL;
428 break;
429 }
430 default:
431 break;
432 }
433
434 return r;
435}
436
401int kvmppc_core_check_processor_compat(void) 437int kvmppc_core_check_processor_compat(void)
402{ 438{
403 if (cpu_has_feature(CPU_FTR_HVMODE)) 439 if (cpu_has_feature(CPU_FTR_HVMODE))
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 00efda6dc0e2..ee222ec7c95c 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -874,6 +874,38 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
874 return 0; 874 return 0;
875} 875}
876 876
877int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
878{
879 int r = -EINVAL;
880
881 switch (reg->id) {
882 case KVM_REG_PPC_HIOR:
883 r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
884 break;
885 default:
886 break;
887 }
888
889 return r;
890}
891
892int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
893{
894 int r = -EINVAL;
895
896 switch (reg->id) {
897 case KVM_REG_PPC_HIOR:
898 r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
899 if (!r)
900 to_book3s(vcpu)->hior_explicit = true;
901 break;
902 default:
903 break;
904 }
905
906 return r;
907}
908
877int kvmppc_core_check_processor_compat(void) 909int kvmppc_core_check_processor_compat(void)
878{ 910{
879 return 0; 911 return 0;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 9e41f45d07ed..ee9e1ee9c858 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -887,6 +887,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
887 return kvmppc_core_set_sregs(vcpu, sregs); 887 return kvmppc_core_set_sregs(vcpu, sregs);
888} 888}
889 889
890int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
891{
892 return -EINVAL;
893}
894
895int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
896{
897 return -EINVAL;
898}
899
890int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 900int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
891{ 901{
892 return -ENOTSUPP; 902 return -ENOTSUPP;
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 59852091b389..e23270779ff5 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -647,44 +647,6 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
647 return r; 647 return r;
648} 648}
649 649
650static int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
651 struct kvm_one_reg *reg)
652{
653 int r = -EINVAL;
654
655 switch (reg->id) {
656#ifdef CONFIG_PPC_BOOK3S
657 case KVM_REG_PPC_HIOR:
658 r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
659 break;
660#endif
661 default:
662 break;
663 }
664
665 return r;
666}
667
668static int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
669 struct kvm_one_reg *reg)
670{
671 int r = -EINVAL;
672
673 switch (reg->id) {
674#ifdef CONFIG_PPC_BOOK3S
675 case KVM_ONE_REG_PPC_HIOR:
676 r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
677 if (!r)
678 to_book3s(vcpu)->hior_explicit = true;
679 break;
680#endif
681 default:
682 break;
683 }
684
685 return r;
686}
687
688int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, 650int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
689 struct kvm_mp_state *mp_state) 651 struct kvm_mp_state *mp_state)
690{ 652{