test_kexec_jump.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <unistd.h>
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <linux/kexec.h>
  6. #include <linux/reboot.h>
  7. #include <sys/reboot.h>
  8. #include <sys/syscall.h>
  9. asm(
  10. " .code64\n"
  11. " .data\n"
  12. "purgatory_start:\n"
  13. // Trigger kexec debug exception handling
  14. " int3\n"
  15. // Set load address for next time
  16. " leaq purgatory_start_b(%rip), %r11\n"
  17. " movq %r11, 8(%rsp)\n"
  18. // Back to Linux
  19. " ret\n"
  20. // Same again
  21. "purgatory_start_b:\n"
  22. // Trigger kexec debug exception handling
  23. " int3\n"
  24. // Set load address for next time
  25. " leaq purgatory_start(%rip), %r11\n"
  26. " movq %r11, 8(%rsp)\n"
  27. // Back to Linux
  28. " ret\n"
  29. "purgatory_end:\n"
  30. ".previous"
  31. );
  32. extern char purgatory_start[], purgatory_end[];
  33. int main (void)
  34. {
  35. struct kexec_segment segment = {};
  36. int ret;
  37. segment.buf = purgatory_start;
  38. segment.bufsz = purgatory_end - purgatory_start;
  39. segment.mem = (void *)0x400000;
  40. segment.memsz = 0x1000;
  41. ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT);
  42. if (ret) {
  43. perror("kexec_load");
  44. exit(1);
  45. }
  46. ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
  47. if (ret) {
  48. perror("kexec reboot");
  49. exit(1);
  50. }
  51. ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
  52. if (ret) {
  53. perror("kexec reboot");
  54. exit(1);
  55. }
  56. printf("Success\n");
  57. return 0;
  58. }