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