IntelSiliconPkg: Fix VS2015 NOOPT IA32 build failure in IntelVTdDxe
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / DmaProtection.h
1 /** @file
2
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #ifndef _DMAR_PROTECTION_H_
15 #define _DMAR_PROTECTION_H_
16
17 #include <Uefi.h>
18 #include <PiDxe.h>
19
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/IoLib.h>
25 #include <Library/PciSegmentLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/UefiLib.h>
28
29 #include <Guid/EventGroup.h>
30 #include <Guid/Acpi.h>
31
32 #include <Protocol/DxeSmmReadyToLock.h>
33 #include <Protocol/PciRootBridgeIo.h>
34 #include <Protocol/PciIo.h>
35 #include <Protocol/PciEnumerationComplete.h>
36 #include <Protocol/AcpiSystemDescriptionTable.h>
37 #include <Protocol/PlatformVtdPolicy.h>
38 #include <Protocol/IoMmu.h>
39
40 #include <IndustryStandard/Pci.h>
41 #include <IndustryStandard/DmaRemappingReportingTable.h>
42 #include <IndustryStandard/Vtd.h>
43
44 #define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))
45
46 #define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))
47 #define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))
48
49 //
50 // This is the initial max PCI descriptor.
51 // The number may be enlarged later.
52 //
53 #define MAX_PCI_DESCRIPTORS 0x100
54
55 typedef struct {
56 BOOLEAN IncludeAllFlag;
57 UINTN PciDescriptorNumber;
58 UINTN PciDescriptorMaxNumber;
59 BOOLEAN *IsRealPciDevice;
60 VTD_SOURCE_ID *PciDescriptors;
61 } PCI_DEVICE_INFORMATION;
62
63 typedef struct {
64 UINTN VtdUnitBaseAddress;
65 UINT16 Segment;
66 VTD_CAP_REG CapReg;
67 VTD_ECAP_REG ECapReg;
68 VTD_ROOT_ENTRY *RootEntryTable;
69 VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;
70 VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;
71 BOOLEAN HasDirtyPages;
72 PCI_DEVICE_INFORMATION PciDeviceInfo;
73 } VTD_UNIT_INFORMATION;
74
75 extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
76
77 extern UINT64 mVtdHostAddressWidthMask;
78 extern UINTN mVtdUnitNumber;
79 extern VTD_UNIT_INFORMATION *mVtdUnitInformation;
80
81 extern UINT64 mBelow4GMemoryLimit;
82 extern UINT64 mAbove4GMemoryLimit;
83
84 extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
85
86 /**
87 Prepare VTD configuration.
88 **/
89 VOID
90 PrepareVtdConfig (
91 VOID
92 );
93
94 /**
95 Setup VTd translation table.
96
97 @retval EFI_SUCCESS Setup translation table successfully.
98 @retval EFI_OUT_OF_RESOURCE Setup translation table fail.
99 **/
100 EFI_STATUS
101 SetupTranslationTable (
102 VOID
103 );
104
105 /**
106 Enable DMAR translation.
107
108 @retval EFI_SUCCESS DMAR translation is enabled.
109 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
110 **/
111 EFI_STATUS
112 EnableDmar (
113 VOID
114 );
115
116 /**
117 Disable DMAR translation.
118
119 @retval EFI_SUCCESS DMAR translation is disabled.
120 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
121 **/
122 EFI_STATUS
123 DisableDmar (
124 VOID
125 );
126
127 /**
128 Invalid VTd IOTLB page.
129
130 @param[in] VtdIndex The index of VTd engine.
131 @param[in] Address The address of IOTLB page.
132 @param[in] AddressMode The address mode of IOTLB page.
133 @param[in] DomainIdentifier The domain ID of the source.
134
135 @retval EFI_SUCCESS VTd IOTLB page is invalidated.
136 @retval EFI_DEVICE_ERROR VTd IOTLB page is not invalidated.
137 **/
138 EFI_STATUS
139 InvalidateVtdIOTLBPage (
140 IN UINTN VtdIndex,
141 IN UINT64 Address,
142 IN UINT8 AddressMode,
143 IN UINT16 DomainIdentifier
144 );
145
146 /**
147 Invalid VTd IOTLB domain.
148
149 @param[in] VtdIndex The index of VTd engine.
150 @param[in] DomainIdentifier The domain ID of the source.
151
152 @retval EFI_SUCCESS VTd IOTLB domain is invalidated.
153 @retval EFI_DEVICE_ERROR VTd IOTLB domain is not invalidated.
154 **/
155 EFI_STATUS
156 InvalidateVtdIOTLBDomain (
157 IN UINTN VtdIndex,
158 IN UINT16 DomainIdentifier
159 );
160
161 /**
162 Invalid VTd global IOTLB.
163
164 @param[in] VtdIndex The index of VTd engine.
165
166 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
167 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
168 **/
169 EFI_STATUS
170 InvalidateVtdIOTLBGlobal (
171 IN UINTN VtdIndex
172 );
173
174 /**
175 Dump VTd registers.
176
177 @param[in] VtdIndex The index of VTd engine.
178 **/
179 VOID
180 DumpVtdRegs (
181 IN UINTN VtdIndex
182 );
183
184 /**
185 Dump VTd registers for all VTd engine.
186 **/
187 VOID
188 DumpVtdRegsAll (
189 VOID
190 );
191
192 /**
193 Dump VTd capability registers.
194
195 @param[in] CapReg The capability register.
196 **/
197 VOID
198 DumpVtdCapRegs (
199 IN VTD_CAP_REG *CapReg
200 );
201
202 /**
203 Dump VTd extended capability registers.
204
205 @param[in] ECapReg The extended capability register.
206 **/
207 VOID
208 DumpVtdECapRegs (
209 IN VTD_ECAP_REG *ECapReg
210 );
211
212 /**
213 Register PCI device to VTd engine as PCI descriptor.
214
215 @param[in] VtdIndex The index of VTd engine.
216 @param[in] Segment The segment of the source.
217 @param[in] SourceId The SourceId of the source.
218 @param[in] IsRealPciDevice TRUE: It is a real PCI device.
219 FALSE: It is not a real PCI device.
220 @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.
221 FALSE: SUCCESS will be returned if the PCI device is registered.
222
223 @retval EFI_SUCCESS The PCI device is registered.
224 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
225 @retval EFI_ALREADY_STARTED The device is already registered.
226 **/
227 EFI_STATUS
228 RegisterPciDevice (
229 IN UINTN VtdIndex,
230 IN UINT16 Segment,
231 IN VTD_SOURCE_ID SourceId,
232 IN BOOLEAN IsRealPciDevice,
233 IN BOOLEAN CheckExist
234 );
235
236 /**
237 Scan PCI bus and register PCI devices under the bus.
238
239 @param[in] VtdIndex The index of VTd engine.
240 @param[in] Segment The segment of the source.
241 @param[in] Bus The bus of the source.
242
243 @retval EFI_SUCCESS The PCI devices under the bus are registered.
244 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
245 **/
246 EFI_STATUS
247 ScanPciBus (
248 IN UINTN VtdIndex,
249 IN UINT16 Segment,
250 IN UINT8 Bus
251 );
252
253 /**
254 Dump the PCI device information managed by this VTd engine.
255
256 @param[in] VtdIndex The index of VTd engine.
257 **/
258 VOID
259 DumpPciDeviceInfo (
260 IN UINTN VtdIndex
261 );
262
263 /**
264 Find the VTd index by the Segment and SourceId.
265
266 @param[in] Segment The segment of the source.
267 @param[in] SourceId The SourceId of the source.
268 @param[out] ExtContextEntry The ExtContextEntry of the source.
269 @param[out] ContextEntry The ContextEntry of the source.
270
271 @return The index of the PCI descriptor.
272 @retval (UINTN)-1 The PCI descriptor is not found.
273 **/
274 UINTN
275 FindVtdIndexByPciDevice (
276 IN UINT16 Segment,
277 IN VTD_SOURCE_ID SourceId,
278 OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,
279 OUT VTD_CONTEXT_ENTRY **ContextEntry
280 );
281
282 /**
283 Get the DMAR ACPI table.
284
285 @retval EFI_SUCCESS The DMAR ACPI table is got.
286 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.
287 **/
288 EFI_STATUS
289 GetDmarAcpiTable (
290 VOID
291 );
292
293 /**
294 Parse DMAR DRHD table.
295
296 @return EFI_SUCCESS The DMAR DRHD table is parsed.
297 **/
298 EFI_STATUS
299 ParseDmarAcpiTableDrhd (
300 VOID
301 );
302
303 /**
304 Parse DMAR RMRR table.
305
306 @return EFI_SUCCESS The DMAR RMRR table is parsed.
307 **/
308 EFI_STATUS
309 ParseDmarAcpiTableRmrr (
310 VOID
311 );
312
313 /**
314 Dump DMAR context entry table.
315
316 @param[in] RootEntry DMAR root entry.
317 **/
318 VOID
319 DumpDmarContextEntryTable (
320 IN VTD_ROOT_ENTRY *RootEntry
321 );
322
323 /**
324 Dump DMAR extended context entry table.
325
326 @param[in] ExtRootEntry DMAR extended root entry.
327 **/
328 VOID
329 DumpDmarExtContextEntryTable (
330 IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
331 );
332
333 /**
334 Dump DMAR second level paging entry.
335
336 @param[in] SecondLevelPagingEntry The second level paging entry.
337 **/
338 VOID
339 DumpSecondLevelPagingEntry (
340 IN VOID *SecondLevelPagingEntry
341 );
342
343 /**
344 Set VTd attribute for a system memory.
345
346 @param[in] VtdIndex The index used to identify a VTd engine.
347 @param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
348 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
349 @param[in] Length The length of device memory address to be used as the DMA memory.
350 @param[in] IoMmuAccess The IOMMU access.
351
352 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
353 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
354 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
355 @retval EFI_INVALID_PARAMETER Length is 0.
356 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
357 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
358 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
359 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
360 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
361 **/
362 EFI_STATUS
363 SetPageAttribute (
364 IN UINTN VtdIndex,
365 IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
366 IN UINT64 BaseAddress,
367 IN UINT64 Length,
368 IN UINT64 IoMmuAccess
369 );
370
371 /**
372 Set VTd attribute for a system memory.
373
374 @param[in] Segment The Segment used to identify a VTd engine.
375 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
376 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
377 @param[in] Length The length of device memory address to be used as the DMA memory.
378 @param[in] IoMmuAccess The IOMMU access.
379
380 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
381 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
382 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
383 @retval EFI_INVALID_PARAMETER Length is 0.
384 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
385 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
386 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
387 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
388 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
389 **/
390 EFI_STATUS
391 SetAccessAttribute (
392 IN UINT16 Segment,
393 IN VTD_SOURCE_ID SourceId,
394 IN UINT64 BaseAddress,
395 IN UINT64 Length,
396 IN UINT64 IoMmuAccess
397 );
398
399 /**
400 Return the index of PCI descriptor.
401
402 @param[in] VtdIndex The index used to identify a VTd engine.
403 @param[in] Segment The Segment used to identify a VTd engine.
404 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
405
406 @return The index of the PCI descriptor.
407 @retval (UINTN)-1 The PCI descriptor is not found.
408 **/
409 UINTN
410 GetPciDescriptor (
411 IN UINTN VtdIndex,
412 IN UINT16 Segment,
413 IN VTD_SOURCE_ID SourceId
414 );
415
416 /**
417 Dump VTd registers if there is error.
418 **/
419 VOID
420 DumpVtdIfError (
421 VOID
422 );
423
424 /**
425 Initialize platform VTd policy.
426 **/
427 VOID
428 InitializePlatformVTdPolicy (
429 VOID
430 );
431
432 /**
433 Always enable the VTd page attribute for the device.
434
435 @param[in] Segment The Segment used to identify a VTd engine.
436 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
437
438 @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
439 **/
440 EFI_STATUS
441 AlwaysEnablePageAttribute (
442 IN UINT16 Segment,
443 IN VTD_SOURCE_ID SourceId
444 );
445
446 /**
447 Convert the DeviceHandle to SourceId and Segment.
448
449 @param[in] DeviceHandle The device who initiates the DMA access request.
450 @param[out] Segment The Segment used to identify a VTd engine.
451 @param[out] SourceId The SourceId used to identify a VTd engine and table entry.
452
453 @retval EFI_SUCCESS The Segment and SourceId are returned.
454 @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
455 @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
456 **/
457 EFI_STATUS
458 DeviceHandleToSourceId (
459 IN EFI_HANDLE DeviceHandle,
460 OUT UINT16 *Segment,
461 OUT VTD_SOURCE_ID *SourceId
462 );
463
464 /**
465 Get device information from mapping.
466
467 @param[in] Mapping The mapping.
468 @param[out] DeviceAddress The device address of the mapping.
469 @param[out] NumberOfPages The number of pages of the mapping.
470
471 @retval EFI_SUCCESS The device information is returned.
472 @retval EFI_INVALID_PARAMETER The mapping is invalid.
473 **/
474 EFI_STATUS
475 GetDeviceInfoFromMapping (
476 IN VOID *Mapping,
477 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
478 OUT UINTN *NumberOfPages
479 );
480
481 /**
482 Initialize DMA protection.
483 **/
484 VOID
485 InitializeDmaProtection (
486 VOID
487 );
488
489 /**
490 Allocate zero pages.
491
492 @param[in] Pages the number of pages.
493
494 @return the page address.
495 @retval NULL No resource to allocate pages.
496 **/
497 VOID *
498 EFIAPI
499 AllocateZeroPages (
500 IN UINTN Pages
501 );
502
503 #endif