Right, so we discovered on IRC that using a physical address as an entry point in a multiboot kernel isn't actually part of the Multiboot specification, however GRUB does have a workaround for it which is why it works. The kexec program from kexec-tools, however, does not support it, therefore tries to use the virtual address. To fix this I defined a symbol __phys_start which points to the physical entry address in the linker script, and set the entry point to it:
Code: Select all
ENTRY (__phys_start)
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH("i386")
VirtBase = 0xC0000000;
PhysBase = 0x100000;
PageSize = 0x1000;
SECTIONS
{
. = VirtBase + PhysBase;
__phys_start = _start - VirtBase;
This allows kexec-loader to load the kernel, and it still works in GRUB.
Also, I discovered that Linux uses hardware VGA scrolling, so output wasn't being displayed on the screen properly when control was passed to my kernel. In kexec-loader revision 297 there's a new configuration directive reset-vga which passes the --reset-vga option to kexec, which makes VGA output display properly.
EDIT: Image of r297:
http://www.solemnwarning.net/kexec-loader-r297.img.gz