lkml.org 
[lkml]   [2025]   [Nov]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH 1/4] efi/libstub: Decouple memory bitmap from the unaccepted table
Date
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@amd.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

\
 
 \ /
  Last update: 2025-11-25 18:58    [from the cache]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and my Meterkast|Read the blog