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