core_32.c 2.1 KB

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