TianoCore EDK2 master
Loading...
Searching...
No Matches
Mmu.c
1/*++
2
3Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
4Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
5Portions copyright (c) 2013-2021, Arm Limited. All rights reserved.<BR>
6Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
7
8SPDX-License-Identifier: BSD-2-Clause-Patent
9
10
11--*/
12
14#include "CpuDxe.h"
15
29SectionToGcdAttributes (
30 IN UINT32 SectionAttributes,
31 OUT UINT64 *GcdAttributes
32 )
33{
34 *GcdAttributes = 0;
35
36 // determine cacheability attributes
37 switch (SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {
38 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:
39 *GcdAttributes |= EFI_MEMORY_UC;
40 break;
41 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:
42 *GcdAttributes |= EFI_MEMORY_UC;
43 break;
44 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
45 *GcdAttributes |= EFI_MEMORY_WT;
46 break;
47 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
48 *GcdAttributes |= EFI_MEMORY_WB;
49 break;
50 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:
51 *GcdAttributes |= EFI_MEMORY_WC;
52 break;
53 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:
54 *GcdAttributes |= EFI_MEMORY_WB;
55 break;
56 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:
57 *GcdAttributes |= EFI_MEMORY_UC;
58 break;
59 default:
60 return EFI_UNSUPPORTED;
61 }
62
63 // determine protection attributes
64 switch (SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {
65 case TT_DESCRIPTOR_SECTION_AP_NO_RW:
66 case TT_DESCRIPTOR_SECTION_AP_RW_RW:
67 // normal read/write access, do not add additional attributes
68 break;
69
70 // read only cases map to write-protect
71 case TT_DESCRIPTOR_SECTION_AP_NO_RO:
72 case TT_DESCRIPTOR_SECTION_AP_RO_RO:
73 *GcdAttributes |= EFI_MEMORY_RO;
74 break;
75 }
76
77 // now process eXectue Never attribute
78 if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0) {
79 *GcdAttributes |= EFI_MEMORY_XP;
80 }
81
82 if ((SectionAttributes & TT_DESCRIPTOR_SECTION_AF) == 0) {
83 *GcdAttributes |= EFI_MEMORY_RP;
84 }
85
86 return EFI_SUCCESS;
87}
88
99UINT64
100RegionAttributeToGcdAttribute (
101 IN UINTN PageAttributes
102 )
103{
104 UINT64 Result;
105
106 SectionToGcdAttributes (PageAttributes, &Result);
107 return Result;
108}
109
120STATIC
122PageToGcdAttributes (
123 IN UINT32 PageAttributes,
124 OUT UINT64 *GcdAttributes
125 )
126{
127 *GcdAttributes = 0;
128
129 // determine cacheability attributes
130 switch (PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {
131 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:
132 *GcdAttributes |= EFI_MEMORY_UC;
133 break;
134 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:
135 *GcdAttributes |= EFI_MEMORY_UC;
136 break;
137 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
138 *GcdAttributes |= EFI_MEMORY_WT;
139 break;
140 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
141 *GcdAttributes |= EFI_MEMORY_WB;
142 break;
143 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:
144 *GcdAttributes |= EFI_MEMORY_WC;
145 break;
146 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:
147 *GcdAttributes |= EFI_MEMORY_WB;
148 break;
149 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:
150 *GcdAttributes |= EFI_MEMORY_UC;
151 break;
152 default:
153 return EFI_UNSUPPORTED;
154 }
155
156 // determine protection attributes
157 switch (PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {
158 case TT_DESCRIPTOR_PAGE_AP_NO_RW:
159 case TT_DESCRIPTOR_PAGE_AP_RW_RW:
160 // normal read/write access, do not add additional attributes
161 break;
162
163 // read only cases map to write-protect
164 case TT_DESCRIPTOR_PAGE_AP_NO_RO:
165 case TT_DESCRIPTOR_PAGE_AP_RO_RO:
166 *GcdAttributes |= EFI_MEMORY_RO;
167 break;
168 }
169
170 // now process eXectue Never attribute
171 if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0) {
172 *GcdAttributes |= EFI_MEMORY_XP;
173 }
174
175 if ((PageAttributes & TT_DESCRIPTOR_PAGE_AF) == 0) {
176 *GcdAttributes |= EFI_MEMORY_RP;
177 }
178
179 return EFI_SUCCESS;
180}
181
200SyncCacheConfigPage (
201 IN UINT32 SectionIndex,
202 IN UINT32 FirstLevelDescriptor,
203 IN UINTN NumberOfDescriptors,
204 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
205 IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase,
206 IN OUT UINT64 *NextRegionLength,
207 IN OUT UINT32 *NextSectionAttributes
208 )
209{
210 EFI_STATUS Status;
211 UINT32 i;
212 volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable;
213 UINT32 NextPageAttributes;
214 UINT32 PageAttributes;
215 UINT32 BaseAddress;
216 UINT64 GcdAttributes;
217
218 // Get the Base Address from FirstLevelDescriptor;
219 BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
220
221 // Convert SectionAttributes into PageAttributes
222 NextPageAttributes =
223 TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (*NextSectionAttributes) |
224 TT_DESCRIPTOR_CONVERT_TO_PAGE_AF (*NextSectionAttributes) |
225 TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (*NextSectionAttributes);
226
227 // obtain page table base
228 SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
229
230 for (i = 0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {
231 if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
232 // extract attributes (cacheability and permissions)
233 PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK | TT_DESCRIPTOR_PAGE_AF);
234
235 if (NextPageAttributes == 0) {
236 // start on a new region
237 *NextRegionLength = 0;
238 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
239 NextPageAttributes = PageAttributes;
240 } else if (PageAttributes != NextPageAttributes) {
241 // Convert Section Attributes into GCD Attributes
242 Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
243 if (EFI_ERROR (Status)) {
244 ASSERT_EFI_ERROR (Status);
245 GcdAttributes = 0;
246 }
247
248 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
249 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
250
251 // start on a new region
252 *NextRegionLength = 0;
253 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
254 NextPageAttributes = PageAttributes;
255 }
256 } else if (NextPageAttributes != 0) {
257 // Convert Page Attributes into GCD Attributes
258 Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
259 if (EFI_ERROR (Status)) {
260 ASSERT_EFI_ERROR (Status);
261 GcdAttributes = 0;
262 }
263
264 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
265 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
266
267 *NextRegionLength = 0;
268 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
269 NextPageAttributes = 0;
270 }
271
272 *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;
273 }
274
275 // Convert back PageAttributes into SectionAttributes
276 *NextSectionAttributes =
277 TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (NextPageAttributes) |
278 TT_DESCRIPTOR_CONVERT_TO_SECTION_AF (NextPageAttributes) |
279 TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (NextPageAttributes);
280
281 return EFI_SUCCESS;
282}
283
293SyncCacheConfig (
294 IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
295 )
296{
297 EFI_STATUS Status;
298 UINT32 i;
299 EFI_PHYSICAL_ADDRESS NextRegionBase;
300 UINT64 NextRegionLength;
301 UINT32 NextSectionAttributes;
302 UINT32 SectionAttributes;
303 UINT64 GcdAttributes;
304 volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
305 UINTN NumberOfDescriptors;
306 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
307
308 DEBUG ((DEBUG_PAGE, "SyncCacheConfig()\n"));
309
310 // This code assumes MMU is enabled and filed with section translations
311 ASSERT (ArmMmuEnabled ());
312
313 //
314 // Get the memory space map from GCD
315 //
316 MemorySpaceMap = NULL;
317 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
318
319 if (EFI_ERROR (Status)) {
320 DEBUG ((DEBUG_ERROR, "SyncCacheConfig - GetMemorySpaceMap() failed! Status: %r\n", Status));
321 ASSERT_EFI_ERROR (Status);
322 return Status;
323 }
324
325 // The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs
326 // to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a
327 // GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were
328 // a client) to update its copy of the attributes. This is bad architecture and should be replaced
329 // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
330
331 // obtain page table base
332 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());
333
334 // Get the first region
335 NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK | TT_DESCRIPTOR_SECTION_AF);
336
337 // iterate through each 1MB descriptor
338 NextRegionBase = NextRegionLength = 0;
339 for (i = 0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {
340 if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {
341 // extract attributes (cacheability and permissions)
342 SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK | TT_DESCRIPTOR_SECTION_AF);
343
344 if (NextSectionAttributes == 0) {
345 // start on a new region
346 NextRegionLength = 0;
347 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
348 NextSectionAttributes = SectionAttributes;
349 } else if (SectionAttributes != NextSectionAttributes) {
350 // Convert Section Attributes into GCD Attributes
351 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
352
353 if (EFI_ERROR (Status)) {
354 DEBUG ((DEBUG_ERROR, "SyncCacheConfig - SectionToGcdAttributes() failed! Status: %r\n", Status));
355 ASSERT_EFI_ERROR (Status);
356 GcdAttributes = 0;
357 }
358
359 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
360 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
361
362 // start on a new region
363 NextRegionLength = 0;
364 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
365 NextSectionAttributes = SectionAttributes;
366 }
367
368 NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
369 } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (FirstLevelTable[i])) {
370 // In this case any bits set in the 'NextSectionAttributes' are garbage and were set from
371 // bits that are actually part of the pagetable address. We clear it out to zero so that
372 // the SyncCacheConfigPage will use the page attributes instead of trying to convert the
373 // section attributes into page attributes
374 NextSectionAttributes = 0;
375 Status = SyncCacheConfigPage (
376 i,
377 FirstLevelTable[i],
378 NumberOfDescriptors,
379 MemorySpaceMap,
380 &NextRegionBase,
381 &NextRegionLength,
382 &NextSectionAttributes
383 );
384 ASSERT_EFI_ERROR (Status);
385 } else {
386 // We do not support yet 16MB sections
387 ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);
388
389 // start on a new region
390 if (NextSectionAttributes != 0) {
391 // Convert Section Attributes into GCD Attributes
392 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
393 if (EFI_ERROR (Status)) {
394 DEBUG ((DEBUG_ERROR, "SyncCacheConfig - SectionToGcdAttributes() failed! Status: %r\n", Status));
395 ASSERT_EFI_ERROR (Status);
396 GcdAttributes = 0;
397 }
398
399 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
400 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
401
402 NextRegionLength = 0;
403 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
404 NextSectionAttributes = 0;
405 }
406
407 NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
408 }
409 } // section entry loop
410
411 if (NextSectionAttributes != 0) {
412 // Convert Section Attributes into GCD Attributes
413 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
414 if (EFI_ERROR (Status)) {
415 DEBUG ((DEBUG_ERROR, "SyncCacheConfig - SectionToGcdAttributes() failed! Status: %r\n", Status));
416 ASSERT_EFI_ERROR (Status);
417 GcdAttributes = 0;
418 }
419
420 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
421 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
422 }
423
424 FreePool (MemorySpaceMap);
425
426 return EFI_SUCCESS;
427}
428
436UINT64
437EfiAttributeToArmAttribute (
438 IN UINT64 EfiAttributes
439 )
440{
441 UINT64 ArmAttributes;
442
443 switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
444 case EFI_MEMORY_UC:
445 // Map to strongly ordered
446 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
447 break;
448
449 case EFI_MEMORY_WC:
450 // Map to normal non-cacheable
451 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
452 break;
453
454 case EFI_MEMORY_WT:
455 // Write through with no-allocate
456 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
457 break;
458
459 case EFI_MEMORY_WB:
460 // Write back (with allocate)
461 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
462 break;
463
464 case EFI_MEMORY_UCE:
465 default:
466 ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
467 break;
468 }
469
470 // Determine protection attributes
471 if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
472 ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
473 } else {
474 ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
475 }
476
477 // Determine eXecute Never attribute
478 if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
479 ArmAttributes |= TT_DESCRIPTOR_SECTION_XN_MASK;
480 }
481
482 if ((EfiAttributes & EFI_MEMORY_RP) == 0) {
483 ArmAttributes |= TT_DESCRIPTOR_SECTION_AF;
484 }
485
486 return ArmAttributes;
487}
488
504STATIC
506GetMemoryRegionPage (
507 IN UINT32 *PageTable,
508 IN UINTN *BaseAddress,
509 IN UINTN *RegionAttributes,
510 OUT UINTN *RegionLength
511 )
512{
513 UINT32 PageAttributes;
514 UINT32 TableIndex;
515 UINT32 PageDescriptor;
516 EFI_STATUS Status;
517
518 // Convert the section attributes into page attributes
519 PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes);
520 Status = EFI_NOT_FOUND;
521 *RegionLength = 0;
522
523 // Calculate index into first level translation table for start of modification
524 TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
525 ASSERT (TableIndex < TRANSLATION_TABLE_PAGE_COUNT);
526
527 // Go through the page table to find the end of the section
528 for ( ; TableIndex < TRANSLATION_TABLE_PAGE_COUNT; TableIndex++) {
529 // Get the section at the given index
530 PageDescriptor = PageTable[TableIndex];
531
532 if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {
533 Status = (*RegionLength > 0) ? EFI_SUCCESS : EFI_NO_MAPPING;
534 break;
535 } else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
536 if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) != PageAttributes) {
537 Status = EFI_SUCCESS;
538 break;
539 }
540
541 *RegionLength += TT_DESCRIPTOR_PAGE_SIZE;
542 } else {
543 // Large pages are unsupported.
544 Status = EFI_UNSUPPORTED;
545 ASSERT (0);
546 break;
547 }
548 }
549
550 return Status;
551}
552
572GetMemoryRegion (
573 IN OUT UINTN *BaseAddress,
574 OUT UINTN *RegionLength,
575 OUT UINTN *RegionAttributes
576 )
577{
578 EFI_STATUS Status;
579 UINT32 TableIndex;
580 UINT32 PageAttributes;
581 UINT32 PageTableIndex;
582 UINT32 SectionDescriptor;
583 ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
584 UINT32 *PageTable;
585 UINTN Length;
586
587 // Initialize the arguments
588 *RegionLength = 0;
589
590 // Obtain page table base
591 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
592
593 // Calculate index into first level translation table for start of modification
594 TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
595
596 if (TableIndex >= TRANSLATION_TABLE_SECTION_COUNT) {
597 ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
598 return EFI_INVALID_PARAMETER;
599 }
600
601 // Get the section at the given index
602 SectionDescriptor = FirstLevelTable[TableIndex];
603 if (!SectionDescriptor) {
604 return EFI_NOT_FOUND;
605 }
606
607 // If 'BaseAddress' belongs to the section then round it to the section boundary
608 if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
609 ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
610 {
611 *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;
612 *RegionAttributes = SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK;
613 } else {
614 // Otherwise, we round it to the page boundary
615 *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK;
616
617 // Get the attribute at the page table level (Level 2)
618 PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
619
620 // Calculate index into first level translation table for start of modification
621 PageTableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
622 ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
623
624 PageAttributes = PageTable[PageTableIndex] & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK;
625 *RegionAttributes = TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (PageAttributes) |
626 TT_DESCRIPTOR_CONVERT_TO_SECTION_S (PageAttributes) |
627 TT_DESCRIPTOR_CONVERT_TO_SECTION_XN (PageAttributes) |
628 TT_DESCRIPTOR_CONVERT_TO_SECTION_AF (PageAttributes) |
629 TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);
630 }
631
632 Status = EFI_NOT_FOUND;
633
634 for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {
635 // Get the section at the given index
636 SectionDescriptor = FirstLevelTable[TableIndex];
637
638 // If the entry is a level-2 page table then we scan it to find the end of the region
639 if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (SectionDescriptor)) {
640 // Extract the page table location from the descriptor
641 PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
642 Length = 0;
643
644 // Scan the page table to find the end of the region.
645 Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionAttributes, &Length);
646 *RegionLength += Length;
647
648 // Status == EFI_NOT_FOUND implies we have not reached the end of the region.
649 if ((Status == EFI_NOT_FOUND) && (Length > 0)) {
650 continue;
651 }
652
653 break;
654 } else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
655 ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
656 {
657 if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK) != *RegionAttributes) {
658 // If the attributes of the section differ from the one targeted then we exit the loop
659 break;
660 } else {
661 *RegionLength = *RegionLength + TT_DESCRIPTOR_SECTION_SIZE;
662 }
663 } else {
664 // If we are on an invalid section then it means it is the end of our section.
665 break;
666 }
667 }
668
669 // Check if the region length was updated.
670 if (*RegionLength > 0) {
671 Status = EFI_SUCCESS;
672 }
673
674 return Status;
675}
UINT64 UINTN
EFI_STATUS SetGcdMemorySpaceAttributes(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: CpuMmuCommon.c:79
EFI_DXE_SERVICES * gDS
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112