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