aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2014-08-08 17:26:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 18:57:33 -0400
commit6a2c20e7d8900ed273dc34a9af9bf02fc478e427 (patch)
treed4825b15aa4b9fd6cc92d4fb107d920544a4548b
parentdd5f726076cc7639d9713b334c8c133f77c6757a (diff)
kexec: support kexec/kdump on EFI systems
This patch does two things. It passes EFI run time mappings to second kernel in bootparams efi_info. Second kernel parse this info and create new mappings in second kernel. That means mappings in first and second kernel will be same. This paves the way to enable EFI in kexec kernel. This patch also prepares and passes EFI setup data through bootparams. This contains bunch of information about various tables and their addresses. These information gathering and passing has been written along the lines of what current kexec-tools is doing to make kexec work with UEFI. [akpm@linux-foundation.org: s/get_efi/efi_get/g, per Matt] Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Cc: Borislav Petkov <bp@suse.de> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Eric Biederman <ebiederm@xmission.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Greg Kroah-Hartman <greg@kroah.com> Cc: Dave Young <dyoung@redhat.com> Cc: WANG Chao <chaowang@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Matt Fleming <matt@console-pimps.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c146
-rw-r--r--drivers/firmware/efi/runtime-map.c21
-rw-r--r--include/linux/efi.h19
3 files changed, 174 insertions, 12 deletions
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index a8e646458a10..623e6c58081f 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -18,10 +18,12 @@
18#include <linux/kexec.h> 18#include <linux/kexec.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/efi.h>
21 22
22#include <asm/bootparam.h> 23#include <asm/bootparam.h>
23#include <asm/setup.h> 24#include <asm/setup.h>
24#include <asm/crash.h> 25#include <asm/crash.h>
26#include <asm/efi.h>
25 27
26#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ 28#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
27 29
@@ -90,7 +92,7 @@ static int setup_cmdline(struct kimage *image, struct boot_params *params,
90 return 0; 92 return 0;
91} 93}
92 94
93static int setup_memory_map_entries(struct boot_params *params) 95static int setup_e820_entries(struct boot_params *params)
94{ 96{
95 unsigned int nr_e820_entries; 97 unsigned int nr_e820_entries;
96 98
@@ -107,8 +109,93 @@ static int setup_memory_map_entries(struct boot_params *params)
107 return 0; 109 return 0;
108} 110}
109 111
110static int setup_boot_parameters(struct kimage *image, 112#ifdef CONFIG_EFI
111 struct boot_params *params) 113static int setup_efi_info_memmap(struct boot_params *params,
114 unsigned long params_load_addr,
115 unsigned int efi_map_offset,
116 unsigned int efi_map_sz)
117{
118 void *efi_map = (void *)params + efi_map_offset;
119 unsigned long efi_map_phys_addr = params_load_addr + efi_map_offset;
120 struct efi_info *ei = &params->efi_info;
121
122 if (!efi_map_sz)
123 return 0;
124
125 efi_runtime_map_copy(efi_map, efi_map_sz);
126
127 ei->efi_memmap = efi_map_phys_addr & 0xffffffff;
128 ei->efi_memmap_hi = efi_map_phys_addr >> 32;
129 ei->efi_memmap_size = efi_map_sz;
130
131 return 0;
132}
133
134static int
135prepare_add_efi_setup_data(struct boot_params *params,
136 unsigned long params_load_addr,
137 unsigned int efi_setup_data_offset)
138{
139 unsigned long setup_data_phys;
140 struct setup_data *sd = (void *)params + efi_setup_data_offset;
141 struct efi_setup_data *esd = (void *)sd + sizeof(struct setup_data);
142
143 esd->fw_vendor = efi.fw_vendor;
144 esd->runtime = efi.runtime;
145 esd->tables = efi.config_table;
146 esd->smbios = efi.smbios;
147
148 sd->type = SETUP_EFI;
149 sd->len = sizeof(struct efi_setup_data);
150
151 /* Add setup data */
152 setup_data_phys = params_load_addr + efi_setup_data_offset;
153 sd->next = params->hdr.setup_data;
154 params->hdr.setup_data = setup_data_phys;
155
156 return 0;
157}
158
159static int
160setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
161 unsigned int efi_map_offset, unsigned int efi_map_sz,
162 unsigned int efi_setup_data_offset)
163{
164 struct efi_info *current_ei = &boot_params.efi_info;
165 struct efi_info *ei = &params->efi_info;
166
167 if (!current_ei->efi_memmap_size)
168 return 0;
169
170 /*
171 * If 1:1 mapping is not enabled, second kernel can not setup EFI
172 * and use EFI run time services. User space will have to pass
173 * acpi_rsdp=<addr> on kernel command line to make second kernel boot
174 * without efi.
175 */
176 if (efi_enabled(EFI_OLD_MEMMAP))
177 return 0;
178
179 ei->efi_loader_signature = current_ei->efi_loader_signature;
180 ei->efi_systab = current_ei->efi_systab;
181 ei->efi_systab_hi = current_ei->efi_systab_hi;
182
183 ei->efi_memdesc_version = current_ei->efi_memdesc_version;
184 ei->efi_memdesc_size = efi_get_runtime_map_desc_size();
185
186 setup_efi_info_memmap(params, params_load_addr, efi_map_offset,
187 efi_map_sz);
188 prepare_add_efi_setup_data(params, params_load_addr,
189 efi_setup_data_offset);
190 return 0;
191}
192#endif /* CONFIG_EFI */
193
194static int
195setup_boot_parameters(struct kimage *image, struct boot_params *params,
196 unsigned long params_load_addr,
197 unsigned int efi_map_offset, unsigned int efi_map_sz,
198 unsigned int efi_setup_data_offset)
112{ 199{
113 unsigned int nr_e820_entries; 200 unsigned int nr_e820_entries;
114 unsigned long long mem_k, start, end; 201 unsigned long long mem_k, start, end;
@@ -140,7 +227,7 @@ static int setup_boot_parameters(struct kimage *image,
140 if (ret) 227 if (ret)
141 return ret; 228 return ret;
142 } else 229 } else
143 setup_memory_map_entries(params); 230 setup_e820_entries(params);
144 231
145 nr_e820_entries = params->e820_entries; 232 nr_e820_entries = params->e820_entries;
146 233
@@ -161,6 +248,12 @@ static int setup_boot_parameters(struct kimage *image,
161 } 248 }
162 } 249 }
163 250
251#ifdef CONFIG_EFI
252 /* Setup EFI state */
253 setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
254 efi_setup_data_offset);
255#endif
256
164 /* Setup EDD info */ 257 /* Setup EDD info */
165 memcpy(params->eddbuf, boot_params.eddbuf, 258 memcpy(params->eddbuf, boot_params.eddbuf,
166 EDDMAXNR * sizeof(struct edd_info)); 259 EDDMAXNR * sizeof(struct edd_info));
@@ -214,6 +307,15 @@ int bzImage64_probe(const char *buf, unsigned long len)
214 return ret; 307 return ret;
215 } 308 }
216 309
310 /*
311 * Can't handle 32bit EFI as it does not allow loading kernel
312 * above 4G. This should be handled by 32bit bzImage loader
313 */
314 if (efi_enabled(EFI_RUNTIME_SERVICES) && !efi_enabled(EFI_64BIT)) {
315 pr_debug("EFI is 32 bit. Can't load kernel above 4G.\n");
316 return ret;
317 }
318
217 /* I've got a bzImage */ 319 /* I've got a bzImage */
218 pr_debug("It's a relocatable bzImage64\n"); 320 pr_debug("It's a relocatable bzImage64\n");
219 ret = 0; 321 ret = 0;
@@ -229,7 +331,7 @@ void *bzImage64_load(struct kimage *image, char *kernel,
229 331
230 struct setup_header *header; 332 struct setup_header *header;
231 int setup_sects, kern16_size, ret = 0; 333 int setup_sects, kern16_size, ret = 0;
232 unsigned long setup_header_size, params_cmdline_sz; 334 unsigned long setup_header_size, params_cmdline_sz, params_misc_sz;
233 struct boot_params *params; 335 struct boot_params *params;
234 unsi