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
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@redhat.com>
---
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(
--
2.43.0
On 6/21/24 15:24, 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@redhat.com> > --- > 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 Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
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@redhat.com>
> ---
> 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(
© 2016 - 2026 Red Hat, Inc.