* [pve-devel] [PATCH qemu-server v9 1/3] fix #3784: config: Parameter for guest vIOMMU + test-cases
2024-04-11 10:48 [pve-devel] [PATCH qemu-server/docs/manager v9 0/3] vIOMMU-Feature #3784 Markus Frank
@ 2024-04-11 10:48 ` Markus Frank
2024-04-11 14:44 ` [pve-devel] applied: " Thomas Lamprecht
2024-04-11 10:48 ` [pve-devel] [PATCH docs v9 2/3] add vIOMMU documentation Markus Frank
2024-04-11 10:48 ` [pve-devel] [PATCH manager v9 3/3] ui: machine: add viommu ComboBox Markus Frank
2 siblings, 1 reply; 7+ messages in thread
From: Markus Frank @ 2024-04-11 10:48 UTC (permalink / raw)
To: pve-devel
vIOMMU enables the option to passthrough pci devices to L2 VMs
in L1 VMs via Nested Virtualisation and adds an extra isolation.
Uses the new property-string from the "config: define machine schema
as property-string"-commit to add the viommu option to the machine
parameter.
Currently there are two vIOMMU implementation in QEMU to choose:
intel or virtio
Virtio-iommu is more recent but less used in production than intel-iommu.
The assert_valid_machine_property 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/i440fx-viommu-intel.conf | 2 ++
test/cfg2cmd/i440fx-viommu-virtio.conf | 1 +
test/cfg2cmd/i440fx-viommu-virtio.conf.cmd | 25 ++++++++++++++++++++++
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 ++++++++++++++++++++
10 files changed, 106 insertions(+), 1 deletion(-)
create mode 100644 test/cfg2cmd/i440fx-viommu-intel.conf
create mode 100644 test/cfg2cmd/i440fx-viommu-virtio.conf
create mode 100644 test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
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 f3ce83d..3eabddd 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1136,6 +1136,7 @@ __PACKAGE__->register_method({
$conf->{machine} = PVE::QemuServer::Machine::print_machine($machine_conf);
}
}
+ PVE::QemuServer::Machine::assert_valid_machine_property($conf, $machine_conf);
$conf->{lock} = 'import' if $live_import_mapping;
@@ -2000,6 +2001,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::assert_valid_machine_property($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 abe175a..c94c90d 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4080,6 +4080,18 @@ sub config_to_command {
}
push @$machineFlags, "type=${machine_type_min}";
+ PVE::QemuServer::Machine::assert_valid_machine_property($conf, $machine_conf);
+
+ my $viommu = $machine_conf->{viommu};
+ if ($viommu) {
+ if ($viommu eq 'intel') {
+ unshift @$devices, '-device', 'intel-iommu,intremap=on,caching-mode=on';
+ push @$machineFlags, 'kernel-irqchip=split';
+ } elsif ($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..3d92c96 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 and set guest vIOMMU variant (Intel vIOMMU needs 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 => '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 assert_valid_machine_property {
+ 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/i440fx-viommu-intel.conf b/test/cfg2cmd/i440fx-viommu-intel.conf
new file mode 100644
index 0000000..bc1eb95
--- /dev/null
+++ b/test/cfg2cmd/i440fx-viommu-intel.conf
@@ -0,0 +1,2 @@
+# EXPECT_ERROR: to use Intel vIOMMU please set the machine type to q35
+machine: pc,viommu=intel
diff --git a/test/cfg2cmd/i440fx-viommu-virtio.conf b/test/cfg2cmd/i440fx-viommu-virtio.conf
new file mode 100644
index 0000000..fe7b514
--- /dev/null
+++ b/test/cfg2cmd/i440fx-viommu-virtio.conf
@@ -0,0 +1 @@
+machine: pc,viommu=virtio
diff --git a/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd b/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
new file mode 100644
index 0000000..0352354
--- /dev/null
+++ b/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
@@ -0,0 +1,25 @@
+/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 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -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=pc+pve0'
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 manager v9 3/3] ui: machine: add viommu ComboBox
2024-04-11 10:48 [pve-devel] [PATCH qemu-server/docs/manager v9 0/3] vIOMMU-Feature #3784 Markus Frank
2024-04-11 10:48 ` [pve-devel] [PATCH qemu-server v9 1/3] fix #3784: config: Parameter for guest vIOMMU + test-cases Markus Frank
2024-04-11 10:48 ` [pve-devel] [PATCH docs v9 2/3] add vIOMMU documentation Markus Frank
@ 2024-04-11 10:48 ` Markus Frank
2024-04-11 15:13 ` Thomas Lamprecht
2 siblings, 1 reply; 7+ messages in thread
From: Markus Frank @ 2024-04-11 10:48 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..45f3d34d 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__', Proxmox.Utils.defaultText + ' (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