1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-02-24 12:22:20 +00:00

cpu_map: Add libcpuinfo as optional data source

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>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Tim Wiederhake 2024-02-05 11:18:43 +01:00
parent b3edf03c31
commit a18b232712
2 changed files with 145 additions and 7 deletions

@ -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>

@ -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 = (
@ -23,6 +28,7 @@ FEATURES_IGNORE = (
"kvm-steal-time",
"kvmclock",
"kvmclock-stable-bit",
"kvmclock2",
"xstore",
"xstore-en",
@ -296,6 +302,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("/\\*.*?\\*/")
@ -451,6 +504,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",
@ -460,14 +519,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(