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 <IndustryStandard/Vtd.h>
21 #include <Ppi/VtdInfo.h>
23 #include "IntelVTdPmrPei.h"
26 Get protected low memory alignment.
28 @param HostAddressWidth The host address width.
29 @param VtdUnitBaseAddress The base address of the VTd engine.
31 @return protected low memory alignment.
35 IN UINT8 HostAddressWidth
,
36 IN UINTN VtdUnitBaseAddress
41 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, 0xFFFFFFFF);
42 Data32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
);
49 Get protected high memory alignment.
51 @param HostAddressWidth The host address width.
52 @param VtdUnitBaseAddress The base address of the VTd engine.
54 @return protected high memory alignment.
58 IN UINT8 HostAddressWidth
,
59 IN UINTN VtdUnitBaseAddress
64 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, 0xFFFFFFFFFFFFFFFF);
65 Data64
= MmioRead64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
);
67 Data64
= Data64
& (LShiftU64 (1, HostAddressWidth
) - 1);
73 Get protected low memory alignment.
75 @param VTdInfo The VTd engine context information.
76 @param EngineMask The mask of the VTd engine to be accessed.
78 @return protected low memory alignment.
81 GetLowMemoryAlignment (
88 UINT32 FinalAlignment
;
91 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
92 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
95 Alignment
= GetPlmrAlignment (VTdInfo
->HostAddressWidth
, (UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
96 if (FinalAlignment
< Alignment
) {
97 FinalAlignment
= Alignment
;
100 return FinalAlignment
;
104 Get protected high memory alignment.
106 @param VTdInfo The VTd engine context information.
107 @param EngineMask The mask of the VTd engine to be accessed.
109 @return protected high memory alignment.
112 GetHighMemoryAlignment (
113 IN VTD_INFO
*VTdInfo
,
119 UINT64 FinalAlignment
;
122 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
123 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
126 Alignment
= GetPhmrAlignment (VTdInfo
->HostAddressWidth
, (UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
127 if (FinalAlignment
< Alignment
) {
128 FinalAlignment
= Alignment
;
131 return FinalAlignment
;
135 Enable PMR in the VTd engine.
137 @param VtdUnitBaseAddress The base address of the VTd engine.
139 @retval EFI_SUCCESS The PMR is enabled.
140 @retval EFI_UNSUPPORTED The PMR is not supported.
144 IN UINTN VtdUnitBaseAddress
150 DEBUG ((DEBUG_INFO
, "EnablePmr - %x\n", VtdUnitBaseAddress
));
152 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
153 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
154 return EFI_UNSUPPORTED
;
157 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
158 if (Reg32
== 0xFFFFFFFF) {
159 DEBUG ((DEBUG_ERROR
, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32
));
163 if ((Reg32
& BIT0
) == 0) {
164 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, BIT31
);
166 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
167 } while((Reg32
& BIT0
) == 0);
170 DEBUG ((DEBUG_INFO
, "EnablePmr - Done\n"));
176 Disable PMR in the VTd engine.
178 @param VtdUnitBaseAddress The base address of the VTd engine.
180 @retval EFI_SUCCESS The PMR is disabled.
181 @retval EFI_UNSUPPORTED The PMR is not supported.
185 IN UINTN VtdUnitBaseAddress
191 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
192 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
193 return EFI_UNSUPPORTED
;
196 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
197 if (Reg32
== 0xFFFFFFFF) {
198 DEBUG ((DEBUG_ERROR
, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32
));
202 if ((Reg32
& BIT0
) != 0) {
203 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, 0x0);
205 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
206 } while((Reg32
& BIT0
) != 0);
213 Set PMR region in the VTd engine.
215 @param HostAddressWidth The host address width.
216 @param VtdUnitBaseAddress The base address of the VTd engine.
217 @param LowMemoryBase The protected low memory region base.
218 @param LowMemoryLength The protected low memory region length.
219 @param HighMemoryBase The protected high memory region base.
220 @param HighMemoryLength The protected high memory region length.
222 @retval EFI_SUCCESS The PMR is set to protected region.
223 @retval EFI_UNSUPPORTED The PMR is not supported.
227 IN UINT8 HostAddressWidth
,
228 IN UINTN VtdUnitBaseAddress
,
229 IN UINT32 LowMemoryBase
,
230 IN UINT32 LowMemoryLength
,
231 IN UINT64 HighMemoryBase
,
232 IN UINT64 HighMemoryLength
236 UINT32 PlmrAlignment
;
237 UINT64 PhmrAlignment
;
239 DEBUG ((DEBUG_INFO
, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress
));
241 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
242 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
243 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR unsupported\n"));
244 return EFI_UNSUPPORTED
;
247 PlmrAlignment
= GetPlmrAlignment (HostAddressWidth
, VtdUnitBaseAddress
);
248 DEBUG ((DEBUG_INFO
, "PlmrAlignment - 0x%x\n", PlmrAlignment
));
249 PhmrAlignment
= GetPhmrAlignment (HostAddressWidth
, VtdUnitBaseAddress
);
250 DEBUG ((DEBUG_INFO
, "PhmrAlignment - 0x%lx\n", PhmrAlignment
));
252 if ((LowMemoryBase
!= ALIGN_VALUE(LowMemoryBase
, PlmrAlignment
)) ||
253 (LowMemoryLength
!= ALIGN_VALUE(LowMemoryLength
, PlmrAlignment
)) ||
254 (HighMemoryBase
!= ALIGN_VALUE(HighMemoryBase
, PhmrAlignment
)) ||
255 (HighMemoryLength
!= ALIGN_VALUE(HighMemoryLength
, PhmrAlignment
))) {
256 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR alignment issue\n"));
257 return EFI_UNSUPPORTED
;
260 if (LowMemoryBase
== 0 && LowMemoryLength
== 0) {
261 LowMemoryBase
= 0xFFFFFFFF;
263 if (HighMemoryBase
== 0 && HighMemoryLength
== 0) {
264 HighMemoryBase
= 0xFFFFFFFFFFFFFFFF;
267 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, LowMemoryBase
);
268 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_LIMITE_REG
, LowMemoryBase
+ LowMemoryLength
- 1);
269 DEBUG ((DEBUG_INFO
, "PLMR set done\n"));
270 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, HighMemoryBase
);
271 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_LIMITE_REG
, HighMemoryBase
+ HighMemoryLength
- 1);
272 DEBUG ((DEBUG_INFO
, "PHMR set done\n"));
278 Set DMA protected region.
280 @param VTdInfo The VTd engine context information.
281 @param EngineMask The mask of the VTd engine to be accessed.
282 @param LowMemoryBase The protected low memory region base.
283 @param LowMemoryLength The protected low memory region length.
284 @param HighMemoryBase The protected high memory region base.
285 @param HighMemoryLength The protected high memory region length.
287 @retval EFI_SUCCESS The DMA protection is set.
288 @retval EFI_UNSUPPORTED The DMA protection is not set.
291 SetDmaProtectedRange (
292 IN VTD_INFO
*VTdInfo
,
293 IN UINT64 EngineMask
,
294 IN UINT32 LowMemoryBase
,
295 IN UINT32 LowMemoryLength
,
296 IN UINT64 HighMemoryBase
,
297 IN UINT64 HighMemoryLength
303 DEBUG ((DEBUG_INFO
, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask
, LowMemoryBase
, LowMemoryLength
, HighMemoryBase
, HighMemoryLength
));
305 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
306 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
309 DisablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
310 Status
= SetPmrRegion (
311 VTdInfo
->HostAddressWidth
,
312 (UINTN
)VTdInfo
->VTdEngineAddress
[Index
],
318 if (EFI_ERROR(Status
)) {
321 Status
= EnablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
322 if (EFI_ERROR(Status
)) {
331 Diable DMA protection.
333 @param VTdInfo The VTd engine context information.
334 @param EngineMask The mask of the VTd engine to be accessed.
336 @retval EFI_SUCCESS DMA protection is disabled.
339 DisableDmaProtection (
340 IN VTD_INFO
*VTdInfo
,
347 DEBUG ((DEBUG_INFO
, "DisableDmaProtection - 0x%lx\n", EngineMask
));
349 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
350 DEBUG ((DEBUG_INFO
, "Disabling...%d\n", Index
));
352 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
355 Status
= DisablePmr ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
356 if (EFI_ERROR(Status
)) {
365 Return if the PMR is enabled.
367 @param VtdUnitBaseAddress The base address of the VTd engine.
369 @retval TRUE PMR is enabled.
370 @retval FALSE PMR is disabled or unsupported.
374 IN UINTN VtdUnitBaseAddress
380 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
381 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
385 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
386 if ((Reg32
& BIT0
) == 0) {
394 Return the mask of the VTd engine which is enabled.
396 @param VTdInfo The VTd engine context information.
397 @param EngineMask The mask of the VTd engine to be accessed.
399 @return the mask of the VTd engine which is enabled.
402 GetDmaProtectionEnabledEngineMask (
403 IN VTD_INFO
*VTdInfo
,
409 UINT64 EnabledEngineMask
;
411 DEBUG ((DEBUG_INFO
, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask
));
413 EnabledEngineMask
= 0;
414 for (Index
= 0; Index
< VTdInfo
->VTdEngineCount
; Index
++) {
415 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
418 Result
= IsPmrEnabled ((UINTN
)VTdInfo
->VTdEngineAddress
[Index
]);
420 EnabledEngineMask
|= LShiftU64(1, Index
);
424 DEBUG ((DEBUG_INFO
, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask
));
425 return EnabledEngineMask
;