1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-02-18 21:57:30 +03:00
Tim Wiederhake afbb7af3ca cpu-gather: Move static model extraction to new script
Signed-off-by: Tim Wiederhake <twiederh@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2020-12-18 23:20:05 +01:00

174 lines
4.8 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import fcntl
import json
import os
import struct
import subprocess
import sys
def gather_name(args):
if args.name:
return args.name
with open("/proc/cpuinfo", "rt") as f:
for line in f.readlines():
if line.startswith("model name"):
return line.split(":", 2)[1].strip()
exit("Error: '/proc/cpuinfo' does not contain a model name.\n"
"Use '--model' to set a model name.")
def gather_cpuid_leaves(args):
cpuid = args.path_to_cpuid or "cpuid"
try:
output = subprocess.check_output(
[cpuid, "-1r"],
universal_newlines=True)
except FileNotFoundError as e:
exit("Error: '{}' not found.\n'cpuid' can be usually found in a "
"package named identically. If your distro does not provide such "
"package, you can find the sources or binary packages at "
"'http://www.etallen.com/cpuid.html'.".format(e.filename))
for line in output.split("\n"):
if not line:
continue
if line == "CPU:":
continue
yield line.strip()
def gather_msr():
IA32_ARCH_CAPABILITIES_MSR = 0x10a
KVM_GET_MSRS = 0xc008ae88
try:
with open("/dev/cpu/0/msr", "rb") as f:
f.seek(IA32_ARCH_CAPABILITIES_MSR)
buf = f.read(8)
msr = struct.unpack("=Q", buf)[0]
return "", {IA32_ARCH_CAPABILITIES_MSR: msr}
except IOError as e:
print("Warning: {}".format(e), file=sys.stderr)
try:
bufIn = struct.pack("=LLLLQ", 1, 0, IA32_ARCH_CAPABILITIES_MSR, 0, 0)
with open("/dev/kvm", "rb") as f:
bufOut = fcntl.ioctl(f, KVM_GET_MSRS, bufIn)
msr = struct.unpack("=LLLLQ", bufOut)[4]
return " via KVM", {IA32_ARCH_CAPABILITIES_MSR: msr}
except IOError as e:
print("Warning: {}".format(e), file=sys.stderr)
return None, {}
def call_qemu(qemu, qmp_cmds):
cmd = [
qemu,
"-machine", "accel=kvm",
"-cpu", "host",
"-nodefaults",
"-nographic",
"-qmp", "stdio"]
stdin = list()
stdin.append("{\"execute\": \"qmp_capabilities\"}")
stdin.extend([json.dumps(o) for o in qmp_cmds])
stdin.append("{\"execute\": \"quit\"}")
try:
output = subprocess.check_output(
cmd,
universal_newlines=True,
input="\n".join(stdin))
except subprocess.CalledProcessError:
exit("Error: Non-zero exit code from '{}'.".format(qemu))
except FileNotFoundError:
exit("Error: File not found: '{}'.".format(qemu))
for line in output.split("\n"):
if line:
yield json.loads(line)
def gather_static_model(args):
output = call_qemu(args.path_to_qemu, [
{
"execute": "query-cpu-model-expansion",
"arguments":
{
"type": "static",
"model": {"name": "host"}
},
"id": "model-expansion"
}])
for o in output:
if o.get("id") == "model-expansion":
return o["return"]["model"]
return None
def main():
parser = argparse.ArgumentParser(description="Gather cpu test data")
parser.add_argument(
"--name",
help="CPU model name. "
"If unset, model name is read from '/proc/cpuinfo'.")
parser.add_argument(
"--path-to-cpuid",
metavar="PATH",
help="Path to 'cpuid' utility. "
"If unset, the first executable 'cpuid' in $PATH is used.")
parser.add_argument(
"--path-to-qemu",
metavar="PATH",
help="Path to qemu. "
"If unset, will try '/usr/bin/qemu-system-x86_64', "
"'/usr/bin/qemu-kvm', and '/usr/libexec/qemu-kvm'.")
args = parser.parse_args()
if not args.path_to_qemu:
args.path_to_qemu = "qemu-system-x86_64"
search = [
"/usr/bin/qemu-system-x86_64",
"/usr/bin/qemu-kvm",
"/usr/libexec/qemu-kvm"]
for f in search:
if os.path.isfile(f):
args.path_to_qemu = f
name = gather_name(args)
print("model name\t: {}".format(name))
leaves = gather_cpuid_leaves(args)
print("CPU:")
for leave in leaves:
print(" {}".format(leave))
print()
via, msr = gather_msr()
if via is not None:
print("MSR{}:".format(via))
for key, value in sorted(msr.items()):
print(" 0x{:x}: 0x{:016x}\n".format(int(key), value))
static_model = gather_static_model(args)
print(end="", flush=True)
os.environ["CPU_GATHER_PY"] = "true"
os.environ["qemu"] = args.path_to_qemu
os.environ["model"] = json.dumps(static_model) if static_model else ""
subprocess.check_call("./cpu-gather.sh")
if __name__ == "__main__":
main()