all lists on 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 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.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal