diff --git a/kexec-tools-fix-arch-on-unload b/kexec-tools-fix-arch-on-unload new file mode 100644 index 0000000..ff0983f --- /dev/null +++ b/kexec-tools-fix-arch-on-unload @@ -0,0 +1,33 @@ +From eeec23d689747e9170c6f711161cf1f1258ee03e Mon Sep 17 00:00:00 2001 +From: Bernhard Walle +Date: Mon, 26 May 2008 14:12:53 +0200 +Subject: [PATCH] Specify the arch on kexec_unload. + +This fixes the problem in kexec-tools that the patch +http://article.gmane.org/gmane.linux.kernel/685027 tries to fix in kernel. + +The fix in userspace is correct. + +Signed-off-by: Bernhard Walle + +--- + kexec/kexec.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -714,6 +714,14 @@ static int my_load(const char *type, int + int k_unload (unsigned long kexec_flags) + { + int result; ++ long native_arch; ++ ++ /* set the arch */ ++ native_arch = physical_arch(); ++ if (native_arch < 0) { ++ return -1; ++ } ++ kexec_flags |= native_arch; + + result = kexec_load(NULL, 0, NULL, kexec_flags); + if (result != 0) { diff --git a/kexec-tools-refactor-architecture-detection b/kexec-tools-refactor-architecture-detection new file mode 100644 index 0000000..16cac70 --- /dev/null +++ b/kexec-tools-refactor-architecture-detection @@ -0,0 +1,527 @@ +From 7c3109cb6c5e1834bb3b6f788c9dcaa0ddbdf090 Mon Sep 17 00:00:00 2001 +From: Jamey Sharp +Date: Thu, 15 May 2008 22:42:10 -0700 +Subject: [PATCH] Factor uname-based native architecture detection into a common function. + +This code was copy-pasted into every architecture and was basically +identical. + +Besides producing a nice net reduction in code, this factors a +portability challenge into a single function that can be easily replaced +at build-time. + +Signed-off-by: Jamey Sharp +Signed-off-by: Simon Horman + +--- + kexec/Makefile | 1 + + kexec/arch/arm/kexec-arm.c | 23 +++++------------------ + kexec/arch/i386/kexec-x86.c | 39 +++++++++++++-------------------------- + kexec/arch/ia64/kexec-ia64.c | 23 +++++------------------ + kexec/arch/mips/kexec-mips.c | 29 ++++++++--------------------- + kexec/arch/ppc/kexec-ppc.c | 29 ++++++++--------------------- + kexec/arch/ppc64/kexec-ppc64.c | 29 ++++++++--------------------- + kexec/arch/s390/kexec-s390.c | 8 ++++++-- + kexec/arch/sh/kexec-sh.c | 34 ++++++++++------------------------ + kexec/arch/x86_64/kexec-x86_64.c | 29 ++++++++--------------------- + kexec/kexec.c | 6 ++++++ + kexec/kexec.h | 9 +++++++++ + kexec/phys_arch.c | 23 +++++++++++++++++++++++ + 13 files changed, 110 insertions(+), 172 deletions(-) + +--- a/kexec/Makefile ++++ b/kexec/Makefile +@@ -20,6 +20,7 @@ KEXEC_SRCS += kexec/kexec-elf-boot.c + KEXEC_SRCS += kexec/kexec-iomem.c + KEXEC_SRCS += kexec/crashdump.c + KEXEC_SRCS += kexec/crashdump-xen.c ++KEXEC_SRCS += kexec/phys_arch.c + + KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C) + +--- a/kexec/arch/arm/kexec-arm.c ++++ b/kexec/arch/arm/kexec-arm.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-arm.h" +@@ -109,25 +108,13 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ { "arm", KEXEC_ARCH_ARM }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strncmp(utsname.machine, "arm",3) == 0) +- { +- info->kexec_flags |= KEXEC_ARCH_ARM; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/i386/kexec-x86.c ++++ b/kexec/arch/i386/kexec-x86.c +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-elf.h" + #include "../../kexec-syscall.h" +@@ -223,29 +222,22 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_386 here. ++ */ ++ { "i386", KEXEC_ARCH_DEFAULT }, ++ { "i486", KEXEC_ARCH_DEFAULT }, ++ { "i586", KEXEC_ARCH_DEFAULT }, ++ { "i686", KEXEC_ARCH_DEFAULT }, ++ { "x86_64", KEXEC_ARCH_X86_64 }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if ( (strcmp(utsname.machine, "i386") == 0) || +- (strcmp(utsname.machine, "i486") == 0) || +- (strcmp(utsname.machine, "i586") == 0) || +- (strcmp(utsname.machine, "i686") == 0)) ++ if ((info->kexec_flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_X86_64) + { +- /* For compatibility with older patches +- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_386 here. +- */ +- info->kexec_flags |= KEXEC_ARCH_DEFAULT; +- } +- else if (strcmp(utsname.machine, "x86_64") == 0) +- { +- info->kexec_flags |= KEXEC_ARCH_X86_64; + if (!info->rhdr.e_shdr) { + fprintf(stderr, + "A trampoline is required for cross architecture support\n"); +@@ -256,11 +248,6 @@ int arch_compat_trampoline(struct kexec_ + + info->entry = (void *)elf_rel_get_addr(&info->rhdr, "compat_x86_64"); + } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/ia64/kexec-ia64.c ++++ b/kexec/arch/ia64/kexec-ia64.c +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + #include "../../kexec.h" + #include "../../kexec-syscall.h" +@@ -204,25 +203,13 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ { "ia64", KEXEC_ARCH_IA_64 }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strcmp(utsname.machine, "ia64") == 0) +- { +- info->kexec_flags |= KEXEC_ARCH_IA_64; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/mips/kexec-mips.c ++++ b/kexec/arch/mips/kexec-mips.c +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-mips.h" +@@ -122,28 +121,16 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here. ++ */ ++ { "mips", KEXEC_ARCH_DEFAULT }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strcmp(utsname.machine, "mips") == 0) +- { +- /* For compatibility with older patches +- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here. +- */ +- info->kexec_flags |= KEXEC_ARCH_DEFAULT; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/ppc/kexec-ppc.c ++++ b/kexec/arch/ppc/kexec-ppc.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-ppc.h" +@@ -117,28 +116,16 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_PPC here. ++ */ ++ { "ppc", KEXEC_ARCH_DEFAULT }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strcmp(utsname.machine, "ppc") == 0) +- { +- /* For compatibility with older patches +- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_PPC here. +- */ +- info->kexec_flags |= KEXEC_ARCH_DEFAULT; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/ppc64/kexec-ppc64.c ++++ b/kexec/arch/ppc64/kexec-ppc64.c +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-ppc64.h" +@@ -681,28 +680,16 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* We are running a 32-bit kexec-tools on 64-bit ppc64. ++ * So pass KEXEC_ARCH_PPC64 here ++ */ ++ { "ppc64", KEXEC_ARCH_PPC64 }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strcmp(utsname.machine, "ppc64") == 0) +- { +- /* We are running a 32-bit kexec-tools on 64-bit ppc64. +- * So pass KEXEC_ARCH_PPC64 here +- */ +- info->kexec_flags |= KEXEC_ARCH_PPC64; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/s390/kexec-s390.c ++++ b/kexec/arch/s390/kexec-s390.c +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-s390.h" +@@ -95,9 +94,14 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ { "s390", KEXEC_ARCH_S390 }, ++ { "s390x", KEXEC_ARCH_S390 }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- info->kexec_flags |= KEXEC_ARCH_S390; + return 0; + } + +--- a/kexec/arch/sh/kexec-sh.c ++++ b/kexec/arch/sh/kexec-sh.c +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-sh.h" +@@ -99,31 +98,18 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_SH here. ++ */ ++ { "sh3", KEXEC_ARCH_DEFAULT }, ++ { "sh4", KEXEC_ARCH_DEFAULT }, ++ { "sh4a", KEXEC_ARCH_DEFAULT }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if ( (strcmp(utsname.machine, "sh3") == 0) || +- (strcmp(utsname.machine, "sh4") == 0) || +- (strcmp(utsname.machine, "sh4a") == 0)) +- { +- /* +- * For compatibility with older patches +- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_SH here. +- */ +- info->kexec_flags |= KEXEC_ARCH_DEFAULT; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/arch/x86_64/kexec-x86_64.c ++++ b/kexec/arch/x86_64/kexec-x86_64.c +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include "../../kexec.h" + #include "../../kexec-elf.h" + #include "../../kexec-syscall.h" +@@ -224,28 +223,16 @@ int arch_process_options(int argc, char + return 0; + } + ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_X86_64 here. ++ */ ++ { "x86_64", KEXEC_ARCH_DEFAULT }, ++ { 0 }, ++}; ++ + int arch_compat_trampoline(struct kexec_info *info) + { +- int result; +- struct utsname utsname; +- result = uname(&utsname); +- if (result < 0) { +- fprintf(stderr, "uname failed: %s\n", +- strerror(errno)); +- return -1; +- } +- if (strcmp(utsname.machine, "x86_64") == 0) +- { +- /* For compatibility with older patches +- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_X86_64 here. +- */ +- info->kexec_flags |= KEXEC_ARCH_DEFAULT; +- } +- else { +- fprintf(stderr, "Unsupported machine type: %s\n", +- utsname.machine); +- return -1; +- } + return 0; + } + +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -607,6 +607,7 @@ static int my_load(const char *type, int + int i = 0; + int result; + struct kexec_info info; ++ long native_arch; + int guess_only = 0; + + memset(&info, 0, sizeof(info)); +@@ -674,6 +675,11 @@ static int my_load(const char *type, int + return -1; + } + /* If we are not in native mode setup an appropriate trampoline */ ++ native_arch = physical_arch(); ++ if (native_arch < 0) { ++ return -1; ++ } ++ info.kexec_flags |= native_arch; + if (arch_compat_trampoline(&info) < 0) { + return -1; + } +--- a/kexec/kexec.h ++++ b/kexec/kexec.h +@@ -4,6 +4,7 @@ + #include "config.h" + + #include ++#include + #include + #define USE_BSD + #include +@@ -125,6 +126,14 @@ struct kexec_info { + unsigned long kern_size; + }; + ++struct arch_map_entry { ++ const char *machine; ++ unsigned long arch; ++}; ++ ++extern const struct arch_map_entry arches[]; ++long physical_arch(void); ++ + void usage(void); + int get_memory_ranges(struct memory_range **range, int *ranges, + unsigned long kexec_flags); +--- /dev/null ++++ b/kexec/phys_arch.c +@@ -0,0 +1,23 @@ ++#include "kexec.h" ++#include ++#include ++#include ++ ++long physical_arch(void) ++{ ++ struct utsname utsname; ++ int i, result = uname(&utsname); ++ if (result < 0) { ++ fprintf(stderr, "uname failed: %s\n", ++ strerror(errno)); ++ return -1; ++ } ++ ++ for (i = 0; arches[i].machine; ++i) ++ if (strcmp(utsname.machine, arches[i].machine) == 0) ++ return arches[i].arch; ++ ++ fprintf(stderr, "Unsupported machine type: %s\n", ++ utsname.machine); ++ return -1; ++} diff --git a/kexec-tools.changes b/kexec-tools.changes index 8f6da4f..be2e644 100644 --- a/kexec-tools.changes +++ b/kexec-tools.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon May 26 14:15:00 CEST 2008 - bwalle@suse.de + +- fix kexec unload (rckdump stop) on ppc64 (bnc#394216) + ------------------------------------------------------------------- Tue May 13 15:19:58 CEST 2008 - bwalle@suse.de diff --git a/kexec-tools.spec b/kexec-tools.spec index dee184d..27ae3b6 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -23,7 +23,7 @@ Requires: %insserv_prereq %fillup_prereq AutoReqProv: on Summary: Tools for fast kernel loading Version: 1.101 -Release: 195 +Release: 198 Source: %{name}-%{package_version}.tar.bz2 Source1: README.SUSE Url: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/ @@ -32,6 +32,8 @@ BuildRequires: zlib-devel Patch1: kexec-tools.ppc32-64bit-purgatory.patch Patch2: kexec-tools.gcc-bug.patch Patch3: kexec-tools-edd-support +Patch4: kexec-tools-refactor-architecture-detection +Patch5: kexec-tools-fix-arch-on-unload %description Kexec is a user space utility for loading another kernel and asking the @@ -55,6 +57,8 @@ Authors: %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build %{?suse_update_config -f} @@ -90,6 +94,8 @@ install -c -m 0644 kexec/kexec.8 $RPM_BUILD_ROOT%{_mandir}/man8 %endif %changelog +* Mon May 26 2008 bwalle@suse.de +- fix kexec unload (rckdump stop) on ppc64 (bnc#394216) * Tue May 13 2008 bwalle@suse.de - implement EDD (bnc#383210) * Tue Mar 25 2008 bwalle@suse.de