* [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