machine_kexec_32.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*
  2. * PPC32 code to handle Linux booting another kernel.
  3. *
  4. * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
  5. * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
  6. * Copyright (C) 2005 IBM Corporation.
  7. *
  8. * This source code is licensed under the GNU General Public License,
  9. * Version 2. See the file COPYING for more details.
  10. */
  11. #include <linux/kexec.h>
  12. #include <linux/mm.h>
  13. #include <linux/string.h>
  14. #include <asm/cacheflush.h>
  15. #include <asm/hw_irq.h>
  16. #include <asm/io.h>
  17. typedef NORET_TYPE void (*relocate_new_kernel_t)(
  18. unsigned long indirection_page,
  19. unsigned long reboot_code_buffer,
  20. unsigned long start_address) ATTRIB_NORET;
  21. /*
  22. * This is a generic machine_kexec function suitable at least for
  23. * non-OpenFirmware embedded platforms.
  24. * It merely copies the image relocation code to the control page and
  25. * jumps to it.
  26. * A platform specific function may just call this one.
  27. */
  28. void default_machine_kexec(struct kimage *image)
  29. {
  30. extern const unsigned char relocate_new_kernel[];
  31. extern const unsigned int relocate_new_kernel_size;
  32. unsigned long page_list;
  33. unsigned long reboot_code_buffer, reboot_code_buffer_phys;
  34. relocate_new_kernel_t rnk;
  35. /* Interrupts aren't acceptable while we reboot */
  36. local_irq_disable();
  37. page_list = image->head;
  38. /* we need both effective and real address here */
  39. reboot_code_buffer =
  40. (unsigned long)page_address(image->control_code_page);
  41. reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
  42. /* copy our kernel relocation code to the control code page */
  43. memcpy((void *)reboot_code_buffer, relocate_new_kernel,
  44. relocate_new_kernel_size);
  45. flush_icache_range(reboot_code_buffer,
  46. reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
  47. printk(KERN_INFO "Bye!\n");
  48. /* now call it */
  49. rnk = (relocate_new_kernel_t) reboot_code_buffer;
  50. (*rnk)(page_list, reboot_code_buffer_phys, image->start);
  51. }
  52. int default_machine_kexec_prepare(struct kimage *image)
  53. {
  54. return 0;
  55. }