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