3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # A script to generate a CSV file showing the x86_64 ABI
6 # compatibility levels for each CPU model.
9 from qemu.qmp.legacy import QEMUMonitorProtocol
12 if len(sys.argv) != 2:
13 print("syntax: %s QMP-SOCK\n\n" % __file__ +
14 "Where QMP-SOCK points to a QEMU process such as\n\n" +
15 " # qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait " +
16 "-display none -accel kvm", file=sys.stderr)
19 # Mandatory CPUID features for each microarch ABI level
59 # Assumes externally launched process such as
61 # qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait -display none -accel kvm
63 # Note different results will be obtained with TCG, as
64 # TCG masks out certain features otherwise present in
65 # the CPU model definitions, as does KVM.
69 shell = QEMUMonitorProtocol(sock)
72 models = shell.cmd("query-cpu-definitions")
74 # These QMP props don't correspond to CPUID fatures
88 for model in models["return"]:
89 if "alias-of" in model:
91 names.append(model["name"])
95 for name in sorted(names):
96 cpu = shell.cmd("query-cpu-model-expansion",
98 "model": { "name": name }})
101 for (feature, present) in cpu["return"]["model"]["props"].items():
102 if present and feature not in skip:
105 if name in ["host", "max", "base"]:
109 # Dict of all present features in this CPU model
112 # Whether each x86-64 ABI level is satisfied
113 "levels": [False, False, False, False],
115 # Number of extra CPUID features compared to the x86-64 ABI level
116 "distance":[-1, -1, -1, -1],
118 # CPUID features present in model, but not in ABI level
119 "delta":[[], [], [], []],
121 # CPUID features in ABI level but not present in model
122 "missing": [[], [], [], []],
126 # Calculate whether the CPU models satisfy each ABI level
127 for name in models.keys():
128 for level in range(len(levels)):
129 got = set(models[name]["features"])
130 want = set(levels[level])
135 models[name]["levels"][level] = match
136 models[name]["missing"][level] = missing
138 # Cache list of CPU models satisfying each ABI level
146 for name in models.keys():
147 for level in range(len(levels)):
148 if models[name]["levels"][level]:
149 abi_models[level].append(name)
152 for level in range(len(abi_models)):
153 # Find the union of features in all CPU models satisfying this ABI
155 for name in abi_models[level]:
156 for feat in models[name]["features"]:
157 allfeatures[feat] = True
159 # Find the intersection of features in all CPU models satisfying this ABI
161 for feat in allfeatures:
163 for name in models.keys():
164 if not models[name]["levels"][level]:
166 if feat not in models[name]["features"]:
169 commonfeatures.append(feat)
171 # Determine how many extra features are present compared to the lowest
173 for name in models.keys():
174 if not models[name]["levels"][level]:
177 delta = set(models[name]["features"].keys()) - set(commonfeatures)
178 models[name]["distance"][level] = len(delta)
179 models[name]["delta"][level] = delta
181 def print_uarch_abi_csv():
182 print("# Automatically generated from '%s'" % __file__)
183 print("Model,baseline,v2,v3,v4")
184 for name in models.keys():
186 for level in range(len(levels)):
187 if models[name]["levels"][level]:
193 print_uarch_abi_csv()