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.
12 if len(sys
.argv
) != 1:
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.
70 shell
= qmp
.QEMUMonitorProtocol(sock
)
73 models
= shell
.cmd("query-cpu-definitions")
75 # These QMP props don't correspond to CPUID fatures
89 for model
in models
["return"]:
90 if "alias-of" in model
:
92 names
.append(model
["name"])
96 for name
in sorted(names
):
97 cpu
= shell
.cmd("query-cpu-model-expansion",
99 "model": { "name": name
}})
102 for (feature
, present
) in cpu
["return"]["model"]["props"].items():
103 if present
and feature
not in skip
:
106 if name
in ["host", "max", "base"]:
110 # Dict of all present features in this CPU model
113 # Whether each x86-64 ABI level is satisfied
114 "levels": [False, False, False, False],
116 # Number of extra CPUID features compared to the x86-64 ABI level
117 "distance":[-1, -1, -1, -1],
119 # CPUID features present in model, but not in ABI level
120 "delta":[[], [], [], []],
122 # CPUID features in ABI level but not present in model
123 "missing": [[], [], [], []],
127 # Calculate whether the CPU models satisfy each ABI level
128 for name
in models
.keys():
129 for level
in range(len(levels
)):
130 got
= set(models
[name
]["features"])
131 want
= set(levels
[level
])
136 models
[name
]["levels"][level
] = match
137 models
[name
]["missing"][level
] = missing
139 # Cache list of CPU models satisfying each ABI level
147 for name
in models
.keys():
148 for level
in range(len(levels
)):
149 if models
[name
]["levels"][level
]:
150 abi_models
[level
].append(name
)
153 for level
in range(len(abi_models
)):
154 # Find the union of features in all CPU models satisfying this ABI
156 for name
in abi_models
[level
]:
157 for feat
in models
[name
]["features"]:
158 allfeatures
[feat
] = True
160 # Find the intersection of features in all CPU models satisfying this ABI
162 for feat
in allfeatures
:
164 for name
in models
.keys():
165 if not models
[name
]["levels"][level
]:
167 if feat
not in models
[name
]["features"]:
170 commonfeatures
.append(feat
)
172 # Determine how many extra features are present compared to the lowest
174 for name
in models
.keys():
175 if not models
[name
]["levels"][level
]:
178 delta
= set(models
[name
]["features"].keys()) - set(commonfeatures
)
179 models
[name
]["distance"][level
] = len(delta
)
180 models
[name
]["delta"][level
] = delta
182 def print_uarch_abi_csv():
183 print("# Automatically generated from '%s'" % __file__
)
184 print("Model,baseline,v2,v3,v4")
185 for name
in models
.keys():
187 for level
in range(len(levels
)):
188 if models
[name
]["levels"][level
]:
194 print_uarch_abi_csv()