3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License which accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/IoLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/CacheMaintenanceLib.h>
22 #include <IndustryStandard/Vtd.h>
23 #include <Ppi/VtdInfo.h>
25 #include "IntelVTdPmrPei.h"
28 Flush VTD page table and context table memory.
30 This action is to make sure the IOMMU engine can get final data in memory.
32 @param[in] Base The base address of memory to be flushed.
33 @param[in] Size The size of memory in bytes to be flushed.
36 FlushPageTableMemory (
41 WriteBackDataCacheRange ((VOID
*)Base
, Size
);
45 Flush VTd engine write buffer.
47 @param VtdUnitBaseAddress The base address of the VTd engine.
51 IN UINTN VtdUnitBaseAddress
57 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
59 if (CapReg
.Bits
.RWBF
!= 0) {
60 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
61 MmioWrite32 (VtdUnitBaseAddress
+ R_GCMD_REG
, Reg32
| B_GMCD_REG_WBF
);
63 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
64 } while ((Reg32
& B_GSTS_REG_WBF
) != 0);
69 Invalidate VTd context cache.
71 @param VtdUnitBaseAddress The base address of the VTd engine.
74 InvalidateContextCache (
75 IN UINTN VtdUnitBaseAddress
80 Reg64
= MmioRead64 (VtdUnitBaseAddress
+ R_CCMD_REG
);
81 if ((Reg64
& B_CCMD_REG_ICC
) != 0) {
82 DEBUG ((DEBUG_ERROR
,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n",VtdUnitBaseAddress
));
83 return EFI_DEVICE_ERROR
;
86 Reg64
&= ((~B_CCMD_REG_ICC
) & (~B_CCMD_REG_CIRG_MASK
));
87 Reg64
|= (B_CCMD_REG_ICC
| V_CCMD_REG_CIRG_GLOBAL
);
88 MmioWrite64 (VtdUnitBaseAddress
+ R_CCMD_REG
, Reg64
);
91 Reg64
= MmioRead64 (VtdUnitBaseAddress
+ R_CCMD_REG
);
92 } while ((Reg64
& B_CCMD_REG_ICC
) != 0);
100 @param VtdUnitBaseAddress The base address of the VTd engine.
104 IN UINTN VtdUnitBaseAddress
108 VTD_ECAP_REG ECapReg
;
110 ECapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_ECAP_REG
);
112 Reg64
= MmioRead64 (VtdUnitBaseAddress
+ (ECapReg
.Bits
.IRO
* 16) + R_IOTLB_REG
);
113 if ((Reg64
& B_IOTLB_REG_IVT
) != 0) {
114 DEBUG ((DEBUG_ERROR
,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VtdUnitBaseAddress
));
115 return EFI_DEVICE_ERROR
;
118 Reg64
&= ((~B_IOTLB_REG_IVT
) & (~B_IOTLB_REG_IIRG_MASK
));
119 Reg64
|= (B_IOTLB_REG_IVT
| V_IOTLB_REG_IIRG_GLOBAL
);
120 MmioWrite64 (VtdUnitBaseAddress
+ (ECapReg
.Bits
.IRO
* 16) + R_IOTLB_REG
, Reg64
);
123 Reg64
= MmioRead64 (VtdUnitBaseAddress
+ (ECapReg
.Bits
.IRO
* 16) + R_IOTLB_REG
);
124 } while ((Reg64
& B_IOTLB_REG_IVT
) != 0);
130 Enable DMAR translation.
132 @param VtdUnitBaseAddress The base address of the VTd engine.
133 @param RootEntryTable The address of the VTd RootEntryTable.
135 @retval EFI_SUCCESS DMAR translation is enabled.
136 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
140 IN UINTN VtdUnitBaseAddress
,
141 IN UINTN RootEntryTable
146 DEBUG((DEBUG_INFO
, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress
));
148 DEBUG((DEBUG_INFO
, "RootEntryTable 0x%x \n", RootEntryTable
));
149 MmioWrite64 (VtdUnitBaseAddress
+ R_RTADDR_REG
, (UINT64
)(UINTN
)RootEntryTable
);
151 MmioWrite32 (VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_SRTP
);
153 DEBUG((DEBUG_INFO
, "EnableDmar: waiting for RTPS bit to be set... \n"));
155 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
156 } while((Reg32
& B_GSTS_REG_RTPS
) == 0);
159 // Init DMAr Fault Event and Data registers
161 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_FEDATA_REG
);
164 // Write Buffer Flush before invalidation
166 FlushWriteBuffer (VtdUnitBaseAddress
);
169 // Invalidate the context cache
171 InvalidateContextCache (VtdUnitBaseAddress
);
174 // Invalidate the IOTLB cache
176 InvalidateIOTLB (VtdUnitBaseAddress
);
181 MmioWrite32 (VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_TE
);
182 DEBUG((DEBUG_INFO
, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
184 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
185 } while ((Reg32
& B_GSTS_REG_TE
) == 0);
187 DEBUG ((DEBUG_INFO
,"VTD () enabled!<<<<<<\n"));
193 Disable DMAR translation.
195 @param VtdUnitBaseAddress The base address of the VTd engine.
197 @retval EFI_SUCCESS DMAR translation is disabled.
198 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
202 IN UINTN VtdUnitBaseAddress
207 DEBUG((DEBUG_INFO
, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress
));
210 // Write Buffer Flush before invalidation
212 FlushWriteBuffer (VtdUnitBaseAddress
);
217 MmioWrite32 (VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_SRTP
);
219 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
220 } while((Reg32
& B_GSTS_REG_RTPS
) == 0);
222 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_GSTS_REG
);
223 DEBUG((DEBUG_INFO
, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32
));
225 MmioWrite64 (VtdUnitBaseAddress
+ R_RTADDR_REG
, 0);
227 DEBUG ((DEBUG_INFO
,"VTD () Disabled!<<<<<<\n"));
233 Enable VTd translation table protection.
235 @param VTdInfo The VTd engine context information.
236 @param EngineMask The mask of the VTd engine to be accessed.
239 EnableVTdTranslationProtection (
240 IN VTD_INFO
*VTdInfo
,
245 VOID
*RootEntryTable
;
247 DEBUG ((DEBUG_INFO
, "EnableVTdTranslationProtection - 0x%lx\n", EngineMask
));
249 RootEntryTable
= AllocatePages (1);
250 ASSERT (RootEntryTable
!= NULL
);
251 if (RootEntryTable
== NULL
) {
252 DEBUG ((DEBUG_INFO
, " EnableVTdTranslationProtection : OutOfResource\n"));
256 ZeroMem (RootEntryTable
, EFI_PAGES_TO_SIZE(1));
257 FlushPageTableMemory ((UINTN
)RootEntryTable
, EFI_PAGES_TO_SIZE(1));
259 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
260 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
263 EnableDmar ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
], (UINTN
)RootEntryTable
);
270 Disable VTd translation table protection.
272 @param VTdInfo The VTd engine context information.
273 @param EngineMask The mask of the VTd engine to be accessed.
276 DisableVTdTranslationProtection (
277 IN VTD_INFO
*VTdInfo
,
283 DEBUG ((DEBUG_INFO
, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask
));
285 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
286 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
289 DisableDmar ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);