aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorMatt Fleming <matt@codeblueprint.co.uk>2016-02-29 16:22:52 -0500
committerMatt Fleming <matt@codeblueprint.co.uk>2016-09-09 11:08:34 -0400
commit816e76129ed5fadd28e526c43397c79775194b5c (patch)
treede3ec000aa5bb1fdbc6d652fbd4db9da0e82ebda /drivers/firmware
parentc45f4da33a297f85435f8dccb26a24852ea01bb9 (diff)
efi: Allow drivers to reserve boot services forever
Today, it is not possible for drivers to reserve EFI boot services for access after efi_free_boot_services() has been called on x86. For ARM/arm64 it can be done simply by calling memblock_reserve(). Having this ability for all three architectures is desirable for a couple of reasons, 1) It saves drivers copying data out of those regions 2) kexec reboot can now make use of things like ESRT Instead of using the standard memblock_reserve() which is insufficient to reserve the region on x86 (see efi_reserve_boot_services()), a new API is introduced in this patch; efi_mem_reserve(). efi.memmap now always represents which EFI memory regions are available. On x86 the EFI boot services regions that have not been reserved via efi_mem_reserve() will be removed from efi.memmap during efi_free_boot_services(). This has implications for kexec, since it is not possible for a newly kexec'd kernel to access the same boot services regions that the initial boot kernel had access to unless they are reserved by every kexec kernel in the chain. Tested-by: Dave Young <dyoung@redhat.com> [kexec/kdump] Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> [arm] Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Leif Lindholm <leif.lindholm@linaro.org> Cc: Peter Jones <pjones@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/efi.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index d4886fd50c16..dfe07316cae5 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -27,6 +27,7 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <linux/ucs2_string.h> 29#include <linux/ucs2_string.h>
30#include <linux/memblock.h>
30 31
31#include <asm/early_ioremap.h> 32#include <asm/early_ioremap.h>
32 33
@@ -396,6 +397,35 @@ u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
396 return end; 397 return end;
397} 398}
398 399
400void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
401
402/**
403 * efi_mem_reserve - Reserve an EFI memory region
404 * @addr: Physical address to reserve
405 * @size: Size of reservation
406 *
407 * Mark a region as reserved from general kernel allocation and
408 * prevent it being released by efi_free_boot_services().
409 *
410 * This function should be called drivers once they've parsed EFI
411 * configuration tables to figure out where their data lives, e.g.
412 * efi_esrt_init().
413 */
414void __init efi_mem_reserve(phys_addr_t addr, u64 size)
415{
416 if (!memblock_is_region_reserved(addr, size))
417 memblock_reserve(addr, size);
418
419 /*
420 * Some architectures (x86) reserve all boot services ranges
421 * until efi_free_boot_services() because of buggy firmware
422 * implementations. This means the above memblock_reserve() is
423 * superfluous on x86 and instead what it needs to do is
424 * ensure the @start, @size is not freed.
425 */
426 efi_arch_mem_reserve(addr, size);
427}
428
399static __initdata efi_config_table_type_t common_tables[] = { 429static __initdata efi_config_table_type_t common_tables[] = {
400 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20}, 430 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
401 {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, 431 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},