]> git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer/PCI.pm
4d9ce2640b87f6a45dbd76461585809d212aca0d
[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 $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 'pci.4' => { bus => 1, addr => 28 },
75 'rng0' => { bus => 1, addr => 29 },
76 'virtio6' => { bus => 2, addr => 1 },
77 'virtio7' => { bus => 2, addr => 2 },
78 'virtio8' => { bus => 2, addr => 3 },
79 'virtio9' => { bus => 2, addr => 4 },
80 'virtio10' => { bus => 2, addr => 5 },
81 'virtio11' => { bus => 2, addr => 6 },
82 'virtio12' => { bus => 2, addr => 7 },
83 'virtio13' => { bus => 2, addr => 8 },
84 'virtio14' => { bus => 2, addr => 9 },
85 'virtio15' => { bus => 2, addr => 10 },
86 'ivshmem' => { bus => 2, addr => 11 },
87 'audio0' => { bus => 2, addr => 12 },
88 hostpci4 => { bus => 2, addr => 13 },
89 hostpci5 => { bus => 2, addr => 14 },
90 hostpci6 => { bus => 2, addr => 15 },
91 hostpci7 => { bus => 2, addr => 16 },
92 hostpci8 => { bus => 2, addr => 17 },
93 hostpci9 => { bus => 2, addr => 18 },
94 hostpci10 => { bus => 2, addr => 19 },
95 hostpci11 => { bus => 2, addr => 20 },
96 hostpci12 => { bus => 2, addr => 21 },
97 hostpci13 => { bus => 2, addr => 22 },
98 hostpci14 => { bus => 2, addr => 23 },
99 hostpci15 => { bus => 2, addr => 24 },
100 'virtioscsi0' => { bus => 3, addr => 1 },
101 'virtioscsi1' => { bus => 3, addr => 2 },
102 'virtioscsi2' => { bus => 3, addr => 3 },
103 'virtioscsi3' => { bus => 3, addr => 4 },
104 'virtioscsi4' => { bus => 3, addr => 5 },
105 'virtioscsi5' => { bus => 3, addr => 6 },
106 'virtioscsi6' => { bus => 3, addr => 7 },
107 'virtioscsi7' => { bus => 3, addr => 8 },
108 'virtioscsi8' => { bus => 3, addr => 9 },
109 'virtioscsi9' => { bus => 3, addr => 10 },
110 'virtioscsi10' => { bus => 3, addr => 11 },
111 'virtioscsi11' => { bus => 3, addr => 12 },
112 'virtioscsi12' => { bus => 3, addr => 13 },
113 'virtioscsi13' => { bus => 3, addr => 14 },
114 'virtioscsi14' => { bus => 3, addr => 15 },
115 'virtioscsi15' => { bus => 3, addr => 16 },
116 'virtioscsi16' => { bus => 3, addr => 17 },
117 'virtioscsi17' => { bus => 3, addr => 18 },
118 'virtioscsi18' => { bus => 3, addr => 19 },
119 'virtioscsi19' => { bus => 3, addr => 20 },
120 'virtioscsi20' => { bus => 3, addr => 21 },
121 'virtioscsi21' => { bus => 3, addr => 22 },
122 'virtioscsi22' => { bus => 3, addr => 23 },
123 'virtioscsi23' => { bus => 3, addr => 24 },
124 'virtioscsi24' => { bus => 3, addr => 25 },
125 'virtioscsi25' => { bus => 3, addr => 26 },
126 'virtioscsi26' => { bus => 3, addr => 27 },
127 'virtioscsi27' => { bus => 3, addr => 28 },
128 'virtioscsi28' => { bus => 3, addr => 29 },
129 'virtioscsi29' => { bus => 3, addr => 30 },
130 'virtioscsi30' => { bus => 3, addr => 31 },
131 'scsihw2' => { bus => 4, addr => 1 },
132 'scsihw3' => { bus => 4, addr => 2 },
133 'scsihw4' => { bus => 4, addr => 3 },
134 } if !defined($pci_addr_map);
135 return $pci_addr_map;
136 }
137
138 my $get_addr_mapping_from_id = sub {
139 my ($map, $id) = @_;
140
141 my $d = $map->{$id};
142 return undef if !defined($d) || !defined($d->{bus}) || !defined($d->{addr});
143
144 return { bus => $d->{bus}, addr => sprintf("0x%x", $d->{addr}) };
145 };
146
147 sub print_pci_addr {
148 my ($id, $bridges, $arch, $machine) = @_;
149
150 my $res = '';
151
152 # using same bus slots on all HW, so we need to check special cases here:
153 my $busname = 'pci';
154 if ($arch eq 'aarch64' && $machine =~ /^virt/) {
155 die "aarch64/virt cannot use IDE devices\n" if $id =~ /^ide/;
156 $busname = 'pcie';
157 }
158
159 my $map = get_pci_addr_map();
160 if (my $d = $get_addr_mapping_from_id->($map, $id)) {
161 $res = ",bus=$busname.$d->{bus},addr=$d->{addr}";
162 $bridges->{$d->{bus}} = 1 if $bridges;
163 }
164
165 return $res;
166 }
167
168 my $pcie_addr_map;
169 sub get_pcie_addr_map {
170 $pcie_addr_map = {
171 vga => { bus => 'pcie.0', addr => 1 },
172 hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 },
173 hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 },
174 hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
175 hostpci3 => { bus => "ich9-pcie-port-4", addr => 0 },
176 hostpci4 => { bus => "ich9-pcie-port-5", addr => 0 },
177 hostpci5 => { bus => "ich9-pcie-port-6", addr => 0 },
178 hostpci6 => { bus => "ich9-pcie-port-7", addr => 0 },
179 hostpci7 => { bus => "ich9-pcie-port-8", addr => 0 },
180 hostpci8 => { bus => "ich9-pcie-port-9", addr => 0 },
181 hostpci9 => { bus => "ich9-pcie-port-10", addr => 0 },
182 hostpci10 => { bus => "ich9-pcie-port-11", addr => 0 },
183 hostpci11 => { bus => "ich9-pcie-port-12", addr => 0 },
184 hostpci12 => { bus => "ich9-pcie-port-13", addr => 0 },
185 hostpci13 => { bus => "ich9-pcie-port-14", addr => 0 },
186 hostpci14 => { bus => "ich9-pcie-port-15", addr => 0 },
187 hostpci15 => { bus => "ich9-pcie-port-16", addr => 0 },
188 # win7 is picky about pcie assignments
189 hostpci0bus0 => { bus => "pcie.0", addr => 16 },
190 hostpci1bus0 => { bus => "pcie.0", addr => 17 },
191 hostpci2bus0 => { bus => "pcie.0", addr => 18 },
192 hostpci3bus0 => { bus => "pcie.0", addr => 19 },
193 ivshmem => { bus => 'pcie.0', addr => 20 },
194 hostpci4bus0 => { bus => "pcie.0", addr => 9 },
195 hostpci5bus0 => { bus => "pcie.0", addr => 10 },
196 hostpci6bus0 => { bus => "pcie.0", addr => 11 },
197 hostpci7bus0 => { bus => "pcie.0", addr => 12 },
198 hostpci8bus0 => { bus => "pcie.0", addr => 13 },
199 hostpci9bus0 => { bus => "pcie.0", addr => 14 },
200 hostpci10bus0 => { bus => "pcie.0", addr => 15 },
201 hostpci11bus0 => { bus => "pcie.0", addr => 21 },
202 hostpci12bus0 => { bus => "pcie.0", addr => 22 },
203 hostpci13bus0 => { bus => "pcie.0", addr => 23 },
204 hostpci14bus0 => { bus => "pcie.0", addr => 24 },
205 hostpci15bus0 => { bus => "pcie.0", addr => 25 },
206 } if !defined($pcie_addr_map);
207
208 return $pcie_addr_map;
209 }
210
211 sub print_pcie_addr {
212 my ($id) = @_;
213
214 my $res = '';
215
216 my $map = get_pcie_addr_map($id);
217 if (my $d = $get_addr_mapping_from_id->($map, $id)) {
218 $res = ",bus=$d->{bus},addr=$d->{addr}";
219 }
220
221 return $res;
222 }
223
224 # Generates the device strings for additional pcie root ports. The first 4 pcie
225 # root ports are defined in the pve-q35*.cfg files.
226 sub print_pcie_root_port {
227 my ($i) = @_;
228 my $res = '';
229
230 my $root_port_addresses = {
231 4 => "10.0",
232 5 => "10.1",
233 6 => "10.2",
234 7 => "10.3",
235 8 => "10.4",
236 9 => "10.5",
237 10 => "10.6",
238 11 => "10.7",
239 12 => "11.0",
240 13 => "11.1",
241 14 => "11.2",
242 15 => "11.3",
243 };
244
245 if (defined($root_port_addresses->{$i})) {
246 my $id = $i + 1;
247 $res = "pcie-root-port,id=ich9-pcie-port-${id}";
248 $res .= ",addr=$root_port_addresses->{$i}";
249 $res .= ",x-speed=16,x-width=32,multifunction=on,bus=pcie.0";
250 $res .= ",port=${id},chassis=${id}";
251 }
252
253 return $res;
254 }
255
256 1;