From: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server v5 06/21] cpu flags: add helper querying CPU flags with nodes supporting them
Date: Fri, 15 May 2026 11:28:23 +0200 [thread overview]
Message-ID: <20260515092839.238064-7-a.bied-charreton@proxmox.com> (raw)
In-Reply-To: <20260515092839.238064-1-a.bied-charreton@proxmox.com>
The get_supported_cpu_flags helper returns a hardcoded list of
VM-specific flags, without any information on which nodes actually
support them.
Add query_available_cpu_flags, which annotates the flags QEMU recognizes
as `-cpu` arguments with the nodes that actually support them to give an
accurate picture of which flags will be accepted when starting a VM. Flags
can be filtered by scope (vm-specific or all) and queried for the
specific acceleration type (kvm/tcg), which determines which nodes report
supporting which flag.
This currently returns early when $arch is set to `aarch64`. This is
intended for vm-specific flags, since there are none that are currently
meant to be settable for VMs. For the general flags list, this is a
limitation due to the fact that it is a lot harder to get a list of
understood flags at QEMU build time for `aarch64`, as opposed to
`x86_64`, where `-cpu help` will just list all of them. It is left for a
future TODO.
Signed-off-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
---
src/PVE/QemuServer/CPUFlags.pm | 132 +++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
diff --git a/src/PVE/QemuServer/CPUFlags.pm b/src/PVE/QemuServer/CPUFlags.pm
index e17ed00c..709828d7 100644
--- a/src/PVE/QemuServer/CPUFlags.pm
+++ b/src/PVE/QemuServer/CPUFlags.pm
@@ -15,6 +15,7 @@ our @EXPORT_OK = qw(
get_supported_cpu_flags
query_understood_cpu_flags
normalize_cpu_flag
+ query_available_cpu_flags
);
my $supported_vm_specific_cpu_flags_by_arch = {
@@ -154,6 +155,11 @@ sub supported_cpu_flags_names() {
return @supported_cpu_flags_name_sorted;
}
+sub supported_cpu_flags_names_by_arch($arch) {
+ my @res = sort map { $_->{name} } $supported_vm_specific_cpu_flags_by_arch->{$arch}->@*;
+ return @res;
+}
+
sub cpu_flag_supported_re() {
return qr/([+-])(@{[join('|', supported_cpu_flags_names())]})/;
}
@@ -187,4 +193,130 @@ sub query_understood_cpu_flags($arch) {
return \@flags;
}
+=head3 flag_is_vm_specific($flag)
+
+Return true if `$flag` may be set for a VM's CPU flags configuration.
+
+=cut
+
+sub flag_is_vm_specific($flag) {
+ return defined($all_supported_vm_specific_cpu_flags->{$flag});
+}
+
+sub flag_descriptions($arch) {
+ return { map { $_->{name} => $_->{description} }
+ $supported_vm_specific_cpu_flags_by_arch->{$arch}->@* };
+}
+
+=head3 query_available_cpu_flags($accel, $vm_specific, $arch)
+
+Retrieve a list of available flags, i.e., flags that will be accepted by PVE in a
+processor config when attempting to spawn a VM. Each flag is returned along with a list
+of nodes that support it. Flags that are not supported on any node are also returned;
+filtering them out is up to the consumer of this API.
+
+B<Parameters:>
+
+=over
+
+=item C<$accel> (C<kvm> | C<tcg>)
+
+Selects which acceleration type flag/node compatibility should be evaluated for.
+
+=item C<$vm_specific> (boolean)
+
+When set to 1, return only VM-specific flags, otherwise return all flags.
+
+=item C<$arch> (C<x86_64> | C<aarch64>)
+
+Specifies which architecture to query flags for. Note that in both scopes (VM-specific
+and all), C<aarch64> returns empty lists: this is intended for VM-specific flags, as no
+C<aarch64> flags are currently settable for a specific VM, however it is a known
+limitation for the "all" scope. PVE does not currently ship a list of understood flags
+for C<aarch64>, as it is not as trivial to obtain as for C<x86_64>, whose flags are easy
+to parse from QEMU's C<-cpu help> output.
+
+=back
+
+In order to get an accurate picture of which flags can actually be used, two sources are
+combined (see C<PVE::QemuServer::query_supported_cpu_flags> for details):
+
+=over
+
+=item 1.
+
+The B<understood> CPU flags, i.e., all flags QEMU accepts as C<-cpu> arguments in
+principle, regardless of whether the host CPU actually supports them.
+
+=item 2.
+
+The B<supported> CPU flags: the flags the host CPU actually supports, cached in the node
+KV store by C<pvestatd>. This is node-specific.
+
+=back
+
+Each flag from (1) is annotated with the subset of nodes from (2) that report supporting
+it.
+
+=cut
+
+sub query_available_cpu_flags($accel, $vm_specific, $arch) {
+ # TODO: a way to get supported flags for aarch64. This is not done because PVE
+ # does not currently ship a list of understood flags for aarch64, as it's more difficult
+ # to obtain during QEMU build - for x86_64, qemu -cpu help will just list the flags.
+ return [] if $arch eq 'aarch64';
+
+ my $descriptions = flag_descriptions($arch);
+ my $base =
+ !$vm_specific
+ ? query_understood_cpu_flags($arch)
+ : [supported_cpu_flags_names_by_arch($arch)];
+ my $available_flags = {
+ map {
+ $_ => { name => $_, 'supported-on' => {}, description => $descriptions->{$_} }
+ } @$base
+ };
+
+ my $kv_store = "cpuflags-$accel";
+ my $flags = PVE::Cluster::get_node_kv($kv_store);
+
+ $available_flags->{'nested-virt'} = {
+ name => 'nested-virt',
+ 'supported-on' => {},
+ description => $descriptions->{'nested-virt'},
+ };
+
+ my $add_flag = sub($node, $name) {
+ return if !defined($available_flags->{$name});
+ $available_flags->{$name}->{'supported-on'}->{$node} = 1;
+ };
+
+ for my $node (keys %$flags) {
+ # This depends on `pvestatd` storing the flags in space-separated format, which
+ # is the case at the time of this commit.
+ for (split(' ', $flags->{$node})) {
+ my $pve_alias = undef;
+ $pve_alias = 'nested-virt' if $_ eq 'svm' || $_ eq 'vmx';
+ next if $vm_specific && !flag_is_vm_specific($_) && !$pve_alias;
+ $add_flag->($node, $_) if !($vm_specific && $pve_alias);
+ $add_flag->($node, $pve_alias) if $pve_alias;
+ }
+ }
+
+ for my $flag (values %$available_flags) {
+ $flag->{'supported-on'} = [sort keys $flag->{'supported-on'}->%*];
+ }
+
+ # Make sure 'nested-virt' is always shown first.
+ my $nested_virt = delete $available_flags->{'nested-virt'};
+
+ # Order flags that are not supported anywhere in the cluster to the end.
+ my @sorted = sort {
+ (scalar($a->{'supported-on'}->@*) == 0) <=> (scalar($b->{'supported-on'}->@*) == 0)
+ || $a->{name} cmp $b->{name}
+ } values %$available_flags;
+
+ return [defined($nested_virt) ? ($nested_virt, @sorted) : @sorted];
+}
+
1;
--
2.47.3
next prev parent reply other threads:[~2026-05-15 9:29 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-15 9:28 [PATCH docs/manager/qemu-server v5 00/21] Add API and UI for custom CPU models Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-docs v5 01/21] qm: add anchor to "CPU Type" section Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 02/21] cpu config: rename CPU models config path variable Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 03/21] cpu flags: move cpu flags-related utilities to their own module Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 04/21] cpu flags: compare against JSON::true when querying supported flags Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 05/21] cpu flags: normalize CPU flags to QEMU's format Arthur Bied-Charreton
2026-05-15 9:28 ` Arthur Bied-Charreton [this message]
2026-05-15 9:28 ` [PATCH qemu-server v5 07/21] cpu config: rename custom CPU model config loader Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 08/21] cpu config: add helpers to lock and write config Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 09/21] cpu: register standard option for CPU format Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 10/21] api: cpu flags: improve flags list returned by endpoint Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH qemu-server v5 11/21] custom cpu models: avoid redundant config load Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 12/21] cluster: reorder imports Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 13/21] cluster: makefile: reorder perl sources and align backslashes Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 14/21] api: add endpoint querying available CPU flags cluster-wide Arthur Bied-Charreton
2026-05-15 9:45 ` Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 15/21] api: add CRUD handlers for custom CPU models Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 16/21] ui: cpu model selector: allow filtering out custom models Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 17/21] ui: add basic custom CPU model editor Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 18/21] ui: cpu flags selector: add CPU flag editor for custom models Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 19/21] ui: cpu flags selector: allow filtering out flags supported on 0 nodes Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 20/21] ui: cpu flags selector: add search bar for large lists of flags Arthur Bied-Charreton
2026-05-15 9:28 ` [PATCH pve-manager v5 21/21] ui: group custom CPU with resource mappings Arthur Bied-Charreton
2026-05-15 17:05 ` [PATCH docs/manager/qemu-server v5 00/21] Add API and UI for custom CPU models Max R. Carrara
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=20260515092839.238064-7-a.bied-charreton@proxmox.com \
--to=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox