KVM: PPC: Move kvm_vcpu_ioctl_[gs]et_one_reg down to platform-specific code
authorPaul Mackerras <paulus@samba.org>
Mon, 12 Dec 2011 12:26:50 +0000 (12:26 +0000)
committerAvi Kivity <avi@redhat.com>
Mon, 5 Mar 2012 12:52:41 +0000 (14:52 +0200)
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>
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/powerpc.c

index fb70414db90c9623d22da187c1aa2c3e65ccbac0..a61b5b5047d6b3ef0ad9d2e47f0a7247bb544053 100644 (file)
@@ -176,6 +176,9 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
index fdc804c839387231a3de2928c5f278a673da24a1..3580db8a23268b9cac3b2b9775555295f727fffe 100644 (file)
@@ -398,6 +398,42 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(0, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+       {
+               u64 hior;
+               /* Only allow this to be set to zero */
+               r = get_user(hior, (u64 __user *)reg->addr);
+               if (!r && (hior != 0))
+                       r = -EINVAL;
+               break;
+       }
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        if (cpu_has_feature(CPU_FTR_HVMODE))
index 00efda6dc0e2b72ac98f43728a2f21a9d917e5b1..ee222ec7c95ce268c960e190be6d7a5b81c5e2d6 100644 (file)
@@ -874,6 +874,38 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               if (!r)
+                       to_book3s(vcpu)->hior_explicit = true;
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        return 0;
index 9e41f45d07ed67f6aba66524a5288edd0f641a51..ee9e1ee9c858116aad1256e35fd27f61eb749994 100644 (file)
@@ -887,6 +887,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return kvmppc_core_set_sregs(vcpu, sregs);
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        return -ENOTSUPP;
index 59852091b38961529d5eb57b24890fe36205e1d9..e23270779ff5d126287be071ff42c24cdfbb3a65 100644 (file)
@@ -647,44 +647,6 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        return r;
 }
 
-static int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
-                                     struct kvm_one_reg *reg)
-{
-       int r = -EINVAL;
-
-       switch (reg->id) {
-#ifdef CONFIG_PPC_BOOK3S
-       case KVM_REG_PPC_HIOR:
-               r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
-               break;
-#endif
-       default:
-               break;
-       }
-
-       return r;
-}
-
-static int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
-                                     struct kvm_one_reg *reg)
-{
-       int r = -EINVAL;
-
-       switch (reg->id) {
-#ifdef CONFIG_PPC_BOOK3S
-       case KVM_ONE_REG_PPC_HIOR:
-               r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
-               if (!r)
-                       to_book3s(vcpu)->hior_explicit = true;
-               break;
-#endif
-       default:
-               break;
-       }
-
-       return r;
-}
-
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
                                     struct kvm_mp_state *mp_state)
 {