kexec fails to boot kernels where CONFIG_RANDOMIZE_BASE=y is set

Baoquan He bhe at
Fri Aug 22 04:59:02 PDT 2014

On 08/22/14 at 11:19am, WANG Chao wrote:
> On 08/21/14 at 02:10pm, Vivek Goyal wrote:
> >
> > If kernel is being moved physically, then we potentially have the issue of
> > it stomping other things. So how do we make sure that it does not overwrite
> > initramfs, or previous kernel's page tables or something else?
> In case you don't read that part, memory of initrd, cmdline and others
> won't be overwritten.
> This work is done in x86/boot/compressed/aslr.c::mem_avoid_init().

Yeah, it's just as Chao said.

And I think it's still about the relocation calculation issue. I tried
the patch Lu Yinghai suggested, now kexec can work.

But this patch only make kexec work. The slot choosing still
doesn't work per the limitation checking, since only range below
CONFIG_RANDOMIZE_BASE_MAX_OFFSET can be chosen and kexec-tools
always likes putting kexec kernel from the end of system ram.

So we have 2 choices for kexec/kdump:
1) kexec/kdump kernel need not randomize the kernel starting point.
Since kexec/kdump kernel is only for testing or emergencey, its life is
not too long.

2) makes slots around the kernel input addr. This is only useful for
kexec. I can't imagine why kdump need it. 

Hi Thomas,
Could you test below patch? 

This is patch is from Lu Yinghai.
 arch/x86/boot/compressed/misc.c |   14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -235,8 +235,9 @@ static void error(char *x)
-static void handle_relocations(void *output, unsigned long output_len)
+static void handle_relocations(void *output_orig, void *output,
+			       unsigned long output_len)
 	int *reloc;
 	unsigned long delta, map, ptr;
@@ -247,7 +248,7 @@ static void handle_relocations(void *out
 	 * Calculate the delta between where vmlinux was linked to load
 	 * and where it was actually loaded.
-	delta = min_addr - LOAD_PHYSICAL_ADDR;
+	delta = min_addr - (unsigned long)output_orig;
 	if (!delta) {
 		debug_putstr("No relocation needed... ");
@@ -304,7 +305,8 @@ static void handle_relocations(void *out
-static inline void handle_relocations(void *output, unsigned long output_len)
+static inline void handle_relocations(void *output_orig, void *output,
+				      unsigned long output_len)
 { }
@@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
 				  unsigned char *output,
 				  unsigned long output_len)
+	unsigned char *output_orig = output;
 	real_mode = rmode;
@@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
 	debug_putstr("... ");
 	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
-	handle_relocations(output, output_len);
+	handle_relocations(output_orig, output, output_len);
 	debug_putstr("done.\nBooting the kernel.\n");
 	return output;

More information about the kexec mailing list