efi: Add support for EFI_MEMORY_HOT_PLUGGABLE
Subsystems (2)
cover efi: Add support for EFI_MEMORY_HOT_PLUGGABLE
From: Ard Biesheuvel <[email protected]>
Adopt the EFI_MEMORY_HOT_PLUGGABLE memory attribute definition from UEFI 2.11 and test for it where appropriate.
Ard Biesheuvel (2):
efi: Avoid cold plugged memory for placing the kernel
efi: Use BIT_ULL() constants for memory attributes
drivers/firmware/efi/efi.c | 6 ++-- drivers/firmware/efi/libstub/randomalloc.c | 3 ++ drivers/firmware/efi/libstub/relocate.c | 3 ++ include/linux/efi.h | 31 ++++++++++---------- 4 files changed, 26 insertions(+), 17 deletions(-)
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH 1/2 efi: Avoid cold plugged memory for placing the kernel
From: Ard Biesheuvel <[email protected]>
UEFI 2.11 introduced EFI_MEMORY_HOT_PLUGGABLE to annotate system memory regions that are 'cold plugged' at boot, i.e., hot pluggable memory that is available from early boot, and described as system RAM by the firmware.
Existing loaders and EFI applications running in the boot context will happily use this memory for allocating data structures that cannot be freed or moved at runtime, and this prevents the memory from being unplugged. Going forward, the new EFI_MEMORY_HOT_PLUGGABLE attribute should be tested, and memory annotated as such should be avoided for such allocations.
In the EFI stub, there are a couple of occurrences where, instead of the high-level AllocatePages() UEFI boot service, a low-level code sequence is used that traverses the EFI memory map and carves out the requested number of pages from a free region. This is needed, e.g., for allocating as low as possible, or for allocating pages at random.
While AllocatePages() should presumably avoid special purpose memory and cold plugged regions, this manual approach needs to incorporate this logic itself, in order to prevent the kernel itself from ending up in a hot unpluggable region, preventing it from being unplugged.
So add the EFI_MEMORY_HOTPLUGGABLE macro definition, and check for it where appropriate.
--- drivers/firmware/efi/efi.c | 6 ++++-- drivers/firmware/efi/libstub/randomalloc.c | 3 +++ drivers/firmware/efi/libstub/relocate.c | 3 +++ include/linux/efi.h | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)
drivers/firmware/efi/efi.c +4 -2
@@ -934,13 +934,15 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,EFI_MEMORY_WB |EFI_MEMORY_UCE |EFI_MEMORY_RO |EFI_MEMORY_WP |EFI_MEMORY_RP |EFI_MEMORY_XP |EFI_MEMORY_NV |EFI_MEMORY_SP |EFI_MEMORY_CPU_CRYPTO | - EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE)) +EFI_MEMORY_MORE_RELIABLE |EFI_MEMORY_HOT_PLUGGABLE | + EFI_MEMORY_RUNTIME)) snprintf(pos, size, "|attr=0x%016llx]", (unsigned long long)attr); else snprintf(pos, size, -"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]" , +"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]" , attr &EFI_MEMORY_RUNTIME ?"RUN" :"" , + attr &EFI_MEMORY_HOT_PLUGGABLE ?"HP" :"" , attr &EFI_MEMORY_MORE_RELIABLE ?"MR" :"" , attr &EFI_MEMORY_CPU_CRYPTO ?"CC" :"" , attr & EFI_MEMORY_SP ? "SP" : "",
drivers/firmware/efi/libstub/randomalloc.c +3 -0
@@ -25,6 +25,9 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,if (md->type !=EFI_CONVENTIONAL_MEMORY )return 0 ; +if (md->attribute &EFI_MEMORY_HOT_PLUGGABLE ) +return 0 ; +if (efi_soft_reserve_enabled () && (md->attribute &EFI_MEMORY_SP ))return 0 ;
drivers/firmware/efi/libstub/relocate.c +3 -0
@@ -53,6 +53,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,if (desc->type !=EFI_CONVENTIONAL_MEMORY )continue ; +if (desc->attribute &EFI_MEMORY_HOT_PLUGGABLE ) +continue ; +if (efi_soft_reserve_enabled () && (desc->attribute &EFI_MEMORY_SP ))continue ;
include/linux/efi.h +1 -0
@@ -128,6 +128,7 @@ typedef struct {#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL)/* read-only */ #define EFI_MEMORY_SP ((u64)0x0000000000040000ULL)/* soft reserved */ #define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL)/* supports encryption */ +#define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20)/* supports unplugging at runtime */ #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL)/* range requires runtime mapping */ #define EFI_MEMORY_DESCRIPTOR_VERSION 1
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH 2/2 efi: Use BIT_ULL() constants for memory attributes
In reply to Ard BiesheuvelFrom: Ard Biesheuvel <[email protected]>
For legibility, use the existing BIT_ULL() to generate the u64 type EFI memory attribute macros.
--- include/linux/efi.h | 30 ++++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-)
include/linux/efi.h +15 -15
@@ -114,22 +114,22 @@ typedef struct {#define EFI_MAX_MEMORY_TYPE 16/* Attribute values: */ -#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL)/* uncached */ -#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL)/* write-coalescing */ -#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL)/* write-through */ -#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL)/* write-back */ -#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL)/* uncached, exported */ -#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL)/* write-protect */ -#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL)/* read-protect */ -#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL)/* execute-protect */ -#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL)/* non-volatile */ -#define EFI_MEMORY_MORE_RELIABLE \ - ((u64)0x0000000000010000ULL)/* higher reliability */ -#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL)/* read-only */ -#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL)/* soft reserved */ -#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL)/* supports encryption */ +#define EFI_MEMORY_UC BIT_ULL(0)/* uncached */ +#define EFI_MEMORY_WC BIT_ULL(1)/* write-coalescing */ +#define EFI_MEMORY_WT BIT_ULL(2)/* write-through */ +#define EFI_MEMORY_WB BIT_ULL(3)/* write-back */ +#define EFI_MEMORY_UCE BIT_ULL(4)/* uncached, exported */ +#define EFI_MEMORY_WP BIT_ULL(12)/* write-protect */ +#define EFI_MEMORY_RP BIT_ULL(13)/* read-protect */ +#define EFI_MEMORY_XP BIT_ULL(14)/* execute-protect */ +#define EFI_MEMORY_NV BIT_ULL(15)/* non-volatile */ +#define EFI_MEMORY_MORE_RELIABLE BIT_ULL(16)/* higher reliability */ +#define EFI_MEMORY_RO BIT_ULL(17)/* read-only */ +#define EFI_MEMORY_SP BIT_ULL(18)/* soft reserved */ +#define EFI_MEMORY_CPU_CRYPTO BIT_ULL(19)/* supports encryption */ #define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20)/* supports unplugging at runtime */ -#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL)/* range requires runtime mapping */ +#define EFI_MEMORY_RUNTIME BIT_ULL(63)/* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1#define EFI_PAGE_SHIFT 12
Signature · 1 line
2.48.1.362.g079036d154-goog