]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
IntelSiliconPkg/IntelVTdPmrPei: Move to feature dir.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmr.c
1 /** @file
2
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4
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
9
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.
12
13 **/
14
15 #include <PiPei.h>
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>
22
23 #include "IntelVTdPmrPei.h"
24
25 extern EDKII_VTD_INFO_PPI *mVTdInfoPpi;
26
27 /**
28 Get protected low memory alignment.
29
30 @param VtdUnitBaseAddress The base address of the VTd engine.
31
32 @return protected low memory alignment.
33 **/
34 UINT32
35 GetPlmrAlignment (
36 IN UINTN VtdUnitBaseAddress
37 )
38 {
39 UINT32 Data32;
40
41 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, 0xFFFFFFFF);
42 Data32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG);
43 Data32 = ~Data32 + 1;
44
45 return Data32;
46 }
47
48 /**
49 Get protected high memory alignment.
50
51 @param VtdUnitBaseAddress The base address of the VTd engine.
52
53 @return protected high memory alignment.
54 **/
55 UINT64
56 GetPhmrAlignment (
57 IN UINTN VtdUnitBaseAddress
58 )
59 {
60 UINT64 Data64;
61 UINT8 HostAddressWidth;
62
63 HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
64
65 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
66 Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
67 Data64 = ~Data64 + 1;
68 Data64 = Data64 & (LShiftU64 (1, HostAddressWidth) - 1);
69
70 return Data64;
71 }
72
73 /**
74 Get protected low memory alignment.
75
76 @return protected low memory alignment.
77 **/
78 UINT32
79 GetLowMemoryAlignment (
80 VOID
81 )
82 {
83 UINTN Index;
84 UINT32 Alignment;
85 UINT32 FinalAlignment;
86
87 FinalAlignment = 0;
88 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
89 Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
90 if (FinalAlignment < Alignment) {
91 FinalAlignment = Alignment;
92 }
93 }
94 return FinalAlignment;
95 }
96
97 /**
98 Get protected high memory alignment.
99
100 @return protected high memory alignment.
101 **/
102 UINT64
103 GetHighMemoryAlignment (
104 VOID
105 )
106 {
107 UINTN Index;
108 UINT64 Alignment;
109 UINT64 FinalAlignment;
110
111 FinalAlignment = 0;
112 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
113 Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
114 if (FinalAlignment < Alignment) {
115 FinalAlignment = Alignment;
116 }
117 }
118 return FinalAlignment;
119 }
120
121 /**
122 Enable PMR in the VTd engine.
123
124 @param VtdUnitBaseAddress The base address of the VTd engine.
125
126 @retval EFI_SUCCESS The PMR is enabled.
127 @retval EFI_UNSUPPORTED The PMR is not supported.
128 **/
129 EFI_STATUS
130 EnablePmr (
131 IN UINTN VtdUnitBaseAddress
132 )
133 {
134 UINT32 Reg32;
135 VTD_CAP_REG CapReg;
136
137 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
138 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
139 return EFI_UNSUPPORTED;
140 }
141
142 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
143 if ((Reg32 & BIT0) == 0) {
144 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
145 do {
146 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
147 } while((Reg32 & BIT0) == 0);
148 }
149
150 return EFI_SUCCESS;
151 }
152
153 /**
154 Disable PMR in the VTd engine.
155
156 @param VtdUnitBaseAddress The base address of the VTd engine.
157
158 @retval EFI_SUCCESS The PMR is disabled.
159 @retval EFI_UNSUPPORTED The PMR is not supported.
160 **/
161 EFI_STATUS
162 DisablePmr (
163 IN UINTN VtdUnitBaseAddress
164 )
165 {
166 UINT32 Reg32;
167 VTD_CAP_REG CapReg;
168
169 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
170 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
171 return EFI_UNSUPPORTED;
172 }
173
174 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
175 if ((Reg32 & BIT0) != 0) {
176 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
177 do {
178 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
179 } while((Reg32 & BIT0) != 0);
180 }
181
182 return EFI_SUCCESS;
183 }
184
185 /**
186 Set PMR region in the VTd engine.
187
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.
193
194 @retval EFI_SUCCESS The PMR is set to protected region.
195 @retval EFI_UNSUPPORTED The PMR is not supported.
196 **/
197 EFI_STATUS
198 SetPmrRegion (
199 IN UINTN VtdUnitBaseAddress,
200 IN UINT32 LowMemoryBase,
201 IN UINT32 LowMemoryLength,
202 IN UINT64 HighMemoryBase,
203 IN UINT64 HighMemoryLength
204 )
205 {
206 VTD_CAP_REG CapReg;
207 UINT32 PlmrAlignment;
208 UINT64 PhmrAlignment;
209
210 DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));
211
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;
216 }
217
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));
222
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;
229 }
230
231 if (LowMemoryBase == 0 && LowMemoryLength == 0) {
232 LowMemoryBase = 0xFFFFFFFF;
233 }
234 if (HighMemoryBase == 0 && HighMemoryLength == 0) {
235 HighMemoryBase = 0xFFFFFFFFFFFFFFFF;
236 }
237
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);
242
243 return EFI_SUCCESS;
244 }
245
246 /**
247 Set DMA protected region.
248
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.
253
254 @retval EFI_SUCCESS The DMA protection is set.
255 @retval EFI_UNSUPPORTED The DMA protection is not set.
256 **/
257 EFI_STATUS
258 SetDmaProtectedRange (
259 IN UINT32 LowMemoryBase,
260 IN UINT32 LowMemoryLength,
261 IN UINT64 HighMemoryBase,
262 IN UINT64 HighMemoryLength
263 )
264 {
265 UINTN Index;
266 EFI_STATUS Status;
267
268 DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
269
270 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
271 DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
272 Status = SetPmrRegion (
273 (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
274 LowMemoryBase,
275 LowMemoryLength,
276 HighMemoryBase,
277 HighMemoryLength
278 );
279 if (EFI_ERROR(Status)) {
280 return Status;
281 }
282 Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
283 if (EFI_ERROR(Status)) {
284 return Status;
285 }
286 }
287
288 return EFI_SUCCESS;
289 }
290
291 /**
292 Diable DMA protection.
293
294 @retval DMA protection is disabled.
295 **/
296 EFI_STATUS
297 DisableDmaProtection (
298 VOID
299 )
300 {
301 UINTN Index;
302 EFI_STATUS Status;
303
304 DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
305
306 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
307 Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
308 if (EFI_ERROR(Status)) {
309 return Status;
310 }
311 }
312
313 return EFI_SUCCESS;
314 }