On Fri, Mar 17, 2017 at 05:36:48PM +0100, Jiri Denemark wrote:
The new command can be used to generate test data for
virCPUUpdateLive.
When "cpu-cpuid.py diff x86-cpuid-Something.json" is run, it reads raw
CPUID data stored in x86-cpuid-Something.xml and CPUID data from QEMU
stored in x86-cpuid-Something.json to produce two more CPUID files:
x86-cpuid-Something-enabled.xml and x86-cpuid-Something-disabled.xml.
- x86-cpuid-Something-enabled.xml will contain CPUID bits present in
x86-cpuid-Something.json (i.e., enabled by QEMU for the "host" CPU)
- x86-cpuid-Something-disabled.xml will contain all CPUID bits from
x86-cpuid-Something.xml which are not present in
x86-cpuid-Something.json (i.e., CPUID bits which the host CPU
supports, but QEMU does not enable them for the "host" CPU)
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
tests/cputestdata/cpu-cpuid.py | 89 +++++++++++++++++++++++++++++++++++++++++-
tests/cputestdata/cpu-parse.sh | 1 +
2 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py
index f4cf6d440..4b9b04ace 100755
--- a/tests/cputestdata/cpu-cpuid.py
+++ b/tests/cputestdata/cpu-cpuid.py
@@ -2,6 +2,7 @@
import sys
import json
+import xmltodict
# This is a list of x86 CPU features as of QEMU 2.8.50 and it won't need any
# updates since in the future because query-cpu-model-expansion will be used
@@ -171,6 +172,16 @@ cpuidMap = [
]
+def reverseCpuidMap():
+ features = {}
+
+ for feature in cpuidMap:
+ for name in feature["names"]:
+ features[name] = feature
+
+ return features
+
+
def cpuidIsSet(cpuid, feature):
in_eax = feature["in_eax"]
in_ecx = feature["in_ecx"]
@@ -201,6 +212,12 @@ def cpuidLeaf(cpuid, in_eax, in_ecx):
return leaf
+def cpuidAdd(cpuid, feature):
+ leaf = cpuidLeaf(cpuid, feature["in_eax"], feature["in_ecx"])
+ for reg in ["eax", "ebx", "ecx", "edx"]:
+ leaf[reg] |= feature[reg]
+
+
def parseFeatureWords(path):
features = None
@@ -240,6 +257,50 @@ def parseFeatureWords(path):
return props, cpuid
+def parseQemu(path, features):
+ cpuid = {}
+ with open(path, "r") as f:
+ data = json.load(f)
+
+ for (prop, val) in
data["return"]["model"]["props"].iteritems():
+ if val and prop in features:
+ cpuidAdd(cpuid, features[prop])
+
+ return cpuid
+
+
+def parseCpuid(path):
+ cpuid = {}
+ with open(path, "r") as f:
+ data = xmltodict.parse(f)
+
+ for leaf in data["cpudata"]["cpuid"]:
I would probably use a new variable to store the converted data, just in
case that we don't mess up the original data. Currently it works but it
could bite us in the future and it would be hard to debug.
+ leaf["in_eax"] = int(leaf["@eax_in"],
0)
+ leaf["in_ecx"] = int(leaf["@ecx_in"], 0)
+ for reg in ["eax", "ebx", "ecx",
"edx"]:
+ leaf[reg] = int(leaf["@" + reg], 0)
+
+ cpuidAdd(cpuid, leaf)
+
+ return cpuid
+
+
+def formatCpuid(cpuid, path, comment):
+ with open(path, "w") as f:
+ f.write("<!-- " + comment + " -->\n")
+ f.write("<cpudata arch='x86'>\n")
+ for in_eax in sorted(cpuid.keys()):
+ for in_ecx in sorted(cpuid[in_eax].keys()):
+ leaf = cpuid[in_eax][in_ecx]
+ line = " <cpuid eax_in='0x%08x' ecx_in='0x%02x'
"
+ line += "eax='0x%08x' ebx='0x%08x' "
+ line += "ecx='0x%08x' edx='0x%08x'/>\n"
It is possible to split the long string into multiple lines like this:
line = ("string 1"
"string 2")
+ f.write(line %(
+ in_eax, in_ecx,
+ leaf["eax"], leaf["ebx"],
leaf["ecx"], leaf["edx"]))
+ f.write("</cpudata>\n")
+
+
def convert(path):
props, cpuid = parseFeatureWords(path)
@@ -255,8 +316,30 @@ def convert(path):
f.write("\n")
+def diff(features, path):
+ base = path.replace(".json", "")
+ jsonFile = path
+ cpuidFile = base + ".xml"
+ enabledFile = base + "-enabled.xml"
+ disabledFile = base + "-disabled.xml"
+
+ cpuid = parseCpuid(cpuidFile)
+ qemu = parseQemu(jsonFile, features)
+
+ enabled = {}
+ disabled = {}
+ for feature in cpuidMap:
+ if cpuidIsSet(qemu, feature):
+ cpuidAdd(enabled, feature)
+ elif cpuidIsSet(cpuid, feature):
+ cpuidAdd(disabled, feature)
+
+ formatCpuid(enabled, enabledFile, "Features enabled by QEMU")
+ formatCpuid(disabled, disabledFile, "Features disabled by QEMU")
+
+
if len(sys.argv) < 3:
- print "Usage: %s convert json_file..." % sys.argv[0]
+ print "Usage: %s convert|diff json_file..." % sys.argv[0]
sys.exit(1)
action = sys.argv[1]
@@ -265,6 +348,10 @@ args = sys.argv[2:]
if action == "convert":
for path in args:
convert(path)
+elif action == "diff":
+ features = reverseCpuidMap()
+ for path in args:
+ diff(features, path)
else:
print "Unknown action: " + action
sys.exit(1)
diff --git a/tests/cputestdata/cpu-parse.sh b/tests/cputestdata/cpu-parse.sh
index d823c399b..cd1ab024b 100755
--- a/tests/cputestdata/cpu-parse.sh
+++ b/tests/cputestdata/cpu-parse.sh
@@ -55,6 +55,7 @@ if [[ -s $fname.json ]]; then
if ! grep -q model-expansion $fname.json; then
$(dirname $0)/cpu-cpuid.py convert $fname.json
fi
+ $(dirname $0)/cpu-cpuid.py diff $fname.json
else
rm $fname.json
fi
--
2.12.0
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list