2019-02-22 03:28:49 +08:00
|
|
|
#!/usr/bin/env python3
|
2017-02-02 00:48:41 +08:00
|
|
|
|
2018-01-05 21:35:42 +08:00
|
|
|
import os
|
2017-02-02 00:48:41 +08:00
|
|
|
import sys
|
|
|
|
import json
|
2017-03-16 19:25:30 +08:00
|
|
|
import xmltodict
|
2017-02-02 00:48:41 +08:00
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
def checkFeature(cpuid, feature):
|
2017-03-15 21:21:48 +08:00
|
|
|
in_eax = feature["in_eax"]
|
|
|
|
in_ecx = feature["in_ecx"]
|
|
|
|
eax = feature["eax"]
|
|
|
|
ebx = feature["ebx"]
|
|
|
|
ecx = feature["ecx"]
|
|
|
|
edx = feature["edx"]
|
|
|
|
|
|
|
|
if in_eax not in cpuid or in_ecx not in cpuid[in_eax]:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
leaf = cpuid[in_eax][in_ecx]
|
|
|
|
return ((eax > 0 and leaf["eax"] & eax > 0) or
|
|
|
|
(ebx > 0 and leaf["ebx"] & ebx > 0) or
|
|
|
|
(ecx > 0 and leaf["ecx"] & ecx > 0) or
|
|
|
|
(edx > 0 and leaf["edx"] & edx > 0))
|
|
|
|
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
def addFeature(cpuid, feature):
|
2019-04-01 19:19:16 +08:00
|
|
|
if feature["in_eax"] not in cpuid:
|
|
|
|
cpuid[feature["in_eax"]] = {}
|
|
|
|
leaf = cpuid[feature["in_eax"]]
|
2017-03-15 21:29:30 +08:00
|
|
|
|
2019-04-01 19:19:16 +08:00
|
|
|
if feature["in_ecx"] not in leaf:
|
|
|
|
leaf[feature["in_ecx"]] = {"eax": 0, "ebx": 0, "ecx": 0, "edx": 0}
|
|
|
|
leaf = leaf[feature["in_ecx"]]
|
2017-03-15 21:29:30 +08:00
|
|
|
|
2017-03-16 19:25:30 +08:00
|
|
|
for reg in ["eax", "ebx", "ecx", "edx"]:
|
|
|
|
leaf[reg] |= feature[reg]
|
|
|
|
|
|
|
|
|
|
|
|
def parseQemu(path, features):
|
2019-04-01 23:06:59 +08:00
|
|
|
cpuData = {}
|
2017-03-16 19:25:30 +08:00
|
|
|
with open(path, "r") as f:
|
2017-09-27 03:08:37 +08:00
|
|
|
data, pos = json.JSONDecoder().raw_decode(f.read())
|
2017-03-16 19:25:30 +08:00
|
|
|
|
2019-02-22 03:28:49 +08:00
|
|
|
for (prop, val) in data["return"]["model"]["props"].items():
|
2017-03-16 19:25:30 +08:00
|
|
|
if val and prop in features:
|
2019-04-01 23:06:59 +08:00
|
|
|
addFeature(cpuData, features[prop])
|
2017-03-16 19:25:30 +08:00
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
return cpuData
|
2017-03-16 19:25:30 +08:00
|
|
|
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
def parseCPUData(path):
|
|
|
|
cpuData = {}
|
2019-02-22 03:28:49 +08:00
|
|
|
with open(path, "rb") as f:
|
2017-03-16 19:25:30 +08:00
|
|
|
data = xmltodict.parse(f)
|
|
|
|
|
|
|
|
for leaf in data["cpudata"]["cpuid"]:
|
|
|
|
feature = {}
|
|
|
|
feature["in_eax"] = int(leaf["@eax_in"], 0)
|
|
|
|
feature["in_ecx"] = int(leaf["@ecx_in"], 0)
|
|
|
|
for reg in ["eax", "ebx", "ecx", "edx"]:
|
|
|
|
feature[reg] = int(leaf["@" + reg], 0)
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
addFeature(cpuData, feature)
|
2017-03-16 19:25:30 +08:00
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
return cpuData
|
2017-03-16 19:25:30 +08:00
|
|
|
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
def parseMapFeature(data):
|
2018-01-05 21:35:42 +08:00
|
|
|
cpuid = {}
|
|
|
|
for reg in ["in_eax", "in_ecx", "eax", "ebx", "ecx", "edx"]:
|
|
|
|
if reg.startswith("in_"):
|
|
|
|
attr = "@%s_in" % reg[3:]
|
|
|
|
else:
|
|
|
|
attr = "@%s" % reg
|
|
|
|
|
|
|
|
if attr in data:
|
|
|
|
cpuid[reg] = int(data[attr], 0)
|
|
|
|
else:
|
|
|
|
cpuid[reg] = 0
|
|
|
|
|
|
|
|
return cpuid
|
|
|
|
|
|
|
|
|
|
|
|
def parseMap():
|
|
|
|
path = os.path.dirname(sys.argv[0])
|
2019-02-22 03:10:48 +08:00
|
|
|
path = os.path.join(path, "..", "..", "src", "cpu_map", "x86_features.xml")
|
2019-02-22 03:28:49 +08:00
|
|
|
with open(path, "rb") as f:
|
2018-01-05 21:35:42 +08:00
|
|
|
data = xmltodict.parse(f)
|
|
|
|
|
|
|
|
cpuMap = {}
|
2019-02-22 03:10:48 +08:00
|
|
|
for feature in data["cpus"]["feature"]:
|
2019-03-19 16:45:48 +08:00
|
|
|
if "cpuid" in feature:
|
2019-04-01 23:06:59 +08:00
|
|
|
cpuMap[feature["@name"]] = parseMapFeature(feature["cpuid"])
|
2018-01-05 21:35:42 +08:00
|
|
|
|
|
|
|
return cpuMap
|
|
|
|
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
def formatCPUData(cpuid, path, comment):
|
2019-02-22 03:28:49 +08:00
|
|
|
print(path)
|
2017-03-16 19:25:30 +08:00
|
|
|
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' "
|
|
|
|
"eax='0x%08x' ebx='0x%08x' "
|
|
|
|
"ecx='0x%08x' edx='0x%08x'/>\n")
|
2018-03-20 14:48:47 +08:00
|
|
|
f.write(line % (
|
2017-03-16 19:25:30 +08:00
|
|
|
in_eax, in_ecx,
|
|
|
|
leaf["eax"], leaf["ebx"], leaf["ecx"], leaf["edx"]))
|
|
|
|
f.write("</cpudata>\n")
|
|
|
|
|
|
|
|
|
2018-01-05 21:35:42 +08:00
|
|
|
def diff(cpuMap, path):
|
2017-03-16 19:25:30 +08:00
|
|
|
base = path.replace(".json", "")
|
|
|
|
jsonFile = path
|
2019-04-01 23:06:59 +08:00
|
|
|
cpuDataFile = base + ".xml"
|
2017-03-16 19:25:30 +08:00
|
|
|
enabledFile = base + "-enabled.xml"
|
|
|
|
disabledFile = base + "-disabled.xml"
|
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
cpuData = parseCPUData(cpuDataFile)
|
2018-01-05 21:35:42 +08:00
|
|
|
qemu = parseQemu(jsonFile, cpuMap)
|
2017-03-16 19:25:30 +08:00
|
|
|
|
|
|
|
enabled = {}
|
|
|
|
disabled = {}
|
2018-01-05 21:35:42 +08:00
|
|
|
for feature in cpuMap.values():
|
2019-04-01 23:06:59 +08:00
|
|
|
if checkFeature(qemu, feature):
|
|
|
|
addFeature(enabled, feature)
|
|
|
|
elif checkFeature(cpuData, feature):
|
|
|
|
addFeature(disabled, feature)
|
2017-03-16 19:25:30 +08:00
|
|
|
|
2019-04-01 23:06:59 +08:00
|
|
|
formatCPUData(enabled, enabledFile, "Features enabled by QEMU")
|
|
|
|
formatCPUData(disabled, disabledFile, "Features disabled by QEMU")
|
2017-03-16 19:25:30 +08:00
|
|
|
|
|
|
|
|
2017-03-15 20:16:37 +08:00
|
|
|
if len(sys.argv) < 3:
|
2019-04-01 19:19:16 +08:00
|
|
|
print("Usage: %s diff json_file..." % sys.argv[0])
|
2017-03-15 20:16:37 +08:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
action = sys.argv[1]
|
|
|
|
args = sys.argv[2:]
|
|
|
|
|
2019-04-01 19:19:16 +08:00
|
|
|
if action == "diff":
|
2018-01-05 21:35:42 +08:00
|
|
|
cpuMap = parseMap()
|
2017-03-16 19:25:30 +08:00
|
|
|
for path in args:
|
2018-01-05 21:35:42 +08:00
|
|
|
diff(cpuMap, path)
|
2017-03-15 20:16:37 +08:00
|
|
|
else:
|
2019-02-22 03:28:49 +08:00
|
|
|
print("Unknown action: %s" % action)
|
2017-03-15 20:16:37 +08:00
|
|
|
sys.exit(1)
|