]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer/PCI.pm
PCI: use warnings/strict and fix setting $vga from config2command
[qemu-server.git] / PVE / QemuServer / PCI.pm
index 39f997023abc244779614ded74a303588d0ab25d..2ee142fc3997a2da9c090bd18dc633ff50ab3ad4 100644 (file)
@@ -1,5 +1,8 @@
 package PVE::QemuServer::PCI;
 
+use warnings;
+use strict;
+
 use PVE::JSONSchema;
 use PVE::SysFSTools;
 
@@ -32,32 +35,40 @@ EODESCR
     },
     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
@@ -70,9 +81,9 @@ 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.
 
@@ -89,7 +100,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 +161,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 },
@@ -215,7 +228,7 @@ my $get_addr_mapping_from_id = sub {
     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}) };
 };
@@ -332,7 +345,7 @@ sub print_pcie_root_port {
 sub parse_hostpci {
     my ($value) = @_;
 
-    return undef if !$value;
+    return if !$value;
 
     my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
 
@@ -347,11 +360,13 @@ sub parse_hostpci {
 }
 
 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});
@@ -372,7 +387,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 = @$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 +423,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};
@@ -395,7 +432,7 @@ sub print_hostpci_devices {
            warn "ignoring mediated device '$id' with multifunction device\n";
        }
 
-       my $j=0;
+       my $j = 0;
        foreach my $pcidevice (@$pcidevices) {
            my $devicestr = "vfio-pci";
 
@@ -413,6 +450,7 @@ sub print_hostpci_devices {
                $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;
@@ -420,7 +458,7 @@ sub print_hostpci_devices {
        }
     }
 
-    return ($kvm_off, $gpu_passthrough);
+    return ($kvm_off, $gpu_passthrough, $legacy_igd);
 }
 
 1;