mirror of
git://git.proxmox.com/git/qemu-server.git
synced 2025-02-04 17:47:16 +03:00
e2b0d85dda
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
252 lines
8.4 KiB
Perl
252 lines
8.4 KiB
Perl
package PVE::QemuServer::PCI;
|
|
|
|
use base 'Exporter';
|
|
|
|
our @EXPORT_OK = qw(
|
|
print_pci_addr
|
|
print_pcie_addr
|
|
print_pcie_root_port
|
|
);
|
|
|
|
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 {
|
|
my ($id, $bridges, $arch, $machine) = @_;
|
|
|
|
my $res = '';
|
|
|
|
# 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/;
|
|
$busname = 'pcie';
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 },
|
|
hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
|
|
hostpci3 => { bus => "ich9-pcie-port-4", addr => 0 },
|
|
hostpci4 => { bus => "ich9-pcie-port-5", addr => 0 },
|
|
hostpci5 => { bus => "ich9-pcie-port-6", addr => 0 },
|
|
hostpci6 => { bus => "ich9-pcie-port-7", addr => 0 },
|
|
hostpci7 => { bus => "ich9-pcie-port-8", addr => 0 },
|
|
hostpci8 => { bus => "ich9-pcie-port-9", addr => 0 },
|
|
hostpci9 => { bus => "ich9-pcie-port-10", addr => 0 },
|
|
hostpci10 => { bus => "ich9-pcie-port-11", addr => 0 },
|
|
hostpci11 => { bus => "ich9-pcie-port-12", addr => 0 },
|
|
hostpci12 => { bus => "ich9-pcie-port-13", addr => 0 },
|
|
hostpci13 => { bus => "ich9-pcie-port-14", addr => 0 },
|
|
hostpci14 => { bus => "ich9-pcie-port-15", addr => 0 },
|
|
hostpci15 => { bus => "ich9-pcie-port-16", addr => 0 },
|
|
# win7 is picky about pcie assignments
|
|
hostpci0bus0 => { bus => "pcie.0", addr => 16 },
|
|
hostpci1bus0 => { bus => "pcie.0", addr => 17 },
|
|
hostpci2bus0 => { bus => "pcie.0", addr => 18 },
|
|
hostpci3bus0 => { bus => "pcie.0", addr => 19 },
|
|
ivshmem => { bus => 'pcie.0', addr => 20 },
|
|
hostpci4bus0 => { bus => "pcie.0", addr => 9 },
|
|
hostpci5bus0 => { bus => "pcie.0", addr => 10 },
|
|
hostpci6bus0 => { bus => "pcie.0", addr => 11 },
|
|
hostpci7bus0 => { bus => "pcie.0", addr => 12 },
|
|
hostpci8bus0 => { bus => "pcie.0", addr => 13 },
|
|
hostpci9bus0 => { bus => "pcie.0", addr => 14 },
|
|
hostpci10bus0 => { bus => "pcie.0", addr => 15 },
|
|
hostpci11bus0 => { bus => "pcie.0", addr => 21 },
|
|
hostpci12bus0 => { bus => "pcie.0", addr => 22 },
|
|
hostpci13bus0 => { bus => "pcie.0", addr => 23 },
|
|
hostpci14bus0 => { bus => "pcie.0", addr => 24 },
|
|
hostpci15bus0 => { bus => "pcie.0", addr => 25 },
|
|
} if !defined($pcie_addr_map);
|
|
|
|
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;
|
|
}
|
|
|
|
# Generates the device strings for additional pcie root ports. The first 4 pcie
|
|
# root ports are defined in the pve-q35*.cfg files.
|
|
sub print_pcie_root_port {
|
|
my ($i) = @_;
|
|
my $res = '';
|
|
|
|
my $root_port_addresses = {
|
|
4 => "10.0",
|
|
5 => "10.1",
|
|
6 => "10.2",
|
|
7 => "10.3",
|
|
8 => "10.4",
|
|
9 => "10.5",
|
|
10 => "10.6",
|
|
11 => "10.7",
|
|
12 => "11.0",
|
|
13 => "11.1",
|
|
14 => "11.2",
|
|
15 => "11.3",
|
|
};
|
|
|
|
if (defined($root_port_addresses->{$i})) {
|
|
my $id = $i + 1;
|
|
$res = "pcie-root-port,id=ich9-pcie-port-${id}";
|
|
$res .= ",addr=$root_port_addresses->{$i}";
|
|
$res .= ",x-speed=16,x-width=32,multifunction=on,bus=pcie.0";
|
|
$res .= ",port=${id},chassis=${id}";
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
1;
|