123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- 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
- @@ -14,10 +14,6 @@
- #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;
- @@ -61,21 +57,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 +105,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 +117,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 */
-
|