From: Borislav Petkov <b...@suse.de>

Add support for the KVM_GET_EMULATED_CPUID ioctl and leave feature bits
enabled, when requested by userspace, if kvm emulates them.

Signed-off-by: Borislav Petkov <b...@suse.de>
[ehabkost: removed target-i386/cpu.c code, changed patch description]
Signed-off-by: Eduardo Habkost <ehabk...@redhat.com>
---
 include/sysemu/kvm.h |  3 +++
 target-i386/kvm.c    | 38 ++++++++++++++++++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index e7ad9d1..ab1ffdb 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -324,6 +324,9 @@ int kvm_check_extension(KVMState *s, unsigned int 
extension);
 
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
+uint32_t kvm_arch_get_emulated_cpuid(KVMState *env, uint32_t function,
+                                     uint32_t index, int reg);
+
 
 #if !defined(CONFIG_USER_ONLY)
 int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f9ffa4b..242df34 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -88,7 +88,7 @@ bool kvm_allows_irq0_override(void)
     return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
 }
 
-static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
+static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int ioctl, int max)
 {
     struct kvm_cpuid2 *cpuid;
     int r, size;
@@ -96,7 +96,7 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
     size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
     cpuid = (struct kvm_cpuid2 *)g_malloc0(size);
     cpuid->nent = max;
-    r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
+    r = kvm_ioctl(s, ioctl, cpuid);
     if (r == 0 && cpuid->nent >= max) {
         r = -E2BIG;
     }
@@ -105,7 +105,10 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int 
max)
             g_free(cpuid);
             return NULL;
         } else {
-            fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
+            fprintf(stderr, "%s failed: %s\n",
+                    (ioctl == (int)KVM_GET_SUPPORTED_CPUID
+                     ? "KVM_GET_SUPPORTED_CPUID"
+                     : "KVM_GET_EMULATED_CPUID"),
                     strerror(-r));
             exit(1);
         }
@@ -120,7 +123,17 @@ static struct kvm_cpuid2 *get_supported_cpuid(KVMState *s)
 {
     struct kvm_cpuid2 *cpuid;
     int max = 1;
-    while ((cpuid = try_get_cpuid(s, max)) == NULL) {
+    while ((cpuid = try_get_cpuid(s, KVM_GET_SUPPORTED_CPUID, max)) == NULL) {
+        max *= 2;
+    }
+    return cpuid;
+}
+
+static struct kvm_cpuid2 *get_emulated_cpuid(KVMState *s)
+{
+    struct kvm_cpuid2 *cpuid;
+    int max = 1;
+    while ((cpuid = try_get_cpuid(s, KVM_GET_EMULATED_CPUID, max)) == NULL) {
         max *= 2;
     }
     return cpuid;
@@ -248,6 +261,23 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, 
uint32_t function,
     return ret;
 }
 
+uint32_t kvm_arch_get_emulated_cpuid(KVMState *s, uint32_t function,
+                                     uint32_t index, int reg)
+{
+    struct kvm_cpuid2 *cpuid __attribute__((unused));
+
+    if (!kvm_check_extension(s, KVM_CAP_EXT_EMUL_CPUID))
+        return 0;
+
+    cpuid = get_emulated_cpuid(s);
+
+    struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index);
+    if (entry)
+        return cpuid_entry_get_reg(entry, reg);
+
+    return 0;
+}
+
 typedef struct HWPoisonPage {
     ram_addr_t ram_addr;
     QLIST_ENTRY(HWPoisonPage) list;
-- 
1.9.0


Reply via email to