]> git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer/PCI.pm
Add support for up to 16 PCI(e) devices
[qemu-server.git] / PVE / QemuServer / PCI.pm
1 package PVE::QemuServer::PCI;
2
3 use base 'Exporter';
4
5 our @EXPORT_OK = qw(
6 print_pci_addr
7 print_pcie_addr
8 print_pcie_root_port
9 );
10
11 my $devices = {
12 piix3 => { bus => 0, addr => 1 },
13 ehci => { bus => 0, addr => 1 }, # instead of piix3 on arm
14 vga => { bus => 0, addr => 2 },
15 balloon0 => { bus => 0, addr => 3 },
16 watchdog => { bus => 0, addr => 4 },
17 scsihw0 => { bus => 0, addr => 5 },
18 'pci.3' => { bus => 0, addr => 5 }, #can also be used for virtio-scsi-single bridge
19 scsihw1 => { bus => 0, addr => 6 },
20 ahci0 => { bus => 0, addr => 7 },
21 qga0 => { bus => 0, addr => 8 },
22 spice => { bus => 0, addr => 9 },
23 virtio0 => { bus => 0, addr => 10 },
24 virtio1 => { bus => 0, addr => 11 },
25 virtio2 => { bus => 0, addr => 12 },
26 virtio3 => { bus => 0, addr => 13 },
27 virtio4 => { bus => 0, addr => 14 },
28 virtio5 => { bus => 0, addr => 15 },
29 hostpci0 => { bus => 0, addr => 16 },
30 hostpci1 => { bus => 0, addr => 17 },
31 net0 => { bus => 0, addr => 18 },
32 net1 => { bus => 0, addr => 19 },
33 net2 => { bus => 0, addr => 20 },
34 net3 => { bus => 0, addr => 21 },
35 net4 => { bus => 0, addr => 22 },
36 net5 => { bus => 0, addr => 23 },
37 vga1 => { bus => 0, addr => 24 },
38 vga2 => { bus => 0, addr => 25 },
39 vga3 => { bus => 0, addr => 26 },
40 hostpci2 => { bus => 0, addr => 27 },
41 hostpci3 => { bus => 0, addr => 28 },
42 #addr29 : usb-host (pve-usb.cfg)
43 'pci.1' => { bus => 0, addr => 30 },
44 'pci.2' => { bus => 0, addr => 31 },
45 'net6' => { bus => 1, addr => 1 },
46 'net7' => { bus => 1, addr => 2 },
47 'net8' => { bus => 1, addr => 3 },
48 'net9' => { bus => 1, addr => 4 },
49 'net10' => { bus => 1, addr => 5 },
50 'net11' => { bus => 1, addr => 6 },
51 'net12' => { bus => 1, addr => 7 },
52 'net13' => { bus => 1, addr => 8 },
53 'net14' => { bus => 1, addr => 9 },
54 'net15' => { bus => 1, addr => 10 },
55 'net16' => { bus => 1, addr => 11 },
56 'net17' => { bus => 1, addr => 12 },
57 'net18' => { bus => 1, addr => 13 },
58 'net19' => { bus => 1, addr => 14 },
59 'net20' => { bus => 1, addr => 15 },
60 'net21' => { bus => 1, addr => 16 },
61 'net22' => { bus => 1, addr => 17 },
62 'net23' => { bus => 1, addr => 18 },
63 'net24' => { bus => 1, addr => 19 },
64 'net25' => { bus => 1, addr => 20 },
65 'net26' => { bus => 1, addr => 21 },
66 'net27' => { bus => 1, addr => 22 },
67 'net28' => { bus => 1, addr => 23 },
68 'net29' => { bus => 1, addr => 24 },
69 'net30' => { bus => 1, addr => 25 },
70 'net31' => { bus => 1, addr => 26 },
71 'xhci' => { bus => 1, addr => 27 },
72 'virtio6' => { bus => 2, addr => 1 },
73 'virtio7' => { bus => 2, addr => 2 },
74 'virtio8' => { bus => 2, addr => 3 },
75 'virtio9' => { bus => 2, addr => 4 },
76 'virtio10' => { bus => 2, addr => 5 },
77 'virtio11' => { bus => 2, addr => 6 },
78 'virtio12' => { bus => 2, addr => 7 },
79 'virtio13' => { bus => 2, addr => 8 },
80 'virtio14' => { bus => 2, addr => 9 },
81 'virtio15' => { bus => 2, addr => 10 },
82 'ivshmem' => { bus => 2, addr => 11 },
83 'audio0' => { bus => 2, addr => 12 },
84 hostpci4 => { bus => 2, addr => 13 },
85 hostpci5 => { bus => 2, addr => 14 },
86 hostpci6 => { bus => 2, addr => 15 },
87 hostpci7 => { bus => 2, addr => 16 },
88 hostpci8 => { bus => 2, addr => 17 },
89 hostpci9 => { bus => 2, addr => 18 },
90 hostpci10 => { bus => 2, addr => 19 },
91 hostpci11 => { bus => 2, addr => 20 },
92 hostpci12 => { bus => 2, addr => 21 },
93 hostpci13 => { bus => 2, addr => 22 },
94 hostpci14 => { bus => 2, addr => 23 },
95 hostpci15 => { bus => 2, addr => 24 },
96 'virtioscsi0' => { bus => 3, addr => 1 },
97 'virtioscsi1' => { bus => 3, addr => 2 },
98 'virtioscsi2' => { bus => 3, addr => 3 },
99 'virtioscsi3' => { bus => 3, addr => 4 },
100 'virtioscsi4' => { bus => 3, addr => 5 },
101 'virtioscsi5' => { bus => 3, addr => 6 },
102 'virtioscsi6' => { bus => 3, addr => 7 },
103 'virtioscsi7' => { bus => 3, addr => 8 },
104 'virtioscsi8' => { bus => 3, addr => 9 },
105 'virtioscsi9' => { bus => 3, addr => 10 },
106 'virtioscsi10' => { bus => 3, addr => 11 },
107 'virtioscsi11' => { bus => 3, addr => 12 },
108 'virtioscsi12' => { bus => 3, addr => 13 },
109 'virtioscsi13' => { bus => 3, addr => 14 },
110 'virtioscsi14' => { bus => 3, addr => 15 },
111 'virtioscsi15' => { bus => 3, addr => 16 },
112 'virtioscsi16' => { bus => 3, addr => 17 },
113 'virtioscsi17' => { bus => 3, addr => 18 },
114 'virtioscsi18' => { bus => 3, addr => 19 },
115 'virtioscsi19' => { bus => 3, addr => 20 },
116 'virtioscsi20' => { bus => 3, addr => 21 },
117 'virtioscsi21' => { bus => 3, addr => 22 },
118 'virtioscsi22' => { bus => 3, addr => 23 },
119 'virtioscsi23' => { bus => 3, addr => 24 },
120 'virtioscsi24' => { bus => 3, addr => 25 },
121 'virtioscsi25' => { bus => 3, addr => 26 },
122 'virtioscsi26' => { bus => 3, addr => 27 },
123 'virtioscsi27' => { bus => 3, addr => 28 },
124 'virtioscsi28' => { bus => 3, addr => 29 },
125 'virtioscsi29' => { bus => 3, addr => 30 },
126 'virtioscsi30' => { bus => 3, addr => 31 },
127 };
128
129 sub print_pci_addr {
130 my ($id, $bridges, $arch, $machine) = @_;
131
132 my $res = '';
133
134 # We use the same bus slots on all hardware, so we need to check special
135 # cases here:
136 my $busname = 'pci';
137 if ($arch eq 'aarch64' && $machine =~ /^virt/) {
138 die "aarch64/virt cannot use IDE devices\n"
139 if $id =~ /^ide/;
140 $busname = 'pcie';
141 }
142
143 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
144 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
145 my $bus = $devices->{$id}->{bus};
146 $res = ",bus=$busname.$bus,addr=$addr";
147 $bridges->{$bus} = 1 if $bridges;
148 }
149 return $res;
150
151 }
152
153 sub print_pcie_addr {
154 my ($id) = @_;
155
156 my $res = '';
157 my $devices = {
158 vga => { bus => 'pcie.0', addr => 1 },
159 hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 },
160 hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 },
161 hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
162 hostpci3 => { bus => "ich9-pcie-port-4", addr => 0 },
163 hostpci4 => { bus => "ich9-pcie-port-5", addr => 0 },
164 hostpci5 => { bus => "ich9-pcie-port-6", addr => 0 },
165 hostpci6 => { bus => "ich9-pcie-port-7", addr => 0 },
166 hostpci7 => { bus => "ich9-pcie-port-8", addr => 0 },
167 hostpci8 => { bus => "ich9-pcie-port-9", addr => 0 },
168 hostpci9 => { bus => "ich9-pcie-port-10", addr => 0 },
169 hostpci10 => { bus => "ich9-pcie-port-11", addr => 0 },
170 hostpci11 => { bus => "ich9-pcie-port-12", addr => 0 },
171 hostpci12 => { bus => "ich9-pcie-port-13", addr => 0 },
172 hostpci13 => { bus => "ich9-pcie-port-14", addr => 0 },
173 hostpci14 => { bus => "ich9-pcie-port-15", addr => 0 },
174 hostpci15 => { bus => "ich9-pcie-port-16", addr => 0 },
175 # win7 is picky about pcie assignments
176 hostpci0bus0 => { bus => "pcie.0", addr => 16 },
177 hostpci1bus0 => { bus => "pcie.0", addr => 17 },
178 hostpci2bus0 => { bus => "pcie.0", addr => 18 },
179 hostpci3bus0 => { bus => "pcie.0", addr => 19 },
180 ivshmem => { bus => 'pcie.0', addr => 20 },
181 hostpci4bus0 => { bus => "pcie.0", addr => 9 },
182 hostpci5bus0 => { bus => "pcie.0", addr => 10 },
183 hostpci6bus0 => { bus => "pcie.0", addr => 11 },
184 hostpci7bus0 => { bus => "pcie.0", addr => 12 },
185 hostpci8bus0 => { bus => "pcie.0", addr => 13 },
186 hostpci9bus0 => { bus => "pcie.0", addr => 14 },
187 hostpci10bus0 => { bus => "pcie.0", addr => 15 },
188 hostpci11bus0 => { bus => "pcie.0", addr => 20 },
189 hostpci12bus0 => { bus => "pcie.0", addr => 21 },
190 hostpci13bus0 => { bus => "pcie.0", addr => 22 },
191 hostpci14bus0 => { bus => "pcie.0", addr => 23 },
192 hostpci15bus0 => { bus => "pcie.0", addr => 24 },
193 };
194
195 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
196 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
197 my $bus = $devices->{$id}->{bus};
198 $res = ",bus=$bus,addr=$addr";
199 }
200 return $res;
201
202 }
203
204 # Generates the device strings for additional pcie root ports. The first 4 pcie
205 # root ports are defined in the pve-q35*.cfg files.
206 sub print_pcie_root_port {
207 my ($i) = @_;
208 my $res = '';
209
210 my $id = $i + 1;
211
212 my $root_port_addresses = {
213 4 => "10.0",
214 5 => "10.1",
215 6 => "10.2",
216 7 => "10.3",
217 8 => "10.4",
218 9 => "10.5",
219 10 => "10.6",
220 11 => "10.7",
221 12 => "11.0",
222 13 => "11.1",
223 14 => "11.2",
224 15 => "11.3",
225 };
226
227 if (defined($root_port_addresses->{$i})) {
228 $res = "pcie-root-port,id=ich9-pcie-port-${id}";
229 $res .= ",addr=$root_port_addresses->{$i}";
230 $res .= ",x-speed=16,x-width=32,multifunction=on,bus=pcie.0";
231 $res .= ",port=${id},chassis=${id}";
232 }
233
234 return $res;
235 }
236
237 1;