[PATCH 02/10] cpu_x86: Prepare for ecx_in CPUID parameter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



CPUID instruction normally takes its parameter from EAX, but sometimes
ECX is used as an additional parameter. This patch prepares the x86 CPU
driver code for the new 'ecx_in' CPUID parameter.

Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx>
---
 src/cpu/cpu_x86.c                                  | 52 +++++++++++++---------
 src/cpu/cpu_x86_data.h                             |  1 +
 src/qemu/qemu_monitor_json.c                       |  4 ++
 .../qemumonitorjson-getcpu-ecx.data                | 10 ++---
 .../qemumonitorjson-getcpu-full.data               |  6 +--
 .../qemumonitorjson-getcpu-host.data               |  8 ++--
 6 files changed, 49 insertions(+), 32 deletions(-)

diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 82921db..ae809de 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -40,7 +40,7 @@ VIR_LOG_INIT("cpu.cpu_x86");
 
 #define VENDOR_STRING_LENGTH    12
 
-static const virCPUx86CPUID cpuidNull = { 0, 0, 0, 0, 0 };
+static const virCPUx86CPUID cpuidNull = { 0 };
 
 static const virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 };
 
@@ -250,6 +250,11 @@ virCPUx86CPUIDSorter(const void *a, const void *b)
     else if (da->eax_in < db->eax_in)
         return -1;
 
+    if (da->ecx_in > db->ecx_in)
+        return 1;
+    else if (da->ecx_in < db->ecx_in)
+        return -1;
+
     return 0;
 }
 
@@ -274,12 +279,13 @@ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator)
 
 static virCPUx86CPUID *
 x86DataCpuid(const virCPUx86Data *data,
-             uint32_t eax_in)
+             const virCPUx86CPUID *cpuid)
 {
     size_t i;
 
     for (i = 0; i < data->len; i++) {
-        if (data->data[i].eax_in == eax_in)
+        if (data->data[i].eax_in == cpuid->eax_in &&
+            data->data[i].ecx_in == cpuid->ecx_in)
             return data->data + i;
     }
 
@@ -345,7 +351,7 @@ virCPUx86DataAddCPUID(virCPUx86Data *data,
 {
     virCPUx86CPUID *existing;
 
-    if ((existing = x86DataCpuid(data, cpuid->eax_in))) {
+    if ((existing = x86DataCpuid(data, cpuid))) {
         x86cpuidSetBits(existing, cpuid);
     } else {
         if (VIR_APPEND_ELEMENT_COPY(data->data, data->len,
@@ -369,7 +375,7 @@ x86DataAdd(virCPUx86Data *data1,
     virCPUx86CPUID *cpuid2;
 
     while ((cpuid2 = x86DataCpuidNext(&iter))) {
-        cpuid1 = x86DataCpuid(data1, cpuid2->eax_in);
+        cpuid1 = x86DataCpuid(data1, cpuid2);
 
         if (cpuid1) {
             x86cpuidSetBits(cpuid1, cpuid2);
@@ -392,7 +398,7 @@ x86DataSubtract(virCPUx86Data *data1,
     virCPUx86CPUID *cpuid2;
 
     while ((cpuid1 = x86DataCpuidNext(&iter))) {
-        cpuid2 = x86DataCpuid(data2, cpuid1->eax_in);
+        cpuid2 = x86DataCpuid(data2, cpuid1);
         x86cpuidClearBits(cpuid1, cpuid2);
     }
 }
@@ -407,7 +413,7 @@ x86DataIntersect(virCPUx86Data *data1,
     virCPUx86CPUID *cpuid2;
 
     while ((cpuid1 = x86DataCpuidNext(&iter))) {
-        cpuid2 = x86DataCpuid(data2, cpuid1->eax_in);
+        cpuid2 = x86DataCpuid(data2, cpuid1);
         if (cpuid2)
             x86cpuidAndBits(cpuid1, cpuid2);
         else
@@ -435,7 +441,7 @@ x86DataIsSubset(const virCPUx86Data *data,
     const virCPUx86CPUID *cpuidSubset;
 
     while ((cpuidSubset = x86DataCpuidNext(&iter))) {
-        if (!(cpuid = x86DataCpuid(data, cpuidSubset->eax_in)) ||
+        if (!(cpuid = x86DataCpuid(data, cpuidSubset)) ||
             !x86cpuidMatchMasked(cpuid, cpuidSubset))
             return false;
     }
@@ -476,7 +482,7 @@ x86DataToVendor(const virCPUx86Data *data,
 
     for (i = 0; i < map->nvendors; i++) {
         virCPUx86VendorPtr vendor = map->vendors[i];
-        if ((cpuid = x86DataCpuid(data, vendor->cpuid.eax_in)) &&
+        if ((cpuid = x86DataCpuid(data, &vendor->cpuid)) &&
             x86cpuidMatchMasked(cpuid, &vendor->cpuid)) {
             x86cpuidClearBits(cpuid, &vendor->cpuid);
             return vendor;
@@ -592,6 +598,7 @@ x86VendorParse(xmlXPathContextPtr ctxt,
     }
 
     vendor->cpuid.eax_in = 0;
+    vendor->cpuid.ecx_in = 0;
     vendor->cpuid.ebx = virReadBufInt32LE(string);
     vendor->cpuid.edx = virReadBufInt32LE(string + 4);
     vendor->cpuid.ecx = virReadBufInt32LE(string + 8);
@@ -715,25 +722,27 @@ static int
 x86ParseCPUID(xmlXPathContextPtr ctxt,
               virCPUx86CPUID *cpuid)
 {
-    unsigned long eax_in;
+    unsigned long eax_in, ecx_in;
     unsigned long eax, ebx, ecx, edx;
-    int ret_eax_in, ret_eax, ret_ebx, ret_ecx, ret_edx;
+    int ret_eax_in, ret_ecx_in, ret_eax, ret_ebx, ret_ecx, ret_edx;
 
     memset(cpuid, 0, sizeof(*cpuid));
 
-    eax_in = 0;
+    eax_in = ecx_in = 0;
     eax = ebx = ecx = edx = 0;
     ret_eax_in = virXPathULongHex("string(@eax_in)", ctxt, &eax_in);
+    ret_ecx_in = virXPathULongHex("string(@ecx_in)", ctxt, &ecx_in);
     ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
     ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
     ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
     ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
 
-    if (ret_eax_in < 0 ||
+    if (ret_eax_in < 0 || ret_ecx_in == -2 ||
         ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2)
         return -1;
 
     cpuid->eax_in = eax_in;
+    cpuid->ecx_in = ecx_in;
     cpuid->eax = eax;
     cpuid->ebx = ebx;
     cpuid->ecx = ecx;
@@ -1004,7 +1013,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
     while ((cpuid1 = x86DataCpuidNext(&iter1))) {
         virCPUx86CompareResult match = SUPERSET;
 
-        if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1->eax_in))) {
+        if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1))) {
             if (x86cpuidMatch(cpuid1, cpuid2))
                 continue;
             else if (!x86cpuidMatchMasked(cpuid1, cpuid2))
@@ -1020,7 +1029,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
     while ((cpuid2 = x86DataCpuidNext(&iter2))) {
         virCPUx86CompareResult match = SUBSET;
 
-        if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2->eax_in))) {
+        if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2))) {
             if (x86cpuidMatch(cpuid2, cpuid1))
                 continue;
             else if (!x86cpuidMatchMasked(cpuid2, cpuid1))
@@ -1265,10 +1274,10 @@ x86CPUDataFormat(const virCPUData *data)
     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
     while ((cpuid = x86DataCpuidNext(&iter))) {
         virBufferAsprintf(&buf,
-                          "  <cpuid eax_in='0x%08x'"
+                          "  <cpuid eax_in='0x%08x' ecx_in='0x%08x'"
                           " eax='0x%08x' ebx='0x%08x'"
                           " ecx='0x%08x' edx='0x%08x'/>\n",
-                          cpuid->eax_in,
+                          cpuid->eax_in, cpuid->ecx_in,
                           cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
     }
     virBufferAddLit(&buf, "</cpudata>\n");
@@ -1860,7 +1869,8 @@ cpuidCall(virCPUx86CPUID *cpuid)
           "=b" (cpuid->ebx),
           "=c" (cpuid->ecx),
           "=d" (cpuid->edx)
-        : "a" (cpuid->eax_in));
+        : "a" (cpuid->eax_in),
+          "c" (cpuid->ecx_in));
 # else
     /* we need to avoid direct use of ebx for CPUID output as it is used
      * for global offset table on i386 with -fPIC
@@ -1876,7 +1886,8 @@ cpuidCall(virCPUx86CPUID *cpuid)
           "=r" (cpuid->ebx),
           "=c" (cpuid->ecx),
           "=d" (cpuid->edx)
-        : "a" (cpuid->eax_in)
+        : "a" (cpuid->eax_in),
+          "c" (cpuid->ecx_in)
         : "cc");
 # endif
 }
@@ -1887,13 +1898,14 @@ cpuidSet(uint32_t base, virCPUx86Data *data)
 {
     uint32_t max;
     uint32_t i;
-    virCPUx86CPUID cpuid = { base, 0, 0, 0, 0 };
+    virCPUx86CPUID cpuid = { .eax_in = base };
 
     cpuidCall(&cpuid);
     max = cpuid.eax;
 
     for (i = base; i <= max; i++) {
         cpuid.eax_in = i;
+        cpuid.ecx_in = 0;
         cpuidCall(&cpuid);
         if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
             return -1;
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
index 75f7b30..4660ab6 100644
--- a/src/cpu/cpu_x86_data.h
+++ b/src/cpu/cpu_x86_data.h
@@ -29,6 +29,7 @@
 typedef struct _virCPUx86CPUID virCPUx86CPUID;
 struct _virCPUx86CPUID {
     uint32_t eax_in;
+    uint32_t ecx_in;
     uint32_t eax;
     uint32_t ebx;
     uint32_t ecx;
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 2cb0198..12d2e22 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -6364,6 +6364,7 @@ qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
 {
     const char *reg;
     unsigned long long eax_in;
+    unsigned long long ecx_in = 0;
     unsigned long long features;
 
     memset(cpuid, 0, sizeof(*cpuid));
@@ -6378,6 +6379,8 @@ qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
                        _("missing or invalid cpuid-input-eax in CPU data"));
         return -1;
     }
+    ignore_value(virJSONValueObjectGetNumberUlong(data, "cpuid-input-ecx",
+                                                  &ecx_in));
     if (virJSONValueObjectGetNumberUlong(data, "features", &features) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("missing or invalid features in CPU data"));
@@ -6385,6 +6388,7 @@ qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
     }
 
     cpuid->eax_in = eax_in;
+    cpuid->ecx_in = ecx_in;
     if (STREQ(reg, "EAX")) {
         cpuid->eax = features;
     } else if (STREQ(reg, "EBX")) {
diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-ecx.data b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-ecx.data
index c39e3dc..457bbbe 100644
--- a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-ecx.data
+++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-ecx.data
@@ -1,7 +1,7 @@
 <cpudata arch='x86'>
-  <cpuid eax_in='0x00000001' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
-  <cpuid eax_in='0x00000007' eax='0x00000000' ebx='0x001c0fbb' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x0000000d' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x40000001' eax='0x010000fb' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x80000001' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
+  <cpuid eax_in='0x00000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
+  <cpuid eax_in='0x00000007' ecx_in='0x00000000' eax='0x00000000' ebx='0x001c0fbb' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x0000000d' ecx_in='0x00000001' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x40000001' ecx_in='0x00000000' eax='0x010000fb' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x80000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
 </cpudata>
diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
index 87a8fb1..b581821 100644
--- a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
+++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
@@ -1,5 +1,5 @@
 <cpudata arch='x86'>
-  <cpuid eax_in='0x00000001' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x078bfbfd'/>
-  <cpuid eax_in='0x40000001' eax='0x0100003b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x80000001' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/>
+  <cpuid eax_in='0x00000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x078bfbfd'/>
+  <cpuid eax_in='0x40000001' ecx_in='0x00000000' eax='0x0100003b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x80000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/>
 </cpudata>
diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
index 83bafe1..a4c503e 100644
--- a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
+++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
@@ -1,6 +1,6 @@
 <cpudata arch='x86'>
-  <cpuid eax_in='0x00000001' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x0f8bfbff'/>
-  <cpuid eax_in='0x00000007' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x40000001' eax='0x0100007b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
-  <cpuid eax_in='0x80000001' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2993fbff'/>
+  <cpuid eax_in='0x00000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x0f8bfbff'/>
+  <cpuid eax_in='0x00000007' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x40000001' ecx_in='0x00000000' eax='0x0100007b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+  <cpuid eax_in='0x80000001' ecx_in='0x00000000' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2993fbff'/>
 </cpudata>
-- 
2.8.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]