Pablo Greco 40546a
From c465e315637d0b2cf01d2957de3d816186e0fd0f Mon Sep 17 00:00:00 2001
Pablo Greco 40546a
Message-Id: <c465e315637d0b2cf01d2957de3d816186e0fd0f@dist-git>
Pablo Greco 40546a
From: Jiri Denemark <jdenemar@redhat.com>
Pablo Greco 40546a
Date: Fri, 21 Jun 2019 09:25:38 +0200
Pablo Greco 40546a
Subject: [PATCH] cpu_x86: Store virCPUx86DataItem content in union
Pablo Greco 40546a
MIME-Version: 1.0
Pablo Greco 40546a
Content-Type: text/plain; charset=UTF-8
Pablo Greco 40546a
Content-Transfer-Encoding: 8bit
Pablo Greco 40546a
Pablo Greco 40546a
The structure can only be used for CPUID data now. Adding a type
Pablo Greco 40546a
indicator and moving the data into a union will let us store alternative
Pablo Greco 40546a
data types.
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Pablo Greco 40546a
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Pablo Greco 40546a
(cherry picked from commit 370177e2f6784319b2fc86d8fe7a271248a5982e)
Pablo Greco 40546a
Pablo Greco 40546a
https://bugzilla.redhat.com/show_bug.cgi?id=1697627
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Pablo Greco 40546a
Message-Id: <00cf7daca0cde66e9a90f64435182ef430983b2e.1561068591.git.jdenemar@redhat.com>
Pablo Greco 40546a
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Pablo Greco 40546a
---
Pablo Greco 40546a
 src/cpu/cpu_x86.c              | 202 ++++++++++++++++++++++++---------
Pablo Greco 40546a
 src/cpu/cpu_x86_data.h         |  10 +-
Pablo Greco 40546a
 src/libxl/libxl_capabilities.c |   3 +-
Pablo Greco 40546a
 src/qemu/qemu_monitor_json.c   |   3 +-
Pablo Greco 40546a
 4 files changed, 160 insertions(+), 58 deletions(-)
Pablo Greco 40546a
Pablo Greco 40546a
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
Pablo Greco 40546a
index 11c023ac31..e6da974b31 100644
Pablo Greco 40546a
--- a/src/cpu/cpu_x86.c
Pablo Greco 40546a
+++ b/src/cpu/cpu_x86.c
Pablo Greco 40546a
@@ -59,7 +59,9 @@ struct _virCPUx86Feature {
Pablo Greco 40546a
 };
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
-#define CPUID(...) { .cpuid = {__VA_ARGS__} }
Pablo Greco 40546a
+#define CPUID(...) \
Pablo Greco 40546a
+    { .type = VIR_CPU_X86_DATA_CPUID, \
Pablo Greco 40546a
+      .data = { .cpuid = {__VA_ARGS__} } }
Pablo Greco 40546a
 
Pablo Greco 40546a
 #define KVM_FEATURE_DEF(Name, Eax_in, Eax) \
Pablo Greco 40546a
     static virCPUx86DataItem Name ## _data[] = { \
Pablo Greco 40546a
@@ -193,10 +195,22 @@ static bool
Pablo Greco 40546a
 virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
Pablo Greco 40546a
                        const virCPUx86DataItem *item2)
Pablo Greco 40546a
 {
Pablo Greco 40546a
-    return (item1->cpuid.eax == item2->cpuid.eax &&
Pablo Greco 40546a
-            item1->cpuid.ebx == item2->cpuid.ebx &&
Pablo Greco 40546a
-            item1->cpuid.ecx == item2->cpuid.ecx &&
Pablo Greco 40546a
-            item1->cpuid.edx == item2->cpuid.edx);
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuid1;
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuid2;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    switch (item1->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        cpuid1 = &item1->data.cpuid;
Pablo Greco 40546a
+        cpuid2 = &item2->data.cpuid;
Pablo Greco 40546a
+        return (cpuid1->eax == cpuid2->eax &&
Pablo Greco 40546a
+                cpuid1->ebx == cpuid2->ebx &&
Pablo Greco 40546a
+                cpuid1->ecx == cpuid2->ecx &&
Pablo Greco 40546a
+                cpuid1->edx == cpuid2->edx);
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        return false;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -204,10 +218,22 @@ static bool
Pablo Greco 40546a
 virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
Pablo Greco 40546a
                              const virCPUx86DataItem *mask)
Pablo Greco 40546a
 {
Pablo Greco 40546a
-    return ((item->cpuid.eax & mask->cpuid.eax) == mask->cpuid.eax &&
Pablo Greco 40546a
-            (item->cpuid.ebx & mask->cpuid.ebx) == mask->cpuid.ebx &&
Pablo Greco 40546a
-            (item->cpuid.ecx & mask->cpuid.ecx) == mask->cpuid.ecx &&
Pablo Greco 40546a
-            (item->cpuid.edx & mask->cpuid.edx) == mask->cpuid.edx);
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuid;
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuidMask;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    switch (item->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        cpuid = &item->data.cpuid;
Pablo Greco 40546a
+        cpuidMask = &mask->data.cpuid;
Pablo Greco 40546a
+        return ((cpuid->eax & cpuidMask->eax) == cpuidMask->eax &&
Pablo Greco 40546a
+                (cpuid->ebx & cpuidMask->ebx) == cpuidMask->ebx &&
Pablo Greco 40546a
+                (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
Pablo Greco 40546a
+                (cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        return false;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -215,13 +241,26 @@ static void
Pablo Greco 40546a
 virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
Pablo Greco 40546a
                          const virCPUx86DataItem *mask)
Pablo Greco 40546a
 {
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid;
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuidMask;
Pablo Greco 40546a
+
Pablo Greco 40546a
     if (!mask)
Pablo Greco 40546a
         return;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    item->cpuid.eax |= mask->cpuid.eax;
Pablo Greco 40546a
-    item->cpuid.ebx |= mask->cpuid.ebx;
Pablo Greco 40546a
-    item->cpuid.ecx |= mask->cpuid.ecx;
Pablo Greco 40546a
-    item->cpuid.edx |= mask->cpuid.edx;
Pablo Greco 40546a
+    switch (item->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        cpuid = &item->data.cpuid;
Pablo Greco 40546a
+        cpuidMask = &mask->data.cpuid;
Pablo Greco 40546a
+        cpuid->eax |= cpuidMask->eax;
Pablo Greco 40546a
+        cpuid->ebx |= cpuidMask->ebx;
Pablo Greco 40546a
+        cpuid->ecx |= cpuidMask->ecx;
Pablo Greco 40546a
+        cpuid->edx |= cpuidMask->edx;
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -229,13 +268,26 @@ static void
Pablo Greco 40546a
 virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
Pablo Greco 40546a
                            const virCPUx86DataItem *mask)
Pablo Greco 40546a
 {
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid;
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuidMask;
Pablo Greco 40546a
+
Pablo Greco 40546a
     if (!mask)
Pablo Greco 40546a
         return;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    item->cpuid.eax &= ~mask->cpuid.eax;
Pablo Greco 40546a
-    item->cpuid.ebx &= ~mask->cpuid.ebx;
Pablo Greco 40546a
-    item->cpuid.ecx &= ~mask->cpuid.ecx;
Pablo Greco 40546a
-    item->cpuid.edx &= ~mask->cpuid.edx;
Pablo Greco 40546a
+    switch (item->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        cpuid = &item->data.cpuid;
Pablo Greco 40546a
+        cpuidMask = &mask->data.cpuid;
Pablo Greco 40546a
+        cpuid->eax &= ~cpuidMask->eax;
Pablo Greco 40546a
+        cpuid->ebx &= ~cpuidMask->ebx;
Pablo Greco 40546a
+        cpuid->ecx &= ~cpuidMask->ecx;
Pablo Greco 40546a
+        cpuid->edx &= ~cpuidMask->edx;
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -243,13 +295,26 @@ static void
Pablo Greco 40546a
 virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
Pablo Greco 40546a
                          const virCPUx86DataItem *mask)
Pablo Greco 40546a
 {
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid;
Pablo Greco 40546a
+    const virCPUx86CPUID *cpuidMask;
Pablo Greco 40546a
+
Pablo Greco 40546a
     if (!mask)
Pablo Greco 40546a
         return;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    item->cpuid.eax &= mask->cpuid.eax;
Pablo Greco 40546a
-    item->cpuid.ebx &= mask->cpuid.ebx;
Pablo Greco 40546a
-    item->cpuid.ecx &= mask->cpuid.ecx;
Pablo Greco 40546a
-    item->cpuid.edx &= mask->cpuid.edx;
Pablo Greco 40546a
+    switch (item->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        cpuid = &item->data.cpuid;
Pablo Greco 40546a
+        cpuidMask = &mask->data.cpuid;
Pablo Greco 40546a
+        cpuid->eax &= cpuidMask->eax;
Pablo Greco 40546a
+        cpuid->ebx &= cpuidMask->ebx;
Pablo Greco 40546a
+        cpuid->ecx &= cpuidMask->ecx;
Pablo Greco 40546a
+        cpuid->edx &= cpuidMask->edx;
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -289,15 +354,29 @@ virCPUx86DataSorter(const void *a, const void *b)
Pablo Greco 40546a
     virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a;
Pablo Greco 40546a
     virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if (da->cpuid.eax_in > db->cpuid.eax_in)
Pablo Greco 40546a
+    if (da->type > db->type)
Pablo Greco 40546a
         return 1;
Pablo Greco 40546a
-    else if (da->cpuid.eax_in < db->cpuid.eax_in)
Pablo Greco 40546a
+    else if (da->type < db->type)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if (da->cpuid.ecx_in > db->cpuid.ecx_in)
Pablo Greco 40546a
-        return 1;
Pablo Greco 40546a
-    else if (da->cpuid.ecx_in < db->cpuid.ecx_in)
Pablo Greco 40546a
-        return -1;
Pablo Greco 40546a
+    switch (da->type) {
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+        if (da->data.cpuid.eax_in > db->data.cpuid.eax_in)
Pablo Greco 40546a
+            return 1;
Pablo Greco 40546a
+        else if (da->data.cpuid.eax_in < db->data.cpuid.eax_in)
Pablo Greco 40546a
+            return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (da->data.cpuid.ecx_in > db->data.cpuid.ecx_in)
Pablo Greco 40546a
+            return 1;
Pablo Greco 40546a
+        else if (da->data.cpuid.ecx_in < db->data.cpuid.ecx_in)
Pablo Greco 40546a
+            return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+    default:
Pablo Greco 40546a
+        break;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 
Pablo Greco 40546a
     return 0;
Pablo Greco 40546a
 }
Pablo Greco 40546a
@@ -526,9 +605,9 @@ x86DataToVendor(const virCPUx86Data *data,
Pablo Greco 40546a
 
Pablo Greco 40546a
 static int
Pablo Greco 40546a
 virCPUx86VendorToData(const char *vendor,
Pablo Greco 40546a
-                      virCPUx86DataItemPtr data)
Pablo Greco 40546a
+                      virCPUx86DataItemPtr item)
Pablo Greco 40546a
 {
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &data->cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (strlen(vendor) != VENDOR_STRING_LENGTH) {
Pablo Greco 40546a
         virReportError(VIR_ERR_INTERNAL_ERROR,
Pablo Greco 40546a
@@ -536,6 +615,8 @@ virCPUx86VendorToData(const char *vendor,
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
     }
Pablo Greco 40546a
 
Pablo Greco 40546a
+    item->type = VIR_CPU_X86_DATA_CPUID;
Pablo Greco 40546a
+    cpuid = &item->data.cpuid;
Pablo Greco 40546a
     cpuid->eax_in = 0;
Pablo Greco 40546a
     cpuid->ecx_in = 0;
Pablo Greco 40546a
     cpuid->ebx = virReadBufInt32LE(vendor);
Pablo Greco 40546a
@@ -611,7 +692,7 @@ x86DataToSignatureFull(const virCPUx86Data *data,
Pablo Greco 40546a
     if (!(item = virCPUx86DataGet(data, &leaf1)))
Pablo Greco 40546a
         return;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    cpuid = &item->cpuid;
Pablo Greco 40546a
+    cpuid = &item->data.cpuid;
Pablo Greco 40546a
     *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf);
Pablo Greco 40546a
     *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf);
Pablo Greco 40546a
     *stepping = cpuid->eax & 0xf;
Pablo Greco 40546a
@@ -630,7 +711,7 @@ x86DataToSignature(const virCPUx86Data *data)
Pablo Greco 40546a
     if (!(item = virCPUx86DataGet(data, &leaf1)))
Pablo Greco 40546a
         return 0;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    return item->cpuid.eax & SIGNATURE_MASK;
Pablo Greco 40546a
+    return item->data.cpuid.eax & SIGNATURE_MASK;
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -885,7 +966,8 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
Pablo Greco 40546a
         ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    cpuid = &item->cpuid;
Pablo Greco 40546a
+    item->type = VIR_CPU_X86_DATA_CPUID;
Pablo Greco 40546a
+    cpuid = &item->data.cpuid;
Pablo Greco 40546a
     cpuid->eax_in = eax_in;
Pablo Greco 40546a
     cpuid->ecx_in = ecx_in;
Pablo Greco 40546a
     cpuid->eax = eax;
Pablo Greco 40546a
@@ -1461,13 +1543,23 @@ virCPUx86DataFormat(const virCPUData *data)
Pablo Greco 40546a
 
Pablo Greco 40546a
     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
Pablo Greco 40546a
     while ((item = virCPUx86DataNext(&iter))) {
Pablo Greco 40546a
-        virCPUx86CPUIDPtr cpuid = &item->cpuid;
Pablo Greco 40546a
-        virBufferAsprintf(&buf,
Pablo Greco 40546a
-                          "  
Pablo Greco 40546a
-                          " eax='0x%08x' ebx='0x%08x'"
Pablo Greco 40546a
-                          " ecx='0x%08x' edx='0x%08x'/>\n",
Pablo Greco 40546a
-                          cpuid->eax_in, cpuid->ecx_in,
Pablo Greco 40546a
-                          cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
Pablo Greco 40546a
+        virCPUx86CPUIDPtr cpuid;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        switch (item->type) {
Pablo Greco 40546a
+        case VIR_CPU_X86_DATA_CPUID:
Pablo Greco 40546a
+            cpuid = &item->data.cpuid;
Pablo Greco 40546a
+            virBufferAsprintf(&buf,
Pablo Greco 40546a
+                              "  
Pablo Greco 40546a
+                              " eax='0x%08x' ebx='0x%08x'"
Pablo Greco 40546a
+                              " ecx='0x%08x' edx='0x%08x'/>\n",
Pablo Greco 40546a
+                              cpuid->eax_in, cpuid->ecx_in,
Pablo Greco 40546a
+                              cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
Pablo Greco 40546a
+            break;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        case VIR_CPU_X86_DATA_NONE:
Pablo Greco 40546a
+        default:
Pablo Greco 40546a
+            break;
Pablo Greco 40546a
+        }
Pablo Greco 40546a
     }
Pablo Greco 40546a
     virBufferAddLit(&buf, "</cpudata>\n");
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -2226,7 +2318,7 @@ cpuidSetLeaf4(virCPUDataPtr data,
Pablo Greco 40546a
               virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = *subLeaf0;
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
@@ -2250,13 +2342,13 @@ cpuidSetLeaf7(virCPUDataPtr data,
Pablo Greco 40546a
               virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = 0x7);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     uint32_t sub;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
Pablo Greco 40546a
+    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
Pablo Greco 40546a
         cpuid->ecx_in = sub;
Pablo Greco 40546a
         cpuidCall(cpuid);
Pablo Greco 40546a
         if (virCPUx86DataAdd(data, &item) < 0)
Pablo Greco 40546a
@@ -2278,7 +2370,7 @@ cpuidSetLeafB(virCPUDataPtr data,
Pablo Greco 40546a
               virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = *subLeaf0;
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
 
Pablo Greco 40546a
     while (cpuid->ecx & 0xff00) {
Pablo Greco 40546a
         if (virCPUx86DataAdd(data, &item) < 0)
Pablo Greco 40546a
@@ -2303,7 +2395,7 @@ cpuidSetLeafD(virCPUDataPtr data,
Pablo Greco 40546a
               virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = 0xd);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     virCPUx86CPUID sub0;
Pablo Greco 40546a
     virCPUx86CPUID sub1;
Pablo Greco 40546a
     uint32_t sub;
Pablo Greco 40546a
@@ -2316,7 +2408,7 @@ cpuidSetLeafD(virCPUDataPtr data,
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, &item) < 0)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    sub0 = subLeaf0->cpuid;
Pablo Greco 40546a
+    sub0 = subLeaf0->data.cpuid;
Pablo Greco 40546a
     sub1 = *cpuid;
Pablo Greco 40546a
     for (sub = 2; sub < 64; sub++) {
Pablo Greco 40546a
         if (sub < 32 &&
Pablo Greco 40546a
@@ -2351,8 +2443,8 @@ cpuidSetLeafResID(virCPUDataPtr data,
Pablo Greco 40546a
                   virCPUx86DataItemPtr subLeaf0,
Pablo Greco 40546a
                   uint32_t res)
Pablo Greco 40546a
 {
Pablo Greco 40546a
-    virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->cpuid.eax_in);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->data.cpuid.eax_in);
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     uint32_t sub;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
@@ -2380,11 +2472,11 @@ cpuidSetLeaf12(virCPUDataPtr data,
Pablo Greco 40546a
                virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = 0x7);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     virCPUx86DataItemPtr leaf7;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (!(leaf7 = virCPUx86DataGet(&data->data.x86, &item)) ||
Pablo Greco 40546a
-        !(leaf7->cpuid.ebx & (1 << 2)))
Pablo Greco 40546a
+        !(leaf7->data.cpuid.ebx & (1 << 2)))
Pablo Greco 40546a
         return 0;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
@@ -2417,13 +2509,13 @@ cpuidSetLeaf14(virCPUDataPtr data,
Pablo Greco 40546a
                virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = 0x14);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     uint32_t sub;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
Pablo Greco 40546a
+    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
Pablo Greco 40546a
         cpuid->ecx_in = sub;
Pablo Greco 40546a
         cpuidCall(cpuid);
Pablo Greco 40546a
         if (virCPUx86DataAdd(data, &item) < 0)
Pablo Greco 40546a
@@ -2443,16 +2535,16 @@ cpuidSetLeaf17(virCPUDataPtr data,
Pablo Greco 40546a
                virCPUx86DataItemPtr subLeaf0)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = 0x17);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
     uint32_t sub;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if (subLeaf0->cpuid.eax < 3)
Pablo Greco 40546a
+    if (subLeaf0->data.cpuid.eax < 3)
Pablo Greco 40546a
         return 0;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virCPUx86DataAdd(data, subLeaf0) < 0)
Pablo Greco 40546a
         return -1;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
Pablo Greco 40546a
+    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
Pablo Greco 40546a
         cpuid->ecx_in = sub;
Pablo Greco 40546a
         cpuidCall(cpuid);
Pablo Greco 40546a
         if (virCPUx86DataAdd(data, &item) < 0)
Pablo Greco 40546a
@@ -2469,7 +2561,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
Pablo Greco 40546a
     uint32_t max;
Pablo Greco 40546a
     uint32_t leaf;
Pablo Greco 40546a
     virCPUx86DataItem item = CPUID(.eax_in = base);
Pablo Greco 40546a
-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
Pablo Greco 40546a
+    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
Pablo Greco 40546a
 
Pablo Greco 40546a
     cpuidCall(cpuid);
Pablo Greco 40546a
     max = cpuid->eax;
Pablo Greco 40546a
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
Pablo Greco 40546a
index e93b355cf0..da8e91fe71 100644
Pablo Greco 40546a
--- a/src/cpu/cpu_x86_data.h
Pablo Greco 40546a
+++ b/src/cpu/cpu_x86_data.h
Pablo Greco 40546a
@@ -71,10 +71,18 @@ struct _virCPUx86CPUID {
Pablo Greco 40546a
 
Pablo Greco 40546a
 # define VIR_CPU_X86_DATA_INIT { 0 }
Pablo Greco 40546a
 
Pablo Greco 40546a
+typedef enum {
Pablo Greco 40546a
+    VIR_CPU_X86_DATA_NONE = 0,
Pablo Greco 40546a
+    VIR_CPU_X86_DATA_CPUID,
Pablo Greco 40546a
+} virCPUx86DataType;
Pablo Greco 40546a
+
Pablo Greco 40546a
 typedef struct _virCPUx86DataItem virCPUx86DataItem;
Pablo Greco 40546a
 typedef virCPUx86DataItem *virCPUx86DataItemPtr;
Pablo Greco 40546a
 struct _virCPUx86DataItem {
Pablo Greco 40546a
-    virCPUx86CPUID cpuid;
Pablo Greco 40546a
+    virCPUx86DataType type;
Pablo Greco 40546a
+    union {
Pablo Greco 40546a
+        virCPUx86CPUID cpuid;
Pablo Greco 40546a
+    } data;
Pablo Greco 40546a
 };
Pablo Greco 40546a
 
Pablo Greco 40546a
 typedef struct _virCPUx86Data virCPUx86Data;
Pablo Greco 40546a
diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
Pablo Greco 40546a
index 2b351fbdde..6630aa2c0b 100644
Pablo Greco 40546a
--- a/src/libxl/libxl_capabilities.c
Pablo Greco 40546a
+++ b/src/libxl/libxl_capabilities.c
Pablo Greco 40546a
@@ -70,8 +70,9 @@ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps)
Pablo Greco 40546a
     virCPUx86DataItem item = { 0 };
Pablo Greco 40546a
     size_t i;
Pablo Greco 40546a
 
Pablo Greco 40546a
+    item.type = VIR_CPU_X86_DATA_CPUID;
Pablo Greco 40546a
     for (i = 0; i < ncaps; i++) {
Pablo Greco 40546a
-        item.cpuid = cpuid[i];
Pablo Greco 40546a
+        item.data.cpuid = cpuid[i];
Pablo Greco 40546a
 
Pablo Greco 40546a
         if (virCPUx86DataAdd(data, &item) < 0) {
Pablo Greco 40546a
             VIR_DEBUG("Failed to add CPUID(%x,%x)",
Pablo Greco 40546a
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
Pablo Greco 40546a
index abfaa6e68a..e6ac82e96b 100644
Pablo Greco 40546a
--- a/src/qemu/qemu_monitor_json.c
Pablo Greco 40546a
+++ b/src/qemu/qemu_monitor_json.c
Pablo Greco 40546a
@@ -7049,9 +7049,10 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
Pablo Greco 40546a
     if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64)))
Pablo Greco 40546a
         goto error;
Pablo Greco 40546a
 
Pablo Greco 40546a
+    item.type = VIR_CPU_X86_DATA_CPUID;
Pablo Greco 40546a
     for (i = 0; i < virJSONValueArraySize(data); i++) {
Pablo Greco 40546a
         if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
Pablo Greco 40546a
-                                                  &item.cpuid) < 0 ||
Pablo Greco 40546a
+                                                  &item.data.cpuid) < 0 ||
Pablo Greco 40546a
             virCPUx86DataAdd(cpudata, &item) < 0)
Pablo Greco 40546a
             goto error;
Pablo Greco 40546a
     }
Pablo Greco 40546a
-- 
Pablo Greco 40546a
2.22.0
Pablo Greco 40546a