public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Markus Frank <m.frank@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server] fix #3784: Parameter for guest vIOMMU & machine as property-string
Date: Tue,  3 May 2022 13:18:59 +0200	[thread overview]
Message-ID: <20220503111901.126976-2-m.frank@proxmox.com> (raw)
In-Reply-To: <20220503111901.126976-1-m.frank@proxmox.com>

Changed the machine parameter to allow multiple machine-specific
parameters via property_string, but also allow old configs (via
default_key)

possible-configurations-example:
machine: q35
machine: pc
machine: q35,viommu=1
machine: type=q35,viommu=1

Also added a Parameter for vIOMMU so nobody has to use a github-script
or change the kvm command on every vm boot.
The args parameter doesn't work because the -device parameter(kvm)
with intel-iommu has to be placed before the other arguments.

vIOMMU enables the option to pass through pci devices to guest-vms
inside guest-vms for nested Virtualisation.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
 PVE/API2/Qemu.pm          |  7 ++---
 PVE/QemuConfig.pm         |  3 ++-
 PVE/QemuServer.pm         | 56 ++++++++++++++++++++++++++++++++++++---
 PVE/QemuServer/Machine.pm |  6 +++--
 4 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 71db264..661227f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -945,12 +945,13 @@ __PACKAGE__->register_method({
 		    if ((!defined($conf->{vmgenid}) || $conf->{vmgenid} eq '1') && $arch ne 'aarch64') {
 			$conf->{vmgenid} = PVE::QemuServer::generate_uuid();
 		    }
-
-		    my $machine = $conf->{machine};
+		    my $machine_conf = PVE::QemuServer::parse_machine($conf->{machine});
+		    my $machine = $machine_conf->{type};
 		    if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
 			# always pin Windows' machine version on create, they get to easily confused
 			if (PVE::QemuServer::windows_version($conf->{ostype})) {
-			    $conf->{machine} = PVE::QemuServer::windows_get_pinned_machine_version($machine);
+			    $machine_conf->{type} = PVE::QemuServer::windows_get_pinned_machine_version($machine);
+			    $conf->{machine} = print_property_string($machine_conf);
 			}
 		    }
 
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index cfef8d3..b82076f 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -430,7 +430,8 @@ sub __snapshot_rollback_hook {
 	} else {
 	    # Note: old code did not store 'machine', so we try to be smart
 	    # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
-	    $data->{forcemachine} = $conf->{machine} || 'pc-i440fx-1.4';
+	    my $machine_conf = PVE::QemuServer::parse_machine($conf->{machine});
+	    $data->{forcemachine} = $machine_conf->{type} || 'pc-i440fx-1.4';
 
 	    # we remove the 'machine' configuration if not explicitly specified
 	    # in the original config.
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 5db10fe..fa2e449 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -111,6 +111,25 @@ PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
     optional => 1,
 });
 
+my $machine_fmt = {
+    type => {
+	default_key => 1,
+	type => 'string',
+	description => "Specifies the Qemu machine type.",
+	pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
+	format_description => "qemu-machine-type",
+	maxLength => 40,
+	optional => 1,
+    },
+    viommu => {
+	type => 'boolean',
+	description => "enable guest vIOMMU (needs kvm to be enabled and q35 to be set as machine)",
+	default => 0,
+	optional => 1,
+    },
+};
+PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt);
+
 PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
 	description => "Specifies the Qemu machine type.",
 	type => 'string',
@@ -627,7 +646,12 @@ EODESCR
 	pattern => $PVE::QemuServer::CPUConfig::qemu_cmdline_cpu_re,
 	format_description => 'QEMU -cpu parameter'
     },
-    machine => get_standard_option('pve-qemu-machine'),
+    machine => {
+	description => "Specifies the Qemu machine type.",
+	type => 'string',
+	optional => 1,
+	format => 'pve-qemu-machine-fmt',
+    },
     arch => {
 	description => "Virtual processor architecture. Defaults to the host.",
 	optional => 1,
@@ -2085,6 +2109,16 @@ sub parse_watchdog {
     return $res;
 }
 
+sub parse_machine {
+    my ($value) = @_;
+
+    return if !$value;
+
+    my $res = eval { parse_property_string($machine_fmt, $value) };
+    warn $@ if $@;
+    return $res;
+}
+
 sub parse_guest_agent {
     my ($conf) = @_;
 
@@ -2156,8 +2190,9 @@ sub qemu_created_version_fixups {
     # check if we need to apply some handling for VMs that always use the latest machine version but
     # had a machine version transition happen that affected HW such that, e.g., an OS config change
     # would be required (we do not want to pin machine version for non-windows OS type)
+    my $machine_conf = parse_machine($conf->{machine});
     if (
-	(!defined($conf->{machine}) || $conf->{machine} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine
+	(!defined($machine_conf->{type}) || $machine_conf->{type} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine
 	&& (!defined($meta->{'creation-qemu'}) || !min_version($meta->{'creation-qemu'}, 6, 1)) # created before 6.1
 	&& (!$forced_vers || min_version($forced_vers, 6, 1)) # handle snapshot-rollback/migrations
 	&& min_version($kvmver, 6, 1) # only need to apply the change since 6.1
@@ -3257,7 +3292,8 @@ sub windows_get_pinned_machine_version {
 sub get_vm_machine {
     my ($conf, $forcemachine, $arch, $add_pve_version, $kvmversion) = @_;
 
-    my $machine = $forcemachine || $conf->{machine};
+    my $machine_conf = parse_machine($conf->{machine});
+    my $machine = $forcemachine || $machine_conf->{type};
 
     if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
 	$kvmversion //= kvm_user_version();
@@ -3472,6 +3508,8 @@ sub config_to_command {
     my $kvm = $conf->{kvm};
     my $nodename = nodename();
 
+    my $machine_conf = parse_machine($conf->{machine});
+
     my $arch = get_vm_arch($conf);
     my $kvm_binary = get_command_for_arch($arch);
     my $kvmver = kvm_user_version($kvm_binary);
@@ -3525,6 +3563,14 @@ sub config_to_command {
     my $use_old_bios_files = undef;
     ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
 
+    if ($machine_conf->{viommu} && (!$kvm || !$q35)) {
+        die "to use vIOMMU please enable kvm and set the machine type to q35";
+    }
+
+    if ($machine_conf->{viommu}) {
+        push @$devices, '-device', 'intel-iommu,intremap=on,caching-mode=on';
+    }
+
     push @$cmd, $kvm_binary;
 
     push @$cmd, '-id', $vmid;
@@ -4068,6 +4114,10 @@ sub config_to_command {
     }
     push @$machineFlags, "type=${machine_type_min}";
 
+    if ($machine_conf->{viommu}) {
+        push @$machineFlags, 'kernel-irqchip=split';
+    }
+
     push @$cmd, @$devices;
     push @$cmd, '-rtc', join(',', @$rtcFlags) if scalar(@$rtcFlags);
     push @$cmd, '-machine', join(',', @$machineFlags) if scalar(@$machineFlags);
diff --git a/PVE/QemuServer/Machine.pm b/PVE/QemuServer/Machine.pm
index d9429ed..33f9a64 100644
--- a/PVE/QemuServer/Machine.pm
+++ b/PVE/QemuServer/Machine.pm
@@ -15,7 +15,8 @@ our $PVE_MACHINE_VERSION = {
 sub machine_type_is_q35 {
     my ($conf) = @_;
 
-    return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
+    my $machine_conf = PVE::QemuServer::parse_machine($conf->{machine});
+    return $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
 }
 
 sub current_from_query_machines {
@@ -120,7 +121,8 @@ sub qemu_machine_pxe {
 
     my $machine =  get_current_qemu_machine($vmid);
 
-    if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
+    my $machine_conf = PVE::QemuServer::parse_machine($conf->{machine});
+    if ($conf->{machine} && $machine_conf->{type} =~ m/\.pxe$/) {
 	$machine .= '.pxe';
     }
 
-- 
2.30.2





  reply	other threads:[~2022-05-03 11:19 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-03 11:18 [pve-devel] [PATCH qemu-server 1/3] tests: replaced somemachine&someothermachine with q35&pc Markus Frank
2022-05-03 11:18 ` Markus Frank [this message]
2022-07-20 11:28   ` [pve-devel] [PATCH qemu-server] fix #3784: Parameter for guest vIOMMU & machine as property-string Markus Frank
2022-05-03 11:19 ` [pve-devel] [PATCH qemu-server] added test-cases for new machine-syntax & viommu Markus Frank
2022-05-03 11:19 ` [pve-devel] [PATCH manager] ui: MachineEdit with viommu checkbox Markus Frank
2022-05-04  7:57 ` [pve-devel] [PATCH qemu-server 1/3] tests: replaced somemachine&someothermachine with q35&pc Markus Frank
2022-05-05 11:08 ` Daniel Tschlatscher

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=20220503111901.126976-2-m.frank@proxmox.com \
    --to=m.frank@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