Linux EFI development
 help / color / mirror / Atom feed
* [PATCH] efi/libstub: Do not accept parts of memory before ExitBootServices()
@ 2025-03-25  9:16 Ard Biesheuvel
  2025-03-25 12:36 ` Kirill A. Shutemov
  0 siblings, 1 reply; 12+ messages in thread
From: Ard Biesheuvel @ 2025-03-25  9:16 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-coco, Ard Biesheuvel, Tom Lendacky, Kirill A. Shutemov,
	Borislav Petkov, Dionna Amalie Glaze, Kevin Loughlin

From: Ard Biesheuvel <ardb@kernel.org>

Currently, setup_e820() in the x86 EFI stub records unaccepted memory in
the associated bitmap, which has a 2 MiB granularity. To avoid
ambiguities, any unaccepted region that is not aligned to 2 MiB will be
partially accepted upfront, so that all regions recorded into the bitmap
are aligned to the bitmap's granularity.

On SEV-SNP, this results in calls into the SEV support code before it is
initialized, and crucially, before ExitBootServices() is called, which
means that the firmware is still in charge at that point, and
initializing the SEV support code is not even permitted.

So instead, round the unaccepted regions outwards, so that all
unaccepted memory is recorded as such in the bitmap, along with possibly
some pages that have already been accepted. This is less efficient in
theory, but should rarely occur -and therefore not matter- in practice.

Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>,
Cc: Dionna Amalie Glaze <dionnaglaze@google.com>,
Cc: Kevin Loughlin <kevinloughlin@google.com>
Fixes: 745e3ed85f71 ("efi/libstub: Implement support for unaccepted memory")
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/libstub/unaccepted_memory.c | 75 ++++----------------
 1 file changed, 14 insertions(+), 61 deletions(-)

diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
index 757dbe734a47..8d783fda5ce3 100644
--- a/drivers/firmware/efi/libstub/unaccepted_memory.c
+++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
@@ -88,86 +88,39 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
 
 /*
  * The accepted memory bitmap only works at unit_size granularity.  Take
- * unaligned start/end addresses and either:
- *  1. Accepts the memory immediately and in its entirety
- *  2. Accepts unaligned parts, and marks *some* aligned part unaccepted
+ * unaligned start/end addresses and round them outwards, so that unaccepted
+ * memory is never misidentified as already accepted.
  *
  * The function will never reach the bitmap_set() with zero bits to set.
  */
 void process_unaccepted_memory(u64 start, u64 end)
 {
 	u64 unit_size = unaccepted_table->unit_size;
-	u64 unit_mask = unaccepted_table->unit_size - 1;
 	u64 bitmap_size = unaccepted_table->size;
 
-	/*
-	 * Ensure that at least one bit will be set in the bitmap by
-	 * immediately accepting all regions under 2*unit_size.  This is
-	 * imprecise and may immediately accept some areas that could
-	 * have been represented in the bitmap.  But, results in simpler
-	 * code below
-	 *
-	 * Consider case like this (assuming unit_size == 2MB):
-	 *
-	 * | 4k | 2044k |    2048k   |
-	 * ^ 0x0        ^ 2MB        ^ 4MB
-	 *
-	 * Only the first 4k has been accepted. The 0MB->2MB region can not be
-	 * represented in the bitmap. The 2MB->4MB region can be represented in
-	 * the bitmap. But, the 0MB->4MB region is <2*unit_size and will be
-	 * immediately accepted in its entirety.
-	 */
-	if (end - start < 2 * unit_size) {
-		arch_accept_memory(start, end);
-		return;
-	}
-
-	/*
-	 * No matter how the start and end are aligned, at least one unaccepted
-	 * unit_size area will remain to be marked in the bitmap.
-	 */
-
-	/* Immediately accept a <unit_size piece at the start: */
-	if (start & unit_mask) {
-		arch_accept_memory(start, round_up(start, unit_size));
-		start = round_up(start, unit_size);
-	}
-
-	/* Immediately accept a <unit_size piece at the end: */
-	if (end & unit_mask) {
-		arch_accept_memory(round_down(end, unit_size), end);
-		end = round_down(end, unit_size);
-	}
+	start = round_down(start, unit_size);
+	end   = round_up(end, unit_size);
 
 	/*
-	 * Accept part of the range that before phys_base and cannot be recorded
+	 * Ignore the range before phys_base that cannot be recorded
 	 * into the bitmap.
 	 */
-	if (start < unaccepted_table->phys_base) {
-		arch_accept_memory(start,
-				   min(unaccepted_table->phys_base, end));
+	if (start < unaccepted_table->phys_base)
 		start = unaccepted_table->phys_base;
-	}
-
-	/* Nothing to record */
-	if (end < unaccepted_table->phys_base)
-		return;
 
 	/* Translate to offsets from the beginning of the bitmap */
 	start -= unaccepted_table->phys_base;
 	end -= unaccepted_table->phys_base;
 
-	/* Accept memory that doesn't fit into bitmap */
-	if (end > bitmap_size * unit_size * BITS_PER_BYTE) {
-		unsigned long phys_start, phys_end;
-
-		phys_start = bitmap_size * unit_size * BITS_PER_BYTE +
-			     unaccepted_table->phys_base;
-		phys_end = end + unaccepted_table->phys_base;
+	/*
+	 * Disregard unaccepted memory that did not exist yet when the bitmap
+	 * was dimensioned and allocated. This shouldn't happen in practice.
+	 */
+	end = min(end, bitmap_size * unit_size * BITS_PER_BYTE);
 
-		arch_accept_memory(phys_start, phys_end);
-		end = bitmap_size * unit_size * BITS_PER_BYTE;
-	}
+	/* Nothing to record */
+	if (end <= start)
+		return;
 
 	/*
 	 * 'start' and 'end' are now both unit_size-aligned.
-- 
2.49.0.395.g12beb8f557-goog


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2025-04-02 18:32 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-25  9:16 [PATCH] efi/libstub: Do not accept parts of memory before ExitBootServices() Ard Biesheuvel
2025-03-25 12:36 ` Kirill A. Shutemov
2025-03-25 12:41   ` Ard Biesheuvel
2025-03-25 12:59     ` Kirill A. Shutemov
2025-03-25 13:09       ` Ard Biesheuvel
2025-03-25 13:44         ` Kirill A. Shutemov
2025-03-25 14:39           ` Ard Biesheuvel
2025-03-25 16:30             ` Tom Lendacky
2025-03-26  9:28               ` Ard Biesheuvel
2025-04-01 15:51                 ` Tom Lendacky
2025-04-01 18:45                   ` Ard Biesheuvel
2025-04-02 18:32                     ` Tom Lendacky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox