public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
To: Fiona Ebner <f.ebner@proxmox.com>
Cc: pve-devel@lists.proxmox.com, Wolfgang Bumiller <w.bumiller@proxmox.com>
Subject: Re: [PATCH qemu-server 7/8] api: qemu: Extend cpu-flags endpoint to return actually supported flags
Date: Mon, 23 Mar 2026 08:25:37 +0100	[thread overview]
Message-ID: <hfuhp4xfhccgbwd5kituii7wo74o6zf5pu2xt5v6izjfghs2lv@uoli5lddcw7l> (raw)
In-Reply-To: <fbfd486d-4f37-48e7-931b-20bf21668591@proxmox.com>

On Fri, Mar 20, 2026 at 06:20:40PM +0100, Fiona Ebner wrote:
> Similar comment regarding the 'qemu' prefix as in patch 6/8
> 
> Note that I'm not finished with the review and will continue next week
> with patch 8/8 and a quick look at the UI patches. Still sending this
> already for discussion.
> 
> Am 12.03.26 um 9:40 AM schrieb Arthur Bied-Charreton:
> > Previously the endpoint returned a hardcoded list of flags. It now
> > returns flags that are both recognized by QEMU, and supported by at
> > least one cluster node to give a somewhat accurate picture of what flags
> > can actually be used on the current cluster.
> > 
> > The 'nested-virt` entry is prepended. An optional 'accel' parameter
> > filters results by virtualization type (kvm or tcg) to help avoid
> > misconfigurations when assigning flags to VMs with a specific
> > acceleration setting.
> > 
> > This deviates from the original patch [0] by adding the functionality to
> > the `cpu-flags` endpoint instead of adding new endpoints. This is
> > because we never need the understood/supported flags alone in the
> > frontend, only their intersection. This also improves the VM CPU flag
> > selector by letting users select from all possible flags in their
> > cluster.
> > 
> > When passed `aarch64` as argument for `arch`, the index returns an empty
> > list, which is consistent with the behavior from before this patch.
> > 
> > [0]
> > https://lore.proxmox.com/pve-devel/20211028114150.3245864-3-s.reiter@proxmox.com/
> > 
> > Originally-by: Stefan Reiter <s.reiter@proxmox.com>
> 
> I don't think there is enough left of the original patch/approach in
> this case to keep that trailer.
> 
Noted
> > Signed-off-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
> > ---
> >  src/PVE/API2/Qemu/CPUFlags.pm | 108 +++++++++++++++++++++++++++++++++-
> >  1 file changed, 107 insertions(+), 1 deletion(-)
> > 
> > diff --git a/src/PVE/API2/Qemu/CPUFlags.pm b/src/PVE/API2/Qemu/CPUFlags.pm
> > index 672bd2d2..9baf6c3e 100644
> > --- a/src/PVE/API2/Qemu/CPUFlags.pm
> > +++ b/src/PVE/API2/Qemu/CPUFlags.pm
> > @@ -10,6 +10,9 @@ use PVE::QemuServer::CPUConfig;
> 
> Missing use statements for PVE::QemuServer and PVE::Cluster
> 
Argh, thanks!
> >  
> >  use base qw(PVE::RESTHandler);
> >  
> > +# vmx/svm are already represented by the nested-virt synthetic entry
> > +my %NESTED_VIRT_ALIASES = map { $_ => 1 } qw(vmx svm);
> 
> I'd prefer a short helper function with a bit more generic name, like
> flag_is_aliased(). And/or maybe have a filter_cpu_flags() function.
> 
> > +
> >  __PACKAGE__->register_method({
> >      name => 'index',
> >      path => '',
> > @@ -21,6 +24,13 @@ __PACKAGE__->register_method({
> >          properties => {
> >              node => get_standard_option('pve-node'),
> >              arch => get_standard_option('pve-qm-cpu-arch', { optional => 1 }),
> > +            accel => {
> > +                description =>
> > +                    'Virtualization type to filter flags by. If not provided, return all flags.',
> > +                type => 'string',
> > +                enum => [qw(kvm tcg)],
> > +                optional => 1,
> > +            },
> >          },
> >      },
> >      returns => {
> > @@ -35,6 +45,13 @@ __PACKAGE__->register_method({
> >                  description => {
> >                      type => 'string',
> >                      description => "Description of the CPU flag.",
> > +                    optional => 1,
> > +                },
> > +                'supported-on' => {
> > +                    description => 'List of nodes supporting the flag.',
> > +                    type => 'array',
> > +                    items => get_standard_option('pve-node'),
> > +                    optional => 1,
> >                  },
> >              },
> >          },
> > @@ -42,10 +59,99 @@ __PACKAGE__->register_method({
> >      code => sub {
> >          my ($param) = @_;
> >  
> > +        my $accel = extract_param($param, 'accel');
> >          my $arch = extract_param($param, 'arch');
> >  
> > -        return PVE::QemuServer::CPUConfig::get_supported_cpu_flags($arch);
> 
> NAK: this endpoint is used for the VM-specific selection right now and
> you can only configure flags that are allow-listed for a VM-specific CPU
> model, i.e. the get_supported_cpu_flags() flags, not all flags. Some
> flags do have security implications for the host too, that's why
> creating custom models with arbitrary flags must be a more privileged
> operation. I also think it would be a bit overkill to have all flags
> there, rather than the ones we deem most useful to expose.
> 
> So the API call should not start providing other flags by default,
> because the non-allow-listed flags cannot be set anyways for a
> VM-specific model. We can add a new API parameter for this, maybe
> "kind/type/something-else?" being an enum with values 'all|vm-specific'
> and by default having 'vm-specific'.
> 
Yes, the UI part of this series filters the flags in the UI, which is
admittedly not very pretty. I like the enum idea, will introduce this in
v2, this will simplify the UI code quite a bit as well. Thanks!
> I don't think there ever is a case where we want all flags regardless of
> accelerator, or is there? If not, we should make 'accel' have a default
> value to avoid the case where it's not provided at all being treated
> differently. I'd opt for 'kvm' as that's the more common use case.
> 
I don't think so either, will add the paramter in v2. I also think `kvm`
is a good default.
> > +        if (defined($arch) && $arch eq 'aarch64') {
> > +            return [];
> 
> We should document this in the description and add a TODO comment for
> the 'all flags' case. Not having any VM-specific flags is intentional
> right now. Not having any usable flags is not. It's just that we don't
> ship a list yet, as it's more difficult to obtain during QEMU build. For
> x86_64, kvm -cpu help will list the flags.
> 
Makes sense, will add a TODO comment and update the endpoint description.
> > +        }
> > +
> > +        my $descriptions = PVE::QemuServer::CPUConfig::description_by_flag($arch);
> 
> We could avoid passing around the descriptions, by having a function
> get_flag_description() and call that where needed. We can also have
> CPUConfig cache it with a hash to avoid re-grepping every time. That
> would feel a bit cleaner to me.
> 
Yes, the reason why I passed it around was to avoid re-grepping, having
it cached in CPUConfig does sound better though.
> > +
> > +        my $nested_virt = {
> > +            name => 'nested-virt',
> > +            description => $descriptions->{'nested-virt'},
> 
> Should we check which hosts do support it? I.e. check for svm|vmx and
> declare support if either is present on a host.
> 
Good call, I made the wrong assumption that they would always be
available - will add a check in v2. 
> > +        };
> > +
> > +        return [$nested_virt, @{ extract_flags($descriptions, $accel) }];
> >      },
> >  });
> >  
> > +# As described here [0], in order to get an accurate picture of which flags can actually be used, we need
> > +# to intersect:
> > +#
> > +# 1. The understood CPU flags, i.e., all flags QEMU accepts in theory, but that may not be actually
> > +#   supported by the host CPU, and
> > +# 2. The supported CPU flags, which returns some settings/flags that cannot be used as `-cpu` arguments.
> > +#
> > +# [0] https://git.proxmox.com/?p=qemu-server.git;a=blob;f=src/PVE/QemuServer.pm;h=09e7a19b2f11ef48d2cfc11837b70338c306817c;hb=refs/heads/master#l2916
> 
> I'd prefer having "See the documentation of query_supported_cpu_flags()
> and query_understood_cpu_flags() for more information." rather than
> putting a web link. Then the reference stays up-to-date with any changes
> there.
> 
Noted, will update the doc comment
> > +sub extract_flags($descriptions, $accel = undef) {
> 
> To me, the 'extract' in the function names here and for the others below
> is rather confusing. The functions take the hash of supported flags
> (currently called $descriptions) and adds more information/other flags.
> The only thing it's extracting is the descriptions.
> 
I will think about better naming, I agree that these are not very
good.
> > +    my $recognized = extract_understood($descriptions);
> > +    my $supported = extract_supported($descriptions, $accel);
> > +
> > +    my %recognized_set = map { $_->{name} => 1 } @$recognized;
> > +
> > +    return [
> > +        map { {
> > +            name => $_->{name},
> > +            'supported-on' => $_->{'supported-on'},
> > +            (defined($_->{description}) ? (description => $_->{description}) : ()),
> > +        } } grep {
> > +            $recognized_set{ $_->{name} }
> > +        } @$supported
> > +    ];
> > +}
> > +
> > +sub extract_understood($descriptions) {
> > +    my $understood_cpu_flags = PVE::QemuServer::query_understood_cpu_flags();
> > +
> > +    return [
> > +        map {
> > +            my $entry = { name => $_ };
> > +            $entry->{description} = $descriptions->{$_} if $descriptions->{$_};
> > +            $entry;
> > +        } grep {
> > +            !$NESTED_VIRT_ALIASES{$_}
> > +        } @$understood_cpu_flags
> > +    ];
> > +}
> > +
> > +# We do not use `PVE::QemuServer::CPUConfig::query_supported_cpu_flags`, which is quite expensive since
> > +# it needs to spawn QEMU instances in order to check which flags are supported. Rather, we use its cached
> > +# output, which is stored by `pvestatd` [0].
> > +#
> > +# [0] https://git.proxmox.com/?p=pve-manager.git;a=blob;f=PVE/Service/pvestatd.pm;h=d0719446e3b9a5f1bd3c861dbe768432cb3d7a0e;hb=refs/heads/master#l87
> 
> Again, not a fan of putting a web reference here. I think it's enough to
> mention that there are entries in the node kv store (regularly updated
> by pvestatd).
> 
Noted
> > +sub extract_supported($descriptions, $accel = undef) {
> > +    my %hash;
> > +
> > +    my sub add_flags($flags_by_node) {
> > +        for my $node (keys %$flags_by_node) {
> > +            # This depends on `pvestatd` storing the flags in space-separated format, which is the case
> > +            # at the time of this commit.
> > +            for (split(' ', $flags_by_node->{$node})) {
> > +                if ($hash{$_}) {
> > +                    $hash{$_}->{'supported-on'}->{$node} = 1;
> > +                } else {
> > +                    $hash{$_} = { 'supported-on' => { $node => 1 }, name => $_ };
> > +                }
> > +            }
> > +        }
> > +    }
> 
> I didn't know you could do nested subs directly and not just by
> assigning a closure to a local variable. I'm not sure we have this
> anywhere else in the code base and if there are any gotchas when doing
> it like this.
> 
> @Wolfgang: anything to be aware of with this construct?
> 
> > +
> > +    add_flags(PVE::Cluster::get_node_kv('cpuflags-kvm')) if !defined($accel) || $accel eq 'kvm';
> > +    add_flags(PVE::Cluster::get_node_kv('cpuflags-tcg')) if !defined($accel) || $accel eq 'tcg';
> > +
> > +    return [
> > +        map {
> > +            my $entry = { %$_, 'supported-on' => [sort keys %{ $_->{'supported-on'} }] };
> > +            $entry->{description} = $descriptions->{ $_->{name} }
> > +                if $descriptions->{ $_->{name} };
> > +            $entry;
> > +        } sort {
> > +            $a->{name} cmp $b->{name}
> > +        } grep {
> > +            !$NESTED_VIRT_ALIASES{ $_->{name} }
> > +        } values %hash
> 
> Style nit: we usually write such things in a more mixed way rather than
> purely functional. One advantage is that one doesn't have to read
> bottom-to-top. Opinionated preference, but I think when you have
> multiple instructions inside a map expression, it is a good sign that
> it's better written as a loop.
> 
Noted, will change that
> > +    ];
> > +}
> >  1;
> 




  reply	other threads:[~2026-03-23  7:25 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-12  8:40 [PATCH manager/qemu-server 0/8] Add API and UI for custom CPU models Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 1/8] ui: VMCPUFlagSelector: Fix unknownFlags behaviour Arthur Bied-Charreton
2026-03-25 15:57   ` Fiona Ebner
2026-03-26 13:47     ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 2/8] ui: CPUModelSelector: Fix dirty state on default Arthur Bied-Charreton
2026-03-26  9:53   ` Fiona Ebner
2026-03-26 14:14     ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 3/8] ui: CPUModelSelector: Allow filtering out custom models Arthur Bied-Charreton
2026-03-26  9:59   ` Fiona Ebner
2026-03-26 14:17     ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 4/8] ui: Add basic custom CPU model editor Arthur Bied-Charreton
2026-03-26 15:10   ` Fiona Ebner
2026-03-27  9:23     ` Arthur Bied-Charreton
2026-03-27  9:32       ` Fiona Ebner
2026-03-27  9:34         ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 5/8] ui: Add CPU flag editor for custom models Arthur Bied-Charreton
2026-03-26 15:22   ` Fiona Ebner
2026-03-27  9:34     ` Arthur Bied-Charreton
2026-03-26 15:40   ` Maximiliano Sandoval
2026-03-27  7:48     ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH qemu-server 6/8] qemu: Add helpers for new custom models endpoints Arthur Bied-Charreton
2026-03-20 17:20   ` Fiona Ebner
2026-03-23  6:56     ` Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH qemu-server 7/8] api: qemu: Extend cpu-flags endpoint to return actually supported flags Arthur Bied-Charreton
2026-03-20 17:20   ` Fiona Ebner
2026-03-23  7:25     ` Arthur Bied-Charreton [this message]
2026-03-12  8:40 ` [PATCH qemu-server 8/8] api: qemu: Add CRUD handlers for custom CPU models Arthur Bied-Charreton
2026-03-23 14:46   ` Fiona Ebner
2026-03-23 16:04     ` Arthur Bied-Charreton
2026-03-23 16:10       ` Arthur Bied-Charreton
2026-03-24  9:27         ` Fiona Ebner
2026-03-26 14:54 ` [PATCH manager/qemu-server 0/8] Add API and UI " Fiona Ebner
2026-03-27 13:07   ` Arthur Bied-Charreton
2026-03-27 13:28     ` Fiona Ebner

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=hfuhp4xfhccgbwd5kituii7wo74o6zf5pu2xt5v6izjfghs2lv@uoli5lddcw7l \
    --to=a.bied-charreton@proxmox.com \
    --cc=f.ebner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    --cc=w.bumiller@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