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