public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784
@ 2024-01-24  9:49 Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string Markus Frank
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Markus Frank @ 2024-01-24  9:49 UTC (permalink / raw)
  To: pve-devel

overall change in v8:
* rebase to master

I was able to clarify any ambiguity regarding vIOMMU:
https://lists.gnu.org/archive/html/qemu-devel/2023-10/msg02370.html

The iommu_platform parameter could be made an optional parameter for VirtIO
devices to add more isolation (with the downside of making them less performant)
in a follow-up patch series.


qemu-server:

v8:
* removed kvm variable since the check does not exist anymore

v7:
* changed viommu to string and added virtio-iommu implementation
* seperated "machine as property-string" patch from "fix #3784" patch
* moved format definition/parsing/printing to QemuServer::Machine
* merged test-cases into "fix #3784" patch
* removed kvm check, since it does not prevent vIOMMU from working
(only nested virtualization requires kvm & host cpu)

v6:
* added helper function for machine config validation
* replaced old standard option for "pve-qemu-machine" to new property string

v5:
* set $kvm to 1 if is_native, so that api kvm check works.

v4:
* added kvm/q35 checks in API
* reused pve-qemu-machine

v3:
* replaced old machine type with property-string with viommu-parameter

v2:
* moved viommu-parameter inside of machine_fmt and added it the new
parameter machine_properties
new Config -> machine_properties: viommu=1,etc
* check if kvm and q35 are set

Markus Frank (2):
  machine as property-string
  fix #3784: Parameter for guest vIOMMU + test-cases

 PVE/API2/Qemu.pm                        | 11 ++++-
 PVE/QemuConfig.pm                       |  3 +-
 PVE/QemuServer.pm                       | 28 +++++++-----
 PVE/QemuServer/Machine.pm               | 57 ++++++++++++++++++++++++-
 test/cfg2cmd/q35-viommu-intel.conf      |  1 +
 test/cfg2cmd/q35-viommu-intel.conf.cmd  | 23 ++++++++++
 test/cfg2cmd/q35-viommu-virtio.conf     |  1 +
 test/cfg2cmd/q35-viommu-virtio.conf.cmd | 23 ++++++++++
 8 files changed, 132 insertions(+), 15 deletions(-)
 create mode 100644 test/cfg2cmd/q35-viommu-intel.conf
 create mode 100644 test/cfg2cmd/q35-viommu-intel.conf.cmd
 create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf
 create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf.cmd


docs:

v8:
* added general explaination of vIOMMU
* removed kvm/host as requirements

v7:
* added virtio-iommu documentation
* changed and seperated requirements

v6:
* changed capitalization and rephrased the text a bit.

v5:
* changed Host and VM Requirements

Markus Frank (1):
  added vIOMMU documentation

 qm-pci-passthrough.adoc | 51 +++++++++++++++++++++++++++++++++++++++++
 qm.adoc                 |  1 +
 2 files changed, 52 insertions(+)


manager:

v7:
* changed viommu checkbox to ComboBox to select either none, intel or VirtIO

v6:
* replaced '=== "1"' check with PVE.Parser.parseBoolean
* replaced hidden kvm ui with view property
* a few style changes

v5:
* added check if kvm is undefined or null

v4:
* check if kvm is enabled
* added kvm+q35 hint

Markus Frank (1):
  ui: MachineEdit with viommu ComboBox

 www/manager6/qemu/MachineEdit.js | 45 ++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

-- 
2.39.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string
  2024-01-24  9:49 [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784 Markus Frank
@ 2024-01-24  9:49 ` Markus Frank
  2024-04-11  8:20   ` [pve-devel] applied: " Thomas Lamprecht
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases Markus Frank
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Markus Frank @ 2024-01-24  9:49 UTC (permalink / raw)
  To: pve-devel

Convert the machine parameter to a property-string and use the
machine type as the default key for backward compatibility.

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

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 9e3cfb5..c23b16a 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1047,11 +1047,13 @@ __PACKAGE__->register_method({
 			$conf->{vmgenid} = PVE::QemuServer::generate_uuid();
 		    }
 
-		    my $machine = $conf->{machine};
+		    my $machine_conf = PVE::QemuServer::Machine::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::Helpers::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} = PVE::QemuServer::Machine::print_machine($machine_conf);
 			}
 		    }
 
@@ -1890,6 +1892,9 @@ my $update_vm_api  = sub {
 			);
 		    }
 		    $conf->{pending}->{$opt} = $param->{$opt};
+		} elsif ($opt eq 'machine') {
+		    my $machine_conf = PVE::QemuServer::Machine::parse_machine($param->{$opt});
+		    $conf->{pending}->{$opt} = $param->{$opt};
 		} else {
 		    $conf->{pending}->{$opt} = $param->{$opt};
 
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index ca30eda..8e8a782 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -432,7 +432,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::Machine::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 bbd1918..6bb2ec3 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -123,14 +123,6 @@ PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
     optional => 1,
 });
 
-PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
-	description => "Specifies the QEMU machine type.",
-	type => 'string',
-	pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
-	maxLength => 40,
-	optional => 1,
-});
-
 # FIXME: remove in favor of just using the INotify one, it's cached there exactly the same way
 my $nodename_cache;
 sub nodename {
@@ -2090,8 +2082,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 = PVE::QemuServer::Machine::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
@@ -3252,7 +3245,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 = PVE::QemuServer::Machine::parse_machine($conf->{machine});
+    my $machine = $forcemachine || $machine_conf->{type};
 
     if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
 	$kvmversion //= kvm_user_version();
@@ -3501,6 +3495,8 @@ sub config_to_command {
     my $kvm = $conf->{kvm};
     my $nodename = nodename();
 
+    my $machine_conf = PVE::QemuServer::Machine::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);
diff --git a/PVE/QemuServer/Machine.pm b/PVE/QemuServer/Machine.pm
index 13721ae..5e3a75c 100644
--- a/PVE/QemuServer/Machine.pm
+++ b/PVE/QemuServer/Machine.pm
@@ -5,6 +5,7 @@ use warnings;
 
 use PVE::QemuServer::Helpers;
 use PVE::QemuServer::Monitor;
+use PVE::JSONSchema qw(get_standard_option parse_property_string);
 
 # Bump this for VM HW layout changes during a release (where the QEMU machine
 # version stays the same)
@@ -12,10 +13,46 @@ our $PVE_MACHINE_VERSION = {
     '4.1' => 2,
 };
 
+my $machine_fmt = {
+    type => {
+	default_key => 1,
+	description => "Specifies the QEMU machine type.",
+	type => 'string',
+	pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
+	maxLength => 40,
+	format_description => 'machine type',
+	optional => 1,
+    },
+};
+
+PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt);
+
+PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
+    description => "Specify the QEMU machine type.",
+    type => 'string',
+    optional => 1,
+    format => PVE::JSONSchema::get_format('pve-qemu-machine-fmt'),
+});
+
+sub parse_machine {
+    my ($value) = @_;
+
+    return if !$value;
+
+    my $res = parse_property_string($machine_fmt, $value);
+    return $res;
+}
+
+sub print_machine {
+    my ($machine_conf) = @_;
+    return print_property_string($machine_conf, $machine_fmt);
+}
+
 sub machine_type_is_q35 {
     my ($conf) = @_;
 
-    return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
+    my $machine_conf = parse_machine($conf->{machine});
+    return $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
 }
 
 # In list context, also returns whether the current machine is deprecated or not.
@@ -126,7 +163,8 @@ sub qemu_machine_pxe {
 
     my $machine =  get_current_qemu_machine($vmid);
 
-    if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
+    my $machine_conf = parse_machine($conf->{machine});
+    if ($machine_conf->{type} && $machine_conf->{type} =~ m/\.pxe$/) {
 	$machine .= '.pxe';
     }
 
-- 
2.39.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases
  2024-01-24  9:49 [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784 Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string Markus Frank
@ 2024-01-24  9:49 ` Markus Frank
  2024-04-11  8:30   ` Thomas Lamprecht
  2024-01-24  9:49 ` [pve-devel] [PATCH docs v8 3/4] added vIOMMU documentation Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH manager v8 4/4] ui: MachineEdit with viommu ComboBox Markus Frank
  3 siblings, 1 reply; 7+ messages in thread
From: Markus Frank @ 2024-01-24  9:49 UTC (permalink / raw)
  To: pve-devel

vIOMMU is the emulation of a hardware IOMMU within a virtual machine,
providing improved memory access control and security for virtualized I/O devices.
vIOMMU also enables the option to passthrough pci devices to L2 VMs
in L1 VMs via Nested Virtualisation.

Currently there are two vIOMMU implementation in QEMU to choose:
intel & virtio

Virtio-iommu is more recent but less used in production than intel-iommu.

The check_machine_config function prevents using intel-iommu with
i440fx.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
 PVE/API2/Qemu.pm                        |  2 ++
 PVE/QemuServer.pm                       | 12 ++++++++++++
 PVE/QemuServer/Machine.pm               | 17 ++++++++++++++++-
 test/cfg2cmd/q35-viommu-intel.conf      |  1 +
 test/cfg2cmd/q35-viommu-intel.conf.cmd  | 23 +++++++++++++++++++++++
 test/cfg2cmd/q35-viommu-virtio.conf     |  1 +
 test/cfg2cmd/q35-viommu-virtio.conf.cmd | 23 +++++++++++++++++++++++
 7 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 test/cfg2cmd/q35-viommu-intel.conf
 create mode 100644 test/cfg2cmd/q35-viommu-intel.conf.cmd
 create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf
 create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf.cmd

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index c23b16a..4a5a833 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1056,6 +1056,7 @@ __PACKAGE__->register_method({
 			    $conf->{machine} = PVE::QemuServer::Machine::print_machine($machine_conf);
 			}
 		    }
+		    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);
 
 		    PVE::QemuConfig->write_config($vmid, $conf);
 
@@ -1894,6 +1895,7 @@ my $update_vm_api  = sub {
 		    $conf->{pending}->{$opt} = $param->{$opt};
 		} elsif ($opt eq 'machine') {
 		    my $machine_conf = PVE::QemuServer::Machine::parse_machine($param->{$opt});
+		    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);
 		    $conf->{pending}->{$opt} = $param->{$opt};
 		} else {
 		    $conf->{pending}->{$opt} = $param->{$opt};
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 6bb2ec3..92832f8 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4070,6 +4070,18 @@ sub config_to_command {
     }
     push @$machineFlags, "type=${machine_type_min}";
 
+    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);
+
+    if ($machine_conf->{viommu}) {
+	if ($machine_conf->{viommu} eq 'intel') {
+	    unshift @$devices, '-device', 'intel-iommu,intremap=on,caching-mode=on';
+	    push @$machineFlags, 'kernel-irqchip=split';
+	}
+	if ($machine_conf->{viommu} eq 'virtio') {
+	    push @$devices, '-device', 'virtio-iommu-pci';
+	}
+    }
+
     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 5e3a75c..71790c4 100644
--- a/PVE/QemuServer/Machine.pm
+++ b/PVE/QemuServer/Machine.pm
@@ -23,12 +23,19 @@ my $machine_fmt = {
 	format_description => 'machine type',
 	optional => 1,
     },
+    viommu => {
+	type => 'string',
+	description => "Enable/disable guest vIOMMU"
+	    ." (needs kvm to be enabled and q35 to be set as machine type).",
+	enum => ['intel', 'virtio'],
+	optional => 1,
+    },
 };
 
 PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt);
 
 PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
-    description => "Specify the QEMU machine type.",
+    description => "Specify the QEMU machine type & enable/disable vIOMMU.",
     type => 'string',
     optional => 1,
     format => PVE::JSONSchema::get_format('pve-qemu-machine-fmt'),
@@ -48,6 +55,14 @@ sub print_machine {
     return print_property_string($machine_conf, $machine_fmt);
 }
 
+sub check_machine_config {
+    my ($conf, $machine_conf) = @_;
+    my $q35 = $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
+    if ($machine_conf->{viommu} && $machine_conf->{viommu} eq "intel" && !$q35) {
+	die "to use Intel vIOMMU please set the machine type to q35\n";
+    }
+}
+
 sub machine_type_is_q35 {
     my ($conf) = @_;
 
diff --git a/test/cfg2cmd/q35-viommu-intel.conf b/test/cfg2cmd/q35-viommu-intel.conf
new file mode 100644
index 0000000..e500ab0
--- /dev/null
+++ b/test/cfg2cmd/q35-viommu-intel.conf
@@ -0,0 +1 @@
+machine: q35,viommu=intel
diff --git a/test/cfg2cmd/q35-viommu-intel.conf.cmd b/test/cfg2cmd/q35-viommu-intel.conf.cmd
new file mode 100644
index 0000000..24e873d
--- /dev/null
+++ b/test/cfg2cmd/q35-viommu-intel.conf.cmd
@@ -0,0 +1,23 @@
+/usr/bin/kvm \
+  -id 8006 \
+  -name 'vm8006,debug-threads=on' \
+  -no-shutdown \
+  -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+  -mon 'chardev=qmp,mode=control' \
+  -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5' \
+  -mon 'chardev=qmp-event,mode=control' \
+  -pidfile /var/run/qemu-server/8006.pid \
+  -daemonize \
+  -smp '1,sockets=1,cores=1,maxcpus=1' \
+  -nodefaults \
+  -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+  -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+  -m 512 \
+  -device 'intel-iommu,intremap=on,caching-mode=on' \
+  -readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
+  -device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
+  -device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
+  -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+  -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+  -machine 'type=q35+pve0,kernel-irqchip=split'
diff --git a/test/cfg2cmd/q35-viommu-virtio.conf b/test/cfg2cmd/q35-viommu-virtio.conf
new file mode 100644
index 0000000..d31b339
--- /dev/null
+++ b/test/cfg2cmd/q35-viommu-virtio.conf
@@ -0,0 +1 @@
+machine: type=q35,viommu=virtio
diff --git a/test/cfg2cmd/q35-viommu-virtio.conf.cmd b/test/cfg2cmd/q35-viommu-virtio.conf.cmd
new file mode 100644
index 0000000..294c353
--- /dev/null
+++ b/test/cfg2cmd/q35-viommu-virtio.conf.cmd
@@ -0,0 +1,23 @@
+/usr/bin/kvm \
+  -id 8006 \
+  -name 'vm8006,debug-threads=on' \
+  -no-shutdown \
+  -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+  -mon 'chardev=qmp,mode=control' \
+  -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5' \
+  -mon 'chardev=qmp-event,mode=control' \
+  -pidfile /var/run/qemu-server/8006.pid \
+  -daemonize \
+  -smp '1,sockets=1,cores=1,maxcpus=1' \
+  -nodefaults \
+  -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+  -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+  -m 512 \
+  -readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
+  -device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
+  -device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
+  -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+  -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+  -device virtio-iommu-pci \
+  -machine 'type=q35+pve0'
-- 
2.39.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pve-devel] [PATCH docs v8 3/4] added vIOMMU documentation
  2024-01-24  9:49 [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784 Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases Markus Frank
@ 2024-01-24  9:49 ` Markus Frank
  2024-01-24  9:49 ` [pve-devel] [PATCH manager v8 4/4] ui: MachineEdit with viommu ComboBox Markus Frank
  3 siblings, 0 replies; 7+ messages in thread
From: Markus Frank @ 2024-01-24  9:49 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
 qm-pci-passthrough.adoc | 51 +++++++++++++++++++++++++++++++++++++++++
 qm.adoc                 |  1 +
 2 files changed, 52 insertions(+)

diff --git a/qm-pci-passthrough.adoc b/qm-pci-passthrough.adoc
index 3abeb50..04a3bc2 100644
--- a/qm-pci-passthrough.adoc
+++ b/qm-pci-passthrough.adoc
@@ -499,6 +499,57 @@ properly used with HA and hardware changes are detected and non root users
 can configure them. See xref:resource_mapping[Resource Mapping]
 for details on that.
 
+[[qm_pci_viommu]]
+vIOMMU (emulated IOMMU)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+vIOMMU is the emulation of a hardware IOMMU within a virtual machine,
+providing improved memory access control and security for virtualized I/O devices.
+Using the vIOMMU option also allows you to to passthrough PCI devices to level-2
+VMs in level-1 VMs via
+https://pve.proxmox.com/wiki/Nested_Virtualization[nested virtualization].
+There are currently two vIOMMU implementations available: Intel and VirtIO.
+
+Host requirement:
+
+* Add `intel_iommu=on` or `amd_iommu=on` depending on your CPU to your kernel
+command line.
+
+Intel vIOMMU
+^^^^^^^^^^^^
+
+Intel vIOMMU specific VM requirements:
+
+* Whether you are using an Intel or AMD CPU on your host, it is important to set
+`intel_iommu=on` in the VMs kernel parameters.
+
+* To use Intel vIOMMU you need to set *q35* as the machine type.
+
+If all requirements are met, you can add `viommu=intel` to the machine parameter
+in the configuration of the VM that should be able to passthrough PCI devices.
+
+----
+# qm set VMID -machine q35,viommu=intel
+----
+
+https://wiki.qemu.org/Features/VT-d[QEMU documentation for VT-d]
+
+VirtIO vIOMMU
+^^^^^^^^^^^^^
+
+This vIOMMU implementation is more recent and does not have as many limitations
+as Intel vIOMMU but is currently less used in production and less documentated.
+
+With VirtIO vIOMMU there is *no* need to set any kernel parameters.
+It is also *not* necessary to use q35 as the machine type, but it is advisable
+if you want to use PCIe.
+
+----
+# qm set VMID -machine q35,viommu=virtio
+----
+
+https://web.archive.org/web/20230804075844/https://michael2012z.medium.com/virtio-iommu-789369049443[Blog-Post by Michael Zhao explaining virtio-iommu]
+
 ifdef::wiki[]
 
 See Also
diff --git a/qm.adoc b/qm.adoc
index fa6a772..ac9738f 100644
--- a/qm.adoc
+++ b/qm.adoc
@@ -152,6 +152,7 @@ https://en.wikipedia.org/wiki/Intel_440FX[Intel 440FX] or the
 https://ark.intel.com/content/www/us/en/ark/products/31918/intel-82q35-graphics-and-memory-controller.html[Q35]
 chipset, which also provides a virtual PCIe bus, and thus may be
 desired if you want to pass through PCIe hardware.
+Additionally, you can select a xref:qm_pci_viommu[vIOMMU] implementation.
 
 Machine Version
 +++++++++++++++
-- 
2.39.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pve-devel] [PATCH manager v8 4/4] ui: MachineEdit with viommu ComboBox
  2024-01-24  9:49 [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784 Markus Frank
                   ` (2 preceding siblings ...)
  2024-01-24  9:49 ` [pve-devel] [PATCH docs v8 3/4] added vIOMMU documentation Markus Frank
@ 2024-01-24  9:49 ` Markus Frank
  3 siblings, 0 replies; 7+ messages in thread
From: Markus Frank @ 2024-01-24  9:49 UTC (permalink / raw)
  To: pve-devel

Added a proxmoxKVComboBox for selecting a vIOMMU implementation for a
VM. If i440fx is selected, a hint tells that q35 is required for Intel vIOMMU.

The UI also needs to parse the new machine parameter as PropertyString.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
 www/manager6/qemu/MachineEdit.js | 45 ++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/www/manager6/qemu/MachineEdit.js b/www/manager6/qemu/MachineEdit.js
index f928c80c..b9e42f14 100644
--- a/www/manager6/qemu/MachineEdit.js
+++ b/www/manager6/qemu/MachineEdit.js
@@ -1,6 +1,7 @@
 Ext.define('PVE.qemu.MachineInputPanel', {
     extend: 'Proxmox.panel.InputPanel',
     xtype: 'pveMachineInputPanel',
+    onlineHelp: 'qm_system_settings',
 
     controller: {
 	xclass: 'Ext.app.ViewController',
@@ -12,11 +13,14 @@ Ext.define('PVE.qemu.MachineInputPanel', {
 	onMachineChange: function(field, value) {
 	    let me = this;
 	    let version = me.lookup('version');
+	    let q35Hint = me.lookup('q35Hint');
 	    let store = version.getStore();
 	    let oldRec = store.findRecord('id', version.getValue(), 0, false, false, true);
 	    let type = value === 'q35' ? 'q35' : 'i440fx';
 	    store.clearFilter();
 	    store.addFilter(val => val.data.id === 'latest' || val.data.type === type);
+	    // show hint when Intel vIOMMU cannot be used
+	    q35Hint.setVisible(type === 'i440fx');
 	    if (!me.getView().isWindows) {
 		version.setValue('latest');
 	    } else {
@@ -40,12 +44,30 @@ Ext.define('PVE.qemu.MachineInputPanel', {
 	    delete values.delete;
 	}
 	delete values.version;
+	if (values.machine === undefined) {
+	    if (values.viommu) {
+		delete values.delete;
+		values.machine = "pc";
+	    } else {
+		values.delete = "machine";
+	    }
+	}
+	if (values.viommu) {
+	    values.machine += ",viommu=" + values.viommu;
+	}
+	if (values.delete === "viommu") {
+	    delete values.delete;
+	}
+	delete values.viommu;
 	return values;
     },
 
     setValues: function(values) {
 	let me = this;
 
+	let machineConf = PVE.Parser.parsePropertyString(values.machine, "type");
+	values.machine = machineConf.type;
+
 	me.isWindows = values.isWindows;
 	if (values.machine === 'pc') {
 	    values.machine = '__default__';
@@ -58,6 +80,9 @@ Ext.define('PVE.qemu.MachineInputPanel', {
 		values.version = 'pc-q35-5.1';
 	    }
 	}
+
+	values.viommu = machineConf.viommu || "__default__";
+
 	if (values.machine !== '__default__' && values.machine !== 'q35') {
 	    values.version = values.machine;
 	    values.machine = values.version.match(/q35/) ? 'q35' : '__default__';
@@ -113,6 +138,26 @@ Ext.define('PVE.qemu.MachineInputPanel', {
 	    fieldLabel: gettext('Note'),
 	    value: gettext('Machine version change may affect hardware layout and settings in the guest OS.'),
 	},
+	{
+	    xtype: 'proxmoxKVComboBox',
+	    fieldLabel: gettext('vIOMMU'),
+	    name: 'viommu',
+	    reference: 'viommu',
+	    value: '__default__',
+	    comboItems: [
+		['__default__', 'none'],
+		['intel', 'Intel'],
+		['virtio', 'VirtIO'],
+	    ],
+	},
+	{
+	    xtype: 'displayfield',
+	    name: 'q35Hint',
+	    reference: 'q35Hint',
+	    userCls: 'pmx-hint',
+	    value: gettext('Intel vIOMMU needs the q35 machine type'),
+	    hidden: true,
+	},
     ],
 });
 
-- 
2.39.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pve-devel] applied: [PATCH qemu-server v8 1/4] machine as property-string
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string Markus Frank
@ 2024-04-11  8:20   ` Thomas Lamprecht
  0 siblings, 0 replies; 7+ messages in thread
From: Thomas Lamprecht @ 2024-04-11  8:20 UTC (permalink / raw)
  To: Proxmox VE development discussion, Markus Frank

Am 24/01/2024 um 10:49 schrieb Markus Frank:
> Convert the machine parameter to a property-string and use the
> machine type as the default key for backward compatibility.
> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
>  PVE/API2/Qemu.pm          |  9 +++++++--
>  PVE/QemuConfig.pm         |  3 ++-
>  PVE/QemuServer.pm         | 16 ++++++---------
>  PVE/QemuServer/Machine.pm | 42 +++++++++++++++++++++++++++++++++++++--
>  4 files changed, 55 insertions(+), 15 deletions(-)
> 
>

applied, thanks!




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases
  2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases Markus Frank
@ 2024-04-11  8:30   ` Thomas Lamprecht
  0 siblings, 0 replies; 7+ messages in thread
From: Thomas Lamprecht @ 2024-04-11  8:30 UTC (permalink / raw)
  To: Proxmox VE development discussion, Markus Frank

Am 24/01/2024 um 10:49 schrieb Markus Frank:
> vIOMMU is the emulation of a hardware IOMMU within a virtual machine,
> providing improved memory access control and security for virtualized I/O devices.
> vIOMMU also enables the option to passthrough pci devices to L2 VMs
> in L1 VMs via Nested Virtualisation.
> 
> Currently there are two vIOMMU implementation in QEMU to choose:
> intel & virtio
> 
> Virtio-iommu is more recent but less used in production than intel-iommu.
> 
> The check_machine_config function prevents using intel-iommu with
> i440fx.
> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
>  PVE/API2/Qemu.pm                        |  2 ++
>  PVE/QemuServer.pm                       | 12 ++++++++++++
>  PVE/QemuServer/Machine.pm               | 17 ++++++++++++++++-
>  test/cfg2cmd/q35-viommu-intel.conf      |  1 +
>  test/cfg2cmd/q35-viommu-intel.conf.cmd  | 23 +++++++++++++++++++++++
>  test/cfg2cmd/q35-viommu-virtio.conf     |  1 +
>  test/cfg2cmd/q35-viommu-virtio.conf.cmd | 23 +++++++++++++++++++++++
>  7 files changed, 78 insertions(+), 1 deletion(-)
>  create mode 100644 test/cfg2cmd/q35-viommu-intel.conf
>  create mode 100644 test/cfg2cmd/q35-viommu-intel.conf.cmd
>  create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf
>  create mode 100644 test/cfg2cmd/q35-viommu-virtio.conf.cmd
> 

this one needs to be rebased.

> diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
> index c23b16a..4a5a833 100644
> --- a/PVE/API2/Qemu.pm
> +++ b/PVE/API2/Qemu.pm
> @@ -1056,6 +1056,7 @@ __PACKAGE__->register_method({
>  			    $conf->{machine} = PVE::QemuServer::Machine::print_machine($machine_conf);
>  			}
>  		    }
> +		    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);
>  
>  		    PVE::QemuConfig->write_config($vmid, $conf);
>  
> @@ -1894,6 +1895,7 @@ my $update_vm_api  = sub {
>  		    $conf->{pending}->{$opt} = $param->{$opt};
>  		} elsif ($opt eq 'machine') {
>  		    my $machine_conf = PVE::QemuServer::Machine::parse_machine($param->{$opt});
> +		    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);
>  		    $conf->{pending}->{$opt} = $param->{$opt};
>  		} else {
>  		    $conf->{pending}->{$opt} = $param->{$opt};
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 6bb2ec3..92832f8 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -4070,6 +4070,18 @@ sub config_to_command {
>      }
>      push @$machineFlags, "type=${machine_type_min}";
>  
> +    PVE::QemuServer::Machine::check_machine_config($conf, $machine_conf);


> +
> +    if ($machine_conf->{viommu}) {
> +	if ($machine_conf->{viommu} eq 'intel') {
> +	    unshift @$devices, '-device', 'intel-iommu,intremap=on,caching-mode=on';
> +	    push @$machineFlags, 'kernel-irqchip=split';
> +	}
> +	if ($machine_conf->{viommu} eq 'virtio') {


could be merged with the line before as `} elsif (...) {`

> +	    push @$devices, '-device', 'virtio-iommu-pci';
> +	}
> +    }
> +
>      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 5e3a75c..71790c4 100644
> --- a/PVE/QemuServer/Machine.pm
> +++ b/PVE/QemuServer/Machine.pm
> @@ -23,12 +23,19 @@ my $machine_fmt = {
>  	format_description => 'machine type',
>  	optional => 1,
>      },
> +    viommu => {
> +	type => 'string',
> +	description => "Enable/disable guest vIOMMU"
> +	    ." (needs kvm to be enabled and q35 to be set as machine type).",

early newline

> +	enum => ['intel', 'virtio'],
> +	optional => 1,
> +    },
>  };
>  
>  PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt);
>  
>  PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
> -    description => "Specify the QEMU machine type.",
> +    description => "Specify the QEMU machine type & enable/disable vIOMMU.",
>      type => 'string',
>      optional => 1,
>      format => PVE::JSONSchema::get_format('pve-qemu-machine-fmt'),
> @@ -48,6 +55,14 @@ sub print_machine {
>      return print_property_string($machine_conf, $machine_fmt);
>  }
>  
> +sub check_machine_config {

maybe name that `assert_valid_machine_property` to better convey that it can die

> +    my ($conf, $machine_conf) = @_;
> +    my $q35 = $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
> +    if ($machine_conf->{viommu} && $machine_conf->{viommu} eq "intel" && !$q35) {
> +	die "to use Intel vIOMMU please set the machine type to q35\n";
> +    }
> +}
> +
>  sub machine_type_is_q35 {
>      my ($conf) = @_;
>  
> diff --git a/test/cfg2cmd/q35-viommu-intel.conf b/test/cfg2cmd/q35-viommu-intel.conf
> new file mode 100644
> index 0000000..e500ab0
> --- /dev/null
> +++ b/test/cfg2cmd/q35-viommu-intel.conf

one test is great, but they do not cost that much (even if big line-wise) so maybe
also test the `virtio` one and some error behavior (e.g., enabled on a VM that has
i440fx as machine-type (one can specify an expected error in a source config, grep
"EXPECT_ERROR" for examples).




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-04-11  8:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-24  9:49 [pve-devel] [PATCH qemu-server/docs/manager v8 0/4] vIOMMU-Feature #3784 Markus Frank
2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 1/4] machine as property-string Markus Frank
2024-04-11  8:20   ` [pve-devel] applied: " Thomas Lamprecht
2024-01-24  9:49 ` [pve-devel] [PATCH qemu-server v8 2/4] fix #3784: Parameter for guest vIOMMU + test-cases Markus Frank
2024-04-11  8:30   ` Thomas Lamprecht
2024-01-24  9:49 ` [pve-devel] [PATCH docs v8 3/4] added vIOMMU documentation Markus Frank
2024-01-24  9:49 ` [pve-devel] [PATCH manager v8 4/4] ui: MachineEdit with viommu ComboBox Markus Frank

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