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