Make it easier to pass information into relocate_kernel by allowing it to have actual variables which are set from the real kernel. To do this, move it into the kernel's .data section, keeping its data and code together with linker script rules. Execute it from the *copy* instead of its original in the kernel data section, and clean it up a bit. Then do what I originally started with, which is add a GDT+IDT and some exception handling so we can actually catch problems instead of just suffering a triple fault and wondering why the world hates us. The serial output of the debug mode can be cleaned up a little, and it's even now possible to pass in information about which serial port to write to. I'll also work on resyncing with the i386 code and applying as many of these cleanups there as possible. And probably also make the 64-bit one use a separate image->arch.pgd instead of lumping it into a single 8KiB "control page" as we do on x86_64 at the moment. But the basic cleanups are probably ready for another round of bikeshedding. Testing the preserve_context mode with the following test case: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <linux/kexec.h> #include <linux/reboot.h> #include <sys/reboot.h> #include <sys/syscall.h> int main (void) { struct kexec_segment segment = {}; unsigned char purgatory[] = { 0x66, 0xba, 0xf8, 0x03, // mov $0x3f8, %dx 0xb0, 0x42, // mov $0x42, %al 0xee, // outb %al, (%dx) 0xc3, // ret }; int ret; segment.buf = &purgatory; segment.bufsz = sizeof(purgatory); segment.mem = (void *)0x400000; segment.memsz = 0x1000; ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT); if (ret) { perror("kexec_load"); exit(1); } return 0; } David Woodhouse (16): x86/kexec: Clean up and document register use in relocate_kernel_64.S x86/kexec: Use named labels in swap_pages in relocate_kernel_64.S x86/kexec: Restore GDT on return from preserve_context kexec x86/kexec: Only swap pages for preserve_context mode x86/kexec: Invoke copy of relocate_kernel() instead of the original x86/kexec: Move relocate_kernel to kernel .data section x86/kexec: Add data section to relocate_kernel x86/kexec: Copy control page into place in machine_kexec_prepare() x86/kexec: Drop page_list argument from relocate_kernel() x86/kexec: Eliminate writes through kernel mapping of relocate_kernel page x86/kexec: Clean up register usage in relocate_kernel() x86/kexec: Mark relocate_kernel page as ROX instead of RWX x86/kexec: Debugging support: load a GDT x86/kexec: Debugging support: Load an IDT and basic exception entry points x86/kexec: Debugging support: Dump registers on exception [DO NOT MERGE] x86/kexec: enable DEBUG arch/x86/include/asm/kexec.h | 13 +- arch/x86/include/asm/sections.h | 1 + arch/x86/kernel/machine_kexec_64.c | 55 +++-- arch/x86/kernel/relocate_kernel_64.S | 384 +++++++++++++++++++++++++++-------- arch/x86/kernel/vmlinux.lds.S | 12 +- 5 files changed, 358 insertions(+), 107 deletions(-)