diff options
author | Borislav Petkov <bp@suse.de> | 2014-01-18 06:48:18 -0500 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2014-03-04 11:17:19 -0500 |
commit | fabb37c736f9f688fe3eec98550a5c032a07cfaa (patch) | |
tree | f13555682673134e7dff1809412be1e72cdb2597 /arch/x86/platform | |
parent | b7b898ae0c0a82489511a1ce1b35f26215e6beb5 (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.c | 148 |
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 | ||
882 | static int __init save_runtime_map(void) | 882 | static 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; | ||
907 | out: | 908 | out: |
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 | */ | ||
916 | static 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 | ||
929 | static void *realloc_pages(void *old_memmap, int old_shift) | 914 | static 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 | ||
977 | static 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 | */ |
1013 | void __init efi_enter_virtual_mode(void) | 1065 | static 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 | ||
1170 | void __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 | */ |