machine_kexec.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * machine_kexec.c for kexec
  3. * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
  4. *
  5. * This source code is licensed under the GNU General Public License,
  6. * Version 2. See the file COPYING for more details.
  7. */
  8. #include <linux/kexec.h>
  9. #include <linux/mm.h>
  10. #include <linux/delay.h>
  11. #include <asm/cacheflush.h>
  12. #include <asm/page.h>
  13. extern const unsigned char relocate_new_kernel[];
  14. extern const size_t relocate_new_kernel_size;
  15. extern unsigned long kexec_start_address;
  16. extern unsigned long kexec_indirection_page;
  17. int
  18. machine_kexec_prepare(struct kimage *kimage)
  19. {
  20. return 0;
  21. }
  22. void
  23. machine_kexec_cleanup(struct kimage *kimage)
  24. {
  25. }
  26. void
  27. machine_shutdown(void)
  28. {
  29. }
  30. void
  31. machine_crash_shutdown(struct pt_regs *regs)
  32. {
  33. }
  34. typedef void (*noretfun_t)(void) __attribute__((noreturn));
  35. void
  36. machine_kexec(struct kimage *image)
  37. {
  38. unsigned long reboot_code_buffer;
  39. unsigned long entry;
  40. unsigned long *ptr;
  41. reboot_code_buffer =
  42. (unsigned long)page_address(image->control_code_page);
  43. kexec_start_address = image->start;
  44. kexec_indirection_page =
  45. (unsigned long) phys_to_virt(image->head & PAGE_MASK);
  46. memcpy((void*)reboot_code_buffer, relocate_new_kernel,
  47. relocate_new_kernel_size);
  48. /*
  49. * The generic kexec code builds a page list with physical
  50. * addresses. they are directly accessible through KSEG0 (or
  51. * CKSEG0 or XPHYS if on 64bit system), hence the
  52. * pys_to_virt() call.
  53. */
  54. for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
  55. ptr = (entry & IND_INDIRECTION) ?
  56. phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
  57. if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
  58. *ptr & IND_DESTINATION)
  59. *ptr = (unsigned long) phys_to_virt(*ptr);
  60. }
  61. /*
  62. * we do not want to be bothered.
  63. */
  64. local_irq_disable();
  65. printk("Will call new kernel at %08lx\n", image->start);
  66. printk("Bye ...\n");
  67. __flush_cache_all();
  68. ((noretfun_t) reboot_code_buffer)();
  69. }