]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
OvmfPkg/XenSupport: remove usage of prefetchable PCI host bridge aperture
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeLib / XenSupport.c
1 /** @file
2 Scan the entire PCI bus for root bridges to support OVMF above Xen.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9 #include <PiDxe.h>
10
11 #include <IndustryStandard/Pci.h>
12 #include <IndustryStandard/Q35MchIch9.h>
13
14 #include <Protocol/PciHostBridgeResourceAllocation.h>
15 #include <Protocol/PciRootBridgeIo.h>
16
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/PciHostBridgeLib.h>
21 #include <Library/PciLib.h>
22 #include "PciHostBridge.h"
23
24 STATIC
25 VOID
26 PcatPciRootBridgeBarExisted (
27 IN UINTN Address,
28 OUT UINT32 *OriginalValue,
29 OUT UINT32 *Value
30 )
31 {
32 //
33 // Preserve the original value
34 //
35 *OriginalValue = PciRead32 (Address);
36
37 //
38 // Disable timer interrupt while the BAR is probed
39 //
40 DisableInterrupts ();
41
42 PciWrite32 (Address, 0xFFFFFFFF);
43 *Value = PciRead32 (Address);
44 PciWrite32 (Address, *OriginalValue);
45
46 //
47 // Enable interrupt
48 //
49 EnableInterrupts ();
50 }
51
52 STATIC
53 VOID
54 PcatPciRootBridgeParseBars (
55 IN UINT16 Command,
56 IN UINTN Bus,
57 IN UINTN Device,
58 IN UINTN Function,
59 IN UINTN BarOffsetBase,
60 IN UINTN BarOffsetEnd,
61 IN PCI_ROOT_BRIDGE_APERTURE *Io,
62 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
63 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G
64
65 )
66 {
67 UINT32 OriginalValue;
68 UINT32 Value;
69 UINT32 OriginalUpperValue;
70 UINT32 UpperValue;
71 UINT64 Mask;
72 UINTN Offset;
73 UINT64 Base;
74 UINT64 Length;
75 UINT64 Limit;
76 PCI_ROOT_BRIDGE_APERTURE *MemAperture;
77
78 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
79 PcatPciRootBridgeBarExisted (
80 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
81 &OriginalValue, &Value
82 );
83 if (Value == 0) {
84 continue;
85 }
86 if ((Value & BIT0) == BIT0) {
87 //
88 // IO Bar
89 //
90 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
91 Mask = 0xfffffffc;
92 Base = OriginalValue & Mask;
93 Length = ((~(Value & Mask)) & Mask) + 0x04;
94 if (!(Value & 0xFFFF0000)) {
95 Length &= 0x0000FFFF;
96 }
97 Limit = Base + Length - 1;
98
99 if (Base < Limit) {
100 if (Io->Base > Base) {
101 Io->Base = Base;
102 }
103 if (Io->Limit < Limit) {
104 Io->Limit = Limit;
105 }
106 }
107 }
108 } else {
109 //
110 // Mem Bar
111 //
112 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
113
114 Mask = 0xfffffff0;
115 Base = OriginalValue & Mask;
116 Length = Value & Mask;
117
118 if ((Value & (BIT1 | BIT2)) == 0) {
119 //
120 // 32bit
121 //
122 Length = ((~Length) + 1) & 0xffffffff;
123
124 MemAperture = Mem;
125 } else {
126 //
127 // 64bit
128 //
129 Offset += 4;
130 PcatPciRootBridgeBarExisted (
131 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
132 &OriginalUpperValue,
133 &UpperValue
134 );
135
136 Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);
137 Length = Length | LShiftU64 ((UINT64) UpperValue, 32);
138 Length = (~Length) + 1;
139
140 MemAperture = MemAbove4G;
141 }
142
143 Limit = Base + Length - 1;
144 if (Base < Limit) {
145 if (MemAperture->Base > Base) {
146 MemAperture->Base = Base;
147 }
148 if (MemAperture->Limit < Limit) {
149 MemAperture->Limit = Limit;
150 }
151 }
152 }
153 }
154 }
155 }
156
157 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
158
159 PCI_ROOT_BRIDGE *
160 ScanForRootBridges (
161 UINTN *NumberOfRootBridges
162 )
163 {
164 UINTN PrimaryBus;
165 UINTN SubBus;
166 UINT8 Device;
167 UINT8 Function;
168 UINTN NumberOfDevices;
169 UINTN Address;
170 PCI_TYPE01 Pci;
171 UINT64 Attributes;
172 UINT64 Base;
173 UINT64 Limit;
174 UINT64 Value;
175 PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture;
176 PCI_ROOT_BRIDGE *RootBridges;
177 UINTN BarOffsetEnd;
178
179
180 *NumberOfRootBridges = 0;
181 RootBridges = NULL;
182
183 //
184 // After scanning all the PCI devices on the PCI root bridge's primary bus,
185 // update the Primary Bus Number for the next PCI root bridge to be this PCI
186 // root bridge's subordinate bus number + 1.
187 //
188 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
189 SubBus = PrimaryBus;
190 Attributes = 0;
191
192 ZeroMem (&Io, sizeof (Io));
193 ZeroMem (&Mem, sizeof (Mem));
194 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
195 Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;
196 //
197 // Scan all the PCI devices on the primary bus of the PCI root bridge
198 //
199 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
200
201 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
202
203 //
204 // Compute the PCI configuration address of the PCI device to probe
205 //
206 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
207
208 //
209 // Read the Vendor ID from the PCI Configuration Header
210 //
211 if (PciRead16 (Address) == MAX_UINT16) {
212 if (Function == 0) {
213 //
214 // If the PCI Configuration Read fails, or a PCI device does not
215 // exist, then skip this entire PCI device
216 //
217 break;
218 } else {
219 //
220 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
221 // PCI function.
222 //
223 continue;
224 }
225 }
226
227 //
228 // Read the entire PCI Configuration Header
229 //
230 PciReadBuffer (Address, sizeof (Pci), &Pci);
231
232 //
233 // Increment the number of PCI device found on the primary bus of the
234 // PCI root bridge
235 //
236 NumberOfDevices++;
237
238 //
239 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
240 // register of the PCI Config Header
241 //
242 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
243 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
244 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
245 }
246
247 BarOffsetEnd = 0;
248
249 //
250 // PCI-PCI Bridge
251 //
252 if (IS_PCI_BRIDGE (&Pci)) {
253 //
254 // Get the Bus range that the PPB is decoding
255 //
256 if (Pci.Bridge.SubordinateBus > SubBus) {
257 //
258 // If the suborinate bus number of the PCI-PCI bridge is greater
259 // than the PCI root bridge's current subordinate bus number,
260 // then update the PCI root bridge's subordinate bus number
261 //
262 SubBus = Pci.Bridge.SubordinateBus;
263 }
264
265 //
266 // Get the I/O range that the PPB is decoding
267 //
268 Value = Pci.Bridge.IoBase & 0x0f;
269 Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;
270 Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
271 if (Value == BIT0) {
272 Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);
273 Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);
274 }
275 if (Base < Limit) {
276 if (Io.Base > Base) {
277 Io.Base = Base;
278 }
279 if (Io.Limit < Limit) {
280 Io.Limit = Limit;
281 }
282 }
283
284 //
285 // Get the Memory range that the PPB is decoding
286 //
287 Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;
288 Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
289 if (Base < Limit) {
290 if (Mem.Base > Base) {
291 Mem.Base = Base;
292 }
293 if (Mem.Limit < Limit) {
294 Mem.Limit = Limit;
295 }
296 }
297
298 //
299 // Get the Prefetchable Memory range that the PPB is decoding
300 // and merge it into Memory range
301 //
302 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
303 Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
304 Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
305 << 16) | 0xfffff;
306 MemAperture = &Mem;
307 if (Value == BIT0) {
308 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
309 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
310 MemAperture = &MemAbove4G;
311 }
312 if (Base < Limit) {
313 if (MemAperture->Base > Base) {
314 MemAperture->Base = Base;
315 }
316 if (MemAperture->Limit < Limit) {
317 MemAperture->Limit = Limit;
318 }
319 }
320
321 //
322 // Look at the PPB Configuration for legacy decoding attributes
323 //
324 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
325 == EFI_PCI_BRIDGE_CONTROL_ISA) {
326 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
327 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
328 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
329 }
330 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
331 == EFI_PCI_BRIDGE_CONTROL_VGA) {
332 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
333 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
334 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
335 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
336 != 0) {
337 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
338 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
339 }
340 }
341
342 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
343 } else {
344 //
345 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
346 // Ranges, and Prefetchable Memory Ranges the device is decoding
347 //
348 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
349 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
350 }
351 }
352
353 PcatPciRootBridgeParseBars (
354 Pci.Hdr.Command,
355 PrimaryBus,
356 Device,
357 Function,
358 OFFSET_OF (PCI_TYPE00, Device.Bar),
359 BarOffsetEnd,
360 &Io,
361 &Mem, &MemAbove4G
362 );
363
364 //
365 // See if the PCI device is an IDE controller
366 //
367 if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,
368 PCI_CLASS_MASS_STORAGE_IDE)) {
369 if (Pci.Hdr.ClassCode[0] & 0x80) {
370 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
371 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
372 }
373 if (Pci.Hdr.ClassCode[0] & 0x01) {
374 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
375 }
376 if (Pci.Hdr.ClassCode[0] & 0x04) {
377 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
378 }
379 }
380
381 //
382 // See if the PCI device is a legacy VGA controller or
383 // a standard VGA controller
384 //
385 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
386 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
387 ) {
388 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
389 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
390 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
391 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
392 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
393 }
394
395 //
396 // See if the PCI Device is a PCI - ISA or PCI - EISA
397 // or ISA_POSITIVIE_DECODE Bridge device
398 //
399 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
400 if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||
401 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||
402 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {
403 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
404 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
405 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
406 }
407 }
408
409 //
410 // If this device is not a multi function device, then skip the rest
411 // of this PCI device
412 //
413 if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
414 break;
415 }
416 }
417 }
418
419 //
420 // If at least one PCI device was found on the primary bus of this PCI
421 // root bridge, then the PCI root bridge exists.
422 //
423 if (NumberOfDevices > 0) {
424 RootBridges = ReallocatePool (
425 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
426 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
427 RootBridges
428 );
429 ASSERT (RootBridges != NULL);
430 InitRootBridge (
431 Attributes, Attributes, 0,
432 (UINT8) PrimaryBus, (UINT8) SubBus,
433 &Io, &Mem, &MemAbove4G, &mNonExistAperture, &mNonExistAperture,
434 &RootBridges[*NumberOfRootBridges]
435 );
436 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
437 //
438 // Increment the index for the next PCI Root Bridge
439 //
440 (*NumberOfRootBridges)++;
441 }
442 }
443
444 return RootBridges;
445 }