[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251125175753.1428857-2-prsampat@amd.com>
Date: Tue, 25 Nov 2025 11:57:50 -0600
From: "Pratik R. Sampat" <prsampat@....com>
To: <linux-mm@...ck.org>, <linux-coco@...ts.linux.dev>,
<linux-efi@...r.kernel.org>, <x86@...nel.org>, <linux-kernel@...r.kernel.org>
CC: <tglx@...utronix.de>, <mingo@...hat.com>, <bp@...en8.de>,
<dave.hansen@...ux.intel.com>, <kas@...nel.org>, <ardb@...nel.org>,
<akpm@...ux-foundation.org>, <david@...hat.com>, <osalvador@...e.de>,
<thomas.lendacky@....com>, <michael.roth@....com>, <prsampat@....com>
Subject: [RFC PATCH 1/4] efi/libstub: Decouple memory bitmap from the unaccepted table
Memory hotplug in secure environments requires the unaccepted memory
bitmap to grow as new memory is added. Currently, the bitmap is
implemented as a flexible array member at the end of struct
efi_unaccepted_memory, which is reserved by memblock at boot and cannot
be resized without reallocating the entire structure.
Replace the flexible array member with a pointer. This allows the bitmap
to be allocated and managed independently from the unaccepted memory
table, enabling dynamic growth to support memory hotplug.
Signed-off-by: Pratik R. Sampat <prsampat@....com>
---
arch/x86/boot/compressed/efi.h | 2 +-
arch/x86/include/asm/unaccepted_memory.h | 9 +++++++++
.../firmware/efi/libstub/unaccepted_memory.c | 11 ++++++++++-
drivers/firmware/efi/unaccepted_memory.c | 19 ++++++++++++++-----
include/linux/efi.h | 2 +-
5 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/arch/x86/boot/compressed/efi.h b/arch/x86/boot/compressed/efi.h
index b22300970f97..4f7027f33def 100644
--- a/arch/x86/boot/compressed/efi.h
+++ b/arch/x86/boot/compressed/efi.h
@@ -102,7 +102,7 @@ struct efi_unaccepted_memory {
u32 unit_size;
u64 phys_base;
u64 size;
- unsigned long bitmap[];
+ unsigned long *bitmap;
};
static inline int efi_guidcmp (efi_guid_t left, efi_guid_t right)
diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
index f5937e9866ac..5da80e68d718 100644
--- a/arch/x86/include/asm/unaccepted_memory.h
+++ b/arch/x86/include/asm/unaccepted_memory.h
@@ -24,4 +24,13 @@ static inline struct efi_unaccepted_memory *efi_get_unaccepted_table(void)
return NULL;
return __va(efi.unaccepted);
}
+
+static inline unsigned long *efi_get_unaccepted_bitmap(void)
+{
+ struct efi_unaccepted_memory *unaccepted = efi_get_unaccepted_table();
+
+ if (!unaccepted)
+ return NULL;
+ return __va(unaccepted->bitmap);
+}
#endif
diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
index 757dbe734a47..c1370fc14555 100644
--- a/drivers/firmware/efi/libstub/unaccepted_memory.c
+++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
@@ -63,13 +63,22 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE);
status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
- sizeof(*unaccepted_table) + bitmap_size,
+ sizeof(*unaccepted_table),
(void **)&unaccepted_table);
if (status != EFI_SUCCESS) {
efi_err("Failed to allocate unaccepted memory config table\n");
return status;
}
+ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ bitmap_size,
+ (void **)&unaccepted_table->bitmap);
+ if (status != EFI_SUCCESS) {
+ efi_bs_call(free_pool, unaccepted_table);
+ efi_err("Failed to allocate unaccepted memory bitmap\n");
+ return status;
+ }
+
unaccepted_table->version = 1;
unaccepted_table->unit_size = EFI_UNACCEPTED_UNIT_SIZE;
unaccepted_table->phys_base = unaccepted_start;
diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
index c2c067eff634..4479aad258f8 100644
--- a/drivers/firmware/efi/unaccepted_memory.c
+++ b/drivers/firmware/efi/unaccepted_memory.c
@@ -36,7 +36,7 @@ void accept_memory(phys_addr_t start, unsigned long size)
unsigned long range_start, range_end;
struct accept_range range, *entry;
phys_addr_t end = start + size;
- unsigned long flags;
+ unsigned long flags, *bitmap;
u64 unit_size;
unaccepted = efi_get_unaccepted_table();
@@ -124,8 +124,12 @@ void accept_memory(phys_addr_t start, unsigned long size)
list_add(&range.list, &accepting_list);
range_start = range.start;
- for_each_set_bitrange_from(range_start, range_end, unaccepted->bitmap,
- range.end) {
+
+ bitmap = efi_get_unaccepted_bitmap();
+ if (!bitmap)
+ return;
+
+ for_each_set_bitrange_from(range_start, range_end, bitmap, range.end) {
unsigned long phys_start, phys_end;
unsigned long len = range_end - range_start;
@@ -147,7 +151,7 @@ void accept_memory(phys_addr_t start, unsigned long size)
arch_accept_memory(phys_start, phys_end);
spin_lock(&unaccepted_memory_lock);
- bitmap_clear(unaccepted->bitmap, range_start, len);
+ bitmap_clear(bitmap, range_start, len);
}
list_del(&range.list);
@@ -197,7 +201,12 @@ bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size)
spin_lock_irqsave(&unaccepted_memory_lock, flags);
while (start < end) {
- if (test_bit(start / unit_size, unaccepted->bitmap)) {
+ unsigned long *bitmap = efi_get_unaccepted_bitmap();
+
+ if (!bitmap)
+ break;
+
+ if (test_bit(start / unit_size, bitmap)) {
ret = true;
break;
}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a98cc39e7aaa..a74b393c54d8 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -545,7 +545,7 @@ struct efi_unaccepted_memory {
u32 unit_size;
u64 phys_base;
u64 size;
- unsigned long bitmap[];
+ unsigned long *bitmap;
};
/*
--
2.51.1
Powered by blists - more mailing lists