aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch')
-rw-r--r--target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch159
1 files changed, 159 insertions, 0 deletions
diff --git a/target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch b/target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch
new file mode 100644
index 0000000000..5ffc2e29bd
--- /dev/null
+++ b/target/linux/generic/patches-2.6.39/331-mips-kexec-enhanche-the-support.patch
@@ -0,0 +1,159 @@
+From 03cd81fbca6b91317ec1a7b3b3c09fb8d08f83a6 Mon Sep 17 00:00:00 2001
+From: Wu Zhangjin <wuzhangjin@gmail.com>
+Date: Tue, 11 Jan 2011 18:42:08 +0000
+Subject: MIPS: Kexec: Enhance the support
+
+Changes:
+ o Print more information in machine_kexec() for debugging
+ E.g. with this information, the kexec_start_address has been found
+ it was wrong with 64bit kernel / o32 kexec-tools. Which must be
+ fixed later.
+ o Link relocate_kernel.S to a section for future extension
+ This allows more functions can be added for the kexec relocation
+ part even written in C. to add code into that section, you just need
+ to mark your function or data with __kexec or
+ __attribute__((__section__(".__kexec.relocate")))
+
+TODO:
+
+1. Make 64bit kernel / o32|n32|64 kexec-tools works
+
+Fix the user-space kexec-tools, seems the tool only work for 32bit
+machine. So, we need to add 64bit support for it. The address of the
+entry point(kexec_start_address) is wrong and make the "kexec -e" fail.
+the real entry point must be read from the new kernel image by the
+user-space kexec-tools, otherwise, it will not work. The above 64bit
+support tested is 64bit kernel with o32 user-space kexec-tools. The root
+cause may be the different definition of virt_to_phys() and
+phys_to_virt() in the kexec-tools and kernel space for 64bit system /
+o32 kernel.
+
+Ref: http://www.linux-mips.org/archives/linux-mips/2009-08/msg00149.html
+
+2. Pass the arguments from kexec-tools to the new kernel image
+
+Please refer to: "MIPS: Loongson: Kexec: Pass parameters to new kernel"
+
+Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
+---
+--- a/arch/mips/include/asm/kexec.h
++++ b/arch/mips/include/asm/kexec.h
+@@ -36,6 +36,16 @@ static inline void crash_setup_regs(stru
+ }
+
+ #ifdef CONFIG_KEXEC
++
++#define __kexec __attribute__((__section__(".__kexec.relocate")))
++
++/* The linker tells us where the relocate_new_kernel part is. */
++extern const unsigned char __start___kexec_relocate;
++extern const unsigned char __end___kexec_relocate;
++
++extern unsigned long kexec_start_address;
++extern unsigned long kexec_indirection_page;
++
+ struct kimage;
+ extern unsigned long kexec_args[4];
+ extern int (*_machine_kexec_prepare)(struct kimage *);
+--- a/arch/mips/kernel/machine_kexec.c
++++ b/arch/mips/kernel/machine_kexec.c
+@@ -13,12 +13,6 @@
+ #include <asm/cacheflush.h>
+ #include <asm/page.h>
+
+-extern const unsigned char relocate_new_kernel[];
+-extern const size_t relocate_new_kernel_size;
+-
+-extern unsigned long kexec_start_address;
+-extern unsigned long kexec_indirection_page;
+-
+ int (*_machine_kexec_prepare)(struct kimage *) = NULL;
+ void (*_machine_kexec_shutdown)(void) = NULL;
+ void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
+@@ -61,21 +55,34 @@ typedef void (*noretfun_t)(void) __attri
+ void
+ machine_kexec(struct kimage *image)
+ {
++ unsigned long kexec_relocate_size;
+ unsigned long reboot_code_buffer;
+ unsigned long entry;
+ unsigned long *ptr;
+
++ kexec_relocate_size = (unsigned long)(&__end___kexec_relocate) -
++ (unsigned long)(&__start___kexec_relocate);
++ pr_info("kexec_relocate_size = %lu\n", kexec_relocate_size);
++
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
++ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer);
+
+ kexec_start_address =
+ (unsigned long) phys_to_virt(image->start);
++ pr_info("kexec_start_address(entry point of new kernel) = %p\n",
++ (void *)kexec_start_address);
+
+ kexec_indirection_page =
+ (unsigned long) phys_to_virt(image->head & PAGE_MASK);
++ pr_info("kexec_indirection_page = %p\n",
++ (void *)kexec_indirection_page);
+
+- memcpy((void*)reboot_code_buffer, relocate_new_kernel,
+- relocate_new_kernel_size);
++ memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
++ kexec_relocate_size);
++
++ pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
++ &__start___kexec_relocate, (void *)reboot_code_buffer);
+
+ /*
+ * The generic kexec code builds a page list with physical
+@@ -96,8 +103,8 @@ machine_kexec(struct kimage *image)
+ */
+ local_irq_disable();
+
+- printk("Will call new kernel at %08lx\n", image->start);
+- printk("Bye ...\n");
++ pr_info("Will call new kernel at %p\n", (void *)kexec_start_address);
++ pr_info("Bye ...\n");
+ __flush_cache_all();
+ #ifdef CONFIG_SMP
+ /* All secondary cpus now may jump to kexec_wait cycle */
+@@ -108,4 +115,3 @@ machine_kexec(struct kimage *image)
+ #endif
+ ((noretfun_t) reboot_code_buffer)();
+ }
+-
+--- a/arch/mips/kernel/relocate_kernel.S
++++ b/arch/mips/kernel/relocate_kernel.S
+@@ -14,6 +14,8 @@
+ #include <asm/stackframe.h>
+ #include <asm/addrspace.h>
+
++ .section .kexec.relocate, "ax"
++
+ LEAF(relocate_new_kernel)
+ PTR_L a0, arg0
+ PTR_L a1, arg1
+@@ -155,9 +157,3 @@ EXPORT(kexec_start_address)
+ EXPORT(kexec_indirection_page)
+ PTR 0
+ .size kexec_indirection_page, PTRSIZE
+-
+-relocate_new_kernel_end:
+-
+-EXPORT(relocate_new_kernel_size)
+- PTR relocate_new_kernel_end - relocate_new_kernel
+- .size relocate_new_kernel_size, PTRSIZE
+--- a/arch/mips/kernel/vmlinux.lds.S
++++ b/arch/mips/kernel/vmlinux.lds.S
+@@ -50,6 +50,10 @@ SECTIONS
+ *(.text.*)
+ *(.fixup)
+ *(.gnu.warning)
++ __start___kexec_relocate = .;
++ KEEP(*(.kexec.relocate))
++ KEEP(*(.__kexec.relocate))
++ __end___kexec_relocate = .;
+ } :text = 0
+ _etext = .; /* End of text section */
+