public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server v2 4/8] cpu config: introduce vendor-agnostic 'nested-virt' CPU flag
Date: Fri,  7 Nov 2025 15:43:42 +0100	[thread overview]
Message-ID: <20251107144429.126790-5-f.ebner@proxmox.com> (raw)
In-Reply-To: <20251107144429.126790-1-f.ebner@proxmox.com>

The flag will automatically resolve to the flag required for the
current CPU on the host. The 'nested-virt' flag takes precendence over
the CPU-specific flag for nesting which might already be present with
custom CPU models. In that case, a warning is printed.

Also make sure that the actual resolved flag is passed along during
live migration, since the nested-virt flag can resolve differently on
different hosts.

Suggested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

Changes in v2:
* Pass running CPU configuration when using 'nested-virt'. This
  ensures that migration fails early if the flag resolves differently
  on the target.
* Describe that live migration still only works if it's the same flag.

I was thinking about using special characters in the flag name or some
custom-/pve-/special- prefix to distinguish from regular flags, but
decided against it in the end, because I got the gut feeling it might
cause more confusion than it helps. Users who are interested in
details will hopefully read the description and for others, having the
flag name be direct and descriptive is better.

 src/PVE/QemuServer/CPUConfig.pm | 52 +++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/src/PVE/QemuServer/CPUConfig.pm b/src/PVE/QemuServer/CPUConfig.pm
index 4cbd7b48..8daafd10 100644
--- a/src/PVE/QemuServer/CPUConfig.pm
+++ b/src/PVE/QemuServer/CPUConfig.pm
@@ -7,7 +7,10 @@ use JSON;
 
 use PVE::JSONSchema;
 use PVE::Cluster qw(cfs_register_file cfs_read_file);
+use PVE::ProcFSTools;
+use PVE::RESTEnvironment qw(log_warn);
 use PVE::Tools qw(run_command get_host_arch);
+
 use PVE::QemuServer::Helpers qw(min_version);
 
 use base qw(PVE::SectionConfig Exporter);
@@ -162,6 +165,11 @@ my $cpu_vendor_list = {
 };
 
 my $supported_cpu_flags = [
+    {
+        name => 'nested-virt',
+        description => "Controls nested virtualization, namely 'svm' for AMD CPUs and 'vmx' for"
+            . " Intel CPUs. Live migration still only works if it's the same flag on both sides.",
+    },
     {
         name => 'md-clear',
         description => "Required to let the guest OS know if MDS is mitigated correctly.",
@@ -261,8 +269,10 @@ my $cpu_fmt = {
     },
     flags => {
         description => "List of additional CPU flags separated by ';'. Use '+FLAG' to enable,"
-            . " '-FLAG' to disable a flag. Custom CPU models can specify any flag supported by"
-            . " QEMU/KVM, VM-specific flags must be from the following set for security reasons: "
+            . " '-FLAG' to disable a flag. There is a special 'nested-virt' shorthand which"
+            . " controls nested virtualization for the current CPU ('svm' for AMD and 'vmx' for"
+            . " Intel). Custom CPU models can specify any flag supported by QEMU/KVM, VM-specific"
+            . " flags must be from the following set for security reasons: "
             . join(', ', @supported_cpu_flags_names),
         format_description => '+FLAG[;-FLAG...]',
         type => 'string',
@@ -580,6 +590,8 @@ determined from the configuration alone. Possible abstractions:
 
 =item custom model: can change with updates to the custom model configuration
 
+=item abstract flag: for example, nested-virt changes with the host
+
 =back
 
 =cut
@@ -589,7 +601,15 @@ sub is_abstracted {
 
     my $cpu_conf = PVE::JSONSchema::parse_property_string('pve-cpu-conf', $cpu_property_string);
 
-    return is_custom_model($cpu_conf->{cputype});
+    return 1 if is_custom_model($cpu_conf->{cputype});
+
+    return if !$cpu_conf->{flags};
+    for my $flag (split(";", $cpu_conf->{flags})) {
+        if ($flag =~ $cpu_flag_supported_re) {
+            return 1 if $2 eq 'nested-virt';
+        }
+    }
+    return;
 }
 
 # Resolves multiple arrays of hashes representing CPU flags with metadata to a
@@ -610,8 +630,34 @@ sub resolve_cpu_flags {
 
     my $flags = {};
 
+    my $nested_flag;
+    my $nested_flag_resolved;
+    my $resolve_nested_flag = sub {
+        if (!$nested_flag_resolved) {
+            my $host_cpu_flags = PVE::ProcFSTools::read_cpuinfo()->{flags};
+            if ($host_cpu_flags =~ m/\s(svm|vmx)\s/) {
+                $nested_flag = $1;
+            } else {
+                log_warn("ignoring 'nested-virt' CPU flag - unable to resolve from host CPU flags");
+            }
+            $nested_flag_resolved = 1;
+        }
+        return $nested_flag;
+    };
+
     for my $hash (@flag_hashes) {
         for my $flag_name (keys %$hash) {
+            if ($flag_name eq 'nested-virt') {
+                my $nested_flag_name = $resolve_nested_flag->() or next;
+                if ($hash->{$nested_flag_name}) {
+                    warn "warning: CPU flag '$flag_name' overrides '$nested_flag_name'\n";
+                } else {
+                    print "CPU flag '$flag_name' resolved to '$nested_flag_name'\n";
+                }
+                $hash->{$nested_flag_name} = delete($hash->{$flag_name});
+                $flag_name = $nested_flag_name;
+            }
+
             my $flag = $hash->{$flag_name};
             my $old_flag = $flags->{$flag_name};
 
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-11-07 14:43 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-07 14:43 [pve-devel] [PATCH-SERIES qemu-server/manager v2 0/8] VM CPU flags: " Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH qemu-server v2 1/8] critic: code style: cpu config: unpack @_ first in resolve_cpu_flags() Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH qemu-server v2 2/8] api: add endpoint for querying available cpu flags Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH qemu-server v2 3/8] cpu config: introduce is_abstracted() helper Fiona Ebner
2025-11-07 14:43 ` Fiona Ebner [this message]
2025-11-07 14:43 ` [pve-devel] [PATCH manager v2 5/8] api: capabilities: register module for VM CPU flags Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH manager v2 6/8] ui: cpu flag selector: code style: use 'let' for declarations Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH manager v2 7/8] ui: cpu flag selector: use simpler method to get all records of the store Fiona Ebner
2025-11-07 14:43 ` [pve-devel] [PATCH manager v2 8/8] ui: cpu flag selector: query CPU flag list via API 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=20251107144429.126790-5-f.ebner@proxmox.com \
    --to=f.ebner@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