]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
IntelSiliconPkg/PlatformIntelVTdInfoSamplePei: Move to feature dir.
[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
21#include <Ppi/VTdInfo.h>\r
22\r
23#include "IntelVTdPmrPei.h"\r
24\r
25extern EDKII_VTD_INFO_PPI *mVTdInfoPpi;\r
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
63 HostAddressWidth = mVTdInfoPpi->HostAddressWidth;\r
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
76 @return protected low memory alignment.\r
77**/\r
78UINT32\r
79GetLowMemoryAlignment (\r
80 VOID\r
81 )\r
82{\r
83 UINTN Index;\r
84 UINT32 Alignment;\r
85 UINT32 FinalAlignment;\r
86\r
87 FinalAlignment = 0;\r
88 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
89 Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
90 if (FinalAlignment < Alignment) {\r
91 FinalAlignment = Alignment;\r
92 }\r
93 }\r
94 return FinalAlignment;\r
95}\r
96\r
97/**\r
98 Get protected high memory alignment.\r
99\r
100 @return protected high memory alignment.\r
101**/\r
102UINT64\r
103GetHighMemoryAlignment (\r
104 VOID\r
105 )\r
106{\r
107 UINTN Index;\r
108 UINT64 Alignment;\r
109 UINT64 FinalAlignment;\r
110\r
111 FinalAlignment = 0;\r
112 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
113 Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
114 if (FinalAlignment < Alignment) {\r
115 FinalAlignment = Alignment;\r
116 }\r
117 }\r
118 return FinalAlignment;\r
119}\r
120\r
121/**\r
122 Enable PMR in the VTd engine.\r
123\r
124 @param VtdUnitBaseAddress The base address of the VTd engine.\r
125\r
126 @retval EFI_SUCCESS The PMR is enabled.\r
127 @retval EFI_UNSUPPORTED The PMR is not supported.\r
128**/\r
129EFI_STATUS\r
130EnablePmr (\r
131 IN UINTN VtdUnitBaseAddress\r
132 )\r
133{\r
134 UINT32 Reg32;\r
135 VTD_CAP_REG CapReg;\r
136\r
137 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
138 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
139 return EFI_UNSUPPORTED;\r
140 }\r
141\r
142 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
143 if ((Reg32 & BIT0) == 0) {\r
144 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);\r
145 do {\r
146 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
147 } while((Reg32 & BIT0) == 0);\r
148 }\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153/**\r
154 Disable PMR in the VTd engine.\r
155\r
156 @param VtdUnitBaseAddress The base address of the VTd engine.\r
157\r
158 @retval EFI_SUCCESS The PMR is disabled.\r
159 @retval EFI_UNSUPPORTED The PMR is not supported.\r
160**/\r
161EFI_STATUS\r
162DisablePmr (\r
163 IN UINTN VtdUnitBaseAddress\r
164 )\r
165{\r
166 UINT32 Reg32;\r
167 VTD_CAP_REG CapReg;\r
168\r
169 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
170 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
171 return EFI_UNSUPPORTED;\r
172 }\r
173\r
174 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
175 if ((Reg32 & BIT0) != 0) {\r
176 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);\r
177 do {\r
178 Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
179 } while((Reg32 & BIT0) != 0);\r
180 }\r
181\r
182 return EFI_SUCCESS;\r
183}\r
184\r
185/**\r
186 Set PMR region in the VTd engine.\r
187\r
188 @param VtdUnitBaseAddress The base address of the VTd engine.\r
189 @param LowMemoryBase The protected low memory region base.\r
190 @param LowMemoryLength The protected low memory region length.\r
191 @param HighMemoryBase The protected high memory region base.\r
192 @param HighMemoryLength The protected high memory region length.\r
193\r
194 @retval EFI_SUCCESS The PMR is set to protected region.\r
195 @retval EFI_UNSUPPORTED The PMR is not supported.\r
196**/\r
197EFI_STATUS\r
198SetPmrRegion (\r
199 IN UINTN VtdUnitBaseAddress,\r
200 IN UINT32 LowMemoryBase,\r
201 IN UINT32 LowMemoryLength,\r
202 IN UINT64 HighMemoryBase,\r
203 IN UINT64 HighMemoryLength\r
204 )\r
205{\r
206 VTD_CAP_REG CapReg;\r
207 UINT32 PlmrAlignment;\r
208 UINT64 PhmrAlignment;\r
209\r
210 DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));\r
211\r
212 CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
213 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
214 DEBUG ((DEBUG_ERROR, "PLMR/PHMR unsupported\n"));\r
215 return EFI_UNSUPPORTED;\r
216 }\r
217\r
218 PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);\r
219 DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));\r
220 PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);\r
221 DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));\r
222\r
223 if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||\r
224 (LowMemoryLength != ALIGN_VALUE(LowMemoryLength, PlmrAlignment)) ||\r
225 (HighMemoryBase != ALIGN_VALUE(HighMemoryBase, PhmrAlignment)) ||\r
226 (HighMemoryLength != ALIGN_VALUE(HighMemoryLength, PhmrAlignment))) {\r
227 DEBUG ((DEBUG_ERROR, "PLMR/PHMR alignment issue\n"));\r
228 return EFI_UNSUPPORTED;\r
229 }\r
230\r
231 if (LowMemoryBase == 0 && LowMemoryLength == 0) {\r
232 LowMemoryBase = 0xFFFFFFFF;\r
233 }\r
234 if (HighMemoryBase == 0 && HighMemoryLength == 0) {\r
235 HighMemoryBase = 0xFFFFFFFFFFFFFFFF;\r
236 }\r
237\r
238 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);\r
239 MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);\r
240 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, HighMemoryBase);\r
241 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);\r
242\r
243 return EFI_SUCCESS;\r
244}\r
245\r
246/**\r
247 Set DMA protected region.\r
248\r
249 @param LowMemoryBase The protected low memory region base.\r
250 @param LowMemoryLength The protected low memory region length.\r
251 @param HighMemoryBase The protected high memory region base.\r
252 @param HighMemoryLength The protected high memory region length.\r
253\r
254 @retval EFI_SUCCESS The DMA protection is set.\r
255 @retval EFI_UNSUPPORTED The DMA protection is not set.\r
256**/\r
257EFI_STATUS\r
258SetDmaProtectedRange (\r
259 IN UINT32 LowMemoryBase,\r
260 IN UINT32 LowMemoryLength,\r
261 IN UINT64 HighMemoryBase,\r
262 IN UINT64 HighMemoryLength\r
263 )\r
264{\r
265 UINTN Index;\r
266 EFI_STATUS Status;\r
267\r
268 DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));\r
269\r
270 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
271 DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
272 Status = SetPmrRegion (\r
273 (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],\r
274 LowMemoryBase,\r
275 LowMemoryLength,\r
276 HighMemoryBase,\r
277 HighMemoryLength\r
278 );\r
279 if (EFI_ERROR(Status)) {\r
280 return Status;\r
281 }\r
282 Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
283 if (EFI_ERROR(Status)) {\r
284 return Status;\r
285 }\r
286 }\r
287\r
288 return EFI_SUCCESS;\r
289}\r
290\r
291/**\r
292 Diable DMA protection.\r
293\r
294 @retval DMA protection is disabled.\r
295**/\r
296EFI_STATUS\r
297DisableDmaProtection (\r
298 VOID\r
299 )\r
300{\r
301 UINTN Index;\r
302 EFI_STATUS Status;\r
303\r
304 DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));\r
305\r
306 for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
307 Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
308 if (EFI_ERROR(Status)) {\r
309 return Status;\r
310 }\r
311 }\r
312\r
313 return EFI_SUCCESS;\r
314}\r