]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
IntelSiliconPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdDxe / DmaProtection.h
1 /** @file
2
3 Copyright (c) 2017 - 2018, 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 Invalid VTd global IOTLB.
173
174 @param[in] VtdIndex The index of VTd engine.
175
176 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
177 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
178 **/
179 EFI_STATUS
180 InvalidateVtdIOTLBGlobal (
181 IN UINTN VtdIndex
182 );
183
184 /**
185 Dump VTd registers.
186
187 @param[in] VtdIndex The index of VTd engine.
188 **/
189 VOID
190 DumpVtdRegs (
191 IN UINTN VtdIndex
192 );
193
194 /**
195 Dump VTd registers for all VTd engine.
196 **/
197 VOID
198 DumpVtdRegsAll (
199 VOID
200 );
201
202 /**
203 Dump VTd capability registers.
204
205 @param[in] CapReg The capability register.
206 **/
207 VOID
208 DumpVtdCapRegs (
209 IN VTD_CAP_REG *CapReg
210 );
211
212 /**
213 Dump VTd extended capability registers.
214
215 @param[in] ECapReg The extended capability register.
216 **/
217 VOID
218 DumpVtdECapRegs (
219 IN VTD_ECAP_REG *ECapReg
220 );
221
222 /**
223 Register PCI device to VTd engine.
224
225 @param[in] VtdIndex The index of VTd engine.
226 @param[in] Segment The segment of the source.
227 @param[in] SourceId The SourceId of the source.
228 @param[in] DeviceType The DMAR device scope type.
229 @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.
230 FALSE: SUCCESS will be returned if the PCI device is registered.
231
232 @retval EFI_SUCCESS The PCI device is registered.
233 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
234 @retval EFI_ALREADY_STARTED The device is already registered.
235 **/
236 EFI_STATUS
237 RegisterPciDevice (
238 IN UINTN VtdIndex,
239 IN UINT16 Segment,
240 IN VTD_SOURCE_ID SourceId,
241 IN UINT8 DeviceType,
242 IN BOOLEAN CheckExist
243 );
244
245 /**
246 The scan bus callback function to always enable page attribute.
247
248 @param[in] Context The context of the callback.
249 @param[in] Segment The segment of the source.
250 @param[in] Bus The bus of the source.
251 @param[in] Device The device of the source.
252 @param[in] Function The function of the source.
253
254 @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
255 **/
256 EFI_STATUS
257 EFIAPI
258 ScanBusCallbackRegisterPciDevice (
259 IN VOID *Context,
260 IN UINT16 Segment,
261 IN UINT8 Bus,
262 IN UINT8 Device,
263 IN UINT8 Function
264 );
265
266 /**
267 Scan PCI bus and invoke callback function for each PCI devices under the bus.
268
269 @param[in] Context The context of the callback function.
270 @param[in] Segment The segment of the source.
271 @param[in] Bus The bus of the source.
272 @param[in] Callback The callback function in PCI scan.
273
274 @retval EFI_SUCCESS The PCI devices under the bus are scaned.
275 **/
276 EFI_STATUS
277 ScanPciBus (
278 IN VOID *Context,
279 IN UINT16 Segment,
280 IN UINT8 Bus,
281 IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback
282 );
283
284 /**
285 Dump the PCI device information managed by this VTd engine.
286
287 @param[in] VtdIndex The index of VTd engine.
288 **/
289 VOID
290 DumpPciDeviceInfo (
291 IN UINTN VtdIndex
292 );
293
294 /**
295 Find the VTd index by the Segment and SourceId.
296
297 @param[in] Segment The segment of the source.
298 @param[in] SourceId The SourceId of the source.
299 @param[out] ExtContextEntry The ExtContextEntry of the source.
300 @param[out] ContextEntry The ContextEntry of the source.
301
302 @return The index of the VTd engine.
303 @retval (UINTN)-1 The VTd engine is not found.
304 **/
305 UINTN
306 FindVtdIndexByPciDevice (
307 IN UINT16 Segment,
308 IN VTD_SOURCE_ID SourceId,
309 OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,
310 OUT VTD_CONTEXT_ENTRY **ContextEntry
311 );
312
313 /**
314 Get the DMAR ACPI table.
315
316 @retval EFI_SUCCESS The DMAR ACPI table is got.
317 @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previously.
318 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.
319 **/
320 EFI_STATUS
321 GetDmarAcpiTable (
322 VOID
323 );
324
325 /**
326 Parse DMAR DRHD table.
327
328 @return EFI_SUCCESS The DMAR DRHD table is parsed.
329 **/
330 EFI_STATUS
331 ParseDmarAcpiTableDrhd (
332 VOID
333 );
334
335 /**
336 Parse DMAR RMRR table.
337
338 @return EFI_SUCCESS The DMAR RMRR table is parsed.
339 **/
340 EFI_STATUS
341 ParseDmarAcpiTableRmrr (
342 VOID
343 );
344
345 /**
346 Dump DMAR context entry table.
347
348 @param[in] RootEntry DMAR root entry.
349 **/
350 VOID
351 DumpDmarContextEntryTable (
352 IN VTD_ROOT_ENTRY *RootEntry
353 );
354
355 /**
356 Dump DMAR extended context entry table.
357
358 @param[in] ExtRootEntry DMAR extended root entry.
359 **/
360 VOID
361 DumpDmarExtContextEntryTable (
362 IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
363 );
364
365 /**
366 Dump DMAR second level paging entry.
367
368 @param[in] SecondLevelPagingEntry The second level paging entry.
369 **/
370 VOID
371 DumpSecondLevelPagingEntry (
372 IN VOID *SecondLevelPagingEntry
373 );
374
375 /**
376 Set VTd attribute for a system memory.
377
378 @param[in] VtdIndex The index used to identify a VTd engine.
379 @param[in] DomainIdentifier The domain ID of the source.
380 @param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
381 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
382 @param[in] Length The length of device memory address to be used as the DMA memory.
383 @param[in] IoMmuAccess The IOMMU access.
384
385 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
386 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
387 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
388 @retval EFI_INVALID_PARAMETER Length is 0.
389 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
390 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
391 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
392 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
393 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
394 **/
395 EFI_STATUS
396 SetPageAttribute (
397 IN UINTN VtdIndex,
398 IN UINT16 DomainIdentifier,
399 IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
400 IN UINT64 BaseAddress,
401 IN UINT64 Length,
402 IN UINT64 IoMmuAccess
403 );
404
405 /**
406 Set VTd attribute for a system memory.
407
408 @param[in] Segment The Segment used to identify a VTd engine.
409 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
410 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
411 @param[in] Length The length of device memory address to be used as the DMA memory.
412 @param[in] IoMmuAccess The IOMMU access.
413
414 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
415 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
416 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
417 @retval EFI_INVALID_PARAMETER Length is 0.
418 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
419 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
420 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
421 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
422 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
423 **/
424 EFI_STATUS
425 SetAccessAttribute (
426 IN UINT16 Segment,
427 IN VTD_SOURCE_ID SourceId,
428 IN UINT64 BaseAddress,
429 IN UINT64 Length,
430 IN UINT64 IoMmuAccess
431 );
432
433 /**
434 Return the index of PCI data.
435
436 @param[in] VtdIndex The index used to identify a VTd engine.
437 @param[in] Segment The Segment used to identify a VTd engine.
438 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
439
440 @return The index of the PCI data.
441 @retval (UINTN)-1 The PCI data is not found.
442 **/
443 UINTN
444 GetPciDataIndex (
445 IN UINTN VtdIndex,
446 IN UINT16 Segment,
447 IN VTD_SOURCE_ID SourceId
448 );
449
450 /**
451 Dump VTd registers if there is error.
452 **/
453 VOID
454 DumpVtdIfError (
455 VOID
456 );
457
458 /**
459 Initialize platform VTd policy.
460 **/
461 VOID
462 InitializePlatformVTdPolicy (
463 VOID
464 );
465
466 /**
467 Always enable the VTd page attribute for the device.
468
469 @param[in] Segment The Segment used to identify a VTd engine.
470 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
471
472 @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
473 **/
474 EFI_STATUS
475 AlwaysEnablePageAttribute (
476 IN UINT16 Segment,
477 IN VTD_SOURCE_ID SourceId
478 );
479
480 /**
481 Convert the DeviceHandle to SourceId and Segment.
482
483 @param[in] DeviceHandle The device who initiates the DMA access request.
484 @param[out] Segment The Segment used to identify a VTd engine.
485 @param[out] SourceId The SourceId used to identify a VTd engine and table entry.
486
487 @retval EFI_SUCCESS The Segment and SourceId are returned.
488 @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
489 @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
490 **/
491 EFI_STATUS
492 DeviceHandleToSourceId (
493 IN EFI_HANDLE DeviceHandle,
494 OUT UINT16 *Segment,
495 OUT VTD_SOURCE_ID *SourceId
496 );
497
498 /**
499 Get device information from mapping.
500
501 @param[in] Mapping The mapping.
502 @param[out] DeviceAddress The device address of the mapping.
503 @param[out] NumberOfPages The number of pages of the mapping.
504
505 @retval EFI_SUCCESS The device information is returned.
506 @retval EFI_INVALID_PARAMETER The mapping is invalid.
507 **/
508 EFI_STATUS
509 GetDeviceInfoFromMapping (
510 IN VOID *Mapping,
511 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
512 OUT UINTN *NumberOfPages
513 );
514
515 /**
516 Initialize DMA protection.
517 **/
518 VOID
519 InitializeDmaProtection (
520 VOID
521 );
522
523 /**
524 Allocate zero pages.
525
526 @param[in] Pages the number of pages.
527
528 @return the page address.
529 @retval NULL No resource to allocate pages.
530 **/
531 VOID *
532 EFIAPI
533 AllocateZeroPages (
534 IN UINTN Pages
535 );
536
537 /**
538 Flush VTD page table and context table memory.
539
540 This action is to make sure the IOMMU engine can get final data in memory.
541
542 @param[in] VtdIndex The index used to identify a VTd engine.
543 @param[in] Base The base address of memory to be flushed.
544 @param[in] Size The size of memory in bytes to be flushed.
545 **/
546 VOID
547 FlushPageTableMemory (
548 IN UINTN VtdIndex,
549 IN UINTN Base,
550 IN UINTN Size
551 );
552
553 /**
554 Get PCI device information from DMAR DevScopeEntry.
555
556 @param[in] Segment The segment number.
557 @param[in] DmarDevScopeEntry DMAR DevScopeEntry
558 @param[out] Bus The bus number.
559 @param[out] Device The device number.
560 @param[out] Function The function number.
561
562 @retval EFI_SUCCESS The PCI device information is returned.
563 **/
564 EFI_STATUS
565 GetPciBusDeviceFunction (
566 IN UINT16 Segment,
567 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,
568 OUT UINT8 *Bus,
569 OUT UINT8 *Device,
570 OUT UINT8 *Function
571 );
572
573 /**
574 Append VTd Access Request to global.
575
576 @param[in] Segment The Segment used to identify a VTd engine.
577 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
578 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
579 @param[in] Length The length of device memory address to be used as the DMA memory.
580 @param[in] IoMmuAccess The IOMMU access.
581
582 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
583 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
584 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
585 @retval EFI_INVALID_PARAMETER Length is 0.
586 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
587 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
588 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
589 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
590 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
591
592 **/
593 EFI_STATUS
594 RequestAccessAttribute (
595 IN UINT16 Segment,
596 IN VTD_SOURCE_ID SourceId,
597 IN UINT64 BaseAddress,
598 IN UINT64 Length,
599 IN UINT64 IoMmuAccess
600 );
601
602 #endif