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