@@ -57,6 +57,8 @@ CheckExcludedRegions (
5757 RMRListNode * Head ;
5858 RMRListNode * Current ;
5959 BOOLEAN Found ;
60+ BOOLEAN FoundInMemoryMap ;
61+ UINT32 FoundMemoryType ;
6062 UNIT_TEST_STATUS TestStatus ;
6163
6264 //
@@ -105,6 +107,8 @@ CheckExcludedRegions (
105107 } else {
106108 UT_LOG_ERROR ("GetMemoryMap Failed\n" );
107109 DEBUG ((DEBUG_ERROR , "%a: GetMemoryMap Failed\n" , __func__ ));
110+ TestStatus = UNIT_TEST_ERROR_TEST_FAILED ;
111+ UT_ASSERT_STATUS_EQUAL (Status , TestStatus );
108112 return UNIT_TEST_ERROR_TEST_FAILED ;
109113 }
110114
@@ -116,8 +120,10 @@ CheckExcludedRegions (
116120 TestStatus = UNIT_TEST_PASSED ;
117121
118122 while (Current != NULL ) {
119- Found = FALSE;
120- EfiMemNext = EfiMemoryMap ;
123+ Found = FALSE;
124+ FoundInMemoryMap = FALSE;
125+ FoundMemoryType = 0 ;
126+ EfiMemNext = EfiMemoryMap ;
121127
122128 UT_LOG_INFO ("Checking RMR region: Base=0x%lX, Length=0x%lX\n" , Current -> BaseAddress , Current -> Length );
123129 DEBUG ((DEBUG_INFO , "%a: Checking RMR region: Base=0x%lX, Length=0x%lX\n" , __func__ , Current -> BaseAddress , Current -> Length ));
@@ -127,6 +133,9 @@ CheckExcludedRegions (
127133 if ((EfiMemNext -> PhysicalStart <= Current -> BaseAddress ) &&
128134 ((EfiMemNext -> PhysicalStart + (EFI_PAGE_SIZE * EfiMemNext -> NumberOfPages )) >= (Current -> BaseAddress + Current -> Length )))
129135 {
136+ FoundInMemoryMap = TRUE;
137+ FoundMemoryType = EfiMemNext -> Type ;
138+
130139 UT_LOG_INFO (
131140 "Found encompassing memory range: Base=0x%lX, Length=0x%lX, Type=%d\n" ,
132141 EfiMemNext -> PhysicalStart ,
@@ -142,22 +151,9 @@ CheckExcludedRegions (
142151 EfiMemNext -> Type
143152 ));
144153
145- // Verify memory range is marked as reserved
146- if (EfiMemNext -> Type == EfiReservedMemoryType ) {
147- UT_LOG_INFO (
148- "RMR between 0x%lX and 0x%lX found with reserved memory type %d\n" ,
149- Current -> BaseAddress ,
150- Current -> BaseAddress + Current -> Length ,
151- EfiMemNext -> Type
152- );
153- DEBUG ((
154- DEBUG_INFO ,
155- "%a: RMR between 0x%lX and 0x%lX found with reserved memory type %d\n" ,
156- __func__ ,
157- Current -> BaseAddress ,
158- Current -> BaseAddress + Current -> Length ,
159- EfiMemNext -> Type
160- ));
154+ if ((EfiMemNext -> Type == EfiReservedMemoryType ) ||
155+ (EfiMemNext -> Type == EfiRuntimeServicesData ))
156+ {
161157 Found = TRUE;
162158 }
163159
@@ -168,28 +164,51 @@ CheckExcludedRegions (
168164 EfiMemNext = NEXT_MEMORY_DESCRIPTOR (EfiMemNext , EfiDescriptorSize );
169165 }
170166
167+ //
168+ // Report whether the RMR region was located in the UEFI memory map,
169+ // and if found, the memory type (even if it is not reserved).
170+ //
171+ if (!FoundInMemoryMap ) {
172+ UT_LOG_INFO (
173+ "RMR region Base=0x%lX, Length=0x%lX was NOT found in the UEFI memory map\n" ,
174+ Current -> BaseAddress ,
175+ Current -> Length
176+ );
177+ DEBUG ((
178+ DEBUG_INFO ,
179+ "%a: RMR region Base=0x%lX, Length=0x%lX was NOT found in the UEFI memory map\n" ,
180+ __func__ ,
181+ Current -> BaseAddress ,
182+ Current -> Length
183+ ));
184+ TestStatus = UNIT_TEST_ERROR_TEST_FAILED ;
185+ }
186+
171187 if (!Found ) {
172188 UT_LOG_ERROR (
173- "RMR between 0x%lX and 0x%lX NOT found with reserved memory type! \n" ,
189+ "RMR between 0x%lX and 0x%lX NOT found with an acceptable memory type (Reserved or RuntimeServicesData)! Memory type found: %d \n" ,
174190 Current -> BaseAddress ,
175- Current -> BaseAddress + Current -> Length
191+ Current -> BaseAddress + Current -> Length ,
192+ FoundMemoryType
176193 );
177194 DEBUG ((
178195 DEBUG_ERROR ,
179- "%a: RMR between 0x%lX and 0x%lX NOT found with reserved memory type! \n" ,
196+ "%a: RMR between 0x%lX and 0x%lX NOT found with an acceptable memory type (Reserved or RuntimeServicesData)! Memory type found: %d \n" ,
180197 __func__ ,
181198 Current -> BaseAddress ,
182- Current -> BaseAddress + Current -> Length
199+ Current -> BaseAddress + Current -> Length ,
200+ FoundMemoryType
183201 ));
184202 TestStatus = UNIT_TEST_ERROR_TEST_FAILED ;
185203 }
186204
187205 Current = Current -> Next ;
188206 }
189207
190- UT_LOG_INFO ("%a: Result=%d\n" , __func__ , TestStatus );
191- DEBUG ((DEBUG_INFO , "%a: Result=%d\n" , __func__ , TestStatus ));
208+ UT_LOG_INFO ("%a: Result=%d (%a) \n" , __func__ , TestStatus , ( TestStatus == UNIT_TEST_PASSED ) ? "PASSED" : "FAILED" );
209+ DEBUG ((DEBUG_INFO , "%a: Result=%d (%a) \n" , __func__ , TestStatus , ( TestStatus == UNIT_TEST_PASSED ) ? "PASSED" : "FAILED" ));
192210
211+ UT_ASSERT_STATUS_EQUAL (TestStatus , UNIT_TEST_PASSED );
193212 return TestStatus ;
194213} // CheckExcludedRegions()
195214
@@ -225,6 +244,8 @@ CheckIOMMUEnabled (
225244 UINT64 StrTabBase ;
226245 UINT64 StrTabBaseAddr ;
227246 UINT32 GError ;
247+ UINT32 GbpaValue ;
248+ UINT32 AbortBit ;
228249 UNIT_TEST_STATUS TestStatus ;
229250
230251 //
@@ -253,6 +274,7 @@ CheckIOMMUEnabled (
253274
254275 //
255276 // Step 4: For each SMMU, check:
277+ // - SMMU GBPA Set (GBPA.ABORT == 1), or:
256278 // - SMMU Enable bit (SMMUEN) in CR0 register
257279 // - Command Queue Enable bit (CMDQEN) in CR0 register
258280 // - Event Queue Enable bit (EVTQEN) in CR0 register
@@ -277,9 +299,41 @@ CheckIOMMUEnabled (
277299 UT_LOG_INFO ("SMMUEN bit: %d\n" , SmmuEnBit );
278300 DEBUG ((DEBUG_INFO , "%a: SMMUEN bit: %d\n" , __func__ , SmmuEnBit ));
279301 if (SmmuEnBit == 0 ) {
280- UT_LOG_ERROR ("SMMUEN bit is disabled for SMMUv3 at base address 0x%lX\n" , SmmuBaseAddresses [Iterator ]);
281- DEBUG ((DEBUG_ERROR , "%a: SMMUEN bit is disabled for SMMUv3 at base address 0x%lX\n" , __func__ , SmmuBaseAddresses [Iterator ]));
302+ //
303+ // SMMU translation is not enabled. The SMMU is still DMA-safe if it is
304+ // configured for global abort (GBPA.ABORT == 1).
305+ //
306+ GbpaValue = MmioRead32 ((UINTN )(SmmuBaseAddresses [Iterator ] + SMMU_GBPA ));
307+ AbortBit = GbpaValue & SMMU_GBPA_ABORT ;
308+ UT_LOG_INFO ("GBPA Register Value: 0x%X, ABORT bit: %d\n" , GbpaValue , AbortBit ? 1 : 0 );
309+ DEBUG ((DEBUG_INFO , "%a: GBPA Register Value: 0x%X, ABORT bit: %d\n" , __func__ , GbpaValue , AbortBit ? 1 : 0 ));
310+
311+ if (AbortBit != 0 ) {
312+ //
313+ // Global abort is set: all DMA is aborted, so this SMMU is DMA-safe.
314+ // Skip the remaining translation-related checks for this SMMU.
315+ //
316+ UT_LOG_INFO ("SMMUEN is disabled but global abort (GBPA.ABORT) is set for SMMUv3 at base address 0x%lX. SMMU is DMA-safe.\n" , SmmuBaseAddresses [Iterator ]);
317+ DEBUG ((DEBUG_INFO , "%a: SMMUEN is disabled but global abort (GBPA.ABORT) is set for SMMUv3 at base address 0x%lX. SMMU is DMA-safe.\n" , __func__ , SmmuBaseAddresses [Iterator ]));
318+ continue ;
319+ }
320+
321+ //
322+ // SMMU is in global bypass (not abort) and not enabled. This is permitted
323+ // only if the SMMU has a Reserved Memory Range (RMR) associated with it in
324+ // the IORT, since the RMR describes memory that is expected to bypass
325+ // translation.
326+ //
327+ if (SmmuHasAssociatedRmr (IortTable , SmmuBaseAddresses [Iterator ])) {
328+ UT_LOG_INFO ("SMMUEN is disabled and SMMU is in global bypass, but an RMR is associated with SMMUv3 at base address 0x%lX. This is permitted.\n" , SmmuBaseAddresses [Iterator ]);
329+ DEBUG ((DEBUG_INFO , "%a: SMMUEN is disabled and SMMU is in global bypass, but an RMR is associated with SMMUv3 at base address 0x%lX. This is permitted.\n" , __func__ , SmmuBaseAddresses [Iterator ]));
330+ continue ;
331+ }
332+
333+ UT_LOG_ERROR ("SMMUEN bit is disabled, global abort is not set, and no RMR is associated for SMMUv3 at base address 0x%lX\n" , SmmuBaseAddresses [Iterator ]);
334+ DEBUG ((DEBUG_ERROR , "%a: SMMUEN bit is disabled, global abort is not set, and no RMR is associated for SMMUv3 at base address 0x%lX\n" , __func__ , SmmuBaseAddresses [Iterator ]));
282335 TestStatus = UNIT_TEST_ERROR_TEST_FAILED ;
336+ continue ;
283337 }
284338
285339 //
@@ -337,8 +391,9 @@ CheckIOMMUEnabled (
337391 }
338392 }
339393
340- UT_LOG_INFO ("%a: Result=%d\n" , __func__ , TestStatus );
341- DEBUG ((DEBUG_INFO , "%a: Result=%d\n" , __func__ , TestStatus ));
394+ UT_LOG_INFO ("%a: Result=%d (%a) \n" , __func__ , TestStatus , ( TestStatus == UNIT_TEST_PASSED ) ? "PASSED" : "FAILED" );
395+ DEBUG ((DEBUG_INFO , "%a: Result=%d (%a) \n" , __func__ , TestStatus , ( TestStatus == UNIT_TEST_PASSED ) ? "PASSED" : "FAILED" ));
342396
397+ UT_ASSERT_STATUS_EQUAL (TestStatus , UNIT_TEST_PASSED );
343398 return TestStatus ;
344399} // CheckIOMMUEnabled()
0 commit comments