Patchwork [v2] kvm: ppc: fixes for KVM_SET_SREGS on init

login
register
mail settings
Submitter Scott Wood
Date April 11, 2011, 11:34 p.m.
Message ID <20110411233434.GA28232@schlenkerla.am.freescale.net>
Download mbox | patch
Permalink /patch/90688/
State New
Headers show

Comments

Scott Wood - April 11, 2011, 11:34 p.m.
Classic/server ppc has had SREGS for a while now (though I think not
always?), but it's still missing for booke.  Check the capability before
calling KVM_SET_SREGS.

Without this, booke kvm fails to boot as of commit
84b4915dd2c0eaa86c970ffc42a68ea8ba9e48b5 (kvm: Handle kvm_init_vcpu
errors).

Also, don't write random stack state into the non-PVR sregs fields --
have kvm fill it in first.

Eventually booke will have sregs and it will have its own capability to
be tested here.  However, we will want a way for platform code to request
to look like the actual CPU we're running on, especially if SoC devices
are being directly assigned.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v2: Use a runtime check for booke, at least for now.

 target-ppc/kvm.c |   33 ++++++++++++++++++++++++++++++---
 1 files changed, 30 insertions(+), 3 deletions(-)

Patch

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2cfb24b..e3cde16 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -77,13 +77,40 @@  int kvm_arch_init(KVMState *s)
     return 0;
 }
 
-int kvm_arch_init_vcpu(CPUState *cenv)
+static int kvm_arch_sync_sregs(CPUState *cenv)
 {
-    int ret = 0;
     struct kvm_sregs sregs;
+    int ret;
+
+    if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
+        return 0;
+    } else {
+#ifdef KVM_CAP_PPC_SEGSTATE
+        if (!kvm_check_extension(cenv->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
+            return 0;
+        }
+#else
+        return 0;
+#endif
+    }
+    
+    ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
+    if (ret) {
+        return ret;
+    }
 
     sregs.pvr = cenv->spr[SPR_PVR];
-    ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
+    return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
+}
+
+int kvm_arch_init_vcpu(CPUState *cenv)
+{
+    int ret;
+
+    ret = kvm_arch_sync_sregs(cenv);
+    if (ret) {
+        return ret;
+    }
 
     idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);