summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kexec/Makefile2
-rw-r--r--kexec/arch/x86_64/Makefile2
-rw-r--r--kexec/arch/x86_64/arch_init.c83
-rw-r--r--kexec/arch/x86_64/crashdump-x86_64.c19
-rw-r--r--kexec/arch/x86_64/crashdump-x86_64.h8
-rw-r--r--kexec/arch_init.c4
-rw-r--r--kexec/kexec.c2
-rw-r--r--kexec/kexec.h2
8 files changed, 111 insertions, 11 deletions
diff --git a/kexec/Makefile b/kexec/Makefile
index 2a985cf..9a55af2 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -44,6 +44,8 @@ $(ARCH)_ADD_BUFFER = kexec/add_buffer.c
KEXEC_SRCS += $($(ARCH)_ADD_BUFFER)
$(ARCH)_ARCH_REUSE_INITRD = kexec/arch_reuse_initrd.c
KEXEC_SRCS += $($(ARCH)_ARCH_REUSE_INITRD)
+$(ARCH)_ARCH_INIT = kexec/arch_init.c
+KEXEC_SRCS += $($(ARCH)_ARCH_INIT)
include $(srcdir)/kexec/arch/alpha/Makefile
include $(srcdir)/kexec/arch/arm/Makefile
diff --git a/kexec/arch/x86_64/Makefile b/kexec/arch/x86_64/Makefile
index 7ca3e7e..e6a8d35 100644
--- a/kexec/arch/x86_64/Makefile
+++ b/kexec/arch/x86_64/Makefile
@@ -13,6 +13,8 @@ x86_64_KEXEC_SRCS += kexec/arch/x86_64/kexec-x86_64.c
x86_64_KEXEC_SRCS += kexec/arch/x86_64/kexec-elf-x86_64.c
x86_64_KEXEC_SRCS += kexec/arch/x86_64/kexec-elf-rel-x86_64.c
+x86_64_ARCH_INIT = kexec/arch/x86_64/arch_init.c
+
dist += kexec/arch/x86_64/Makefile $(x86_64_KEXEC_SRCS) \
kexec/arch/x86_64/kexec-x86_64.h kexec/arch/x86_64/crashdump-x86_64.h \
kexec/arch/x86_64/include/arch/options.h
diff --git a/kexec/arch/x86_64/arch_init.c b/kexec/arch/x86_64/arch_init.c
new file mode 100644
index 0000000..79fb642
--- /dev/null
+++ b/kexec/arch/x86_64/arch_init.c
@@ -0,0 +1,83 @@
+#include <errno.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "crashdump-x86_64.h"
+
+#define KERNEL_VERSION(major, minor, patch) \
+ (((major) << 16) | ((minor) << 8) | patch)
+
+long kernel_version(void)
+{
+ struct utsname utsname;
+ unsigned long major, minor, patch;
+ char *p;
+
+ if (uname(&utsname) < 0) {
+ fprintf(stderr, "uname failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ p = utsname.release;
+ major = strtoul(p, &p, 10);
+ if (major == ULONG_MAX) {
+ fprintf(stderr, "strtoul failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (*p++ != '.') {
+ fprintf(stderr, "Unsupported utsname.release: %s\n",
+ utsname.release);
+ return -1;
+ }
+
+ minor = strtoul(p, &p, 10);
+ if (major == ULONG_MAX) {
+ fprintf(stderr, "strtoul failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (*p++ != '.') {
+ fprintf(stderr, "Unsupported utsname.release: %s\n",
+ utsname.release);
+ return -1;
+ }
+
+ patch = strtoul(p, &p, 10);
+ if (major == ULONG_MAX) {
+ fprintf(stderr, "strtoul failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (major >= 256 || minor >= 256 || patch >= 256) {
+ fprintf(stderr, "Unsupported utsname.release: %s\n",
+ utsname.release);
+ return -1;
+ }
+
+ return KERNEL_VERSION(major, minor, patch);
+}
+
+#define PAGE_OFFSET_PRE_2_6_27 0xffff810000000000UL
+#define PAGE_OFFSET 0xffff880000000000UL
+
+unsigned long page_offset;
+
+int arch_init(void)
+{
+ int kv;
+
+ kv = kernel_version();
+ if (kv < 0)
+ return -1;
+
+ if (kv < KERNEL_VERSION(2, 6, 27))
+ page_offset = PAGE_OFFSET_PRE_2_6_27;
+ else
+ page_offset = PAGE_OFFSET;
+
+ return 0;
+}
diff --git a/kexec/arch/x86_64/crashdump-x86_64.c b/kexec/arch/x86_64/crashdump-x86_64.c
index b6b410b..29e9602 100644
--- a/kexec/arch/x86_64/crashdump-x86_64.c
+++ b/kexec/arch/x86_64/crashdump-x86_64.c
@@ -36,15 +36,6 @@
#include "crashdump-x86_64.h"
#include <x86/x86-linux.h>
-static struct crash_elf_info elf_info =
-{
- class: ELFCLASS64,
- data: ELFDATA2LSB,
- machine: EM_X86_64,
- backup_src_start: BACKUP_SRC_START,
- backup_src_end: BACKUP_SRC_END,
- page_offset: PAGE_OFFSET,
-};
/* Forward Declaration. */
static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end);
@@ -604,6 +595,16 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
int nr_ranges, align = 1024, i;
struct memory_range *mem_range, *memmap_p;
+ struct crash_elf_info elf_info =
+ {
+ class: ELFCLASS64,
+ data: ELFDATA2LSB,
+ machine: EM_X86_64,
+ backup_src_start: BACKUP_SRC_START,
+ backup_src_end: BACKUP_SRC_END,
+ page_offset: page_offset,
+ };
+
if (get_kernel_paddr(info))
return -1;
diff --git a/kexec/arch/x86_64/crashdump-x86_64.h b/kexec/arch/x86_64/crashdump-x86_64.h
index 0e83527..2129104 100644
--- a/kexec/arch/x86_64/crashdump-x86_64.h
+++ b/kexec/arch/x86_64/crashdump-x86_64.h
@@ -1,12 +1,16 @@
#ifndef CRASHDUMP_X86_64_H
#define CRASHDUMP_X86_64_H
+#include "../../kexec.h"
+
int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
unsigned long max_addr, unsigned long min_base);
#define __START_KERNEL_map 0xffffffff80000000UL
-#define PAGE_OFFSET 0xffff810000000000UL
-#define __pa(x) (((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - PAGE_OFFSET)
+
+extern unsigned long page_offset;
+
+#define __pa(x) (((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - page_offset)
#define MAXMEM 0x3fffffffffffUL
diff --git a/kexec/arch_init.c b/kexec/arch_init.c
new file mode 100644
index 0000000..afce72f
--- /dev/null
+++ b/kexec/arch_init.c
@@ -0,0 +1,4 @@
+int arch_init(void)
+{
+ return 0;
+}
diff --git a/kexec/kexec.c b/kexec/kexec.c
index c4eb254..d282ade 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -1041,6 +1041,8 @@ int main(int argc, char *argv[])
};
static const char short_options[] = KEXEC_OPT_STR;
+ arch_init();
+
opterr = 0; /* Don't complain about unrecognized options here */
while ((opt = getopt_long(argc, argv, short_options,
options, 0)) != -1) {
diff --git a/kexec/kexec.h b/kexec/kexec.h
index ccda539..4d22017 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -249,6 +249,8 @@ int kexec_iomem_for_each_line(char *match,
int parse_iomem_single(char *str, uint64_t *start, uint64_t *end);
const char * proc_iomem(void);
+int arch_init(void);
+
extern int add_backup_segments(struct kexec_info *info,
unsigned long backup_base,
unsigned long backup_size);