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
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
["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()