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