IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmr.c
CommitLineData
3f5ed3fa
JY
1/** @file\r
2\r
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
4\r
5 This program and the accompanying materials are licensed and made available under\r
6 the terms and conditions of the BSD License which accompanies this distribution.\r
7 The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/IoLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <IndustryStandard/Vtd.h>\r
4084ccfa 21#include <Ppi/VtdInfo.h>\r
3f5ed3fa
JY
22\r
23#include "IntelVTdPmrPei.h"\r
24\r
8e9da4ba 25extern VTD_INFO *mVTdInfo;\r
3f5ed3fa
JY
26\r
27/**\r
28 Get protected low memory alignment.\r
29\r
30 @param VtdUnitBaseAddress The base address of the VTd engine.\r
31\r
32 @return protected low memory alignment.\r
33**/\r
34UINT32\r
35GetPlmrAlignment (\r
36 IN UINTN VtdUnitBaseAddress\r
37 )\r
38{\r
39 UINT32 Data32;\r
40\r
41 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, 0xFFFFFFFF);\r
42 Data32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG);\r
43 Data32 = ~Data32 + 1;\r
44\r
45 return Data32;\r
46}\r
47\r
48/**\r
49 Get protected high memory alignment.\r
50\r
51 @param VtdUnitBaseAddress The base address of the VTd engine.\r
52\r
53 @return protected high memory alignment.\r
54**/\r
55UINT64\r
56GetPhmrAlignment (\r
57 IN UINTN VtdUnitBaseAddress\r
58 )\r
59{\r
60 UINT64 Data64;\r
61 UINT8 HostAddressWidth;\r
62\r
8e9da4ba 63 HostAddressWidth = mVTdInfo->HostAddressWidth;\r
3f5ed3fa
JY
64\r
65 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);\r
66 Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);\r
67 Data64 = ~Data64 + 1;\r
68 Data64 = Data64 & (LShiftU64 (1, HostAddressWidth) - 1);\r
69\r
70 return Data64;\r
71}\r
72\r
73/**\r
74 Get protected low memory alignment.\r
75\r
8e9da4ba
JY
76 @param EngineMask The mask of the VTd engine to be accessed.\r
77\r
3f5ed3fa
JY
78 @return protected low memory alignment.\r
79**/\r
80UINT32\r
81GetLowMemoryAlignment (\r
8e9da4ba 82 IN UINT64 EngineMask\r
3f5ed3fa
JY
83 )\r
84{\r
85 UINTN Index;\r
86 UINT32 Alignment;\r
87 UINT32 FinalAlignment;\r
88\r
89 FinalAlignment = 0;\r
8e9da4ba
JY
90 for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
91 if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
92 continue;\r
93 }\r
94 Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
3f5ed3fa
JY
95 if (FinalAlignment < Alignment) {\r
96 FinalAlignment = Alignment;\r
97 }\r
98 }\r
99 return FinalAlignment;\r
100}\r
101\r
102/**\r
103 Get protected high memory alignment.\r
104\r
8e9da4ba
JY
105 @param EngineMask The mask of the VTd engine to be accessed.\r
106\r
3f5ed3fa
JY
107 @return protected high memory alignment.\r
108**/\r
109UINT64\r
110GetHighMemoryAlignment (\r
8e9da4ba 111 IN UINT64 EngineMask\r
3f5ed3fa
JY
112 )\r
113{\r
114 UINTN Index;\r
115 UINT64 Alignment;\r
116 UINT64 FinalAlignment;\r
117\r
118 FinalAlignment = 0;\r
8e9da4ba
JY
119 for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
120 if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
121 continue;\r
122 }\r
123 Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
3f5ed3fa
JY
124 if (FinalAlignment < Alignment) {\r
125 FinalAlignment = Alignment;\r
126 }\r
127 }\r
128 return FinalAlignment;\r
129}\r
130\r
131/**\r
132 Enable PMR in the VTd engine.\r
133\r
134 @param VtdUnitBaseAddress The base address of the VTd engine.\r
135\r
136 @retval EFI_SUCCESS The PMR is enabled.\r
137 @retval EFI_UNSUPPORTED The PMR is not supported.\r
138**/\r
139EFI_STATUS\r
140EnablePmr (\r
141 IN UINTN VtdUnitBaseAddress\r
142 )\r
143{\r
144 UINT32 Reg32;\r
145 VTD_CAP_REG CapReg;\r
146\r
147 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
148 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
149 return EFI_UNSUPPORTED;\r
150 }\r
151\r
152 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
153 if ((Reg32 & BIT0) == 0) {\r
154 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);\r
155 do {\r
156 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
157 } while((Reg32 & BIT0) == 0);\r
158 }\r
159\r
160 return EFI_SUCCESS;\r
161}\r
162\r
163/**\r
164 Disable PMR in the VTd engine.\r
165\r
166 @param VtdUnitBaseAddress The base address of the VTd engine.\r
167\r
168 @retval EFI_SUCCESS The PMR is disabled.\r
169 @retval EFI_UNSUPPORTED The PMR is not supported.\r
170**/\r
171EFI_STATUS\r
172DisablePmr (\r
173 IN UINTN VtdUnitBaseAddress\r
174 )\r
175{\r
176 UINT32 Reg32;\r
177 VTD_CAP_REG CapReg;\r
178\r
179 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
180 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
181 return EFI_UNSUPPORTED;\r
182 }\r
183\r
184 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
185 if ((Reg32 & BIT0) != 0) {\r
186 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);\r
187 do {\r
188 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
189 } while((Reg32 & BIT0) != 0);\r
190 }\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195/**\r
196 Set PMR region in the VTd engine.\r
197\r
198 @param VtdUnitBaseAddress The base address of the VTd engine.\r
199 @param LowMemoryBase The protected low memory region base.\r
200 @param LowMemoryLength The protected low memory region length.\r
201 @param HighMemoryBase The protected high memory region base.\r
202 @param HighMemoryLength The protected high memory region length.\r
203\r
204 @retval EFI_SUCCESS The PMR is set to protected region.\r
205 @retval EFI_UNSUPPORTED The PMR is not supported.\r
206**/\r
207EFI_STATUS\r
208SetPmrRegion (\r
209 IN UINTN VtdUnitBaseAddress,\r
210 IN UINT32 LowMemoryBase,\r
211 IN UINT32 LowMemoryLength,\r
212 IN UINT64 HighMemoryBase,\r
213 IN UINT64 HighMemoryLength\r
214 )\r
215{\r
216 VTD_CAP_REG CapReg;\r
217 UINT32 PlmrAlignment;\r
218 UINT64 PhmrAlignment;\r
219\r
220 DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));\r
221\r
222 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
223 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
224 DEBUG ((DEBUG_ERROR, "PLMR/PHMR unsupported\n"));\r
225 return EFI_UNSUPPORTED;\r
226 }\r
227\r
228 PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);\r
229 DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));\r
230 PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);\r
231 DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));\r
232\r
233 if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||\r
234 (LowMemoryLength != ALIGN_VALUE(LowMemoryLength, PlmrAlignment)) ||\r
235 (HighMemoryBase != ALIGN_VALUE(HighMemoryBase, PhmrAlignment)) ||\r
236 (HighMemoryLength != ALIGN_VALUE(HighMemoryLength, PhmrAlignment))) {\r
237 DEBUG ((DEBUG_ERROR, "PLMR/PHMR alignment issue\n"));\r
238 return EFI_UNSUPPORTED;\r
239 }\r
240\r
241 if (LowMemoryBase == 0 && LowMemoryLength == 0) {\r
242 LowMemoryBase = 0xFFFFFFFF;\r
243 }\r
244 if (HighMemoryBase == 0 && HighMemoryLength == 0) {\r
245 HighMemoryBase = 0xFFFFFFFFFFFFFFFF;\r
246 }\r
247\r
248 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);\r
249 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);\r
250 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, HighMemoryBase);\r
251 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);\r
252\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256/**\r
257 Set DMA protected region.\r
258\r
8e9da4ba 259 @param EngineMask The mask of the VTd engine to be accessed.\r
3f5ed3fa
JY
260 @param LowMemoryBase The protected low memory region base.\r
261 @param LowMemoryLength The protected low memory region length.\r
262 @param HighMemoryBase The protected high memory region base.\r
263 @param HighMemoryLength The protected high memory region length.\r
264\r
265 @retval EFI_SUCCESS The DMA protection is set.\r
266 @retval EFI_UNSUPPORTED The DMA protection is not set.\r
267**/\r
268EFI_STATUS\r
269SetDmaProtectedRange (\r
8e9da4ba 270 IN UINT64 EngineMask,\r
3f5ed3fa
JY
271 IN UINT32 LowMemoryBase,\r
272 IN UINT32 LowMemoryLength,\r
273 IN UINT64 HighMemoryBase,\r
274 IN UINT64 HighMemoryLength\r
275 )\r
276{\r
277 UINTN Index;\r
278 EFI_STATUS Status;\r
279\r
8e9da4ba 280 DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));\r
3f5ed3fa 281\r
8e9da4ba
JY
282 for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
283 if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
284 continue;\r
285 }\r
286 DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
3f5ed3fa 287 Status = SetPmrRegion (\r
8e9da4ba 288 (UINTN)mVTdInfo->VTdEngineAddress[Index],\r
3f5ed3fa
JY
289 LowMemoryBase,\r
290 LowMemoryLength,\r
291 HighMemoryBase,\r
292 HighMemoryLength\r
293 );\r
294 if (EFI_ERROR(Status)) {\r
295 return Status;\r
296 }\r
8e9da4ba 297 Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
3f5ed3fa
JY
298 if (EFI_ERROR(Status)) {\r
299 return Status;\r
300 }\r
301 }\r
302\r
303 return EFI_SUCCESS;\r
304}\r
305\r
306/**\r
307 Diable DMA protection.\r
308\r
8e9da4ba
JY
309 @param EngineMask The mask of the VTd engine to be accessed.\r
310\r
3f5ed3fa
JY
311 @retval DMA protection is disabled.\r
312**/\r
313EFI_STATUS\r
314DisableDmaProtection (\r
8e9da4ba 315 IN UINT64 EngineMask\r
3f5ed3fa
JY
316 )\r
317{\r
318 UINTN Index;\r
319 EFI_STATUS Status;\r
320\r
321 DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));\r
322\r
8e9da4ba
JY
323 for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
324 if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
325 continue;\r
326 }\r
327 Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
3f5ed3fa
JY
328 if (EFI_ERROR(Status)) {\r
329 return Status;\r
330 }\r
331 }\r
332\r
333 return EFI_SUCCESS;\r
334}\r