diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2018-09-21 09:32:46 -0700 |
---|---|---|
committer | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2018-09-26 12:03:57 +0200 |
commit | a23d3bb05ccbd815c79293d2207fedede0b3515d (patch) | |
tree | e6516189fd4911feabcc212e2639402f2864bb38 /drivers/firmware | |
parent | b844470f22061e8cd646cb355e85d2f518b2c913 (diff) |
efi: add API to reserve memory persistently across kexec reboot
Add kernel plumbing to reserve memory regions persistently on a EFI
system by adding entries to the MEMRESERVE linked list.
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/efi.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 688132ac8a0a..249eb70691b0 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -962,6 +962,38 @@ bool efi_is_table_address(unsigned long phys_addr) return false; } +static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); + +int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) +{ + struct linux_efi_memreserve *rsv, *parent; + + if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR) + return -ENODEV; + + rsv = kmalloc(sizeof(*rsv), GFP_KERNEL); + if (!rsv) + return -ENOMEM; + + parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB); + if (!parent) { + kfree(rsv); + return -ENOMEM; + } + + rsv->base = addr; + rsv->size = size; + + spin_lock(&efi_mem_reserve_persistent_lock); + rsv->next = parent->next; + parent->next = __pa(rsv); + spin_unlock(&efi_mem_reserve_persistent_lock); + + memunmap(parent); + + return 0; +} + #ifdef CONFIG_KEXEC static int update_efi_random_seed(struct notifier_block *nb, unsigned long code, void *unused) |