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"
25 extern VTD_INFO
*mVTdInfo
;
28 Get protected low memory alignment.
30 @param VtdUnitBaseAddress The base address of the VTd engine.
32 @return protected low memory alignment.
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 VtdUnitBaseAddress The base address of the VTd engine.
53 @return protected high memory alignment.
57 IN UINTN VtdUnitBaseAddress
61 UINT8 HostAddressWidth
;
63 HostAddressWidth
= mVTdInfo
->HostAddressWidth
;
65 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, 0xFFFFFFFFFFFFFFFF);
66 Data64
= MmioRead64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
);
68 Data64
= Data64
& (LShiftU64 (1, HostAddressWidth
) - 1);
74 Get protected low memory alignment.
76 @param EngineMask The mask of the VTd engine to be accessed.
78 @return protected low memory alignment.
81 GetLowMemoryAlignment (
87 UINT32 FinalAlignment
;
90 for (Index
= 0; Index
< mVTdInfo
->VTdEngineCount
; Index
++) {
91 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
94 Alignment
= GetPlmrAlignment ((UINTN
)mVTdInfo
->VTdEngineAddress
[Index
]);
95 if (FinalAlignment
< Alignment
) {
96 FinalAlignment
= Alignment
;
99 return FinalAlignment
;
103 Get protected high memory alignment.
105 @param EngineMask The mask of the VTd engine to be accessed.
107 @return protected high memory alignment.
110 GetHighMemoryAlignment (
116 UINT64 FinalAlignment
;
119 for (Index
= 0; Index
< mVTdInfo
->VTdEngineCount
; Index
++) {
120 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
123 Alignment
= GetPhmrAlignment ((UINTN
)mVTdInfo
->VTdEngineAddress
[Index
]);
124 if (FinalAlignment
< Alignment
) {
125 FinalAlignment
= Alignment
;
128 return FinalAlignment
;
132 Enable PMR in the VTd engine.
134 @param VtdUnitBaseAddress The base address of the VTd engine.
136 @retval EFI_SUCCESS The PMR is enabled.
137 @retval EFI_UNSUPPORTED The PMR is not supported.
141 IN UINTN VtdUnitBaseAddress
147 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
148 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
149 return EFI_UNSUPPORTED
;
152 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
153 if ((Reg32
& BIT0
) == 0) {
154 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, BIT31
);
156 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
157 } while((Reg32
& BIT0
) == 0);
164 Disable PMR in the VTd engine.
166 @param VtdUnitBaseAddress The base address of the VTd engine.
168 @retval EFI_SUCCESS The PMR is disabled.
169 @retval EFI_UNSUPPORTED The PMR is not supported.
173 IN UINTN VtdUnitBaseAddress
179 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
180 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
181 return EFI_UNSUPPORTED
;
184 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
185 if ((Reg32
& BIT0
) != 0) {
186 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, 0x0);
188 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
189 } while((Reg32
& BIT0
) != 0);
196 Set PMR region in the VTd engine.
198 @param VtdUnitBaseAddress The base address of the VTd engine.
199 @param LowMemoryBase The protected low memory region base.
200 @param LowMemoryLength The protected low memory region length.
201 @param HighMemoryBase The protected high memory region base.
202 @param HighMemoryLength The protected high memory region length.
204 @retval EFI_SUCCESS The PMR is set to protected region.
205 @retval EFI_UNSUPPORTED The PMR is not supported.
209 IN UINTN VtdUnitBaseAddress
,
210 IN UINT32 LowMemoryBase
,
211 IN UINT32 LowMemoryLength
,
212 IN UINT64 HighMemoryBase
,
213 IN UINT64 HighMemoryLength
217 UINT32 PlmrAlignment
;
218 UINT64 PhmrAlignment
;
220 DEBUG ((DEBUG_INFO
, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress
));
222 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
223 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
224 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR unsupported\n"));
225 return EFI_UNSUPPORTED
;
228 PlmrAlignment
= GetPlmrAlignment (VtdUnitBaseAddress
);
229 DEBUG ((DEBUG_INFO
, "PlmrAlignment - 0x%x\n", PlmrAlignment
));
230 PhmrAlignment
= GetPhmrAlignment (VtdUnitBaseAddress
);
231 DEBUG ((DEBUG_INFO
, "PhmrAlignment - 0x%lx\n", PhmrAlignment
));
233 if ((LowMemoryBase
!= ALIGN_VALUE(LowMemoryBase
, PlmrAlignment
)) ||
234 (LowMemoryLength
!= ALIGN_VALUE(LowMemoryLength
, PlmrAlignment
)) ||
235 (HighMemoryBase
!= ALIGN_VALUE(HighMemoryBase
, PhmrAlignment
)) ||
236 (HighMemoryLength
!= ALIGN_VALUE(HighMemoryLength
, PhmrAlignment
))) {
237 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR alignment issue\n"));
238 return EFI_UNSUPPORTED
;
241 if (LowMemoryBase
== 0 && LowMemoryLength
== 0) {
242 LowMemoryBase
= 0xFFFFFFFF;
244 if (HighMemoryBase
== 0 && HighMemoryLength
== 0) {
245 HighMemoryBase
= 0xFFFFFFFFFFFFFFFF;
248 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, LowMemoryBase
);
249 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_LIMITE_REG
, LowMemoryBase
+ LowMemoryLength
- 1);
250 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, HighMemoryBase
);
251 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_LIMITE_REG
, HighMemoryBase
+ HighMemoryLength
- 1);
257 Set DMA protected region.
259 @param EngineMask The mask of the VTd engine to be accessed.
260 @param LowMemoryBase The protected low memory region base.
261 @param LowMemoryLength The protected low memory region length.
262 @param HighMemoryBase The protected high memory region base.
263 @param HighMemoryLength The protected high memory region length.
265 @retval EFI_SUCCESS The DMA protection is set.
266 @retval EFI_UNSUPPORTED The DMA protection is not set.
269 SetDmaProtectedRange (
270 IN UINT64 EngineMask
,
271 IN UINT32 LowMemoryBase
,
272 IN UINT32 LowMemoryLength
,
273 IN UINT64 HighMemoryBase
,
274 IN UINT64 HighMemoryLength
280 DEBUG ((DEBUG_INFO
, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask
, LowMemoryBase
, LowMemoryLength
, HighMemoryBase
, HighMemoryLength
));
282 for (Index
= 0; Index
< mVTdInfo
->VTdEngineCount
; Index
++) {
283 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
286 DisablePmr ((UINTN
)mVTdInfo
->VTdEngineAddress
[Index
]);
287 Status
= SetPmrRegion (
288 (UINTN
)mVTdInfo
->VTdEngineAddress
[Index
],
294 if (EFI_ERROR(Status
)) {
297 Status
= EnablePmr ((UINTN
)mVTdInfo
->VTdEngineAddress
[Index
]);
298 if (EFI_ERROR(Status
)) {
307 Diable DMA protection.
309 @param EngineMask The mask of the VTd engine to be accessed.
311 @retval DMA protection is disabled.
314 DisableDmaProtection (
321 DEBUG ((DEBUG_INFO
, "DisableDmaProtection\n"));
323 for (Index
= 0; Index
< mVTdInfo
->VTdEngineCount
; Index
++) {
324 if ((EngineMask
& LShiftU64(1, Index
)) == 0) {
327 Status
= DisablePmr ((UINTN
)mVTdInfo
->VTdEngineAddress
[Index
]);
328 if (EFI_ERROR(Status
)) {