summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target-ppc/kvm.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 546c11604c..1975323eb7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1127,18 +1127,38 @@ int kvmppc_reset_htab(int shift_hint)
 {
     uint32_t shift = shift_hint;
 
-    if (kvm_enabled() &&
-        kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
+    if (!kvm_enabled()) {
+        /* Full emulation, tell caller to allocate htab itself */
+        return 0;
+    }
+    if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
         int ret;
         ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
-        if (ret < 0) {
+        if (ret == -ENOTTY) {
+            /* At least some versions of PR KVM advertise the
+             * capability, but don't implement the ioctl().  Oops.
+             * Return 0 so that we allocate the htab in qemu, as is
+             * correct for PR. */
+            return 0;
+        } else if (ret < 0) {
             return ret;
         }
         return shift;
     }
 
-    /* For now.. */
-    return 0;
+    /* We have a kernel that predates the htab reset calls.  For PR
+     * KVM, we need to allocate the htab ourselves, for an HV KVM of
+     * this era, it has allocated a 16MB fixed size hash table
+     * already.  Kernels of this era have the GET_PVINFO capability
+     * only on PR, so we use this hack to determine the right
+     * answer */
+    if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
+        /* PR - tell caller to allocate htab */
+        return 0;
+    } else {
+        /* HV - assume 16MB kernel allocated htab */
+        return 24;
+    }
 }
 
 static inline uint32_t mfpvr(void)