From d7d698f60cfc5afa5397bf67ce74598300de6ac9 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Fri, 6 Sep 2019 19:10:34 +0200 Subject: [PATCH] pci: add conflict tests best viewed with: git show -w Signed-off-by: Thomas Lamprecht --- PVE/QemuServer/PCI.pm | 289 +++++++++++++++++++----------------- test/Makefile | 5 +- test/run_pci_addr_checks.pl | 58 ++++++++ 3 files changed, 214 insertions(+), 138 deletions(-) create mode 100755 test/run_pci_addr_checks.pl diff --git a/PVE/QemuServer/PCI.pm b/PVE/QemuServer/PCI.pm index 728cde36..869b1ecb 100644 --- a/PVE/QemuServer/PCI.pm +++ b/PVE/QemuServer/PCI.pm @@ -8,122 +8,135 @@ print_pcie_addr print_pcie_root_port ); -my $devices = { - piix3 => { bus => 0, addr => 1 }, - ehci => { bus => 0, addr => 1 }, # instead of piix3 on arm - vga => { bus => 0, addr => 2 }, - balloon0 => { bus => 0, addr => 3 }, - watchdog => { bus => 0, addr => 4 }, - scsihw0 => { bus => 0, addr => 5 }, - 'pci.3' => { bus => 0, addr => 5 }, #can also be used for virtio-scsi-single bridge - scsihw1 => { bus => 0, addr => 6 }, - ahci0 => { bus => 0, addr => 7 }, - qga0 => { bus => 0, addr => 8 }, - spice => { bus => 0, addr => 9 }, - virtio0 => { bus => 0, addr => 10 }, - virtio1 => { bus => 0, addr => 11 }, - virtio2 => { bus => 0, addr => 12 }, - virtio3 => { bus => 0, addr => 13 }, - virtio4 => { bus => 0, addr => 14 }, - virtio5 => { bus => 0, addr => 15 }, - hostpci0 => { bus => 0, addr => 16 }, - hostpci1 => { bus => 0, addr => 17 }, - net0 => { bus => 0, addr => 18 }, - net1 => { bus => 0, addr => 19 }, - net2 => { bus => 0, addr => 20 }, - net3 => { bus => 0, addr => 21 }, - net4 => { bus => 0, addr => 22 }, - net5 => { bus => 0, addr => 23 }, - vga1 => { bus => 0, addr => 24 }, - vga2 => { bus => 0, addr => 25 }, - vga3 => { bus => 0, addr => 26 }, - hostpci2 => { bus => 0, addr => 27 }, - hostpci3 => { bus => 0, addr => 28 }, - #addr29 : usb-host (pve-usb.cfg) - 'pci.1' => { bus => 0, addr => 30 }, - 'pci.2' => { bus => 0, addr => 31 }, - 'net6' => { bus => 1, addr => 1 }, - 'net7' => { bus => 1, addr => 2 }, - 'net8' => { bus => 1, addr => 3 }, - 'net9' => { bus => 1, addr => 4 }, - 'net10' => { bus => 1, addr => 5 }, - 'net11' => { bus => 1, addr => 6 }, - 'net12' => { bus => 1, addr => 7 }, - 'net13' => { bus => 1, addr => 8 }, - 'net14' => { bus => 1, addr => 9 }, - 'net15' => { bus => 1, addr => 10 }, - 'net16' => { bus => 1, addr => 11 }, - 'net17' => { bus => 1, addr => 12 }, - 'net18' => { bus => 1, addr => 13 }, - 'net19' => { bus => 1, addr => 14 }, - 'net20' => { bus => 1, addr => 15 }, - 'net21' => { bus => 1, addr => 16 }, - 'net22' => { bus => 1, addr => 17 }, - 'net23' => { bus => 1, addr => 18 }, - 'net24' => { bus => 1, addr => 19 }, - 'net25' => { bus => 1, addr => 20 }, - 'net26' => { bus => 1, addr => 21 }, - 'net27' => { bus => 1, addr => 22 }, - 'net28' => { bus => 1, addr => 23 }, - 'net29' => { bus => 1, addr => 24 }, - 'net30' => { bus => 1, addr => 25 }, - 'net31' => { bus => 1, addr => 26 }, - 'xhci' => { bus => 1, addr => 27 }, - 'virtio6' => { bus => 2, addr => 1 }, - 'virtio7' => { bus => 2, addr => 2 }, - 'virtio8' => { bus => 2, addr => 3 }, - 'virtio9' => { bus => 2, addr => 4 }, - 'virtio10' => { bus => 2, addr => 5 }, - 'virtio11' => { bus => 2, addr => 6 }, - 'virtio12' => { bus => 2, addr => 7 }, - 'virtio13' => { bus => 2, addr => 8 }, - 'virtio14' => { bus => 2, addr => 9 }, - 'virtio15' => { bus => 2, addr => 10 }, - 'ivshmem' => { bus => 2, addr => 11 }, - 'audio0' => { bus => 2, addr => 12 }, - hostpci4 => { bus => 2, addr => 13 }, - hostpci5 => { bus => 2, addr => 14 }, - hostpci6 => { bus => 2, addr => 15 }, - hostpci7 => { bus => 2, addr => 16 }, - hostpci8 => { bus => 2, addr => 17 }, - hostpci9 => { bus => 2, addr => 18 }, - hostpci10 => { bus => 2, addr => 19 }, - hostpci11 => { bus => 2, addr => 20 }, - hostpci12 => { bus => 2, addr => 21 }, - hostpci13 => { bus => 2, addr => 22 }, - hostpci14 => { bus => 2, addr => 23 }, - hostpci15 => { bus => 2, addr => 24 }, - 'virtioscsi0' => { bus => 3, addr => 1 }, - 'virtioscsi1' => { bus => 3, addr => 2 }, - 'virtioscsi2' => { bus => 3, addr => 3 }, - 'virtioscsi3' => { bus => 3, addr => 4 }, - 'virtioscsi4' => { bus => 3, addr => 5 }, - 'virtioscsi5' => { bus => 3, addr => 6 }, - 'virtioscsi6' => { bus => 3, addr => 7 }, - 'virtioscsi7' => { bus => 3, addr => 8 }, - 'virtioscsi8' => { bus => 3, addr => 9 }, - 'virtioscsi9' => { bus => 3, addr => 10 }, - 'virtioscsi10' => { bus => 3, addr => 11 }, - 'virtioscsi11' => { bus => 3, addr => 12 }, - 'virtioscsi12' => { bus => 3, addr => 13 }, - 'virtioscsi13' => { bus => 3, addr => 14 }, - 'virtioscsi14' => { bus => 3, addr => 15 }, - 'virtioscsi15' => { bus => 3, addr => 16 }, - 'virtioscsi16' => { bus => 3, addr => 17 }, - 'virtioscsi17' => { bus => 3, addr => 18 }, - 'virtioscsi18' => { bus => 3, addr => 19 }, - 'virtioscsi19' => { bus => 3, addr => 20 }, - 'virtioscsi20' => { bus => 3, addr => 21 }, - 'virtioscsi21' => { bus => 3, addr => 22 }, - 'virtioscsi22' => { bus => 3, addr => 23 }, - 'virtioscsi23' => { bus => 3, addr => 24 }, - 'virtioscsi24' => { bus => 3, addr => 25 }, - 'virtioscsi25' => { bus => 3, addr => 26 }, - 'virtioscsi26' => { bus => 3, addr => 27 }, - 'virtioscsi27' => { bus => 3, addr => 28 }, - 'virtioscsi28' => { bus => 3, addr => 29 }, - 'virtioscsi29' => { bus => 3, addr => 30 }, - 'virtioscsi30' => { bus => 3, addr => 31 }, +my $pci_addr_map; +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 }, + balloon0 => { bus => 0, addr => 3 }, + watchdog => { bus => 0, addr => 4 }, + scsihw0 => { bus => 0, addr => 5, conflict_ok => qw(pci.3) }, + 'pci.3' => { bus => 0, addr => 5, conflict_ok => qw(scsihw0) }, # also used for virtio-scsi-single bridge + scsihw1 => { bus => 0, addr => 6 }, + ahci0 => { bus => 0, addr => 7 }, + qga0 => { bus => 0, addr => 8 }, + spice => { bus => 0, addr => 9 }, + virtio0 => { bus => 0, addr => 10 }, + virtio1 => { bus => 0, addr => 11 }, + virtio2 => { bus => 0, addr => 12 }, + virtio3 => { bus => 0, addr => 13 }, + virtio4 => { bus => 0, addr => 14 }, + virtio5 => { bus => 0, addr => 15 }, + hostpci0 => { bus => 0, addr => 16 }, + hostpci1 => { bus => 0, addr => 17 }, + net0 => { bus => 0, addr => 18 }, + net1 => { bus => 0, addr => 19 }, + net2 => { bus => 0, addr => 20 }, + net3 => { bus => 0, addr => 21 }, + net4 => { bus => 0, addr => 22 }, + net5 => { bus => 0, addr => 23 }, + vga1 => { bus => 0, addr => 24 }, + vga2 => { bus => 0, addr => 25 }, + vga3 => { bus => 0, addr => 26 }, + hostpci2 => { bus => 0, addr => 27 }, + hostpci3 => { bus => 0, addr => 28 }, + #addr29 : usb-host (pve-usb.cfg) + 'pci.1' => { bus => 0, addr => 30 }, + 'pci.2' => { bus => 0, addr => 31 }, + 'net6' => { bus => 1, addr => 1 }, + 'net7' => { bus => 1, addr => 2 }, + 'net8' => { bus => 1, addr => 3 }, + 'net9' => { bus => 1, addr => 4 }, + 'net10' => { bus => 1, addr => 5 }, + 'net11' => { bus => 1, addr => 6 }, + 'net12' => { bus => 1, addr => 7 }, + 'net13' => { bus => 1, addr => 8 }, + 'net14' => { bus => 1, addr => 9 }, + 'net15' => { bus => 1, addr => 10 }, + 'net16' => { bus => 1, addr => 11 }, + 'net17' => { bus => 1, addr => 12 }, + 'net18' => { bus => 1, addr => 13 }, + 'net19' => { bus => 1, addr => 14 }, + 'net20' => { bus => 1, addr => 15 }, + 'net21' => { bus => 1, addr => 16 }, + 'net22' => { bus => 1, addr => 17 }, + 'net23' => { bus => 1, addr => 18 }, + 'net24' => { bus => 1, addr => 19 }, + 'net25' => { bus => 1, addr => 20 }, + 'net26' => { bus => 1, addr => 21 }, + 'net27' => { bus => 1, addr => 22 }, + 'net28' => { bus => 1, addr => 23 }, + 'net29' => { bus => 1, addr => 24 }, + 'net30' => { bus => 1, addr => 25 }, + 'net31' => { bus => 1, addr => 26 }, + 'xhci' => { bus => 1, addr => 27 }, + 'virtio6' => { bus => 2, addr => 1 }, + 'virtio7' => { bus => 2, addr => 2 }, + 'virtio8' => { bus => 2, addr => 3 }, + 'virtio9' => { bus => 2, addr => 4 }, + 'virtio10' => { bus => 2, addr => 5 }, + 'virtio11' => { bus => 2, addr => 6 }, + 'virtio12' => { bus => 2, addr => 7 }, + 'virtio13' => { bus => 2, addr => 8 }, + 'virtio14' => { bus => 2, addr => 9 }, + 'virtio15' => { bus => 2, addr => 10 }, + 'ivshmem' => { bus => 2, addr => 11 }, + 'audio0' => { bus => 2, addr => 12 }, + hostpci4 => { bus => 2, addr => 13 }, + hostpci5 => { bus => 2, addr => 14 }, + hostpci6 => { bus => 2, addr => 15 }, + hostpci7 => { bus => 2, addr => 16 }, + hostpci8 => { bus => 2, addr => 17 }, + hostpci9 => { bus => 2, addr => 18 }, + hostpci10 => { bus => 2, addr => 19 }, + hostpci11 => { bus => 2, addr => 20 }, + hostpci12 => { bus => 2, addr => 21 }, + hostpci13 => { bus => 2, addr => 22 }, + hostpci14 => { bus => 2, addr => 23 }, + hostpci15 => { bus => 2, addr => 24 }, + 'virtioscsi0' => { bus => 3, addr => 1 }, + 'virtioscsi1' => { bus => 3, addr => 2 }, + 'virtioscsi2' => { bus => 3, addr => 3 }, + 'virtioscsi3' => { bus => 3, addr => 4 }, + 'virtioscsi4' => { bus => 3, addr => 5 }, + 'virtioscsi5' => { bus => 3, addr => 6 }, + 'virtioscsi6' => { bus => 3, addr => 7 }, + 'virtioscsi7' => { bus => 3, addr => 8 }, + 'virtioscsi8' => { bus => 3, addr => 9 }, + 'virtioscsi9' => { bus => 3, addr => 10 }, + 'virtioscsi10' => { bus => 3, addr => 11 }, + 'virtioscsi11' => { bus => 3, addr => 12 }, + 'virtioscsi12' => { bus => 3, addr => 13 }, + 'virtioscsi13' => { bus => 3, addr => 14 }, + 'virtioscsi14' => { bus => 3, addr => 15 }, + 'virtioscsi15' => { bus => 3, addr => 16 }, + 'virtioscsi16' => { bus => 3, addr => 17 }, + 'virtioscsi17' => { bus => 3, addr => 18 }, + 'virtioscsi18' => { bus => 3, addr => 19 }, + 'virtioscsi19' => { bus => 3, addr => 20 }, + 'virtioscsi20' => { bus => 3, addr => 21 }, + 'virtioscsi21' => { bus => 3, addr => 22 }, + 'virtioscsi22' => { bus => 3, addr => 23 }, + 'virtioscsi23' => { bus => 3, addr => 24 }, + 'virtioscsi24' => { bus => 3, addr => 25 }, + 'virtioscsi25' => { bus => 3, addr => 26 }, + 'virtioscsi26' => { bus => 3, addr => 27 }, + 'virtioscsi27' => { bus => 3, addr => 28 }, + 'virtioscsi28' => { bus => 3, addr => 29 }, + 'virtioscsi29' => { bus => 3, addr => 30 }, + 'virtioscsi30' => { bus => 3, addr => 31 }, + } if !defined($pci_addr_map); + return $pci_addr_map; +} + +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 { bus => $d->{bus}, addr => sprintf("0x%x", $d->{addr}) }; }; sub print_pci_addr { @@ -131,30 +144,25 @@ sub print_pci_addr { my $res = ''; - # We use the same bus slots on all hardware, so we need to check special - # cases here: + # using same bus slots on all HW, so we need to check special cases here: my $busname = 'pci'; if ($arch eq 'aarch64' && $machine =~ /^virt/) { - die "aarch64/virt cannot use IDE devices\n" - if $id =~ /^ide/; + die "aarch64/virt cannot use IDE devices\n" if $id =~ /^ide/; $busname = 'pcie'; } - if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) { - my $addr = sprintf("0x%x", $devices->{$id}->{addr}); - my $bus = $devices->{$id}->{bus}; - $res = ",bus=$busname.$bus,addr=$addr"; - $bridges->{$bus} = 1 if $bridges; + my $map = get_pci_addr_map(); + if (my $d = $get_addr_mapping_from_id->($map, $id)) { + $res = ",bus=$busname.$d->{bus},addr=$d->{addr}"; + $bridges->{$d->{bus}} = 1 if $bridges; } - return $res; + return $res; } -sub print_pcie_addr { - my ($id) = @_; - - my $res = ''; - my $devices = { +my $pcie_addr_map; +sub get_pcie_addr_map { + $pcie_addr_map = { vga => { bus => 'pcie.0', addr => 1 }, hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 }, hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 }, @@ -190,15 +198,22 @@ sub print_pcie_addr { hostpci13bus0 => { bus => "pcie.0", addr => 22 }, hostpci14bus0 => { bus => "pcie.0", addr => 23 }, hostpci15bus0 => { bus => "pcie.0", addr => 24 }, - }; + } if !defined($pcie_addr_map); - if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) { - my $addr = sprintf("0x%x", $devices->{$id}->{addr}); - my $bus = $devices->{$id}->{bus}; - $res = ",bus=$bus,addr=$addr"; + return $pcie_addr_map; +} + +sub print_pcie_addr { + my ($id) = @_; + + my $res = ''; + + my $map = get_pcie_addr_map($id); + if (my $d = $get_addr_mapping_from_id->($map, $id)) { + $res = ",bus=$d->{bus},addr=$d->{addr}"; } - return $res; + return $res; } # Generates the device strings for additional pcie root ports. The first 4 pcie diff --git a/test/Makefile b/test/Makefile index 48ea0a48..902d9e35 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ all: test -test: test_snapshot test_ovf test_cfg_to_cmd +test: test_snapshot test_ovf test_cfg_to_cmd test_pci_addr_conflicts test_snapshot: run_snapshot_tests.pl ./run_snapshot_tests.pl @@ -11,3 +11,6 @@ test_ovf: run_ovf_tests.pl test_cfg_to_cmd: run_config2command_tests.pl cfg2cmd/*.conf perl -I../ ./run_config2command_tests.pl + +test_pci_addr_conflicts: run_pci_addr_checks.pl + ./run_pci_addr_checks.pl diff --git a/test/run_pci_addr_checks.pl b/test/run_pci_addr_checks.pl new file mode 100755 index 00000000..fff05ac1 --- /dev/null +++ b/test/run_pci_addr_checks.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use experimental 'smartmatch'; + +use lib qw(..); + +use Test::More; + +use PVE::QemuServer::PCI; + +print "testing PCI(e) address conflicts\n"; + +# exec tests + +#FIXME: make cross PCI <-> PCIe check sense at all?? +my $addr_map = {}; +my ($fail, $ignored) = (0, 0); +sub check_conflict { + my ($id, $what) = @_; + + my ($bus, $addr) = $what->@{qw(bus addr)}; + my $full_addr = "$bus:$addr"; + + if (defined(my $conflict = $addr_map->{$full_addr})) { + if (my @ignores = $what->{conflict_ok}) { + if ($conflict ~~ @ignores) { + note("OK: ignore conflict for '$full_addr' between '$id' and '$conflict'"); + $ignored++; + return; + } + } + note("ERR: conflict for '$full_addr' between '$id' and '$conflict'"); + $fail++; + } else { + $addr_map->{$full_addr} = $id; + } +} + + +my $pci_map = PVE::QemuServer::PCI::get_pci_addr_map(); +while (my ($id, $what) = each %$pci_map) { + check_conflict($id, $what); +} + +my $pcie_map = PVE::QemuServer::PCI::get_pcie_addr_map(); +while (my ($id, $what) = each %$pcie_map) { + check_conflict($id, $what); +} + +if ($fail) { + fail("PCI(e) address conflict check, ignored: $ignored, conflicts: $fail"); +} else { + pass("PCI(e) address conflict check, ignored: $ignored"); +} + +done_testing();