public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Taylor Beebe" <t@taylorbeebe.com>
To: devel@edk2.groups.io
Cc: Taylor Beebe <tabeebe@microsoft.com>,
	Leif Lindholm <quic_llindhol@quicinc.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Taylor Beebe <t@taylorbeebe.com>
Subject: [PATCH 2/4] ArmPkg: Update GetMemoryRegion() to Handle No mapping
Date: Thu, 29 Jun 2023 09:17:56 -0700	[thread overview]
Message-ID: <20032a1dfef2d6b83e40821532038f186420d318.1687989723.git.t@taylorbeebe.com> (raw)
In-Reply-To: <cover.1687989723.git.t@taylorbeebe.com>

From: Taylor Beebe <tabeebe@microsoft.com>

This patch updates the GetMemoryRegion() function to handle the case
where there is no mapping for the requested address.

The original logic for the ARM would hit an ASSERT after
GetMemoryRegionPage() returned EFI_SUCCESS but did not update The
RegionLength parameter.

The original logic for the AARCH64 would never initialize the
RegionLength parameter to zero and return EFI_SUCCESS after
traversing an unknown number of pages.

To fix this, the logic for both architecture has updated to
return EFI_NO_MAPPING if the BaseAddress being checked is unmapped.

Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>

Signed-off-by: Taylor Beebe <t@taylorbeebe.com>
---
 ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c | 30 +++++++------
 ArmPkg/Drivers/CpuDxe/Arm/Mmu.c     | 65 +++++++++++++++++++----------
 2 files changed, 60 insertions(+), 35 deletions(-)

diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c b/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c
index 1d02e41e18d8..0d3bc2809682 100644
--- a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c
+++ b/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c
@@ -380,10 +380,10 @@ GetMemoryRegionRec (
                RegionAttributes
                );
 
-    // In case of 'Success', it means the end of the block region has been found into the upper
-    // level translation table
-    if (!EFI_ERROR (Status)) {
-      return EFI_SUCCESS;
+    // EFI_SUCCESS:     The end of the end of the region was found.
+    // EFI_NO_MAPPING:  The translation entry associated with BaseAddress is invalid.
+    if (Status != EFI_NOT_FOUND) {
+      return Status;
     }
 
     // Now we processed the table move to the next entry
@@ -395,12 +395,13 @@ GetMemoryRegionRec (
     *RegionLength     = 0;
     *RegionAttributes = *BlockEntry & TT_ATTRIBUTES_MASK;
   } else {
-    // We have an 'Invalid' entry
-    return EFI_UNSUPPORTED;
+    return EFI_NO_MAPPING;
   }
 
   while (BlockEntry <= LastBlockEntry) {
-    if ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes) {
+    if (((*BlockEntry & TT_TYPE_MASK) == BlockEntryType) &&
+        ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes))
+    {
       *RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL (TableLevel);
     } else {
       // In case we have found the end of the region we return success
@@ -412,7 +413,7 @@ GetMemoryRegionRec (
 
   // If we have reached the end of the TranslationTable and we have not found the end of the region then
   // we return EFI_NOT_FOUND.
-  // The caller will continue to look for the memory region at its level
+  // The caller will continue to look for the memory region at its level.
   return EFI_NOT_FOUND;
 }
 
@@ -433,6 +434,11 @@ GetMemoryRegion (
 
   TranslationTable = ArmGetTTBR0BaseAddress ();
 
+  // Initialize the output parameters. These paramaters are only valid if the
+  // result is EFI_SUCCESS.
+  *RegionLength     = 0;
+  *RegionAttributes = 0;
+
   T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
   // Get the Table info from T0SZ
   GetRootTranslationTableInfo (T0SZ, &TableLevel, &EntryCount);
@@ -447,10 +453,10 @@ GetMemoryRegion (
              );
 
   // If the region continues up to the end of the root table then GetMemoryRegionRec()
-  // will return EFI_NOT_FOUND
-  if (Status == EFI_NOT_FOUND) {
+  // will return EFI_NOT_FOUND. Check if the region length was updated.
+  if ((Status == EFI_NOT_FOUND) && (*RegionLength > 0)) {
     return EFI_SUCCESS;
-  } else {
-    return Status;
   }
+
+  return Status;
 }
diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
index afd6aab60204..268c0bf3f9ae 100644
--- a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
+++ b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
@@ -427,17 +427,20 @@ EfiAttributeToArmAttribute (
 EFI_STATUS
 GetMemoryRegionPage (
   IN     UINT32  *PageTable,
-  IN OUT UINTN   *BaseAddress,
-  OUT    UINTN   *RegionLength,
-  OUT    UINTN   *RegionAttributes
+  IN     UINTN   *BaseAddress,
+  IN     UINTN   *RegionAttributes,
+  OUT    UINTN   *RegionLength
   )
 {
-  UINT32  PageAttributes;
-  UINT32  TableIndex;
-  UINT32  PageDescriptor;
+  UINT32      PageAttributes;
+  UINT32      TableIndex;
+  UINT32      PageDescriptor;
+  EFI_STATUS  Status;
 
   // Convert the section attributes into page attributes
   PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes);
+  Status         = EFI_NOT_FOUND;
+  *RegionLength  = 0;
 
   // Calculate index into first level translation table for start of modification
   TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK)  >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
@@ -449,23 +452,24 @@ GetMemoryRegionPage (
     PageDescriptor = PageTable[TableIndex];
 
     if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {
-      // Case: End of the boundary of the region
-      return EFI_SUCCESS;
+      Status = (*RegionLength > 0) ? EFI_SUCCESS : EFI_NO_MAPPING;
+      break;
     } else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
-      if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) == PageAttributes) {
-        *RegionLength = *RegionLength + TT_DESCRIPTOR_PAGE_SIZE;
-      } else {
-        // Case: End of the boundary of the region
-        return EFI_SUCCESS;
+      if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) != PageAttributes) {
+        Status = EFI_SUCCESS;
+        break;
       }
+
+      *RegionLength += TT_DESCRIPTOR_PAGE_SIZE;
     } else {
-      // We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.
+      // Large pages are unsupported.
+      Status = EFI_UNSUPPORTED;
       ASSERT (0);
-      return EFI_SUCCESS;
+      break;
     }
   }
 
-  return EFI_NOT_FOUND;
+  return Status;
 }
 
 EFI_STATUS
@@ -482,6 +486,7 @@ GetMemoryRegion (
   UINT32                      SectionDescriptor;
   ARM_FIRST_LEVEL_DESCRIPTOR  *FirstLevelTable;
   UINT32                      *PageTable;
+  UINTN                       Length;
 
   // Initialize the arguments
   *RegionLength = 0;
@@ -491,7 +496,11 @@ GetMemoryRegion (
 
   // Calculate index into first level translation table for start of modification
   TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
-  ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
+
+  if (TableIndex >= TRANSLATION_TABLE_SECTION_COUNT) {
+    ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
+    return EFI_INVALID_PARAMETER;
+  }
 
   // Get the section at the given index
   SectionDescriptor = FirstLevelTable[TableIndex];
@@ -524,6 +533,8 @@ GetMemoryRegion (
                         TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);
   }
 
+  Status = EFI_NOT_FOUND;
+
   for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {
     // Get the section at the given index
     SectionDescriptor = FirstLevelTable[TableIndex];
@@ -532,15 +543,18 @@ GetMemoryRegion (
     if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (SectionDescriptor)) {
       // Extract the page table location from the descriptor
       PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
+      Length    = 0;
 
       // Scan the page table to find the end of the region.
-      Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);
-      ASSERT (*RegionLength > 0);
+      Status         = GetMemoryRegionPage (PageTable, BaseAddress, RegionAttributes, &Length);
+      *RegionLength += Length;
 
-      // If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop
-      if (Status == EFI_SUCCESS) {
-        break;
+      // Status == EFI_NOT_FOUND implies we have not reached the end of the region.
+      if ((Status == EFI_NOT_FOUND) && (Length > 0)) {
+        continue;
       }
+
+      break;
     } else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
                ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
     {
@@ -556,5 +570,10 @@ GetMemoryRegion (
     }
   }
 
-  return EFI_SUCCESS;
+  // Check if the region length was updated.
+  if (*RegionLength > 0) {
+    Status = EFI_SUCCESS;
+  }
+
+  return Status;
 }
-- 
2.41.0.windows.1


  parent reply	other threads:[~2023-06-29 16:20 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-29 16:17 [PATCH 0/4] Update CpuDxe MMU Logic to Improve Consistency Taylor Beebe
2023-06-29 16:17 ` [PATCH 1/4] ArmPkg: Apply Uncrustify to Non-Compliant Files Taylor Beebe
2023-06-29 16:17 ` Taylor Beebe [this message]
2023-06-29 16:17 ` [PATCH 3/4] ArmPkg: Fix Unsafe ASSERTs in MMU Logic Taylor Beebe
2023-06-29 16:17 ` [PATCH 4/4] ArmPkg: Add Function Headers to " Taylor Beebe
2023-07-03 14:17 ` [PATCH 0/4] Update CpuDxe MMU Logic to Improve Consistency Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20032a1dfef2d6b83e40821532038f186420d318.1687989723.git.t@taylorbeebe.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox