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