aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2014-01-18 06:48:18 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-03-04 11:17:19 -0500
commitfabb37c736f9f688fe3eec98550a5c032a07cfaa (patch)
treef13555682673134e7dff1809412be1e72cdb2597 /arch/x86/platform
parentb7b898ae0c0a82489511a1ce1b35f26215e6beb5 (diff)
x86/efi: Split efi_enter_virtual_mode
... into a kexec flavor for better code readability and simplicity. The original one was getting ugly with ifdeffery. Signed-off-by: Borislav Petkov <bp@suse.de> 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.c148
1 files changed, 98 insertions, 50 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 576bb126593a..6f0a46730826 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -879,8 +879,9 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md)
879 } 879 }
880} 880}
881 881
882static int __init save_runtime_map(void) 882static void __init save_runtime_map(void)
883{ 883{
884#ifdef CONFIG_KEXEC
884 efi_memory_desc_t *md; 885 efi_memory_desc_t *md;
885 void *tmp, *p, *q = NULL; 886 void *tmp, *p, *q = NULL;
886 int count = 0; 887 int count = 0;
@@ -902,28 +903,12 @@ static int __init save_runtime_map(void)
902 } 903 }
903 904
904 efi_runtime_map_setup(q, count, memmap.desc_size); 905 efi_runtime_map_setup(q, count, memmap.desc_size);
906 return;
905 907
906 return 0;
907out: 908out:
908 kfree(q); 909 kfree(q);
909 return -ENOMEM; 910 pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
910} 911#endif
911
912/*
913 * Map efi regions which were passed via setup_data. The virt_addr is a fixed
914 * addr which was used in first kernel of a kexec boot.
915 */
916static void __init efi_map_regions_fixed(void)
917{
918 void *p;
919 efi_memory_desc_t *md;
920
921 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
922 md = p;
923 efi_map_region_fixed(md); /* FIXME: add error handling */
924 get_systab_virt_addr(md);
925 }
926
927} 912}
928 913
929static void *realloc_pages(void *old_memmap, int old_shift) 914static void *realloc_pages(void *old_memmap, int old_shift)
@@ -989,6 +974,72 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
989 return new_memmap; 974 return new_memmap;
990} 975}
991 976
977static void __init kexec_enter_virtual_mode(void)
978{
979#ifdef CONFIG_KEXEC
980 efi_memory_desc_t *md;
981 void *p;
982
983 efi.systab = NULL;
984
985 /*
986 * We don't do virtual mode, since we don't do runtime services, on
987 * non-native EFI
988 */
989 if (!efi_is_native()) {
990 efi_unmap_memmap();
991 return;
992 }
993
994 /*
995 * Map efi regions which were passed via setup_data. The virt_addr is a
996 * fixed addr which was used in first kernel of a kexec boot.
997 */
998 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
999 md = p;
1000 efi_map_region_fixed(md); /* FIXME: add error handling */
1001 get_systab_virt_addr(md);
1002 }
1003
1004 save_runtime_map();
1005
1006 BUG_ON(!efi.systab);
1007
1008 efi_sync_low_kernel_mappings();
1009
1010 /*
1011 * Now that EFI is in virtual mode, update the function
1012 * pointers in the runtime service table to the new virtual addresses.
1013 *
1014 * Call EFI services through wrapper functions.
1015 */
1016 efi.runtime_version = efi_systab.hdr.revision;
1017 efi.get_time = virt_efi_get_time;
1018 efi.set_time = virt_efi_set_time;
1019 efi.get_wakeup_time = virt_efi_get_wakeup_time;
1020 efi.set_wakeup_time = virt_efi_set_wakeup_time;
1021 efi.get_variable = virt_efi_get_variable;
1022 efi.get_next_variable = virt_efi_get_next_variable;
1023 efi.set_variable = virt_efi_set_variable;
1024 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
1025 efi.reset_system = virt_efi_reset_system;
1026 efi.set_virtual_address_map = NULL;
1027 efi.query_variable_info = virt_efi_query_variable_info;
1028 efi.update_capsule = virt_efi_update_capsule;
1029 efi.query_capsule_caps = virt_efi_query_capsule_caps;
1030
1031 if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
1032 runtime_code_page_mkexec();
1033
1034 /* clean DUMMY object */
1035 efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
1036 EFI_VARIABLE_NON_VOLATILE |
1037 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1038 EFI_VARIABLE_RUNTIME_ACCESS,
1039 0, NULL);
1040#endif
1041}
1042
992/* 1043/*
993 * This function will switch the EFI runtime services to virtual mode. 1044 * This function will switch the EFI runtime services to virtual mode.
994 * Essentially, we look through the EFI memmap and map every region that 1045 * Essentially, we look through the EFI memmap and map every region that
@@ -1008,11 +1059,12 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
1008 * 1059 *
1009 * Specially for kexec boot, efi runtime maps in previous kernel should 1060 * Specially for kexec boot, efi runtime maps in previous kernel should
1010 * be passed in via setup_data. In that case runtime ranges will be mapped 1061 * be passed in via setup_data. In that case runtime ranges will be mapped
1011 * to the same virtual addresses as the first kernel. 1062 * to the same virtual addresses as the first kernel, see
1063 * kexec_enter_virtual_mode().
1012 */ 1064 */
1013void __init efi_enter_virtual_mode(void) 1065static void __init __efi_enter_virtual_mode(void)
1014{ 1066{
1015 int err, count = 0, pg_shift = 0; 1067 int count = 0, pg_shift = 0;
1016 void *new_memmap = NULL; 1068 void *new_memmap = NULL;
1017 efi_status_t status; 1069 efi_status_t status;
1018 1070
@@ -1027,43 +1079,33 @@ void __init efi_enter_virtual_mode(void)
1027 return; 1079 return;
1028 } 1080 }
1029 1081
1030 if (efi_setup) { 1082 efi_merge_regions();
1031 efi_map_regions_fixed(); 1083 new_memmap = efi_map_regions(&count, &pg_shift);
1032 } else { 1084 if (!new_memmap) {
1033 efi_merge_regions(); 1085 pr_err("Error reallocating memory, EFI runtime non-functional!\n");
1034 new_memmap = efi_map_regions(&count, &pg_shift); 1086 return;
1035 if (!new_memmap) {
1036 pr_err("Error reallocating memory, EFI runtime non-functional!\n");
1037 return;
1038 }
1039
1040 err = save_runtime_map();
1041 if (err)
1042 pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
1043 } 1087 }
1044 1088
1089 save_runtime_map();
1090
1045 BUG_ON(!efi.systab); 1091 BUG_ON(!efi.systab);
1046 1092
1047 if (!efi_setup) { 1093 if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
1048 if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift)) 1094 return;
1049 return;
1050 }
1051 1095
1052 efi_sync_low_kernel_mappings(); 1096 efi_sync_low_kernel_mappings();
1053 efi_dump_pagetable(); 1097 efi_dump_pagetable();
1054 1098
1055 if (!efi_setup) { 1099 status = phys_efi_set_virtual_address_map(
1056 status = phys_efi_set_virtual_address_map(
1057 memmap.desc_size * count, 1100 memmap.desc_size * count,
1058 memmap.desc_size, 1101 memmap.desc_size,
1059 memmap.desc_version, 1102 memmap.desc_version,
1060 (efi_memory_desc_t *)__pa(new_memmap)); 1103 (efi_memory_desc_t *)__pa(new_memmap));
1061 1104
1062 if (status != EFI_SUCCESS) { 1105 if (status != EFI_SUCCESS) {
1063 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n", 1106 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
1064 status); 1107 status);
1065 panic("EFI call to SetVirtualAddressMap() failed!"); 1108 panic("EFI call to SetVirtualAddressMap() failed!");
1066 }
1067 } 1109 }
1068 1110
1069 /* 1111 /*
@@ -1089,7 +1131,6 @@ void __init efi_enter_virtual_mode(void)
1089 1131
1090 efi_runtime_mkexec(); 1132 efi_runtime_mkexec();
1091 1133
1092
1093 /* 1134 /*
1094 * We mapped the descriptor array into the EFI pagetable above but we're 1135 * We mapped the descriptor array into the EFI pagetable above but we're
1095 * not unmapping it here. Here's why: 1136 * not unmapping it here. Here's why:
@@ -1116,8 +1157,7 @@ void __init efi_enter_virtual_mode(void)
1116 * 1157 *
1117 * efi_cleanup_page_tables(__pa(new_memmap), 1 << pg_shift); 1158 * efi_cleanup_page_tables(__pa(new_memmap), 1 << pg_shift);
1118 */ 1159 */
1119 if (!efi_setup) 1160 free_pages((unsigned long)new_memmap, pg_shift);
1120 free_pages((unsigned long)new_memmap, pg_shift);
1121 1161
1122 /* clean DUMMY object */ 1162 /* clean DUMMY object */
1123 efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, 1163 efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
@@ -1127,6 +1167,14 @@ void __init efi_enter_virtual_mode(void)
1127 0, NULL); 1167 0, NULL);
1128} 1168}
1129 1169
1170void __init efi_enter_virtual_mode(void)
1171{
1172 if (efi_setup)
1173 kexec_enter_virtual_mode();
1174 else
1175 __efi_enter_virtual_mode();
1176}
1177
1130/* 1178/*
1131 * Convenience functions to obtain memory types and attributes 1179 * Convenience functions to obtain memory types and attributes
1132 */ 1180 */