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