Old usage:
cpu-cpuid.py diff FILE...
New usage:
cpu-gather.py diff FILE...
Signed-off-by: Tim Wiederhake <twiederh(a)redhat.com>
---
tests/cputestdata/cpu-cpuid.py | 152 --------------------------------
tests/cputestdata/cpu-gather.py | 137 +++++++++++++++++++++++++++-
2 files changed, 134 insertions(+), 155 deletions(-)
delete mode 100755 tests/cputestdata/cpu-cpuid.py
diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py
deleted file mode 100755
index 3e852d5d55..0000000000
--- a/tests/cputestdata/cpu-cpuid.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-import sys
-import json
-import xml.etree.ElementTree
-
-
-_KEYS = {
- "cpuid": ["eax_in", "ecx_in"],
- "msr": ["index"],
-}
-
-_REGS = {
- "cpuid": ["eax", "ebx", "ecx",
"edx"],
- "msr": ["eax", "edx"],
-}
-
-
-def checkFeature(cpuData, feature):
- for key in ["type"] + _KEYS.get(feature["type"], list()):
- if feature[key] not in cpuData:
- return False
- cpuData = cpuData[feature[key]]
-
- for reg in _REGS.get(feature["type"], list()):
- if feature[reg] > 0 and feature[reg] == feature[reg] & cpuData[reg]:
- return True
- return False
-
-
-def addFeature(cpuData, feature):
- for key in ["type"] + _KEYS.get(feature["type"], list()):
- if feature[key] not in cpuData:
- cpuData[feature[key]] = dict()
- cpuData = cpuData[feature[key]]
-
- for reg in _REGS.get(feature["type"], list()):
- cpuData[reg] = cpuData.get(reg, 0) | feature[reg]
-
-
-def parseQemu(path, features):
- cpuData = {}
- with open(path, "r") as f:
- data, pos = json.JSONDecoder().raw_decode(f.read())
-
- for (prop, val) in
data["return"]["model"]["props"].items():
- if val and prop in features:
- addFeature(cpuData, features[prop])
-
- return cpuData
-
-
-def parseCPUData(path):
- cpuData = dict()
- for f in xml.etree.ElementTree.parse(path).getroot():
- if f.tag not in ("cpuid", "msr"):
- continue
-
- feature = {"type": f.tag}
- for reg in _KEYS[f.tag] + _REGS[f.tag]:
- feature[reg] = int(f.attrib.get(reg, "0"), 0)
- addFeature(cpuData, feature)
- return cpuData
-
-
-def parseMap():
- path = os.path.dirname(sys.argv[0])
- path = os.path.join(path, "..", "..", "src",
"cpu_map", "x86_features.xml")
-
- cpuMap = dict()
- for f in xml.etree.ElementTree.parse(path).getroot().iter("feature"):
- if f[0].tag not in ("cpuid", "msr"):
- continue
-
- feature = {"type": f[0].tag}
- for reg in _KEYS[f[0].tag] + _REGS[f[0].tag]:
- feature[reg] = int(f[0].attrib.get(reg, "0"), 0)
- cpuMap[f.attrib["name"]] = feature
- return cpuMap
-
-
-def formatCPUData(cpuData, path, comment):
- print(path)
- with open(path, "w") as f:
- f.write("<!-- " + comment + " -->\n")
- f.write("<cpudata arch='x86'>\n")
-
- cpuid = cpuData["cpuid"]
- for eax_in in sorted(cpuid.keys()):
- for ecx_in in sorted(cpuid[eax_in].keys()):
- leaf = cpuid[eax_in][ecx_in]
- line = (" <cpuid eax_in='0x%08x' ecx_in='0x%02x'
"
- "eax='0x%08x' ebx='0x%08x' "
- "ecx='0x%08x' edx='0x%08x'/>\n")
- f.write(line % (
- eax_in, ecx_in,
- leaf["eax"], leaf["ebx"],
leaf["ecx"], leaf["edx"]))
-
- if "msr" in cpuData:
- msr = cpuData["msr"]
- for index in sorted(msr.keys()):
- f.write(" <msr index='0x%x' edx='0x%08x'
eax='0x%08x'/>\n" %
- (index, msr[index]['edx'], msr[index]['eax']))
-
- f.write("</cpudata>\n")
-
-
-def diff(args):
- cpuMap = parseMap()
-
- for jsonFile in args.json_files:
- cpuDataFile = jsonFile.replace(".json", ".xml")
- enabledFile = jsonFile.replace(".json", "-enabled.xml")
- disabledFile = jsonFile.replace(".json", "-disabled.xml")
-
- cpuData = parseCPUData(cpuDataFile)
- qemu = parseQemu(jsonFile, cpuMap)
-
- enabled = dict()
- disabled = dict()
- for feature in cpuMap.values():
- if checkFeature(qemu, feature):
- addFeature(enabled, feature)
- elif checkFeature(cpuData, feature):
- addFeature(disabled, feature)
-
- formatCPUData(enabled, enabledFile, "Features enabled by QEMU")
- formatCPUData(disabled, disabledFile, "Features disabled by QEMU")
-
-
-def main():
- parser = argparse.ArgumentParser(description="Diff cpuid results")
- subparsers = parser.add_subparsers(dest="action", required=True)
- diffparser = subparsers.add_parser(
- "diff",
- help="Diff json description of CPU model against known features.")
- diffparser.add_argument(
- "json_files",
- nargs="+",
- metavar="FILE",
- type=os.path.realpath,
- help="Path to one or more json CPU model descriptions.")
- args = parser.parse_args()
-
- diff(args)
- exit(0)
-
-
-if __name__ == "__main__":
- main()
diff --git a/tests/cputestdata/cpu-gather.py b/tests/cputestdata/cpu-gather.py
index a4a4050e42..f679fb9066 100755
--- a/tests/cputestdata/cpu-gather.py
+++ b/tests/cputestdata/cpu-gather.py
@@ -8,6 +8,18 @@ import re
import struct
import subprocess
import sys
+import xml.etree.ElementTree
+
+
+_KEYS = {
+ "cpuid": ["eax_in", "ecx_in"],
+ "msr": ["index"],
+}
+
+_REGS = {
+ "cpuid": ["eax", "ebx", "ecx",
"edx"],
+ "msr": ["eax", "edx"],
+}
def gather_name(args):
@@ -304,6 +316,118 @@ def parse(args, data):
args.json_files = getattr(args, "json_files", list()) + [filename_json]
+def checkFeature(cpuData, feature):
+ for key in ["type"] + _KEYS.get(feature["type"], list()):
+ if feature[key] not in cpuData:
+ return False
+ cpuData = cpuData[feature[key]]
+
+ for reg in _REGS.get(feature["type"], list()):
+ if feature[reg] > 0 and feature[reg] == feature[reg] & cpuData[reg]:
+ return True
+ return False
+
+
+def addFeature(cpuData, feature):
+ for key in ["type"] + _KEYS.get(feature["type"], list()):
+ if feature[key] not in cpuData:
+ cpuData[feature[key]] = dict()
+ cpuData = cpuData[feature[key]]
+
+ for reg in _REGS.get(feature["type"], list()):
+ cpuData[reg] = cpuData.get(reg, 0) | feature[reg]
+
+
+def parseQemu(path, features):
+ cpuData = {}
+ with open(path, "r") as f:
+ data, pos = json.JSONDecoder().raw_decode(f.read())
+
+ for (prop, val) in
data["return"]["model"]["props"].items():
+ if val and prop in features:
+ addFeature(cpuData, features[prop])
+
+ return cpuData
+
+
+def parseCPUData(path):
+ cpuData = dict()
+ for f in xml.etree.ElementTree.parse(path).getroot():
+ if f.tag not in ("cpuid", "msr"):
+ continue
+
+ feature = {"type": f.tag}
+ for reg in _KEYS[f.tag] + _REGS[f.tag]:
+ feature[reg] = int(f.attrib.get(reg, "0"), 0)
+ addFeature(cpuData, feature)
+ return cpuData
+
+
+def parseMap():
+ path = os.path.dirname(sys.argv[0])
+ path = os.path.join(path, "..", "..", "src",
"cpu_map", "x86_features.xml")
+
+ cpuMap = dict()
+ for f in xml.etree.ElementTree.parse(path).getroot().iter("feature"):
+ if f[0].tag not in ("cpuid", "msr"):
+ continue
+
+ feature = {"type": f[0].tag}
+ for reg in _KEYS[f[0].tag] + _REGS[f[0].tag]:
+ feature[reg] = int(f[0].attrib.get(reg, "0"), 0)
+ cpuMap[f.attrib["name"]] = feature
+ return cpuMap
+
+
+def formatCPUData(cpuData, path, comment):
+ print(path)
+ with open(path, "w") as f:
+ f.write("<!-- " + comment + " -->\n")
+ f.write("<cpudata arch='x86'>\n")
+
+ cpuid = cpuData["cpuid"]
+ for eax_in in sorted(cpuid.keys()):
+ for ecx_in in sorted(cpuid[eax_in].keys()):
+ leaf = cpuid[eax_in][ecx_in]
+ line = (" <cpuid eax_in='0x%08x' ecx_in='0x%02x'
"
+ "eax='0x%08x' ebx='0x%08x' "
+ "ecx='0x%08x' edx='0x%08x'/>\n")
+ f.write(line % (
+ eax_in, ecx_in,
+ leaf["eax"], leaf["ebx"],
leaf["ecx"], leaf["edx"]))
+
+ if "msr" in cpuData:
+ msr = cpuData["msr"]
+ for index in sorted(msr.keys()):
+ f.write(" <msr index='0x%x' edx='0x%08x'
eax='0x%08x'/>\n" %
+ (index, msr[index]['edx'], msr[index]['eax']))
+
+ f.write("</cpudata>\n")
+
+
+def diff(args):
+ cpuMap = parseMap()
+
+ for jsonFile in args.json_files:
+ cpuDataFile = jsonFile.replace(".json", ".xml")
+ enabledFile = jsonFile.replace(".json", "-enabled.xml")
+ disabledFile = jsonFile.replace(".json", "-disabled.xml")
+
+ cpuData = parseCPUData(cpuDataFile)
+ qemu = parseQemu(jsonFile, cpuMap)
+
+ enabled = dict()
+ disabled = dict()
+ for feature in cpuMap.values():
+ if checkFeature(qemu, feature):
+ addFeature(enabled, feature)
+ elif checkFeature(cpuData, feature):
+ addFeature(disabled, feature)
+
+ formatCPUData(enabled, enabledFile, "Features enabled by QEMU")
+ formatCPUData(disabled, disabledFile, "Features disabled by QEMU")
+
+
def main():
parser = argparse.ArgumentParser(description="Gather cpu test data")
parser.add_argument(
@@ -332,6 +456,15 @@ def main():
subparsers.add_parser(
"full",
help="Equivalent to `cpu-gather gather | cpu-gather parse`.")
+ diffparser = subparsers.add_parser(
+ "diff",
+ help="Diff json description of CPU model against known features.")
+ diffparser.add_argument(
+ "json_files",
+ nargs="+",
+ metavar="FILE",
+ type=os.path.realpath,
+ help="Path to one or more json CPU model descriptions.")
args = parser.parse_args()
@@ -359,9 +492,7 @@ def main():
parse(args, data)
if "json_files" in args:
- cmd = ["./cpu-cpuid.py", "diff"]
- cmd.extend(args.json_files)
- subprocess.check_call(cmd, universal_newlines=True)
+ diff(args)
if __name__ == "__main__":
--
2.26.2