]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/cpu-x86-uarch-abi.py
hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper
[mirror_qemu.git] / scripts / cpu-x86-uarch-abi.py
CommitLineData
4e2f5f3a
DB
1#!/usr/bin/python3
2#
3# SPDX-License-Identifier: GPL-2.0-or-later
4#
5# A script to generate a CSV file showing the x86_64 ABI
6# compatibility levels for each CPU model.
7#
8
37094b6d 9from qemu.qmp.legacy import QEMUMonitorProtocol
4e2f5f3a
DB
10import sys
11
99221256 12if len(sys.argv) != 2:
4e2f5f3a
DB
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)
17 sys.exit(1)
18
19# Mandatory CPUID features for each microarch ABI level
20levels = [
21 [ # x86-64 baseline
22 "cmov",
23 "cx8",
24 "fpu",
25 "fxsr",
26 "mmx",
27 "syscall",
28 "sse",
29 "sse2",
30 ],
31 [ # x86-64-v2
32 "cx16",
33 "lahf-lm",
34 "popcnt",
35 "pni",
36 "sse4.1",
37 "sse4.2",
38 "ssse3",
39 ],
40 [ # x86-64-v3
41 "avx",
42 "avx2",
43 "bmi1",
44 "bmi2",
45 "f16c",
46 "fma",
47 "abm",
48 "movbe",
49 ],
50 [ # x86-64-v4
51 "avx512f",
52 "avx512bw",
53 "avx512cd",
54 "avx512dq",
55 "avx512vl",
56 ],
57]
58
59# Assumes externally launched process such as
60#
61# qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait -display none -accel kvm
62#
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.
66
67
68sock = sys.argv[1]
0665410d 69shell = QEMUMonitorProtocol(sock)
4e2f5f3a
DB
70shell.connect()
71
684750ab 72models = shell.cmd("query-cpu-definitions")
4e2f5f3a
DB
73
74# These QMP props don't correspond to CPUID fatures
75# so ignore them
76skip = [
77 "family",
78 "min-level",
79 "min-xlevel",
80 "vendor",
81 "model",
82 "model-id",
83 "stepping",
84]
85
86names = []
87
7f521b02 88for model in models:
4e2f5f3a
DB
89 if "alias-of" in model:
90 continue
91 names.append(model["name"])
92
93models = {}
94
95for name in sorted(names):
684750ab 96 cpu = shell.cmd("query-cpu-model-expansion",
3e7ebf58
ZL
97 type="static",
98 model={ "name": name })
4e2f5f3a
DB
99
100 got = {}
7f521b02 101 for (feature, present) in cpu["model"]["props"].items():
4e2f5f3a
DB
102 if present and feature not in skip:
103 got[feature] = True
104
105 if name in ["host", "max", "base"]:
106 continue
107
108 models[name] = {
109 # Dict of all present features in this CPU model
110 "features": got,
111
112 # Whether each x86-64 ABI level is satisfied
113 "levels": [False, False, False, False],
114
115 # Number of extra CPUID features compared to the x86-64 ABI level
116 "distance":[-1, -1, -1, -1],
117
118 # CPUID features present in model, but not in ABI level
119 "delta":[[], [], [], []],
120
121 # CPUID features in ABI level but not present in model
122 "missing": [[], [], [], []],
123 }
124
125
126# Calculate whether the CPU models satisfy each ABI level
127for name in models.keys():
128 for level in range(len(levels)):
129 got = set(models[name]["features"])
130 want = set(levels[level])
131 missing = want - got
132 match = True
133 if len(missing) > 0:
134 match = False
135 models[name]["levels"][level] = match
136 models[name]["missing"][level] = missing
137
138# Cache list of CPU models satisfying each ABI level
139abi_models = [
140 [],
141 [],
142 [],
143 [],
144]
145
146for name in models.keys():
147 for level in range(len(levels)):
148 if models[name]["levels"][level]:
149 abi_models[level].append(name)
150
151
152for level in range(len(abi_models)):
153 # Find the union of features in all CPU models satisfying this ABI
154 allfeatures = {}
155 for name in abi_models[level]:
156 for feat in models[name]["features"]:
157 allfeatures[feat] = True
158
159 # Find the intersection of features in all CPU models satisfying this ABI
160 commonfeatures = []
161 for feat in allfeatures:
162 present = True
163 for name in models.keys():
164 if not models[name]["levels"][level]:
165 continue
166 if feat not in models[name]["features"]:
167 present = False
168 if present:
169 commonfeatures.append(feat)
170
171 # Determine how many extra features are present compared to the lowest
172 # common denominator
173 for name in models.keys():
174 if not models[name]["levels"][level]:
175 continue
176
177 delta = set(models[name]["features"].keys()) - set(commonfeatures)
178 models[name]["distance"][level] = len(delta)
179 models[name]["delta"][level] = delta
180
181def print_uarch_abi_csv():
182 print("# Automatically generated from '%s'" % __file__)
183 print("Model,baseline,v2,v3,v4")
184 for name in models.keys():
185 print(name, end="")
186 for level in range(len(levels)):
187 if models[name]["levels"][level]:
188 print(",✅", end="")
189 else:
190 print(",", end="")
191 print()
192
193print_uarch_abi_csv()