public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server v2 04/17] cpu flags: Add query_available_cpu_flags helper
Date: Wed,  1 Apr 2026 10:00:15 +0200	[thread overview]
Message-ID: <20260401080028.62513-5-a.bied-charreton@proxmox.com> (raw)
In-Reply-To: <20260401080028.62513-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 accleration 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
`86_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 | 104 +++++++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/src/PVE/QemuServer/CPUFlags.pm b/src/PVE/QemuServer/CPUFlags.pm
index 51d7753e..0bf560b4 100644
--- a/src/PVE/QemuServer/CPUFlags.pm
+++ b/src/PVE/QemuServer/CPUFlags.pm
@@ -14,6 +14,7 @@ our @EXPORT_OK = qw(
     supported_cpu_flags_names
     get_supported_cpu_flags
     query_understood_cpu_flags
+    query_available_cpu_flags
 );
 
 my $supported_vm_specific_cpu_flags_by_arch = {
@@ -98,6 +99,10 @@ sub supported_cpu_flags_names() {
     return sort keys $all_supported_vm_specific_cpu_flags->%*;
 }
 
+sub supported_cpu_flags_names_by_arch($arch) {
+    return sort map { $_->{name} } $supported_vm_specific_cpu_flags_by_arch->{$arch}->@*;
+}
+
 sub cpu_flag_supported_re() {
     return qr/([+-])(@{[join('|', supported_cpu_flags_names())]})/;
 }
@@ -123,4 +128,103 @@ sub query_understood_cpu_flags($arch) {
 
     return \@flags;
 }
+
+# Return true if `$flag` may be set for a single VM.
+sub flag_is_vm_specific($flag) {
+    return defined($all_supported_vm_specific_cpu_flags->{$flag});
+}
+
+# Flag is represented by the `nested-virt` alias
+sub flag_is_aliased($flag) {
+    return $flag eq 'vmx' || $flag eq 'svm';
+}
+
+sub description_by_flag($arch) {
+    return { map { $_->{name} => $_->{description} }
+        $supported_vm_specific_cpu_flags_by_arch->{$arch}->@* };
+}
+
+# Retrieve a list of available flags, i.e., flags that will be accepted as `-cpu` arguments by QEMU
+# 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.
+#
+# The $accel parameter (`kvm`|`tcg`) selects which acceleration type flag <> node compatibility should
+# be evaluated.
+#
+# The $vm_specific boolean parameter allows filtering by flag scope. When set to 1, return only
+# vm-specific flags, otherwise return all flags.
+#
+# The $arch parameter (`x86_64`|`aarch64`) specifies which architecture to query flags for. Note that
+# in both scopes (`vm-specific`,`all`), `aarch64` returns empty lists: this is wanted for `vm-specific`,
+# as no `aarch64` flags are currently intended to be settable for a specific VM, however this is a
+# known limitation for `all`. PVE does not currently ship a list of understood flags for `aarch64`,
+# it is not as trivial to get as for `x86_64`, whose flags are easy to parse out of QEMU's `-cpu help`
+# output.
+#
+# In order to get an accurate picture of which flags can actually be used, we combine two sources (see
+# PVE::QemuServer::query_supported_cpu_flags for details):
+#
+# 1. The understood CPU flags, i.e., all flags QEMU accepts as `-cpu` arguments in principle, regardless
+#    whether the host CPU actually supports them.
+# 2. The supported CPU flags: the flags the host CPU actually supports, cached in the node KV store by
+#    `pvestatd`. This is node-specific.
+#
+# Each flag from 1. is annotated with the subset of nodes from 2. that report supporting it.
+sub query_available_cpu_flags($accel, $vm_specific, $arch) {
+    # TODO: Find out 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 = description_by_flag($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 = $accel eq 'kvm' ? 'cpuflags-kvm' : 'cpuflags-tcg';
+    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 $aliased = flag_is_aliased($_);
+            next if $vm_specific && !flag_is_vm_specific($_) && !$aliased;
+            $add_flag->($node, $_) if !($vm_specific && $aliased);
+            $add_flag->($node, 'nested-virt') if $aliased;
+        }
+    }
+
+    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'};
+    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




  parent reply	other threads:[~2026-04-01  8:02 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-01  8:00 [PATCH docs/manager/qemu-server v2 00/17] Add API and UI for custom CPU models Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-docs v2 01/17] qm: Add anchor to "CPU Type" section Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH qemu-server v2 02/17] cpu config: Rename CPU models config path variable Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH qemu-server v2 03/17] cpu flags: Create CPUFlags module Arthur Bied-Charreton
2026-04-01  8:00 ` Arthur Bied-Charreton [this message]
2026-04-01  8:00 ` [PATCH qemu-server v2 05/17] cpu config: Add helpers to lock and write config Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH qemu-server v2 06/17] cpu: Register standard option for CPU format Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH qemu-server v2 07/17] cpu config: Set 'type' field before writing Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH qemu-server v2 08/17] cpu flags: Improve flags list returned by endpoint Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 09/17] api: Add endpoint querying available CPU flags cluster-wide Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 10/17] api: Add CRUD handlers for custom CPU models Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 11/17] ui: CPUModelSelector: Allow filtering out custom models Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 12/17] ui: Add basic custom CPU model editor Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 13/17] ui: VMCPUFlagSelector: Add CPU flag editor for custom models Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 14/17] ui: VMCPUFlagSelector: Fix buffered rendering error Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 15/17] ui: VMCPUFlagSelector: Allow filtering out flags supported on 0 nodes Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 16/17] ui: VMCPUFlagSelector: Add search bar for large lists of flags Arthur Bied-Charreton
2026-04-01  8:00 ` [PATCH pve-manager v2 17/17] RFC: ui: Group custom CPU with resource mappings Arthur Bied-Charreton

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=20260401080028.62513-5-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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal