ping On Fri, 2024-06-21 at 15:24 +0200, Tim Wiederhake wrote: > This adds an option to use libcpuinfo [1] as data source for > libvirt's list of x86 cpu features. This is purely optional and > does not change the script's behavior if libcpuinfo is not > installed. > > libcpuinfo is a cross-vendor, cross-architecture source for CPU > related information that has the capability to replace libvirt's > dependence on qemu's cpu feature list. > > [1] https://gitlab.com/twiederh/libcpuinfo > > Signed-off-by: Tim Wiederhake <twiederh@xxxxxxxxxx> > --- > src/cpu_map/libcpuinfo_aliases.xml | 75 > +++++++++++++++++++++++++ > src/cpu_map/sync_qemu_features_i386.py | 77 +++++++++++++++++++++++- > -- > 2 files changed, 145 insertions(+), 7 deletions(-) > create mode 100644 src/cpu_map/libcpuinfo_aliases.xml > > diff --git a/src/cpu_map/libcpuinfo_aliases.xml > b/src/cpu_map/libcpuinfo_aliases.xml > new file mode 100644 > index 0000000000..75d243fead > --- /dev/null > +++ b/src/cpu_map/libcpuinfo_aliases.xml > @@ -0,0 +1,75 @@ > +<!-- > + libvirt uses slightly different names for some cpu features than > other > + software does. Install this file into libcpuinfo's alias > directory > + (e.g. /usr/share/libcpuinfo/aliases/libvirt.xml) to have > libcpuinfo > + automatically translate feature names into the names libvirt > uses. > +--> > + > +<external_aliases> > + <external_alias> > + <type>feature</type> > + <canonical>pclmulqdq</canonical> > + <name>pclmuldq</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>ds-cpl</canonical> > + <name>ds_cpl</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>sse4-1</canonical> > + <name>sse4.1</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>sse4-2</canonical> > + <name>sse4.2</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>tsc-adjust</canonical> > + <name>tsc_adjust</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>lahf-lm</canonical> > + <name>lahf_lm</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>cmp-legacy</canonical> > + <name>cmp_legacy</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>nodeid-msr</canonical> > + <name>nodeid_msr</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>perfctr-core</canonical> > + <name>perfctr_core</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>perfctr-nb</canonical> > + <name>perfctr_nb</name> > + <domain>libvirt</domain> > + </external_alias> > + <external_alias> > + <type>feature</type> > + <canonical>fxsr-opt</canonical> > + <name>fxsr_opt</name> > + <domain>libvirt</domain> > + </external_alias> > +</external_aliases> > diff --git a/src/cpu_map/sync_qemu_features_i386.py > b/src/cpu_map/sync_qemu_features_i386.py > index e4b1f7275a..3b3ad5a643 100755 > --- a/src/cpu_map/sync_qemu_features_i386.py > +++ b/src/cpu_map/sync_qemu_features_i386.py > @@ -4,6 +4,11 @@ import argparse > import os > import re > > +try: > + import pycpuinfo > +except ImportError: > + pycpuinfo = None > + > > # features in qemu that we do not want in libvirt > FEATURES_IGNORE = ( > @@ -22,6 +27,7 @@ FEATURES_IGNORE = ( > "kvm-steal-time", > "kvmclock", > "kvmclock-stable-bit", > + "kvmclock2", > > "xstore", > "xstore-en", > @@ -295,6 +301,53 @@ def add_feature_qemu(query, data): > add_feature_cpuid(eax, ecx, reg, bit, name) > > > +def add_features_cpuinfo(): > + def decode_bit(value): > + for i in range(0, 64): > + if value == (1 << i): > + return i > + > + def decode_cpuid(v): > + if v[0] != 0 and v[1] == 0 and v[2] == 0 and v[3] == 0: > + reg, val = "eax", v[0] > + if v[0] == 0 and v[1] != 0 and v[2] == 0 and v[3] == 0: > + reg, val = "ebx", v[1] > + if v[0] == 0 and v[1] == 0 and v[2] != 0 and v[3] == 0: > + reg, val = "ecx", v[2] > + if v[0] == 0 and v[1] == 0 and v[2] == 0 and v[3] != 0: > + reg, val = "edx", v[3] > + > + return reg, decode_bit(val) > + > + x86 = pycpuinfo.Family.find("x86", "") > + > + for feature in pycpuinfo.features(): > + if feature.family() != x86: > + continue > + > + if list(feature.features()): > + continue > + > + name = feature.name("libvirt") > + if name in FEATURES_IGNORE: > + continue > + > + cpuid = feature.extra_x86_cpuid() > + if cpuid: > + eax = cpuid[0] > + ecx = cpuid[1] > + if ecx == pycpuinfo.x86.CPUINFO_X86_CPUID_ECX_NONE: > + ecx = None > + reg, bit = decode_cpuid(cpuid[2:]) > + add_feature_cpuid(eax, ecx, reg, bit, name) > + > + msr = feature.extra_x86_msr() > + if msr: > + index = msr[0] > + bit = decode_bit(msr[1] | (msr[2] << 32)) > + add_feature_msr(index, bit, name) > + > + > # read the `feature_word_info` struct from qemu's cpu.c into a list > of strings > def read_cpu_c(path): > pattern_comment = re.compile("/\\*.*?\\*/") > @@ -450,6 +503,12 @@ def main(): > nargs="?", > type=os.path.realpath, > ) > + if pycpuinfo: > + parser.add_argument( > + "--libcpuinfo", > + help="Use libcpuinfo as data source instead", > + action="store_true", > + ) > parser.add_argument( > "--output", > "-o", > @@ -459,14 +518,18 @@ def main(): > ) > args = parser.parse_args() > > - if not os.path.isdir(args.qemu): > - parser.print_help() > - exit("qemu source directory not found") > + if pycpuinfo and args.libcpuinfo: > + add_features_cpuinfo() > + else: > + if not os.path.isdir(args.qemu): > + parser.print_help() > + exit("qemu source directory not found") > + > + read_headers(args.qemu) > + lines = read_cpu_c(args.qemu) > + parse_feature_words(lines) > + add_extra_features() > > - read_headers(args.qemu) > - lines = read_cpu_c(args.qemu) > - parse_feature_words(lines) > - add_extra_features() > write_output(args.output) > > print(