]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/IntelVTdDxe/VtdReg.c
IntelSiliconPkg/IntelVTdDxe: Fix typo for VTd IOTLB domain ID
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / VtdReg.c
1 /** @file
2
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #include "DmaProtection.h"
15
16 UINT64 mVtdHostAddressWidthMask;
17 UINTN mVtdUnitNumber;
18 VTD_UNIT_INFORMATION *mVtdUnitInformation;
19
20 BOOLEAN mVtdEnabled;
21
22 /**
23 Invalid VTd global IOTLB.
24
25 @param[in] VtdIndex The index of VTd engine.
26
27 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
28 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
29 **/
30 EFI_STATUS
31 InvalidateVtdIOTLBGlobal (
32 IN UINTN VtdIndex
33 )
34 {
35 UINT64 Reg64;
36 UINT32 Reg32;
37
38 if (!mVtdEnabled) {
39 return EFI_SUCCESS;
40 }
41
42 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));
43
44 AsmWbinvd();
45
46 //
47 // Write Buffer Flush before invalidation
48 //
49 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);
50 if ((Reg32 & B_CAP_REG_RWBF) != 0) {
51 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);
52 }
53
54 //
55 // Invalidate the context cache
56 //
57 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
58 if ((Reg64 & B_CCMD_REG_ICC) != 0) {
59 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
60 return EFI_DEVICE_ERROR;
61 }
62
63 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
64 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
65 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);
66
67 do {
68 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
69 } while ((Reg64 & B_CCMD_REG_ICC) != 0);
70
71 //
72 // Invalidate the IOTLB cache
73 //
74
75 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
76 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
77 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
78 return EFI_DEVICE_ERROR;
79 }
80
81 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
82 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
83 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
84
85 do {
86 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
87 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
88
89 //
90 // Disable VTd
91 //
92 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
93 do {
94 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
95 } while((Reg32 & B_GSTS_REG_RTPS) == 0);
96
97 //
98 // Enable VTd
99 //
100 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
101 do {
102 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
103 } while ((Reg32 & B_GSTS_REG_TE) == 0);
104
105 return EFI_SUCCESS;
106 }
107
108 /**
109 Invalid VTd IOTLB domain.
110
111 @param[in] VtdIndex The index of VTd engine.
112 @param[in] DomainIdentifier The domain ID of the source.
113
114 @retval EFI_SUCCESS VTd IOTLB domain is invalidated.
115 @retval EFI_DEVICE_ERROR VTd IOTLB domain is not invalidated.
116 **/
117 EFI_STATUS
118 InvalidateVtdIOTLBDomain (
119 IN UINTN VtdIndex,
120 IN UINT16 DomainIdentifier
121 )
122 {
123 UINT64 Reg64;
124
125 if (!mVtdEnabled) {
126 return EFI_SUCCESS;
127 }
128
129 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBDomain(%d): 0x%016lx (0x%04x)\n", VtdIndex, DomainIdentifier));
130
131 //
132 // Invalidate the context cache
133 //
134 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
135 if ((Reg64 & B_CCMD_REG_ICC) != 0) {
136 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
137 return EFI_DEVICE_ERROR;
138 }
139
140 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
141 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);
142 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);
143 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);
144
145 do {
146 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
147 } while ((Reg64 & B_CCMD_REG_ICC) != 0);
148
149 //
150 // Invalidate the IOTLB cache
151 //
152
153 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
154 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
155 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
156 return EFI_DEVICE_ERROR;
157 }
158
159 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
160 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_DOMAIN);
161 Reg64 |= LShiftU64 (DomainIdentifier, 32);
162 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
163
164 do {
165 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
166 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
167
168 return EFI_SUCCESS;
169 }
170
171 /**
172 Invalid VTd IOTLB page.
173
174 @param[in] VtdIndex The index of VTd engine.
175 @param[in] Address The address of IOTLB page.
176 @param[in] AddressMode The address mode of IOTLB page.
177 @param[in] DomainIdentifier The domain ID of the source.
178
179 @retval EFI_SUCCESS VTd IOTLB page is invalidated.
180 @retval EFI_DEVICE_ERROR VTd IOTLB page is not invalidated.
181 **/
182 EFI_STATUS
183 InvalidateVtdIOTLBPage (
184 IN UINTN VtdIndex,
185 IN UINT64 Address,
186 IN UINT8 AddressMode,
187 IN UINT16 DomainIdentifier
188 )
189 {
190 UINT64 Reg64;
191 UINT64 Data64;
192
193 if (!mVtdEnabled) {
194 return EFI_SUCCESS;
195 }
196
197 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBPage(%d): 0x%016lx (0x%02x)\n", VtdIndex, Address, AddressMode));
198
199 if (mVtdUnitInformation[VtdIndex].CapReg.Bits.PSI != 0) {
200 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
201 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
202 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBPage: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
203 return EFI_DEVICE_ERROR;
204 }
205
206 Data64 = Address | AddressMode;
207 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG, Data64);
208
209 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
210 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_PAGE);
211 Reg64 |= LShiftU64 (DomainIdentifier, 32);
212 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
213
214 do {
215 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
216 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
217 } else {
218 InvalidateVtdIOTLBGlobal (VtdIndex);
219 }
220
221 return EFI_SUCCESS;
222 }
223
224 /**
225 Prepare VTD configuration.
226 **/
227 VOID
228 PrepareVtdConfig (
229 VOID
230 )
231 {
232 UINTN Index;
233 UINTN DomainNumber;
234
235 for (Index = 0; Index < mVtdUnitNumber; Index++) {
236 DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));
237 mVtdUnitInformation[Index].CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
238 DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);
239 mVtdUnitInformation[Index].ECapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_ECAP_REG);
240 DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);
241
242 if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
243 DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index));
244 }
245 if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
246 DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", Index));
247 return ;
248 }
249
250 DomainNumber = (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index].CapReg.Bits.ND * 2 + 4);
251 if (mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptorNumber >= DomainNumber) {
252 DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptorNumber, DomainNumber));
253 return ;
254 }
255 }
256 return ;
257 }
258
259 /**
260 Enable DMAR translation.
261
262 @retval EFI_SUCCESS DMAR translation is enabled.
263 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
264 **/
265 EFI_STATUS
266 EnableDmar (
267 VOID
268 )
269 {
270 UINTN Index;
271 UINT64 Reg64;
272 UINT32 Reg32;
273
274 AsmWbinvd();
275
276 for (Index = 0; Index < mVtdUnitNumber; Index++) {
277 DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));
278
279 if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
280 DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));
281 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);
282 } else {
283 DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));
284 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);
285 }
286
287 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
288
289 DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
290 do {
291 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
292 } while((Reg32 & B_GSTS_REG_RTPS) == 0);
293
294 //
295 // Init DMAr Fault Event and Data registers
296 //
297 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);
298
299 //
300 // Write Buffer Flush before invalidation
301 //
302 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
303 if ((Reg32 & B_CAP_REG_RWBF) != 0) {
304 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);
305 }
306
307 //
308 // Invalidate the context cache
309 //
310 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG);
311 if ((Reg64 & B_CCMD_REG_ICC) != 0) {
312 DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_CCMD_REG_ICC is set for VTD(%d)\n",Index));
313 return EFI_DEVICE_ERROR;
314 }
315
316 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
317 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
318 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG, Reg64);
319
320 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_CCMD_REG_ICC ...\n"));
321 do {
322 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG);
323 } while ((Reg64 & B_CCMD_REG_ICC) != 0);
324
325 //
326 // Invalidate the IOTLB cache
327 //
328 DEBUG((DEBUG_INFO, "EnableDmar: IRO 0x%x\n", mVtdUnitInformation[Index].ECapReg.Bits.IRO));
329
330 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
331 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
332 DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_IOTLB_REG_IVT is set for VTD(%d)\n", Index));
333 return EFI_DEVICE_ERROR;
334 }
335
336 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
337 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
338 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
339
340 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_IOTLB_REG_IVT ...\n"));
341 do {
342 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
343 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
344
345 //
346 // Enable VTd
347 //
348 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
349 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
350 do {
351 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
352 } while ((Reg32 & B_GSTS_REG_TE) == 0);
353
354 DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
355 }
356
357 mVtdEnabled = TRUE;
358
359 return EFI_SUCCESS;
360 }
361
362 /**
363 Disable DMAR translation.
364
365 @retval EFI_SUCCESS DMAR translation is disabled.
366 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
367 **/
368 EFI_STATUS
369 DisableDmar (
370 VOID
371 )
372 {
373 UINTN Index;
374 UINT32 Reg32;
375
376 AsmWbinvd();
377
378 for (Index = 0; Index < mVtdUnitNumber; Index++) {
379 DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));
380
381 //
382 // Write Buffer Flush before invalidation
383 //
384 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
385 if ((Reg32 & B_CAP_REG_RWBF) != 0) {
386 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);
387 }
388
389 //
390 // Disable VTd
391 //
392 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
393 do {
394 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
395 } while((Reg32 & B_GSTS_REG_RTPS) == 0);
396
397 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
398 DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
399
400 DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));
401 }
402
403 mVtdEnabled = FALSE;
404
405 return EFI_SUCCESS;
406 }
407
408 /**
409 Dump VTd capability registers.
410
411 @param[in] CapReg The capability register.
412 **/
413 VOID
414 DumpVtdCapRegs (
415 IN VTD_CAP_REG *CapReg
416 )
417 {
418 DEBUG((DEBUG_INFO, " CapReg:\n", CapReg->Uint64));
419 DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));
420 DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));
421 DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));
422 DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));
423 DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));
424 DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));
425 DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));
426 DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));
427 DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));
428 DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));
429 DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));
430 DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));
431 DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));
432 DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV));
433 DEBUG((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD));
434 DEBUG((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD));
435 DEBUG((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP));
436 DEBUG((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI));
437 }
438
439 /**
440 Dump VTd extended capability registers.
441
442 @param[in] ECapReg The extended capability register.
443 **/
444 VOID
445 DumpVtdECapRegs (
446 IN VTD_ECAP_REG *ECapReg
447 )
448 {
449 DEBUG((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64));
450 DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));
451 DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));
452 DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));
453 DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));
454 DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));
455 DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));
456 DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));
457 DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));
458 DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));
459 DEBUG((DEBUG_INFO, " ECS - 0x%x\n", ECapReg->Bits.ECS));
460 DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS));
461 DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST));
462 DEBUG((DEBUG_INFO, " DIS - 0x%x\n", ECapReg->Bits.DIS));
463 DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID));
464 DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS));
465 DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS));
466 DEBUG((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS));
467 DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS));
468 DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS));
469 DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));
470 }
471
472 /**
473 Dump VTd registers.
474
475 @param[in] VtdIndex The index of VTd engine.
476 **/
477 VOID
478 DumpVtdRegs (
479 IN UINTN VtdIndex
480 )
481 {
482 UINTN Index;
483 UINT64 Reg64;
484 VTD_FRCD_REG FrcdReg;
485 VTD_CAP_REG CapReg;
486 UINT32 Reg32;
487 VTD_SOURCE_ID SourceId;
488
489 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) Begin ####\n", VtdIndex));
490
491 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_VER_REG);
492 DEBUG((DEBUG_INFO, " VER_REG - 0x%08x\n", Reg32));
493
494 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);
495 DEBUG((DEBUG_INFO, " CAP_REG - 0x%016lx\n", CapReg.Uint64));
496
497 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_ECAP_REG);
498 DEBUG((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", Reg64));
499
500 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
501 DEBUG((DEBUG_INFO, " GSTS_REG - 0x%08x \n", Reg32));
502
503 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR_REG);
504 DEBUG((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", Reg64));
505
506 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
507 DEBUG((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", Reg64));
508
509 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);
510 DEBUG((DEBUG_INFO, " FSTS_REG - 0x%08x\n", Reg32));
511
512 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FECTL_REG);
513 DEBUG((DEBUG_INFO, " FECTL_REG - 0x%08x\n", Reg32));
514
515 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEDATA_REG);
516 DEBUG((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", Reg32));
517
518 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEADDR_REG);
519 DEBUG((DEBUG_INFO, " FEADDR_REG - 0x%08x\n",Reg32));
520
521 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEUADDR_REG);
522 DEBUG((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n",Reg32));
523
524 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
525 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
526 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
527 DEBUG((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));
528 if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) {
529 DEBUG((DEBUG_INFO, " Fault Info - 0x%016lx\n", LShiftU64(FrcdReg.Bits.FI, 12)));
530 SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID;
531 DEBUG((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
532 DEBUG((DEBUG_INFO, " Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write"));
533 DEBUG((DEBUG_INFO, " Reason - %x\n", FrcdReg.Bits.FR));
534 }
535 }
536
537 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG);
538 DEBUG((DEBUG_INFO, " IVA_REG - 0x%016lx\n",Reg64));
539
540 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
541 DEBUG((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n",Reg64));
542
543 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) End ####\n", VtdIndex));
544 }
545
546 /**
547 Dump VTd registers for all VTd engine.
548 **/
549 VOID
550 DumpVtdRegsAll (
551 VOID
552 )
553 {
554 UINTN Num;
555
556 for (Num = 0; Num < mVtdUnitNumber; Num++) {
557 DumpVtdRegs (Num);
558 }
559 }
560
561 /**
562 Dump VTd registers if there is error.
563 **/
564 VOID
565 DumpVtdIfError (
566 VOID
567 )
568 {
569 UINTN Num;
570 UINTN Index;
571 VTD_FRCD_REG FrcdReg;
572 VTD_CAP_REG CapReg;
573 UINT32 Reg32;
574 BOOLEAN HasError;
575
576 for (Num = 0; Num < mVtdUnitNumber; Num++) {
577 HasError = FALSE;
578 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG);
579 if (Reg32 != 0) {
580 HasError = TRUE;
581 }
582 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FECTL_REG);
583 if ((Reg32 & BIT30) != 0) {
584 HasError = TRUE;
585 }
586
587 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_CAP_REG);
588 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
589 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
590 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
591 if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
592 HasError = TRUE;
593 }
594 }
595
596 if (HasError) {
597 DEBUG((DEBUG_INFO, "#### ERROR ####\n"));
598 DumpVtdRegs (Num);
599 DEBUG((DEBUG_INFO, "#### ERROR ####\n"));
600 }
601 }
602 }