[libvirt PATCH v2 15/20] virhostcpu: Add virHostCPUGetCPUID

Tim Wiederhake twiederh at redhat.com
Thu Nov 4 16:27:15 UTC 2021


Signed-off-by: Tim Wiederhake <twiederh at redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/util/virhostcpu.c    | 43 ++++++++++++++++++++++++++++++++++++++++
 src/util/virhostcpu.h    |  2 ++
 3 files changed, 46 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 665db255a6..e92670c85d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2396,6 +2396,7 @@ virHookPresent;
 # util/virhostcpu.h
 virHostCPUGetAvailableCPUsBitmap;
 virHostCPUGetCount;
+virHostCPUGetCPUID;
 virHostCPUGetHaltPollTime;
 virHostCPUGetInfo;
 virHostCPUGetKVMMaxVCPUs;
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index 5dd2baf2df..3563a662d5 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -1336,6 +1336,41 @@ virHostCPUGetMSR(unsigned long index,
 }
 
 
+struct kvm_cpuid2 *
+virHostCPUGetCPUID(void)
+{
+    size_t i;
+    VIR_AUTOCLOSE fd = open(KVM_DEVICE, O_RDONLY);
+
+    if (fd < 0) {
+        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
+        return NULL;
+    }
+
+    for (i = 1; i < INT32_MAX; i *= 2) {
+        g_autofree struct kvm_cpuid2 *kvm_cpuid = NULL;
+        kvm_cpuid = g_malloc0(sizeof(struct kvm_cpuid2) +
+                              sizeof(struct kvm_cpuid_entry2) * i);
+        kvm_cpuid->nent = i;
+
+        if (ioctl(fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) == 0) {
+            /* filter out local apic id */
+            for (i = 0; i < kvm_cpuid->nent; ++i) {
+                struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i];
+                if (entry->function == 0x01 && entry->index == 0x00)
+                    entry->ebx &= 0x00ffffff;
+                if (entry->function == 0x0b)
+                    entry->edx &= 0xffffff00;
+            }
+
+            return g_steal_pointer(&kvm_cpuid);
+        }
+    }
+
+    virReportSystemError(errno, "%s", _("Cannot read host CPUID"));
+    return NULL;
+}
+
 /*
  * This function should only be called when the host CPU supports invariant TSC
  * (invtsc CPUID feature).
@@ -1391,6 +1426,14 @@ virHostCPUGetTscInfo(void)
 
 #else
 
+struct kvm_cpuid2 *
+virHostCPUGetCPUID(void)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Reading CPUID is not supported on this platform"));
+    return NULL;
+}
+
 int
 virHostCPUGetMSR(unsigned long index G_GNUC_UNUSED,
                  uint64_t *msr G_GNUC_UNUSED)
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
index d98385d53f..a96dd5afba 100644
--- a/src/util/virhostcpu.h
+++ b/src/util/virhostcpu.h
@@ -80,6 +80,8 @@ virHostCPUGetMicrocodeVersion(virArch hostArch) G_GNUC_NO_INLINE;
 int virHostCPUGetMSR(unsigned long index,
                      uint64_t *msr);
 
+struct kvm_cpuid2 *virHostCPUGetCPUID(void);
+
 virHostCPUTscInfo *virHostCPUGetTscInfo(void);
 
 int virHostCPUGetSignature(char **signature);
-- 
2.31.1




More information about the libvir-list mailing list