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