From: Fiona Ebner <f.ebner@proxmox.com>
To: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>,
pve-devel@lists.proxmox.com
Subject: Re: [PATCH qemu-server] cpu config: Move CPU flags utils to CPUConfig module
Date: Wed, 18 Feb 2026 11:42:05 +0100 [thread overview]
Message-ID: <b124759f-0298-4bdd-8d49-81d6cf5f128e@proxmox.com> (raw)
In-Reply-To: <20260217105050.194368-1-a.bied-charreton@proxmox.com>
Am 17.02.26 um 11:51 AM schrieb Arthur Bied-Charreton:
> ...where they fit better alongside other CPU-related utilities.
>
> Signed-off-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
When sending multiple patches, please always use a cover letter [0].
It's really helpful for tooling like b4 and to keep a better overview.
> ---
> src/PVE/QemuServer.pm | 131 +-------------------------------
> src/PVE/QemuServer/CPUConfig.pm | 131 +++++++++++++++++++++++++++++++-
> 2 files changed, 131 insertions(+), 131 deletions(-)
>
> diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
> index 5d2dbe03..2121f7c8 100644
> --- a/src/PVE/QemuServer.pm
> +++ b/src/PVE/QemuServer.pm
> @@ -46,8 +46,7 @@ use PVE::SafeSyslog;
> use PVE::Storage;
> use PVE::SysFSTools;
> use PVE::Systemd;
> -use PVE::Tools
> - qw(run_command file_read_firstline file_get_contents dir_glob_foreach get_host_arch $IPV6RE);
> +use PVE::Tools qw(run_command file_read_firstline file_get_contents dir_glob_foreach $IPV6RE);
>
> use PVE::QMPClient;
> use PVE::QemuConfig;
> @@ -2911,134 +2910,6 @@ sub vga_conf_has_spice {
> return $1 || 1;
> }
>
> -# To use query_supported_cpu_flags and query_understood_cpu_flags to get flags
> -# to use in a QEMU command line (-cpu element), first array_intersect the result
> -# of query_supported_ with query_understood_. This is necessary because:
> -#
> -# a) query_understood_ returns flags the host cannot use and
> -# b) query_supported_ (rather the QMP call) doesn't actually return CPU
> -# flags, but CPU settings - with most of them being flags. Those settings
> -# (and some flags, curiously) cannot be specified as a "-cpu" argument.
> -#
> -# query_supported_ needs to start up to 2 temporary VMs and is therefore rather
> -# expensive. If you need the value returned from this, you can get it much
> -# cheaper from pmxcfs using PVE::Cluster::get_node_kv('cpuflags-$accel') with
> -# $accel being 'kvm' or 'tcg'.
> -#
> -# pvestatd calls this function on startup and whenever the QEMU/KVM version
> -# changes, automatically populating pmxcfs.
> -#
> -# Returns: { kvm => [ flagX, flagY, ... ], tcg => [ flag1, flag2, ... ] }
> -# since kvm and tcg machines support different flags
> -#
> -sub query_supported_cpu_flags {
If you remove it here, it will require having a versioned Breaks in
qemu-server's d/control towards older pve-manager. I'd keep a wrapper
here, which we can drop in the future.
---snip 8<---
> diff --git a/src/PVE/QemuServer/CPUConfig.pm b/src/PVE/QemuServer/CPUConfig.pm
> index 32ec4954..e53f0978 100644
> --- a/src/PVE/QemuServer/CPUConfig.pm
> +++ b/src/PVE/QemuServer/CPUConfig.pm
> @@ -9,7 +9,8 @@ use PVE::JSONSchema qw(json_bool);
> use PVE::Cluster qw(cfs_register_file cfs_read_file);
> use PVE::ProcFSTools;
> use PVE::RESTEnvironment qw(log_warn);
> -use PVE::Tools qw(run_command);
> +use PVE::Tools qw(run_command get_host_arch);
> +use PVE::QemuServer::Monitor qw(mon_cmd);
>
> use PVE::QemuServer::Helpers qw(min_version);
>
> @@ -579,6 +580,134 @@ sub add_cpu_json_properties {
> return $prop;
> }
>
> +# To use query_supported_cpu_flags and query_understood_cpu_flags to get flags
> +# to use in a QEMU command line (-cpu element), first array_intersect the result
> +# of query_supported_ with query_understood_. This is necessary because:
> +#
> +# a) query_understood_ returns flags the host cannot use and
> +# b) query_supported_ (rather the QMP call) doesn't actually return CPU
> +# flags, but CPU settings - with most of them being flags. Those settings
> +# (and some flags, curiously) cannot be specified as a "-cpu" argument.
> +#
> +# query_supported_ needs to start up to 2 temporary VMs and is therefore rather
> +# expensive. If you need the value returned from this, you can get it much
> +# cheaper from pmxcfs using PVE::Cluster::get_node_kv('cpuflags-$accel') with
> +# $accel being 'kvm' or 'tcg'.
> +#
> +# pvestatd calls this function on startup and whenever the QEMU/KVM version
> +# changes, automatically populating pmxcfs.
> +#
> +# Returns: { kvm => [ flagX, flagY, ... ], tcg => [ flag1, flag2, ... ] }
> +# since kvm and tcg machines support different flags
> +#
> +sub query_supported_cpu_flags {
> + my ($arch) = @_;
> +
> + $arch //= get_host_arch();
> + my $default_machine = PVE::QemuServer::Machine::default_machine_for_arch($arch);
> +
> + my $flags = {};
> +
> + # FIXME: Once this is merged, the code below should work for ARM as well:
> + # https://lists.nongnu.org/archive/html/qemu-devel/2019-06/msg04947.html
> + die "QEMU/KVM cannot detect CPU flags on ARM (aarch64)\n"
> + if $arch eq "aarch64";
> +
> + my $kvm_supported = defined(PVE::QemuServer::kvm_version());
Ah, we cannot depend on PVE::QemuServer here, because that is a cyclic
dependency. That helper could be moved to the Helpers module anyways,
but...[continued below]
> + my $qemu_cmd = PVE::QemuServer::Helpers::get_command_for_arch($arch);
> + my $fakevmid = -1;
> + my $pidfile = PVE::QemuServer::Helpers::vm_pidfile_name($fakevmid);
> +
> + # Start a temporary (frozen) VM with vmid -1 to allow sending a QMP command
> + my $query_supported_run_qemu = sub {
> + my ($kvm) = @_;
> +
> + my $flags = {};
> + my $cmd = [
> + $qemu_cmd,
> + '-machine',
> + $default_machine,
> + '-display',
> + 'none',
> + '-chardev',
> + "socket,id=qmp,path=/var/run/qemu-server/$fakevmid.qmp,server=on,wait=off",
> + '-mon',
> + 'chardev=qmp,mode=control',
> + '-pidfile',
> + $pidfile,
> + '-S',
> + '-daemonize',
> + ];
> +
> + if (!$kvm) {
> + push @$cmd, '-accel', 'tcg';
> + }
> +
> + my $rc = run_command($cmd, noerr => 1, quiet => 0);
> + die "QEMU flag querying VM exited with code " . $rc if $rc;
> +
> + eval {
> + my $cmd_result = mon_cmd(
> + $fakevmid,
> + 'query-cpu-model-expansion',
> + type => 'full',
> + model => { name => 'host' },
> + );
> +
> + my $props = $cmd_result->{model}->{props};
> + foreach my $prop (keys %$props) {
> + next if $props->{$prop} ne '1';
> + # QEMU returns some flags multiple times, with '_', '.' or '-'
> + # (e.g. lahf_lm and lahf-lm; sse4.2, sse4-2 and sse4_2; ...).
> + # We only keep those with underscores, to match /proc/cpuinfo
> + $prop =~ s/\.|-/_/g;
> + $flags->{$prop} = 1;
> + }
> + };
> + my $err = $@;
> +
> + # force stop with 10 sec timeout and 'nocheck', always stop, even if QMP failed
> + PVE::QemuServer::vm_stop(undef, $fakevmid, 1, 1, 10, 0, 1);
...the vm_stop() call will be harder to deal with. The right module for
it would be the RunState module, but this requires more untangling
first. In particular, vm_stop_cleanup() calls vmconfig_apply_pending()
so that would also need to move to another module first. This is out of
scope for the feature you are working on. I'm also wondering if a
Capabilities::CPU module would not be better fitting than the CPUConfig
too. Let's just keep the functions in QemuServer.pm for now.
> +
> + die $err if $err;
> +
> + return [sort keys %$flags];
> + };
> +
> + # We need to query QEMU twice, since KVM and TCG have different supported flags
> + PVE::QemuConfig->lock_config(
You would also need to include the QemuConfig module, but this would not
be a dealbreaker from a first glance.
> + $fakevmid,
> + sub {
> + $flags->{tcg} = eval { $query_supported_run_qemu->(0) };
> + warn "warning: failed querying supported tcg flags: $@\n" if $@;
> +
> + if ($kvm_supported) {
> + $flags->{kvm} = eval { $query_supported_run_qemu->(1) };
> + warn "warning: failed querying supported kvm flags: $@\n" if $@;
> + }
> + },
> + );
> +
> + return $flags;
> +}
> +
> +# Understood CPU flags are written to a file at 'pve-qemu' compile time
> +my $understood_cpu_flag_dir = "/usr/share/kvm";
> +
> +sub query_understood_cpu_flags {
> + my $arch = get_host_arch();
> + my $filepath = "$understood_cpu_flag_dir/recognized-CPUID-flags-$arch";
> +
> + die "Cannot query understood QEMU CPU flags for architecture: $arch (file not found)\n"
> + if !-e $filepath;
> +
> + my $raw = PVE::Tools::file_get_contents($filepath);
> + $raw =~ s/^\s+|\s+$//g;
> + my @flags = split(/\s+/, $raw);
> +
> + return \@flags;
> +}
> +
> sub get_cpu_models {
> my ($include_custom, $arch) = @_;
>
[0]:
https://lore.proxmox.com/all/176174696524.1776006.10760334798456181474.b4-ty@proxmox.com/
prev parent reply other threads:[~2026-02-18 10:41 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-17 10:50 Arthur Bied-Charreton
2026-02-17 10:50 ` [PATCH pve-manager] cpu config: Update path to query_supported_cpu_flags Arthur Bied-Charreton
2026-02-18 10:42 ` Fiona Ebner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b124759f-0298-4bdd-8d49-81d6cf5f128e@proxmox.com \
--to=f.ebner@proxmox.com \
--cc=a.bied-charreton@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.