package PVE::QemuServer::PCI;
+use warnings;
+use strict;
+
use PVE::JSONSchema;
use PVE::SysFSTools;
},
rombar => {
type => 'boolean',
- description => "Specify whether or not the device's ROM will be visible in the guest's memory map.",
+ description => "Specify whether or not the device's ROM will be visible in the"
+ ." guest's memory map.",
optional => 1,
default => 1,
},
romfile => {
- type => 'string',
- pattern => '[^,;]+',
- format_description => 'string',
- description => "Custom pci device rom filename (must be located in /usr/share/kvm/).",
- optional => 1,
+ type => 'string',
+ pattern => '[^,;]+',
+ format_description => 'string',
+ description => "Custom pci device rom filename (must be located in /usr/share/kvm/).",
+ optional => 1,
},
pcie => {
type => 'boolean',
- description => "Choose the PCI-express bus (needs the 'q35' machine model).",
+ description => "Choose the PCI-express bus (needs the 'q35' machine model).",
optional => 1,
default => 0,
},
'x-vga' => {
type => 'boolean',
- description => "Enable vfio-vga device support.",
+ description => "Enable vfio-vga device support.",
+ optional => 1,
+ default => 0,
+ },
+ 'legacy-igd' => {
+ type => 'boolean',
+ description => "Pass this device in legacy IGD mode, making it the primary and exclusive"
+ ." graphics device in the VM. Requires 'pc-i440fx' machine type and VGA set to 'none'.",
optional => 1,
default => 0,
},
'mdev' => {
type => 'string',
- format_description => 'string',
+ format_description => 'string',
pattern => '[^/\.:]+',
optional => 1,
description => <<EODESCR
PVE::JSONSchema::register_format('pve-qm-hostpci', $hostpci_fmt);
our $hostpcidesc = {
- optional => 1,
- type => 'string', format => 'pve-qm-hostpci',
- description => "Map host PCI devices into guest.",
+ optional => 1,
+ type => 'string', format => 'pve-qm-hostpci',
+ description => "Map host PCI devices into guest.",
verbose_description => <<EODESCR,
Map host PCI devices into guest.
$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) },
'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 },
my ($map, $id) = @_;
my $d = $map->{$id};
- return undef if !defined($d) || !defined($d->{bus}) || !defined($d->{addr});
+ return if !defined($d) || !defined($d->{bus}) || !defined($d->{addr});
return { bus => $d->{bus}, addr => sprintf("0x%x", $d->{addr}) };
};
sub parse_hostpci {
my ($value) = @_;
- return undef if !$value;
+ return if !$value;
my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
}
sub print_hostpci_devices {
- my ($conf, $devices, $winversion, $q35, $bridges, $arch, $machine_type) = @_;
+ my ($vmid, $conf, $devices, $vga, $winversion, $q35, $bridges, $arch, $machine_type, $bootorder) = @_;
my $kvm_off = 0;
my $gpu_passthrough = 0;
+ my $legacy_igd = 0;
+ my $pciaddr;
for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
my $id = "hostpci$i";
my $d = parse_hostpci($conf->{$id});
$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 = @$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 = '';
$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};
warn "ignoring mediated device '$id' with multifunction device\n";
}
- my $j=0;
+ my $j = 0;
foreach my $pcidevice (@$pcidevices) {
my $devicestr = "vfio-pci";
$devicestr .= "$xvga";
$devicestr .= ",multifunction=on" if $multifunction;
$devicestr .= ",romfile=/usr/share/kvm/$d->{romfile}" if $d->{romfile};
+ $devicestr .= ",bootindex=$bootorder->{$id}" if $bootorder->{$id};
}
push @$devices, '-device', $devicestr;
}
}
- return ($kvm_off, $gpu_passthrough);
+ return ($kvm_off, $gpu_passthrough, $legacy_igd);
}
1;