mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-10-04 21:14:21 +00:00
fix #2794: allow legacy IGD passthrough
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.reiter@proxmox.com>
This commit is contained in:
parent
74c17b7a23
commit
13d689792e
@ -3102,7 +3102,7 @@ sub config_to_command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# host pci device passthrough
|
# 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);
|
$conf, $devices, $winversion, $q35, $bridges, $arch, $machine_type);
|
||||||
|
|
||||||
# usb devices
|
# usb devices
|
||||||
@ -3458,7 +3458,13 @@ sub config_to_command {
|
|||||||
|
|
||||||
for my $k (sort {$b cmp $a} keys %$bridges) {
|
for my $k (sort {$b cmp $a} keys %$bridges) {
|
||||||
next if $q35 && $k < 4; # q35.cfg already includes bridges up to 3
|
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";
|
my $devstr = "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr";
|
||||||
if ($q35) {
|
if ($q35) {
|
||||||
# add after -readconfig pve-q35.cfg
|
# add after -readconfig pve-q35.cfg
|
||||||
|
@ -55,6 +55,14 @@ EODESCR
|
|||||||
optional => 1,
|
optional => 1,
|
||||||
default => 0,
|
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' => {
|
'mdev' => {
|
||||||
type => 'string',
|
type => 'string',
|
||||||
format_description => 'string',
|
format_description => 'string',
|
||||||
@ -89,7 +97,8 @@ sub get_pci_addr_map {
|
|||||||
$pci_addr_map = {
|
$pci_addr_map = {
|
||||||
piix3 => { bus => 0, addr => 1, conflict_ok => qw(ehci) },
|
piix3 => { bus => 0, addr => 1, conflict_ok => qw(ehci) },
|
||||||
ehci => { bus => 0, addr => 1, conflict_ok => qw(piix3) }, # instead of piix3 on arm
|
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 },
|
balloon0 => { bus => 0, addr => 3 },
|
||||||
watchdog => { bus => 0, addr => 4 },
|
watchdog => { bus => 0, addr => 4 },
|
||||||
scsihw0 => { bus => 0, addr => 5, conflict_ok => qw(pci.3) },
|
scsihw0 => { bus => 0, addr => 5, conflict_ok => qw(pci.3) },
|
||||||
@ -149,6 +158,7 @@ sub get_pci_addr_map {
|
|||||||
'xhci' => { bus => 1, addr => 27 },
|
'xhci' => { bus => 1, addr => 27 },
|
||||||
'pci.4' => { bus => 1, addr => 28 },
|
'pci.4' => { bus => 1, addr => 28 },
|
||||||
'rng0' => { bus => 1, addr => 29 },
|
'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 },
|
'virtio6' => { bus => 2, addr => 1 },
|
||||||
'virtio7' => { bus => 2, addr => 2 },
|
'virtio7' => { bus => 2, addr => 2 },
|
||||||
'virtio8' => { bus => 2, addr => 3 },
|
'virtio8' => { bus => 2, addr => 3 },
|
||||||
@ -351,6 +361,7 @@ sub print_hostpci_devices {
|
|||||||
|
|
||||||
my $kvm_off = 0;
|
my $kvm_off = 0;
|
||||||
my $gpu_passthrough = 0;
|
my $gpu_passthrough = 0;
|
||||||
|
my $legacy_igd = 0;
|
||||||
|
|
||||||
for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
|
for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
|
||||||
my $id = "hostpci$i";
|
my $id = "hostpci$i";
|
||||||
@ -372,7 +383,32 @@ sub print_hostpci_devices {
|
|||||||
$pciaddr = print_pcie_addr($id);
|
$pciaddr = print_pcie_addr($id);
|
||||||
}
|
}
|
||||||
} else {
|
} 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 = '';
|
my $xvga = '';
|
||||||
@ -383,9 +419,6 @@ sub print_hostpci_devices {
|
|||||||
$gpu_passthrough = 1;
|
$gpu_passthrough = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $pcidevices = $d->{pciid};
|
|
||||||
my $multifunction = 1 if @$pcidevices > 1;
|
|
||||||
|
|
||||||
my $sysfspath;
|
my $sysfspath;
|
||||||
if ($d->{mdev} && scalar(@$pcidevices) == 1) {
|
if ($d->{mdev} && scalar(@$pcidevices) == 1) {
|
||||||
my $pci_id = $pcidevices->[0]->{id};
|
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;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user