diff options
-rw-r--r-- | kexec/Makefile | 1 | ||||
-rw-r--r-- | kexec/arch/i386/crashdump-x86.c | 61 | ||||
-rw-r--r-- | kexec/arch/i386/kexec-x86.c | 2 | ||||
-rw-r--r-- | kexec/arch/ia64/kexec-ia64.c | 1 | ||||
-rw-r--r-- | kexec/arch/ppc/kexec-ppc.c | 1 | ||||
-rw-r--r-- | kexec/arch/x86_64/crashdump-x86_64.c | 49 | ||||
-rw-r--r-- | kexec/arch/x86_64/kexec-x86_64.c | 1 | ||||
-rw-r--r-- | kexec/crashdump.c | 65 | ||||
-rw-r--r-- | kexec/crashdump.h | 9 | ||||
-rw-r--r-- | kexec/kexec.h | 1 |
10 files changed, 107 insertions, 84 deletions
diff --git a/kexec/Makefile b/kexec/Makefile index 812da81..284b1e8 100644 --- a/kexec/Makefile +++ b/kexec/Makefile @@ -15,6 +15,7 @@ KEXEC_C_SRCS+= kexec/kexec-elf.c KEXEC_C_SRCS+= kexec/kexec-elf-exec.c KEXEC_C_SRCS+= kexec/kexec-elf-rel.c KEXEC_C_SRCS+= kexec/kexec-elf-boot.c +KEXEC_C_SRCS+= kexec/crashdump.c KEXEC_C_SRCS+= $(PURGATORY_HEX_C) KEXEC_S_SRCS:= include kexec/arch/$(ARCH)/Makefile diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c index 9553faf..03995d8 100644 --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -29,12 +29,11 @@ #include "../../kexec.h" #include "../../kexec-elf.h" #include "../../kexec-syscall.h" +#include "../../crashdump.h" #include "kexec-x86.h" #include "crashdump-x86.h" #include <x86/x86-linux.h> -#define MAX_LINE 160 - extern struct arch_options_t arch_options; /* Forward Declaration. */ @@ -429,41 +428,36 @@ static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr) return 0; } -/* Returns the virtual address of start of crash notes buffer for a cpu. */ -static int get_crash_notes_section_addr(int cpu, unsigned long long *addr) + +/* + * This routine is specific to i386 architecture to maintain the + * backward compatibility, other architectures can use the per + * cpu version get_crash_notes_per_cpu() directly. + */ +static int get_crash_notes(int cpu, uint64_t *addr) { -#define MAX_SYSFS_PATH_LEN 70 - char crash_notes[MAX_SYSFS_PATH_LEN]; + char crash_notes[PATH_MAX]; char line[MAX_LINE]; FILE *fp; - struct stat cpu_stat; + unsigned long vaddr; + int count; - sprintf(crash_notes, "/sys/devices/system/cpu"); - if (stat(crash_notes, &cpu_stat)) { - die("Cannot stat %s: %s\nTry mounting sysfs\n", - crash_notes, strerror(errno)); - } - - sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu); + sprintf(crash_notes, "/sys/kernel/crash_notes"); fp = fopen(crash_notes, "r"); - if (!fp) { - /* CPU is not physically present.*/ - *addr = 0; - return -1; - } - - if (fgets(line, sizeof(line), fp) != 0) { - int count; - count = sscanf(line, "%Lx", addr); - if (count != 1) { - *addr = 0; - return -1; + if (fp) { + if (fgets(line, sizeof(line), fp) != 0) { + count = sscanf(line, "%lx", &vaddr); + if (count != 1) + die("Cannot parse %s: %s\n", crash_notes, + strerror(errno)); } + *addr = __pa(vaddr + (cpu * MAX_NOTE_BYTES)); #if 0 printf("crash_notes addr = %Lx\n", *addr); #endif - } - return 0; + return 0; + } else + return get_crash_notes_per_cpu(cpu, addr); } /* Prepares the crash memory elf64 headers and stores in supplied buffer. */ @@ -475,7 +469,7 @@ static int prepare_crash_memory_elf64_headers(struct kexec_info *info, int i; char *bufp; long int nr_cpus = 0; - unsigned long long notes_addr; + uint64_t notes_addr; bufp = (char*) buf; @@ -508,11 +502,8 @@ static int prepare_crash_memory_elf64_headers(struct kexec_info *info, return -1; } - /* Need to find a better way to determine per cpu notes section size. */ -#define MAX_NOTE_BYTES 1024 - for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes_section_addr (i, ¬es_addr) < 0) { + if (get_crash_notes(i, ¬es_addr) < 0) { /* This cpu is not present. Skip it. */ continue; } @@ -571,7 +562,7 @@ static int prepare_crash_memory_elf32_headers(struct kexec_info *info, int i; char *bufp; long int nr_cpus = 0; - unsigned long long notes_addr; + uint64_t notes_addr; bufp = (char*) buf; @@ -607,7 +598,7 @@ static int prepare_crash_memory_elf32_headers(struct kexec_info *info, /* Need to find a better way to determine per cpu notes section size. */ #define MAX_NOTE_BYTES 1024 for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes_section_addr (i, ¬es_addr) < 0) { + if (get_crash_notes(i, ¬es_addr) < 0) { /* This cpu is not present. Skip it. */ return -1; } diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c index 26cbbb0..1c8d188 100644 --- a/kexec/arch/i386/kexec-x86.c +++ b/kexec/arch/i386/kexec-x86.c @@ -33,8 +33,6 @@ #include "crashdump-x86.h" #include <arch/options.h> -#define MAX_LINE 160 - static struct memory_range memory_range[MAX_MEMORY_RANGES]; /* Return a sorted list of memory ranges. */ diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c index a2221e6..f631cef 100644 --- a/kexec/arch/ia64/kexec-ia64.c +++ b/kexec/arch/ia64/kexec-ia64.c @@ -34,7 +34,6 @@ #include <arch/options.h> #define MAX_MEMORY_RANGES 64 -#define MAX_LINE 160 static struct memory_range memory_range[MAX_MEMORY_RANGES]; /* Return a sorted list of available memory ranges. */ diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c index 455febf..16ea584 100644 --- a/kexec/arch/ppc/kexec-ppc.c +++ b/kexec/arch/ppc/kexec-ppc.c @@ -19,7 +19,6 @@ #include <arch/options.h> #define MAX_MEMORY_RANGES 64 -#define MAX_LINE 160 static struct memory_range memory_range[MAX_MEMORY_RANGES]; /* Return a sorted list of memory ranges. */ diff --git a/kexec/arch/x86_64/crashdump-x86_64.c b/kexec/arch/x86_64/crashdump-x86_64.c index f104b89..3d0f3a5 100644 --- a/kexec/arch/x86_64/crashdump-x86_64.c +++ b/kexec/arch/x86_64/crashdump-x86_64.c @@ -30,12 +30,11 @@ #include "../../kexec.h" #include "../../kexec-elf.h" #include "../../kexec-syscall.h" +#include "../../crashdump.h" #include "kexec-x86_64.h" #include "crashdump-x86_64.h" #include <x86/x86-linux.h> -#define MAX_LINE 160 - extern struct arch_options_t arch_options; /* Forward Declaration. */ @@ -471,44 +470,6 @@ static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start, return 0; } -/* Returns the virtual address of start of crash notes buffer for a cpu. */ -static int get_crash_notes_section_addr(int cpu, unsigned long long *addr) -{ - -#define MAX_SYSFS_PATH_LEN 70 - char crash_notes[MAX_SYSFS_PATH_LEN]; - char line[MAX_LINE]; - FILE *fp; - struct stat cpu_stat; - - sprintf(crash_notes, "/sys/devices/system/cpu"); - if (stat(crash_notes, &cpu_stat)) { - die("Cannot stat %s: %s\nTry mounting sysfs\n", - crash_notes, strerror(errno)); - } - - sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu); - fp = fopen(crash_notes, "r"); - if (!fp) { - /* CPU is not physically present.*/ - *addr = 0; - return -1; - } - - if (fgets(line, sizeof(line), fp) != 0) { - int count; - count = sscanf(line, "%Lx", addr); - if (count != 1) { - *addr = 0; - return -1; - } -#if 0 - printf("crash_notes addr = %Lx\n", *addr); -#endif - } - return 0; -} - /* Prepares the crash memory elf64 headers and stores in supplied buffer. */ static int prepare_crash_memory_elf64_headers(struct kexec_info *info, void *buf, unsigned long size) @@ -518,7 +479,7 @@ static int prepare_crash_memory_elf64_headers(struct kexec_info *info, int i; char *bufp; long int nr_cpus = 0; - unsigned long long notes_addr; + uint64_t notes_addr; bufp = (char*) buf; @@ -554,7 +515,7 @@ static int prepare_crash_memory_elf64_headers(struct kexec_info *info, /* Need to find a better way to determine per cpu notes section size. */ #define MAX_NOTE_BYTES 1024 for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes_section_addr (i, ¬es_addr) < 0) { + if (get_crash_notes_per_cpu(i, ¬es_addr) < 0) { /* This cpu is not present. Skip it. */ continue; } @@ -624,7 +585,7 @@ static int prepare_crash_memory_elf32_headers(struct kexec_info *info, int i; char *bufp; long int nr_cpus = 0; - unsigned long long notes_addr; + uint64_t notes_addr; bufp = (char*) buf; @@ -660,7 +621,7 @@ static int prepare_crash_memory_elf32_headers(struct kexec_info *info, /* Need to find a better way to determine per cpu notes section size. */ #define MAX_NOTE_BYTES 1024 for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes_section_addr (i, ¬es_addr) < 0) { + if (get_crash_notes_per_cpu(i, ¬es_addr) < 0) { /* This cpu is not present. Skip it. */ return -1; } diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c index 3ed3844..db3e5d4 100644 --- a/kexec/arch/x86_64/kexec-x86_64.c +++ b/kexec/arch/x86_64/kexec-x86_64.c @@ -34,7 +34,6 @@ #include <arch/options.h> #define MAX_MEMORY_RANGES 64 -#define MAX_LINE 160 static struct memory_range memory_range[MAX_MEMORY_RANGES]; /* Return a sorted list of memory ranges. */ diff --git a/kexec/crashdump.c b/kexec/crashdump.c new file mode 100644 index 0000000..9e5bf15 --- /dev/null +++ b/kexec/crashdump.c @@ -0,0 +1,65 @@ +/* + * crashdump.c: Architecture independent code for crashdump support. + * + * Created by: Vivek Goyal (vgoyal@in.ibm.com) + * Copyright (C) IBM Corporation, 2005. All rights reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <elf.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "kexec.h" +#include "crashdump.h" + +/* Returns the physical address of start of crash notes buffer for a cpu. */ +int get_crash_notes_per_cpu(int cpu, uint64_t *addr) +{ + char crash_notes[PATH_MAX]; + char line[MAX_LINE]; + FILE *fp; + struct stat cpu_stat; + int count; + unsigned long long temp; + + sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu); + fp = fopen(crash_notes, "r"); + if (!fp) { + /* Either sysfs is not mounted or CPU is not present*/ + if (stat("/sys/devices", &cpu_stat)) + die("Sysfs is not mounted. Try mounting sysfs\n"); + + /* CPU is not physically present.*/ + *addr = 0; + return errno; + } + if (fgets(line, sizeof(line), fp) != 0) { + count = sscanf(line, "%Lx", &temp); + if (count != 1) + die("Cannot parse %s: %s\n", crash_notes, + strerror(errno)); + *addr = (uint64_t) temp; + } +#if 0 + printf("crash_notes addr = %Lx\n", *addr); +#endif + return 0; +} diff --git a/kexec/crashdump.h b/kexec/crashdump.h new file mode 100644 index 0000000..682dd53 --- /dev/null +++ b/kexec/crashdump.h @@ -0,0 +1,9 @@ +#ifndef CRASHDUMP_H +#define CRASHDUMP_H + +extern int get_crash_notes_per_cpu(int cpu, uint64_t *addr); + +/* Need to find a better way to determine per cpu notes section size. */ +#define MAX_NOTE_BYTES 1024 + +#endif /* CRASHDUMP_H */ diff --git a/kexec/kexec.h b/kexec/kexec.h index a125cb7..57fca7d 100644 --- a/kexec/kexec.h +++ b/kexec/kexec.h @@ -196,4 +196,5 @@ int arch_process_options(int argc, char **argv); int arch_compat_trampoline(struct kexec_info *info); void arch_update_purgatory(struct kexec_info *info); +#define MAX_LINE 160 #endif /* KEXEC_H */ |