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