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 EDKII_VTD_INFO_PPI
*mVTdInfoPpi
;
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
= mVTdInfoPpi
->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 @return protected low memory alignment.
79 GetLowMemoryAlignment (
85 UINT32 FinalAlignment
;
88 for (Index
= 0; Index
< mVTdInfoPpi
->VTdEngineCount
; Index
++) {
89 Alignment
= GetPlmrAlignment ((UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
]);
90 if (FinalAlignment
< Alignment
) {
91 FinalAlignment
= Alignment
;
94 return FinalAlignment
;
98 Get protected high memory alignment.
100 @return protected high memory alignment.
103 GetHighMemoryAlignment (
109 UINT64 FinalAlignment
;
112 for (Index
= 0; Index
< mVTdInfoPpi
->VTdEngineCount
; Index
++) {
113 Alignment
= GetPhmrAlignment ((UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
]);
114 if (FinalAlignment
< Alignment
) {
115 FinalAlignment
= Alignment
;
118 return FinalAlignment
;
122 Enable PMR in the VTd engine.
124 @param VtdUnitBaseAddress The base address of the VTd engine.
126 @retval EFI_SUCCESS The PMR is enabled.
127 @retval EFI_UNSUPPORTED The PMR is not supported.
131 IN UINTN VtdUnitBaseAddress
137 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
138 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
139 return EFI_UNSUPPORTED
;
142 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
143 if ((Reg32
& BIT0
) == 0) {
144 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, BIT31
);
146 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
147 } while((Reg32
& BIT0
) == 0);
154 Disable PMR in the VTd engine.
156 @param VtdUnitBaseAddress The base address of the VTd engine.
158 @retval EFI_SUCCESS The PMR is disabled.
159 @retval EFI_UNSUPPORTED The PMR is not supported.
163 IN UINTN VtdUnitBaseAddress
169 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
170 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
171 return EFI_UNSUPPORTED
;
174 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
175 if ((Reg32
& BIT0
) != 0) {
176 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
, 0x0);
178 Reg32
= MmioRead32 (VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
179 } while((Reg32
& BIT0
) != 0);
186 Set PMR region in the VTd engine.
188 @param VtdUnitBaseAddress The base address of the VTd engine.
189 @param LowMemoryBase The protected low memory region base.
190 @param LowMemoryLength The protected low memory region length.
191 @param HighMemoryBase The protected high memory region base.
192 @param HighMemoryLength The protected high memory region length.
194 @retval EFI_SUCCESS The PMR is set to protected region.
195 @retval EFI_UNSUPPORTED The PMR is not supported.
199 IN UINTN VtdUnitBaseAddress
,
200 IN UINT32 LowMemoryBase
,
201 IN UINT32 LowMemoryLength
,
202 IN UINT64 HighMemoryBase
,
203 IN UINT64 HighMemoryLength
207 UINT32 PlmrAlignment
;
208 UINT64 PhmrAlignment
;
210 DEBUG ((DEBUG_INFO
, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress
));
212 CapReg
.Uint64
= MmioRead64 (VtdUnitBaseAddress
+ R_CAP_REG
);
213 if (CapReg
.Bits
.PLMR
== 0 || CapReg
.Bits
.PHMR
== 0) {
214 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR unsupported\n"));
215 return EFI_UNSUPPORTED
;
218 PlmrAlignment
= GetPlmrAlignment (VtdUnitBaseAddress
);
219 DEBUG ((DEBUG_INFO
, "PlmrAlignment - 0x%x\n", PlmrAlignment
));
220 PhmrAlignment
= GetPhmrAlignment (VtdUnitBaseAddress
);
221 DEBUG ((DEBUG_INFO
, "PhmrAlignment - 0x%lx\n", PhmrAlignment
));
223 if ((LowMemoryBase
!= ALIGN_VALUE(LowMemoryBase
, PlmrAlignment
)) ||
224 (LowMemoryLength
!= ALIGN_VALUE(LowMemoryLength
, PlmrAlignment
)) ||
225 (HighMemoryBase
!= ALIGN_VALUE(HighMemoryBase
, PhmrAlignment
)) ||
226 (HighMemoryLength
!= ALIGN_VALUE(HighMemoryLength
, PhmrAlignment
))) {
227 DEBUG ((DEBUG_ERROR
, "PLMR/PHMR alignment issue\n"));
228 return EFI_UNSUPPORTED
;
231 if (LowMemoryBase
== 0 && LowMemoryLength
== 0) {
232 LowMemoryBase
= 0xFFFFFFFF;
234 if (HighMemoryBase
== 0 && HighMemoryLength
== 0) {
235 HighMemoryBase
= 0xFFFFFFFFFFFFFFFF;
238 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_BASE_REG
, LowMemoryBase
);
239 MmioWrite32 (VtdUnitBaseAddress
+ R_PMEN_LOW_LIMITE_REG
, LowMemoryBase
+ LowMemoryLength
- 1);
240 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_BASE_REG
, HighMemoryBase
);
241 MmioWrite64 (VtdUnitBaseAddress
+ R_PMEN_HIGH_LIMITE_REG
, HighMemoryBase
+ HighMemoryLength
- 1);
247 Set DMA protected region.
249 @param LowMemoryBase The protected low memory region base.
250 @param LowMemoryLength The protected low memory region length.
251 @param HighMemoryBase The protected high memory region base.
252 @param HighMemoryLength The protected high memory region length.
254 @retval EFI_SUCCESS The DMA protection is set.
255 @retval EFI_UNSUPPORTED The DMA protection is not set.
258 SetDmaProtectedRange (
259 IN UINT32 LowMemoryBase
,
260 IN UINT32 LowMemoryLength
,
261 IN UINT64 HighMemoryBase
,
262 IN UINT64 HighMemoryLength
268 DEBUG ((DEBUG_INFO
, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase
, LowMemoryLength
, HighMemoryBase
, HighMemoryLength
));
270 for (Index
= 0; Index
< mVTdInfoPpi
->VTdEngineCount
; Index
++) {
271 DisablePmr ((UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
]);
272 Status
= SetPmrRegion (
273 (UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
],
279 if (EFI_ERROR(Status
)) {
282 Status
= EnablePmr ((UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
]);
283 if (EFI_ERROR(Status
)) {
292 Diable DMA protection.
294 @retval DMA protection is disabled.
297 DisableDmaProtection (
304 DEBUG ((DEBUG_INFO
, "DisableDmaProtection\n"));
306 for (Index
= 0; Index
< mVTdInfoPpi
->VTdEngineCount
; Index
++) {
307 Status
= DisablePmr ((UINTN
)mVTdInfoPpi
->VTdEngineAddress
[Index
]);
308 if (EFI_ERROR(Status
)) {