aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
authorDave Young <dyoung@redhat.com>2013-12-20 05:02:19 -0500
committerMatt Fleming <matt.fleming@intel.com>2013-12-29 08:09:05 -0500
commit1fec0533693cd74f2d1a46edd29449cfee429df0 (patch)
treea8061175bda3cda7a3a651a2925b9fb16a6c9912 /arch/x86/platform
parent926172d46038d7610b6b8d84e40db727cefb482d (diff)
x86/efi: Pass necessary EFI data for kexec via setup_data
Add a new setup_data type SETUP_EFI for kexec use. Passing the saved fw_vendor, runtime, config tables and EFI runtime mappings. When entering virtual mode, directly mapping the EFI runtime regions which we passed in previously. And skip the step to call SetVirtualAddressMap(). Specially for HP z420 workstation we need save the smbios physical address. The kernel boot sequence proceeds in the following order. Step 2 requires efi.smbios to be the physical address. However, I found that on HP z420 EFI system table has a virtual address of SMBIOS in step 1. Hence, we need set it back to the physical address with the smbios in efi_setup_data. (When it is still the physical address, it simply sets the same value.) 1. efi_init() - Set efi.smbios from EFI system table 2. dmi_scan_machine() - Temporary map efi.smbios to access SMBIOS table 3. efi_enter_virtual_mode() - Map EFI ranges Tested on ovmf+qemu, lenovo thinkpad, a dell laptop and an HP z420 workstation. 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/x86/platform')
-rw-r--r--arch/x86/platform/efi/efi.c158
-rw-r--r--arch/x86/platform/efi/efi_32.c1
-rw-r--r--arch/x86/platform/efi/efi_64.c6
3 files changed, 140 insertions, 25 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 74fe7a719508..9965ff403c6e 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -78,6 +78,8 @@ static __initdata efi_config_table_type_t arch_tables[] = {
78 78
79static void *efi_runtime_map; 79static void *efi_runtime_map;
80static int nr_efi_runtime_map; 80static int nr_efi_runtime_map;
81u64 efi_setup; /* efi setup_data physical address */
82u32 efi_data_len; /* efi setup_data payload length */
81 83
82/* 84/*
83 * Returns 1 if 'facility' is enabled, 0 otherwise. 85 * Returns 1 if 'facility' is enabled, 0 otherwise.
@@ -115,7 +117,6 @@ static int __init setup_storage_paranoia(char *arg)
115} 117}
116early_param("efi_no_storage_paranoia", setup_storage_paranoia); 118early_param("efi_no_storage_paranoia", setup_storage_paranoia);
117 119
118
119static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) 120static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
120{ 121{
121 unsigned long flags; 122 unsigned long flags;
@@ -494,18 +495,27 @@ static int __init efi_systab_init(void *phys)
494{ 495{
495 if (efi_enabled(EFI_64BIT)) { 496 if (efi_enabled(EFI_64BIT)) {
496 efi_system_table_64_t *systab64; 497 efi_system_table_64_t *systab64;
498 struct efi_setup_data *data = NULL;
497 u64 tmp = 0; 499 u64 tmp = 0;
498 500
501 if (efi_setup) {
502 data = early_memremap(efi_setup, sizeof(*data));
503 if (!data)
504 return -ENOMEM;
505 }
499 systab64 = early_ioremap((unsigned long)phys, 506 systab64 = early_ioremap((unsigned long)phys,
500 sizeof(*systab64)); 507 sizeof(*systab64));
501 if (systab64 == NULL) { 508 if (systab64 == NULL) {
502 pr_err("Couldn't map the system table!\n"); 509 pr_err("Couldn't map the system table!\n");
510 if (data)
511 early_iounmap(data, sizeof(*data));
503 return -ENOMEM; 512 return -ENOMEM;
504 } 513 }
505 514
506 efi_systab.hdr = systab64->hdr; 515 efi_systab.hdr = systab64->hdr;
507 efi_systab.fw_vendor = systab64->fw_vendor; 516 efi_systab.fw_vendor = data ? (unsigned long)data->fw_vendor :
508 tmp |= systab64->fw_vendor; 517 systab64->fw_vendor;
518 tmp |= data ? data->fw_vendor : systab64->fw_vendor;
509 efi_systab.fw_revision = systab64->fw_revision; 519 efi_systab.fw_revision = systab64->fw_revision;
510 efi_systab.con_in_handle = systab64->con_in_handle; 520 efi_systab.con_in_handle = systab64->con_in_handle;
511 tmp |= systab64->con_in_handle; 521 tmp |= systab64->con_in_handle;
@@ -519,15 +529,20 @@ static int __init efi_systab_init(void *phys)
519 tmp |= systab64->stderr_handle; 529 tmp |= systab64->stderr_handle;
520 efi_systab.stderr = systab64->stderr; 530 efi_systab.stderr = systab64->stderr;
521 tmp |= systab64->stderr; 531 tmp |= systab64->stderr;
522 efi_systab.runtime = (void *)(unsigned long)systab64->runtime; 532 efi_systab.runtime = data ?
523 tmp |= systab64->runtime; 533 (void *)(unsigned long)data->runtime :
534 (void *)(unsigned long)systab64->runtime;
535 tmp |= data ? data->runtime : systab64->runtime;
524 efi_systab.boottime = (void *)(unsigned long)systab64->boottime; 536 efi_systab.boottime = (void *)(unsigned long)systab64->boottime;
525 tmp |= systab64->boottime; 537 tmp |= systab64->boottime;
526 efi_systab.nr_tables = systab64->nr_tables; 538 efi_systab.nr_tables = systab64->nr_tables;
527 efi_systab.tables = systab64->tables; 539 efi_systab.tables = data ? (unsigned long)data->tables :
528 tmp |= systab64->tables; 540 systab64->tables;
541 tmp |= data ? data->tables : systab64->tables;
529 542
530 early_iounmap(systab64, sizeof(*systab64)); 543 early_iounmap(systab64, sizeof(*systab64));
544 if (data)
545 early_iounmap(data, sizeof(*data));
531#ifdef CONFIG_X86_32 546#ifdef CONFIG_X86_32
532 if (tmp >> 32) { 547 if (tmp >> 32) {
533 pr_err("EFI data located above 4GB, disabling EFI.\n"); 548 pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -631,6 +646,71 @@ static int __init efi_memmap_init(void)
631 return 0; 646 return 0;
632} 647}
633 648
649/*
650 * A number of config table entries get remapped to virtual addresses
651 * after entering EFI virtual mode. However, the kexec kernel requires
652 * their physical addresses therefore we pass them via setup_data and
653 * correct those entries to their respective physical addresses here.
654 *
655 * Currently only handles smbios which is necessary for some firmware
656 * implementation.
657 */
658static int __init efi_reuse_config(u64 tables, int nr_tables)
659{
660 int i, sz, ret = 0;
661 void *p, *tablep;
662 struct efi_setup_data *data;
663
664 if (!efi_setup)
665 return 0;
666
667 if (!efi_enabled(EFI_64BIT))
668 return 0;
669
670 data = early_memremap(efi_setup, sizeof(*data));
671 if (!data) {
672 ret = -ENOMEM;
673 goto out;
674 }
675
676 if (!data->smbios)
677 goto out_memremap;
678
679 sz = sizeof(efi_config_table_64_t);
680
681 p = tablep = early_memremap(tables, nr_tables * sz);
682 if (!p) {
683 pr_err("Could not map Configuration table!\n");
684 ret = -ENOMEM;
685 goto out_memremap;
686 }
687
688 for (i = 0; i < efi.systab->nr_tables; i++) {
689 efi_guid_t guid;
690
691 guid = ((efi_config_table_64_t *)p)->guid;
692
693 if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
694 ((efi_config_table_64_t *)p)->table = data->smbios;
695 p += sz;
696 }
697 early_iounmap(tablep, nr_tables * sz);
698
699out_memremap:
700 early_iounmap(data, sizeof(*data));
701out:
702 return ret;
703}
704
705static void get_nr_runtime_map(void)
706{
707 if (!efi_setup)
708 return;
709
710 nr_efi_runtime_map = (efi_data_len - sizeof(struct efi_setup_data)) /
711 sizeof(efi_memory_desc_t);
712}
713
634void __init efi_init(void) 714void __init efi_init(void)
635{ 715{
636 efi_char16_t *c16; 716 efi_char16_t *c16;
@@ -638,6 +718,7 @@ void __init efi_init(void)
638 int i = 0; 718 int i = 0;
639 void *tmp; 719 void *tmp;
640 720
721 get_nr_runtime_map();
641#ifdef CONFIG_X86_32 722#ifdef CONFIG_X86_32
642 if (boot_params.efi_info.efi_systab_hi || 723 if (boot_params.efi_info.efi_systab_hi ||
643 boot_params.efi_info.efi_memmap_hi) { 724 boot_params.efi_info.efi_memmap_hi) {
@@ -676,6 +757,9 @@ void __init efi_init(void)
676 efi.systab->hdr.revision >> 16, 757 efi.systab->hdr.revision >> 16,
677 efi.systab->hdr.revision & 0xffff, vendor); 758 efi.systab->hdr.revision & 0xffff, vendor);
678 759
760 if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables))
761 return;
762
679 if (efi_config_init(arch_tables)) 763 if (efi_config_init(arch_tables))
680 return; 764 return;
681 765
@@ -861,6 +945,23 @@ out:
861} 945}
862 946
863/* 947/*
948 * Map efi regions which were passed via setup_data. The virt_addr is a fixed
949 * addr which was used in first kernel of a kexec boot.
950 */
951static void __init efi_map_regions_fixed(void)
952{
953 void *p;
954 efi_memory_desc_t *md;
955
956 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
957 md = p;
958 efi_map_region_fixed(md); /* FIXME: add error handling */
959 get_systab_virt_addr(md);
960 }
961
962}
963
964/*
864 * Map efi memory ranges for runtime serivce and update new_memmap with virtual 965 * Map efi memory ranges for runtime serivce and update new_memmap with virtual
865 * addresses. 966 * addresses.
866 */ 967 */
@@ -914,6 +1015,10 @@ out:
914 * so that we're in a different address space when calling a runtime 1015 * so that we're in a different address space when calling a runtime
915 * function. For function arguments passing we do copy the PGDs of the 1016 * function. For function arguments passing we do copy the PGDs of the
916 * kernel page table into ->trampoline_pgd prior to each call. 1017 * kernel page table into ->trampoline_pgd prior to each call.
1018 *
1019 * Specially for kexec boot, efi runtime maps in previous kernel should
1020 * be passed in via setup_data. In that case runtime ranges will be mapped
1021 * to the same virtual addresses as the first kernel.
917 */ 1022 */
918void __init efi_enter_virtual_mode(void) 1023void __init efi_enter_virtual_mode(void)
919{ 1024{
@@ -932,12 +1037,15 @@ void __init efi_enter_virtual_mode(void)
932 return; 1037 return;
933 } 1038 }
934 1039
935 efi_merge_regions(); 1040 if (efi_setup) {
936 1041 efi_map_regions_fixed();
937 new_memmap = efi_map_regions(&count); 1042 } else {
938 if (!new_memmap) { 1043 efi_merge_regions();
939 pr_err("Error reallocating memory, EFI runtime non-functional!\n"); 1044 new_memmap = efi_map_regions(&count);
940 return; 1045 if (!new_memmap) {
1046 pr_err("Error reallocating memory, EFI runtime non-functional!\n");
1047 return;
1048 }
941 } 1049 }
942 1050
943 err = save_runtime_map(); 1051 err = save_runtime_map();
@@ -949,16 +1057,18 @@ void __init efi_enter_virtual_mode(void)
949 efi_setup_page_tables(); 1057 efi_setup_page_tables();
950 efi_sync_low_kernel_mappings(); 1058 efi_sync_low_kernel_mappings();
951 1059
952 status = phys_efi_set_virtual_address_map( 1060 if (!efi_setup) {
953 memmap.desc_size * count, 1061 status = phys_efi_set_virtual_address_map(
954 memmap.desc_size, 1062 memmap.desc_size * count,
955 memmap.desc_version, 1063 memmap.desc_size,
956 (efi_memory_desc_t *)__pa(new_memmap)); 1064 memmap.desc_version,
957 1065 (efi_memory_desc_t *)__pa(new_memmap));
958 if (status != EFI_SUCCESS) { 1066
959 pr_alert("Unable to switch EFI into virtual mode " 1067 if (status != EFI_SUCCESS) {
960 "(status=%lx)!\n", status); 1068 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
961 panic("EFI call to SetVirtualAddressMap() failed!"); 1069 status);
1070 panic("EFI call to SetVirtualAddressMap() failed!");
1071 }
962 } 1072 }
963 1073
964 /* 1074 /*
@@ -993,8 +1103,6 @@ void __init efi_enter_virtual_mode(void)
993 EFI_VARIABLE_BOOTSERVICE_ACCESS | 1103 EFI_VARIABLE_BOOTSERVICE_ACCESS |
994 EFI_VARIABLE_RUNTIME_ACCESS, 1104 EFI_VARIABLE_RUNTIME_ACCESS,
995 0, NULL); 1105 0, NULL);
996
997 return;
998} 1106}
999 1107
1000/* 1108/*
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index 7b3ec6ed99af..249b183cf417 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -48,6 +48,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
48} 48}
49 49
50void __init efi_map_region_fixed(efi_memory_desc_t *md) {} 50void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
51void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
51 52
52void efi_call_phys_prelog(void) 53void efi_call_phys_prelog(void)
53{ 54{
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index ff08cb19630b..324b65103851 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -228,3 +228,9 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
228 228
229 return (void __iomem *)__va(phys_addr); 229 return (void __iomem *)__va(phys_addr);
230} 230}
231
232void __init parse_efi_setup(u64 phys_addr, u32 data_len)
233{
234 efi_setup = phys_addr + sizeof(struct setup_data);
235 efi_data_len = data_len - sizeof(struct setup_data);
236}