3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/IoLib.h>
13 #include <Library/DebugLib.h>
14 #include <IndustryStandard/Vtd.h>
15 #include <Ppi/VtdInfo.h>
17 #include "IntelVTdPmrPei.h"
20 Get protected low memory alignment.
22 @param HostAddressWidth The host address width.
23 @param VtdUnitBaseAddress The base address of the VTd engine.
25 @return protected low memory alignment.
29 IN UINT8 HostAddressWidth
,
30 IN UINTN VtdUnitBaseAddress
35 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, 0xFFFFFFFF);
36 Data32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
);
43 Get protected high memory alignment.
45 @param HostAddressWidth The host address width.
46 @param VtdUnitBaseAddress The base address of the VTd engine.
48 @return protected high memory alignment.
52 IN UINT8 HostAddressWidth
,
53 IN UINTN VtdUnitBaseAddress
58 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, 0xFFFFFFFFFFFFFFFF);
59 Data64
= MmioRead64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
);
61 Data64
= Data64
& (LShiftU64 (1, HostAddressWidth
) - 1);
67 Get protected low memory alignment.
69 @param VTdInfo The VTd engine context information.
70 @param EngineMask The mask of the VTd engine to be accessed.
72 @return protected low memory alignment.
75 GetLowMemoryAlignment (
82 UINT32 FinalAlignment
;
85 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
86 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
89 Alignment
= GetPlmrAlignment (VTdInfo
->HostAddressWidth
, (UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
90 if (FinalAlignment
< Alignment
) {
91 FinalAlignment
= Alignment
;
94 return FinalAlignment
;
98 Get protected high memory alignment.
100 @param VTdInfo The VTd engine context information.
101 @param EngineMask The mask of the VTd engine to be accessed.
103 @return protected high memory alignment.
106 GetHighMemoryAlignment (
107 IN VTD_INFO
*VTdInfo
,
113 UINT64 FinalAlignment
;
116 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
117 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
120 Alignment
= GetPhmrAlignment (VTdInfo
->HostAddressWidth
, (UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
121 if (FinalAlignment
< Alignment
) {
122 FinalAlignment
= Alignment
;
125 return FinalAlignment
;
129 Enable PMR in the VTd engine.
131 @param VtdUnitBaseAddress The base address of the VTd engine.
133 @retval EFI_SUCCESS The PMR is enabled.
134 @retval EFI_UNSUPPORTED The PMR is not supported.
138 IN UINTN VtdUnitBaseAddress
144 DEBUG ((DEBUG_INFO
, "EnablePmr - %x\n", VtdUnitBaseAddress
));
146 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
147 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
148 return EFI_UNSUPPORTED
;
151 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
152 if (Reg32
== 0xFFFFFFFF) {
153 DEBUG ((DEBUG_ERROR
, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32
));
157 if ((Reg32
& BIT0
) == 0) {
158 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, BIT31
);
160 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
161 } while((Reg32
& BIT0
) == 0);
164 DEBUG ((DEBUG_INFO
, "EnablePmr - Done\n"));
170 Disable PMR in the VTd engine.
172 @param VtdUnitBaseAddress The base address of the VTd engine.
174 @retval EFI_SUCCESS The PMR is disabled.
175 @retval EFI_UNSUPPORTED The PMR is not supported.
179 IN UINTN VtdUnitBaseAddress
185 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
186 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
187 return EFI_UNSUPPORTED
;
190 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
191 if (Reg32
== 0xFFFFFFFF) {
192 DEBUG ((DEBUG_ERROR
, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32
));
196 if ((Reg32
& BIT0
) != 0) {
197 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, 0x0);
199 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
200 } while((Reg32
& BIT0
) != 0);
207 Set PMR region in the VTd engine.
209 @param HostAddressWidth The host address width.
210 @param VtdUnitBaseAddress The base address of the VTd engine.
211 @param LowMemoryBase The protected low memory region base.
212 @param LowMemoryLength The protected low memory region length.
213 @param HighMemoryBase The protected high memory region base.
214 @param HighMemoryLength The protected high memory region length.
216 @retval EFI_SUCCESS The PMR is set to protected region.
217 @retval EFI_UNSUPPORTED The PMR is not supported.
221 IN UINT8 HostAddressWidth
,
222 IN UINTN VtdUnitBaseAddress
,
223 IN UINT32 LowMemoryBase
,
224 IN UINT32 LowMemoryLength
,
225 IN UINT64 HighMemoryBase
,
226 IN UINT64 HighMemoryLength
230 UINT32 PlmrAlignment
;
231 UINT64 PhmrAlignment
;
233 DEBUG ((DEBUG_INFO
, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress
));
235 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
236 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
237 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR unsupported\n"));
238 return EFI_UNSUPPORTED
;
241 PlmrAlignment
= GetPlmrAlignment (HostAddressWidth
, VtdUnitBaseAddress
);
242 DEBUG ((DEBUG_INFO
, "PlmrAlignment - 0x%x\n", PlmrAlignment
));
243 PhmrAlignment
= GetPhmrAlignment (HostAddressWidth
, VtdUnitBaseAddress
);
244 DEBUG ((DEBUG_INFO
, "PhmrAlignment - 0x%lx\n", PhmrAlignment
));
246 if ((LowMemoryBase
!= ALIGN_VALUE(LowMemoryBase
, PlmrAlignment
)) ||
247 (LowMemoryLength
!= ALIGN_VALUE(LowMemoryLength
, PlmrAlignment
)) ||
248 (HighMemoryBase
!= ALIGN_VALUE(HighMemoryBase
, PhmrAlignment
)) ||
249 (HighMemoryLength
!= ALIGN_VALUE(HighMemoryLength
, PhmrAlignment
))) {
250 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR alignment issue\n"));
251 return EFI_UNSUPPORTED
;
254 if (LowMemoryBase
== 0 && LowMemoryLength
== 0) {
255 LowMemoryBase
= 0xFFFFFFFF;
257 if (HighMemoryBase
== 0 && HighMemoryLength
== 0) {
258 HighMemoryBase
= 0xFFFFFFFFFFFFFFFF;
261 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, LowMemoryBase
);
262 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_LIMITE_REG
, LowMemoryBase
+ LowMemoryLength
- 1);
263 DEBUG ((DEBUG_INFO
, "PLMR set done\n"));
264 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, HighMemoryBase
);
265 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_LIMITE_REG
, HighMemoryBase
+ HighMemoryLength
- 1);
266 DEBUG ((DEBUG_INFO
, "PHMR set done\n"));
272 Set DMA protected region.
274 @param VTdInfo The VTd engine context information.
275 @param EngineMask The mask of the VTd engine to be accessed.
276 @param LowMemoryBase The protected low memory region base.
277 @param LowMemoryLength The protected low memory region length.
278 @param HighMemoryBase The protected high memory region base.
279 @param HighMemoryLength The protected high memory region length.
281 @retval EFI_SUCCESS The DMA protection is set.
282 @retval EFI_UNSUPPORTED The DMA protection is not set.
285 SetDmaProtectedRange (
286 IN VTD_INFO
*VTdInfo
,
287 IN UINT64 EngineMask
,
288 IN UINT32 LowMemoryBase
,
289 IN UINT32 LowMemoryLength
,
290 IN UINT64 HighMemoryBase
,
291 IN UINT64 HighMemoryLength
297 DEBUG ((DEBUG_INFO
, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask
, LowMemoryBase
, LowMemoryLength
, HighMemoryBase
, HighMemoryLength
));
299 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
300 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
303 DisablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
304 Status
= SetPmrRegion (
305 VTdInfo
->HostAddressWidth
,
306 (UINTN
)VTdInfo
->VTdEngineAddress
[Index
],
312 if (EFI_ERROR(Status
)) {
315 Status
= EnablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
316 if (EFI_ERROR(Status
)) {
325 Diable DMA protection.
327 @param VTdInfo The VTd engine context information.
328 @param EngineMask The mask of the VTd engine to be accessed.
330 @retval EFI_SUCCESS DMA protection is disabled.
333 DisableDmaProtection (
334 IN VTD_INFO
*VTdInfo
,
341 DEBUG ((DEBUG_INFO
, "DisableDmaProtection - 0x%lx\n", EngineMask
));
343 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
344 DEBUG ((DEBUG_INFO
, "Disabling...%d\n", Index
));
346 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
349 Status
= DisablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
350 if (EFI_ERROR(Status
)) {
359 Return if the PMR is enabled.
361 @param VtdUnitBaseAddress The base address of the VTd engine.
363 @retval TRUE PMR is enabled.
364 @retval FALSE PMR is disabled or unsupported.
368 IN UINTN VtdUnitBaseAddress
374 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
375 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
379 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
380 if ((Reg32
& BIT0
) == 0) {
388 Return the mask of the VTd engine which is enabled.
390 @param VTdInfo The VTd engine context information.
391 @param EngineMask The mask of the VTd engine to be accessed.
393 @return the mask of the VTd engine which is enabled.
396 GetDmaProtectionEnabledEngineMask (
397 IN VTD_INFO
*VTdInfo
,
403 UINT64 EnabledEngineMask
;
405 DEBUG ((DEBUG_INFO
, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask
));
407 EnabledEngineMask
= 0;
408 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
409 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
412 Result
= IsPmrEnabled ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
414 EnabledEngineMask
|= LShiftU64(1, Index
);
418 DEBUG ((DEBUG_INFO
, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask
));
419 return EnabledEngineMask
;