Legacy IGD passthrough requires address 00:1f.0 to not be assigned to
anything on QEMU startup (currently it's assigned to bridge pci.2).
Changing this in general would break live-migration, so introduce a new
hostpci parameter "legacy-igd", which if set to 1 will move that bridge
to be nested under bridge 1.

This is safe because:
* Bridge 1 is unconditionally created on i440fx, so nesting is ok
* Defaults are not changed, i.e. PCI layout only changes when the new
parameter is specified manually
* hostpci forbids migration anyway

Additionally, the PT device has to be assigned address 00:02.0 in the
guest as well, which is usually used for VGA assignment. Luckily, IGD PT
requires vga=none, so that is not an issue either.

See https://git.qemu.org/?p=qemu.git;a=blob;f=docs/igd-assign.txt

Signed-off-by: Stefan Reiter <s.rei...@proxmox.com>
---
 PVE/QemuServer.pm     | 10 ++++++++--
 PVE/QemuServer/PCI.pm | 45 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 1c08222..1abe64b 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3102,7 +3102,7 @@ sub config_to_command {
     }
 
     # host pci device passthrough
-    my ($kvm_off, $gpu_passthrough) = 
PVE::QemuServer::PCI::print_hostpci_devices(
+    my ($kvm_off, $gpu_passthrough, $legacy_igd) = 
PVE::QemuServer::PCI::print_hostpci_devices(
        $conf, $devices, $winversion, $q35, $bridges, $arch, $machine_type);
 
     # usb devices
@@ -3458,7 +3458,13 @@ sub config_to_command {
 
     for my $k (sort {$b cmp $a} keys %$bridges) {
        next if $q35 && $k < 4; # q35.cfg already includes bridges up to 3
-       $pciaddr = print_pci_addr("pci.$k", undef, $arch, $machine_type);
+
+       my $k_name = $k;
+       if ($k == 2 && $legacy_igd) {
+           $k_name = "$k-igd";
+       }
+       $pciaddr = print_pci_addr("pci.$k_name", undef, $arch, $machine_type);
+
        my $devstr = "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr";
        if ($q35) {
            # add after -readconfig pve-q35.cfg
diff --git a/PVE/QemuServer/PCI.pm b/PVE/QemuServer/PCI.pm
index 39f9970..e835f39 100644
--- a/PVE/QemuServer/PCI.pm
+++ b/PVE/QemuServer/PCI.pm
@@ -55,6 +55,14 @@ EODESCR
        optional => 1,
        default => 0,
     },
+    'legacy-igd' => {
+       type => 'boolean',
+       description => "Pass this device in legacy IGD mode (allows required"
+                    . " 1f.0 PCI bridge and assigns correct address)."
+                    . " Requires i440fx machine type and VGA set to 'none'.",
+       optional => 1,
+       default => 0,
+    },
     'mdev' => {
        type => 'string',
         format_description => 'string',
@@ -89,7 +97,8 @@ sub get_pci_addr_map {
     $pci_addr_map = {
        piix3 => { bus => 0, addr => 1, conflict_ok => qw(ehci)  },
        ehci => { bus => 0, addr => 1, conflict_ok => qw(piix3) }, # instead of 
piix3 on arm
-       vga => { bus => 0, addr => 2 },
+       vga => { bus => 0, addr => 2, conflict_ok => qw(legacy-igd) },
+       'legacy-igd' => { bus => 0, addr => 2, conflict_ok => qw(vga) }, # 
legacy-igd requires vga=none
        balloon0 => { bus => 0, addr => 3 },
        watchdog => { bus => 0, addr => 4 },
        scsihw0 => { bus => 0, addr => 5, conflict_ok => qw(pci.3) },
@@ -149,6 +158,7 @@ sub get_pci_addr_map {
        'xhci' => { bus => 1, addr => 27 },
        'pci.4' => { bus => 1, addr => 28 },
        'rng0' => { bus => 1, addr => 29 },
+       'pci.2-igd' => { bus => 1, addr => 30 }, # replaces pci.2 in case a 
legacy IGD device is passed through
        'virtio6' => { bus => 2, addr => 1 },
        'virtio7' => { bus => 2, addr => 2 },
        'virtio8' => { bus => 2, addr => 3 },
@@ -351,6 +361,7 @@ sub print_hostpci_devices {
 
     my $kvm_off = 0;
     my $gpu_passthrough = 0;
+    my $legacy_igd = 0;
 
     for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++)  {
        my $id = "hostpci$i";
@@ -372,7 +383,32 @@ sub print_hostpci_devices {
                $pciaddr = print_pcie_addr($id);
            }
        } else {
-           $pciaddr = print_pci_addr($id, $bridges, $arch, $machine_type);
+           my $pci_name = $d->{'legacy-igd'} ? 'legacy-igd' : $id;
+           $pciaddr = print_pci_addr($pci_name, $bridges, $arch, 
$machine_type);
+       }
+
+       my $pcidevices = $d->{pciid};
+       my $multifunction = 1 if @$pcidevices > 1;
+
+       if ($d->{'legacy-igd'}) {
+           die "only one device can be assigned in legacy-igd mode\n"
+               if $legacy_igd;
+           $legacy_igd = 1;
+
+           die "legacy IGD assignment requires VGA mode to be 'none'\n"
+               if !defined($conf->{'vga'}) || $conf->{'vga'} ne 'none';
+           die "legacy IGD assignment requires rombar to be enabled\n"
+               if defined($d->{rombar}) && !$d->{rombar};
+           die "legacy IGD assignment is not compatible with x-vga\n"
+               if $d->{'x-vga'};
+           die "legacy IGD assignment is not compatible with mdev\n"
+               if $d->{mdev};
+           die "legacy IGD assignment is not compatible with q35\n"
+               if $q35;
+           die "legacy IGD assignment is not compatible with multifunction 
devices\n"
+               if $multifunction;
+           die "legacy IGD assignment only works for devices on host bus 
00:02.0\n"
+               if $pcidevices->[0]->{id} !~ m/02\.0$/;
        }
 
        my $xvga = '';
@@ -383,9 +419,6 @@ sub print_hostpci_devices {
            $gpu_passthrough = 1;
        }
 
-       my $pcidevices = $d->{pciid};
-       my $multifunction = 1 if @$pcidevices > 1;
-
        my $sysfspath;
        if ($d->{mdev} && scalar(@$pcidevices) == 1) {
            my $pci_id = $pcidevices->[0]->{id};
@@ -420,7 +453,7 @@ sub print_hostpci_devices {
        }
     }
 
-    return ($kvm_off, $gpu_passthrough);
+    return ($kvm_off, $gpu_passthrough, $legacy_igd);
 }
 
 1;
-- 
2.20.1


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

Reply via email to