diff options
author | Dave Young <dyoung@redhat.com> | 2013-12-20 18:02:18 +0800 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2013-12-21 15:29:36 +0000 |
commit | 926172d46038d7610b6b8d84e40db727cefb482d (patch) | |
tree | 8963aaa9fccd0a4ee0d59717b4de8e8cdfebbe62 /arch | |
parent | a0998eb15afeffbf52a2c2829318f67df9ac57b8 (diff) |
efi: Export EFI runtime memory mapping to sysfs
kexec kernel will need exactly same mapping for EFI runtime memory
ranges. Thus here export the runtime ranges mapping to sysfs,
kexec-tools will assemble them and pass to 2nd kernel via setup_data.
Introducing a new directory /sys/firmware/efi/runtime-map just like
/sys/firmware/memmap. Containing below attribute in each file of that
directory:
attribute num_pages phys_addr type virt_addr
Signed-off-by: Dave Young <dyoung@redhat.com>
Tested-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/platform/efi/efi.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 28591072fbb7..74fe7a719508 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -76,6 +76,9 @@ static __initdata efi_config_table_type_t arch_tables[] = { {NULL_GUID, NULL, NULL}, }; +static void *efi_runtime_map; +static int nr_efi_runtime_map; + /* * Returns 1 if 'facility' is enabled, 0 otherwise. */ @@ -824,6 +827,39 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) } } +static int __init save_runtime_map(void) +{ + efi_memory_desc_t *md; + void *tmp, *p, *q = NULL; + int count = 0; + + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + md = p; + + if (!(md->attribute & EFI_MEMORY_RUNTIME) || + (md->type == EFI_BOOT_SERVICES_CODE) || + (md->type == EFI_BOOT_SERVICES_DATA)) + continue; + tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL); + if (!tmp) + goto out; + q = tmp; + + memcpy(q + count * memmap.desc_size, md, memmap.desc_size); + count++; + } + + efi_runtime_map = q; + nr_efi_runtime_map = count; + efi_runtime_map_setup(efi_runtime_map, nr_efi_runtime_map, + boot_params.efi_info.efi_memdesc_size); + + return 0; +out: + kfree(q); + return -ENOMEM; +} + /* * Map efi memory ranges for runtime serivce and update new_memmap with virtual * addresses. @@ -849,7 +885,7 @@ static void * __init efi_map_regions(int *count) tmp = krealloc(new_memmap, (*count + 1) * memmap.desc_size, GFP_KERNEL); if (!tmp) - goto out_krealloc; + goto out; new_memmap = tmp; memcpy(new_memmap + (*count * memmap.desc_size), md, memmap.desc_size); @@ -857,7 +893,7 @@ static void * __init efi_map_regions(int *count) } return new_memmap; -out_krealloc: +out: kfree(new_memmap); return NULL; } @@ -883,7 +919,7 @@ void __init efi_enter_virtual_mode(void) { efi_status_t status; void *new_memmap = NULL; - int count = 0; + int err, count = 0; efi.systab = NULL; @@ -904,6 +940,10 @@ void __init efi_enter_virtual_mode(void) return; } + err = save_runtime_map(); + if (err) + pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n"); + BUG_ON(!efi.systab); efi_setup_page_tables(); |