aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/ia64/Kconfig2
-rw-r--r--arch/m68k/Kconfig2
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/tile/Kconfig2
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/kernel/machine_kexec_64.c142
10 files changed, 160 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8e9dbcbcf5af..cacc8d5355b3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2065,6 +2065,8 @@ config XIP_PHYS_ADDR
2065config KEXEC 2065config KEXEC
2066 bool "Kexec system call (EXPERIMENTAL)" 2066 bool "Kexec system call (EXPERIMENTAL)"
2067 depends on (!SMP || PM_SLEEP_SMP) 2067 depends on (!SMP || PM_SLEEP_SMP)
2068 select CRYPTO
2069 select CRYPTO_SHA256
2068 help 2070 help
2069 kexec is a system call that implements the ability to shutdown your 2071 kexec is a system call that implements the ability to shutdown your
2070 current kernel, and to start another kernel. It is like a reboot 2072 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index c84c88bbbbd7..64aefb76bd69 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -549,6 +549,8 @@ source "drivers/sn/Kconfig"
549config KEXEC 549config KEXEC
550 bool "kexec system call" 550 bool "kexec system call"
551 depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) 551 depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
552 select CRYPTO
553 select CRYPTO_SHA256
552 help 554 help
553 kexec is a system call that implements the ability to shutdown your 555 kexec is a system call that implements the ability to shutdown your
554 current kernel, and to start another kernel. It is like a reboot 556 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 87b7c7581b1d..3ff8c9a25335 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -91,6 +91,8 @@ config MMU_SUN3
91config KEXEC 91config KEXEC
92 bool "kexec system call" 92 bool "kexec system call"
93 depends on M68KCLASSIC 93 depends on M68KCLASSIC
94 select CRYPTO
95 select CRYPTO_SHA256
94 help 96 help
95 kexec is a system call that implements the ability to shutdown your 97 kexec is a system call that implements the ability to shutdown your
96 current kernel, and to start another kernel. It is like a reboot 98 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 900c7e5333b6..df51e78a72cc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2396,6 +2396,8 @@ source "kernel/Kconfig.preempt"
2396 2396
2397config KEXEC 2397config KEXEC
2398 bool "Kexec system call" 2398 bool "Kexec system call"
2399 select CRYPTO
2400 select CRYPTO_SHA256
2399 help 2401 help
2400 kexec is a system call that implements the ability to shutdown your 2402 kexec is a system call that implements the ability to shutdown your
2401 current kernel, and to start another kernel. It is like a reboot 2403 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4bc7b62fb4b6..a577609f8ed6 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -399,6 +399,8 @@ config PPC64_SUPPORTS_MEMORY_FAILURE
399config KEXEC 399config KEXEC
400 bool "kexec system call" 400 bool "kexec system call"
401 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) 401 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
402 select CRYPTO
403 select CRYPTO_SHA256
402 help 404 help
403 kexec is a system call that implements the ability to shutdown your 405 kexec is a system call that implements the ability to shutdown your
404 current kernel, and to start another kernel. It is like a reboot 406 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 05c78bb5f570..ab39ceb89ecf 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -48,6 +48,8 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
48 48
49config KEXEC 49config KEXEC
50 def_bool y 50 def_bool y
51 select CRYPTO
52 select CRYPTO_SHA256
51 53
52config AUDIT_ARCH 54config AUDIT_ARCH
53 def_bool y 55 def_bool y
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index aa2df3eaeb29..453fa5c09550 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -595,6 +595,8 @@ source kernel/Kconfig.hz
595config KEXEC 595config KEXEC
596 bool "kexec system call (EXPERIMENTAL)" 596 bool "kexec system call (EXPERIMENTAL)"
597 depends on SUPERH32 && MMU 597 depends on SUPERH32 && MMU
598 select CRYPTO
599 select CRYPTO_SHA256
598 help 600 help
599 kexec is a system call that implements the ability to shutdown your 601 kexec is a system call that implements the ability to shutdown your
600 current kernel, and to start another kernel. It is like a reboot 602 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 7fcd492adbfc..a3ffe2dd4832 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -191,6 +191,8 @@ source "kernel/Kconfig.hz"
191 191
192config KEXEC 192config KEXEC
193 bool "kexec system call" 193 bool "kexec system call"
194 select CRYPTO
195 select CRYPTO_SHA256
194 ---help--- 196 ---help---
195 kexec is a system call that implements the ability to shutdown your 197 kexec is a system call that implements the ability to shutdown your
196 current kernel, and to start another kernel. It is like a reboot 198 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 98fe3df6df82..9558b9fcafbf 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1583,6 +1583,8 @@ source kernel/Kconfig.hz
1583config KEXEC 1583config KEXEC
1584 bool "kexec system call" 1584 bool "kexec system call"
1585 select BUILD_BIN2C 1585 select BUILD_BIN2C
1586 select CRYPTO
1587 select CRYPTO_SHA256
1586 ---help--- 1588 ---help---
1587 kexec is a system call that implements the ability to shutdown your 1589 kexec is a system call that implements the ability to shutdown your
1588 current kernel, and to start another kernel. It is like a reboot 1590 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index c8875b5545e1..88404c440727 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -6,6 +6,8 @@
6 * Version 2. See the file COPYING for more details. 6 * Version 2. See the file COPYING for more details.
7 */ 7 */
8 8
9#define pr_fmt(fmt) "kexec: " fmt
10
9#include <linux/mm.h> 11#include <linux/mm.h>
10#include <linux/kexec.h> 12#include <linux/kexec.h>
11#include <linux/string.h> 13#include <linux/string.h>
@@ -328,3 +330,143 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
328 330
329 return image->fops->cleanup(image); 331 return image->fops->cleanup(image);
330} 332}
333
334/*
335 * Apply purgatory relocations.
336 *
337 * ehdr: Pointer to elf headers
338 * sechdrs: Pointer to section headers.
339 * relsec: section index of SHT_RELA section.
340 *
341 * TODO: Some of the code belongs to generic code. Move that in kexec.c.
342 */
343int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
344 Elf64_Shdr *sechdrs, unsigned int relsec)
345{
346 unsigned int i;
347 Elf64_Rela *rel;
348 Elf64_Sym *sym;
349 void *location;
350 Elf64_Shdr *section, *symtabsec;
351 unsigned long address, sec_base, value;
352 const char *strtab, *name, *shstrtab;
353
354 /*
355 * ->sh_offset has been modified to keep the pointer to section
356 * contents in memory
357 */
358 rel = (void *)sechdrs[relsec].sh_offset;
359
360 /* Section to which relocations apply */
361 section = &sechdrs[sechdrs[relsec].sh_info];
362
363 pr_debug("Applying relocate section %u to %u\n", relsec,
364 sechdrs[relsec].sh_info);
365
366 /* Associated symbol table */
367 symtabsec = &sechdrs[sechdrs[relsec].sh_link];
368
369 /* String table */
370 if (symtabsec->sh_link >= ehdr->e_shnum) {
371 /* Invalid strtab section number */
372 pr_err("Invalid string table section index %d\n",
373 symtabsec->sh_link);
374 return -ENOEXEC;
375 }
376
377 strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset;
378
379 /* section header string table */
380 shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset;
381
382 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
383
384 /*
385 * rel[i].r_offset contains byte offset from beginning
386 * of section to the storage unit affected.
387 *
388 * This is location to update (->sh_offset). This is temporary
389 * buffer where section is currently loaded. This will finally
390 * be loaded to a different address later, pointed to by
391 * ->sh_addr. kexec takes care of moving it
392 * (kexec_load_segment()).
393 */
394 location = (void *)(section->sh_offset + rel[i].r_offset);
395
396 /* Final address of the location */
397 address = section->sh_addr + rel[i].r_offset;
398
399 /*
400 * rel[i].r_info contains information about symbol table index
401 * w.r.t which relocation must be made and type of relocation
402 * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
403 * these respectively.
404 */
405 sym = (Elf64_Sym *)symtabsec->sh_offset +
406 ELF64_R_SYM(rel[i].r_info);
407
408 if (sym->st_name)
409 name = strtab + sym->st_name;
410 else
411 name = shstrtab + sechdrs[sym->st_shndx].sh_name;
412
413 pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n",
414 name, sym->st_info, sym->st_shndx, sym->st_value,
415 sym->st_size);
416
417 if (sym->st_shndx == SHN_UNDEF) {
418 pr_err("Undefined symbol: %s\n", name);
419 return -ENOEXEC;
420 }
421
422 if (sym->st_shndx == SHN_COMMON) {
423 pr_err("symbol '%s' in common section\n", name);
424 return -ENOEXEC;
425 }
426
427 if (sym->st_shndx == SHN_ABS)
428 sec_base = 0;
429 else if (sym->st_shndx >= ehdr->e_shnum) {
430 pr_err("Invalid section %d for symbol %s\n",
431 sym->st_shndx, name);
432 return -ENOEXEC;
433 } else
434 sec_base = sechdrs[sym->st_shndx].sh_addr;
435
436 value = sym->st_value;
437 value += sec_base;
438 value += rel[i].r_addend;
439
440 switch (ELF64_R_TYPE(rel[i].r_info)) {
441 case R_X86_64_NONE:
442 break;
443 case R_X86_64_64:
444 *(u64 *)location = value;
445 break;
446 case R_X86_64_32:
447 *(u32 *)location = value;
448 if (value != *(u32 *)location)
449 goto overflow;
450 break;
451 case R_X86_64_32S:
452 *(s32 *)location = value;
453 if ((s64)value != *(s32 *)location)
454 goto overflow;
455 break;
456 case R_X86_64_PC32:
457 value -= (u64)address;
458 *(u32 *)location = value;
459 break;
460 default:
461 pr_err("Unknown rela relocation: %llu\n",
462 ELF64_R_TYPE(rel[i].r_info));
463 return -ENOEXEC;
464 }
465 }
466 return 0;
467
468overflow:
469 pr_err("Overflow in relocation type %d value 0x%lx\n",
470 (int)ELF64_R_TYPE(rel[i].r_info), value);
471 return -ENOEXEC;
472}