Signed-off-by: Tim Wiederhake <twiederh@xxxxxxxxxx> --- src/cpu_map/x86_features.py | 119 ++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100755 src/cpu_map/x86_features.py diff --git a/src/cpu_map/x86_features.py b/src/cpu_map/x86_features.py new file mode 100755 index 0000000000..5bc7e06216 --- /dev/null +++ b/src/cpu_map/x86_features.py @@ -0,0 +1,119 @@ +#!/bin/env python3 + +import os +import pycpuinfo + +non_migratable = ( + "invtsc", + "xsaves", +) + +family_x86 = pycpuinfo.Family.find("x86") + +features_cpuid = dict() +features_msr = dict() + + +def cpuid_to_reg_value(data): + if data[2]: + return "eax", data[2] + if data[3]: + return "ebx", data[3] + if data[4]: + return "ecx", data[4] + if data[5]: + return "edx", data[5] + + +def add_cpuid(feature): + name = feature.name("libvirt") + data = feature.extra_x86_cpuid() + reg_value = cpuid_to_reg_value(data) + + if data[0] not in features_cpuid: + features_cpuid[data[0]] = dict() + + if data[1] not in features_cpuid[data[0]]: + features_cpuid[data[0]][data[1]] = dict() + + if reg_value[0] not in features_cpuid[data[0]][data[1]]: + features_cpuid[data[0]][data[1]][reg_value[0]] = set() + + features_cpuid[data[0]][data[1]][reg_value[0]].add(( + reg_value[1], + name, + )) + + +def add_msr(feature): + data = feature.extra_x86_msr() + if data[0] not in features_msr: + features_msr[data[0]] = set() + + features_msr[data[0]].add(( + data[2], + data[1], + feature.name("libvirt"), + )) + + +def print_feature_cpuid(f): + tmpl_ecx = ( + " <!-- cpuid level 0x{0:08x}, ecx 0x{1:04x} ({2}) -->\n", + " <cpuid eax_in='0x{0:08x}' ecx_in='0x{1:08x}' {2}='0x{3:08x}'/>\n" + ) + tmpl_any = ( + " <!-- cpuid level 0x{0:08x} ({2}) -->\n", + " <cpuid eax_in='0x{0:08x}' {2}='0x{3:08x}'/>\n" + ) + + for eax in sorted(features_cpuid): + for ecx in sorted(features_cpuid[eax]): + if ecx == pycpuinfo.x86.CPUINFO_X86_CPUID_ECX_NONE: + template = tmpl_any + else: + template = tmpl_ecx + + for reg in sorted(features_cpuid[eax][ecx]): + f.write(template[0].format(eax, ecx, reg)) + for data in sorted(features_cpuid[eax][ecx][reg]): + extra = "" + if data[1] in non_migratable: + extra = " migratable='no'" + f.write(" <feature name='{}'{}>\n".format(data[1], extra)) + f.write(template[1].format(eax, ecx, reg, data[0])) + f.write(" </feature>\n") + f.write("\n") + + +def print_feature_msr(f): + template = " <msr index='0x{:08x}' edx='0x{:08x}' eax='0x{:08x}'/>\n" + for msr in sorted(features_msr): + f.write(" <!-- msr 0x{:08x} -->\n".format(msr)) + for data in sorted(features_msr[msr]): + f.write(" <feature name='{}'>\n".format(data[2])) + f.write(template.format(msr, data[0], data[1])) + f.write(" </feature>\n") + f.write("\n") + + +for feature in pycpuinfo.features(): + if feature.family() != family_x86: + continue + + if feature.extra_x86_cpuid(): + add_cpuid(feature) + elif feature.extra_x86_msr(): + add_msr(feature) + + +filename = os.path.join(os.path.dirname(__file__), "x86_features.xml") +with open(filename, "tw") as f: + f.write( + "<!--\n After adding new features, update existing test files with\n" + "\n tests/cputestdata/cpu-data.py diff tests/cputestdata/x86_64-" + "cpuid-*.json\n\n-->\n") + f.write("<cpus>\n") + print_feature_cpuid(f) + print_feature_msr(f) + f.write("</cpus>\n") -- 2.39.2