diff -up kexec-tools-2.0.0/kexec/arch/ppc64/crashdump-ppc64.h.orig kexec-tools-2.0.0/kexec/arch/ppc64/crashdump-ppc64.h --- kexec-tools-2.0.0/kexec/arch/ppc64/crashdump-ppc64.h.orig 2008-07-14 07:28:19.000000000 -0400 +++ kexec-tools-2.0.0/kexec/arch/ppc64/crashdump-ppc64.h 2009-11-02 13:08:55.000000000 -0500 @@ -23,6 +23,8 @@ void add_usable_mem_rgns(unsigned long l #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) #define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) +#define KERNEL_RUN_AT_ZERO_MAGIC 0x72756e30 /* "run0" */ + extern uint64_t crash_base; extern uint64_t crash_size; extern unsigned int rtas_base; diff -up kexec-tools-2.0.0/kexec/arch/ppc64/fs2dt.c.orig kexec-tools-2.0.0/kexec/arch/ppc64/fs2dt.c --- kexec-tools-2.0.0/kexec/arch/ppc64/fs2dt.c.orig 2008-07-14 07:28:19.000000000 -0400 +++ kexec-tools-2.0.0/kexec/arch/ppc64/fs2dt.c 2009-11-02 13:08:55.000000000 -0500 @@ -41,7 +41,7 @@ static char pathname[MAXPATH], *pathstart; static char propnames[NAMESPACE] = { 0 }; -static unsigned dtstruct[TREEWORDS], *dt; +static unsigned dtstruct[TREEWORDS] __attribute__ ((aligned (8))), *dt; static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0, 0 }; static int crash_param = 0; diff -up kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-ppc64.c.orig kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-ppc64.c --- kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-ppc64.c.orig 2008-07-14 07:28:19.000000000 -0400 +++ kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-ppc64.c 2009-11-02 13:08:55.000000000 -0500 @@ -92,6 +92,7 @@ int elf_ppc64_load(int argc, char **argv unsigned int my_panic_kernel; uint64_t my_stack, my_backup_start; uint64_t toc_addr; + uint32_t my_run_at_load; unsigned int slave_code[256/sizeof (unsigned int)], master_entry; #define OPT_APPEND (OPT_ARCH_MAX+0) @@ -307,6 +308,18 @@ int elf_ppc64_load(int argc, char **argv my_backup_start = info->backup_start; elf_rel_set_symbol(&info->rhdr, "backup_start", &my_backup_start, sizeof(my_backup_start)); + + /* Tell relocatable kernel to run at load address + * via word before slave code in purgatory + */ + + elf_rel_get_symbol(&info->rhdr, "run_at_load", &my_run_at_load, + sizeof(my_run_at_load)); + if (my_run_at_load == KERNEL_RUN_AT_ZERO_MAGIC) + my_run_at_load = 1; + /* else it should be a fixed offset image */ + elf_rel_set_symbol(&info->rhdr, "run_at_load", &my_run_at_load, + sizeof(my_run_at_load)); } /* Set stack address */ @@ -325,10 +338,13 @@ int elf_ppc64_load(int argc, char **argv my_backup_start = 0; my_stack = 0; toc_addr = 0; + my_run_at_load = 0; elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel)); elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset, sizeof(my_dt_offset)); + elf_rel_get_symbol(&info->rhdr, "run_at_load", &my_run_at_load, + sizeof(my_run_at_load)); elf_rel_get_symbol(&info->rhdr, "panic_kernel", &my_panic_kernel, sizeof(my_panic_kernel)); elf_rel_get_symbol(&info->rhdr, "backup_start", &my_backup_start, @@ -340,6 +356,7 @@ int elf_ppc64_load(int argc, char **argv fprintf(stderr, "info->entry is %p\n", info->entry); fprintf(stderr, "kernel is %lx\n", my_kernel); fprintf(stderr, "dt_offset is %lx\n", my_dt_offset); + fprintf(stderr, "run_at_load flag is %x\n", my_run_at_load); fprintf(stderr, "panic_kernel is %x\n", my_panic_kernel); fprintf(stderr, "backup_start is %lx\n", my_backup_start); fprintf(stderr, "stack is %lx\n", my_stack); diff -up kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-rel-ppc64.c.orig kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-rel-ppc64.c --- kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-rel-ppc64.c.orig 2008-07-14 07:28:19.000000000 -0400 +++ kexec-tools-2.0.0/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2009-11-02 13:08:55.000000000 -0500 @@ -60,6 +60,10 @@ void machine_apply_elf_rel(struct mem_eh *(uint64_t *)location = value; break; + case R_PPC64_REL32: + *(uint32_t *)location = value - (uint32_t)location; + break; + case R_PPC64_TOC: *(uint64_t *)location = my_r2(ehdr); break; diff -up kexec-tools-2.0.0/purgatory/arch/ppc64/v2wrap.S.orig kexec-tools-2.0.0/purgatory/arch/ppc64/v2wrap.S --- kexec-tools-2.0.0/purgatory/arch/ppc64/v2wrap.S.orig 2008-07-14 07:28:19.000000000 -0400 +++ kexec-tools-2.0.0/purgatory/arch/ppc64/v2wrap.S 2009-11-02 13:08:55.000000000 -0500 @@ -49,6 +49,11 @@ .machine ppc64 .globl purgatory_start purgatory_start: b master + .org purgatory_start + 0x5c # ABI: possible run_at_load flag at 0x5c + .globl run_at_load +run_at_load: + .long 0 + .size run_at_load, . - run_at_load .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys slave: b $ .org purgatory_start + 0x100 # ABI: end of copied region @@ -56,7 +61,7 @@ slave: b $ # # The above 0x100 bytes at purgatory_start are replaced with the -# code from the kernel (or next stage) by kexec/arch/ppc64/kexec-ppc64.c +# code from the kernel (or next stage) by kexec/arch/ppc64/kexec-elf-ppc64.c # master: @@ -90,6 +95,9 @@ master: 80: LOADADDR(6,kernel) ld 4,0(6) # load the kernel address + LOADADDR(6,run_at_load) # the load flag + lwz 7,0(6) # possibly patched by kexec-elf-ppc64 + stw 7,0x5c(4) # and patch it into the kernel li 5,0 # r5 will be 0 for kernel mtctr 4 # prepare branch too mr 3,16 # restore dt address