331-mips-kexec-enhanche-the-support.patch 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. From 03cd81fbca6b91317ec1a7b3b3c09fb8d08f83a6 Mon Sep 17 00:00:00 2001
  2. From: Wu Zhangjin <wuzhangjin@gmail.com>
  3. Date: Tue, 11 Jan 2011 18:42:08 +0000
  4. Subject: MIPS: Kexec: Enhance the support
  5. Changes:
  6. o Print more information in machine_kexec() for debugging
  7. E.g. with this information, the kexec_start_address has been found
  8. it was wrong with 64bit kernel / o32 kexec-tools. Which must be
  9. fixed later.
  10. o Link relocate_kernel.S to a section for future extension
  11. This allows more functions can be added for the kexec relocation
  12. part even written in C. to add code into that section, you just need
  13. to mark your function or data with __kexec or
  14. __attribute__((__section__(".__kexec.relocate")))
  15. TODO:
  16. 1. Make 64bit kernel / o32|n32|64 kexec-tools works
  17. Fix the user-space kexec-tools, seems the tool only work for 32bit
  18. machine. So, we need to add 64bit support for it. The address of the
  19. entry point(kexec_start_address) is wrong and make the "kexec -e" fail.
  20. the real entry point must be read from the new kernel image by the
  21. user-space kexec-tools, otherwise, it will not work. The above 64bit
  22. support tested is 64bit kernel with o32 user-space kexec-tools. The root
  23. cause may be the different definition of virt_to_phys() and
  24. phys_to_virt() in the kexec-tools and kernel space for 64bit system /
  25. o32 kernel.
  26. Ref: http://www.linux-mips.org/archives/linux-mips/2009-08/msg00149.html
  27. 2. Pass the arguments from kexec-tools to the new kernel image
  28. Please refer to: "MIPS: Loongson: Kexec: Pass parameters to new kernel"
  29. Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
  30. ---
  31. --- a/arch/mips/include/asm/kexec.h
  32. +++ b/arch/mips/include/asm/kexec.h
  33. @@ -36,6 +36,16 @@ static inline void crash_setup_regs(stru
  34. }
  35. #ifdef CONFIG_KEXEC
  36. +
  37. +#define __kexec __attribute__((__section__(".__kexec.relocate")))
  38. +
  39. +/* The linker tells us where the relocate_new_kernel part is. */
  40. +extern const unsigned char __start___kexec_relocate;
  41. +extern const unsigned char __end___kexec_relocate;
  42. +
  43. +extern unsigned long kexec_start_address;
  44. +extern unsigned long kexec_indirection_page;
  45. +
  46. struct kimage;
  47. extern unsigned long kexec_args[4];
  48. extern int (*_machine_kexec_prepare)(struct kimage *);
  49. --- a/arch/mips/kernel/machine_kexec.c
  50. +++ b/arch/mips/kernel/machine_kexec.c
  51. @@ -14,10 +14,6 @@
  52. #include <asm/page.h>
  53. extern const unsigned char relocate_new_kernel[];
  54. -extern const size_t relocate_new_kernel_size;
  55. -
  56. -extern unsigned long kexec_start_address;
  57. -extern unsigned long kexec_indirection_page;
  58. int (*_machine_kexec_prepare)(struct kimage *) = NULL;
  59. void (*_machine_kexec_shutdown)(void) = NULL;
  60. @@ -61,21 +57,34 @@ typedef void (*noretfun_t)(void) __attri
  61. void
  62. machine_kexec(struct kimage *image)
  63. {
  64. + unsigned long kexec_relocate_size;
  65. unsigned long reboot_code_buffer;
  66. unsigned long entry;
  67. unsigned long *ptr;
  68. + kexec_relocate_size = (unsigned long)(&__end___kexec_relocate) -
  69. + (unsigned long)(&__start___kexec_relocate);
  70. + pr_info("kexec_relocate_size = %lu\n", kexec_relocate_size);
  71. +
  72. reboot_code_buffer =
  73. (unsigned long)page_address(image->control_code_page);
  74. + pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer);
  75. kexec_start_address =
  76. (unsigned long) phys_to_virt(image->start);
  77. + pr_info("kexec_start_address(entry point of new kernel) = %p\n",
  78. + (void *)kexec_start_address);
  79. kexec_indirection_page =
  80. (unsigned long) phys_to_virt(image->head & PAGE_MASK);
  81. + pr_info("kexec_indirection_page = %p\n",
  82. + (void *)kexec_indirection_page);
  83. - memcpy((void*)reboot_code_buffer, relocate_new_kernel,
  84. - relocate_new_kernel_size);
  85. + memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
  86. + kexec_relocate_size);
  87. +
  88. + pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
  89. + &__start___kexec_relocate, (void *)reboot_code_buffer);
  90. /*
  91. * The generic kexec code builds a page list with physical
  92. @@ -96,8 +105,8 @@ machine_kexec(struct kimage *image)
  93. */
  94. local_irq_disable();
  95. - printk("Will call new kernel at %08lx\n", image->start);
  96. - printk("Bye ...\n");
  97. + pr_info("Will call new kernel at %p\n", (void *)kexec_start_address);
  98. + pr_info("Bye ...\n");
  99. __flush_cache_all();
  100. #ifdef CONFIG_SMP
  101. /* All secondary cpus now may jump to kexec_wait cycle */
  102. @@ -108,4 +117,3 @@ machine_kexec(struct kimage *image)
  103. #endif
  104. ((noretfun_t) reboot_code_buffer)();
  105. }
  106. -
  107. --- a/arch/mips/kernel/relocate_kernel.S
  108. +++ b/arch/mips/kernel/relocate_kernel.S
  109. @@ -14,6 +14,8 @@
  110. #include <asm/stackframe.h>
  111. #include <asm/addrspace.h>
  112. + .section .kexec.relocate, "ax"
  113. +
  114. LEAF(relocate_new_kernel)
  115. PTR_L a0, arg0
  116. PTR_L a1, arg1
  117. @@ -155,9 +157,3 @@ EXPORT(kexec_start_address)
  118. EXPORT(kexec_indirection_page)
  119. PTR 0
  120. .size kexec_indirection_page, PTRSIZE
  121. -
  122. -relocate_new_kernel_end:
  123. -
  124. -EXPORT(relocate_new_kernel_size)
  125. - PTR relocate_new_kernel_end - relocate_new_kernel
  126. - .size relocate_new_kernel_size, PTRSIZE
  127. --- a/arch/mips/kernel/vmlinux.lds.S
  128. +++ b/arch/mips/kernel/vmlinux.lds.S
  129. @@ -50,6 +50,10 @@ SECTIONS
  130. *(.text.*)
  131. *(.fixup)
  132. *(.gnu.warning)
  133. + __start___kexec_relocate = .;
  134. + KEEP(*(.kexec.relocate))
  135. + KEEP(*(.__kexec.relocate))
  136. + __end___kexec_relocate = .;
  137. } :text = 0
  138. _etext = .; /* End of text section */