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
next prev 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