--- kexec/arch/ppc64/fs2dt.c | 7 +-- kexec/arch/ppc64/kexec-elf-ppc64.c | 10 +++++ kexec/arch/ppc64/kexec-elf-rel-ppc64.c | 2 - purgatory/arch/ppc64/v2wrap.S | 61 +++++++++------------------------ 4 files changed, 30 insertions(+), 50 deletions(-) Index: kexec/arch/ppc64/fs2dt.c =================================================================== --- kexec/arch/ppc64/fs2dt.c.orig +++ kexec/arch/ppc64/fs2dt.c @@ -43,7 +43,6 @@ static char propnames[NAMESPACE] = { 0 } static unsigned dtstruct[TREEWORDS], *dt; static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0, 0 }; -static int initrd_found = 0; static int crash_param = 0; static char local_cmdline[COMMAND_LINE_SIZE] = { "" }; static unsigned *dt_len; /* changed len of modified cmdline @@ -343,10 +342,8 @@ static void putnode(void) putprops(dn, namelist, numlist); - /* Add initrd entries to the second kernel if first kernel does not - * have and second kernel needs. - */ - if (initrd_base && !initrd_found && !strcmp(basename,"/chosen/")) { + /* Add initrd entries to the second kernel */ + if (initrd_base && !strcmp(basename,"/chosen/")) { int len = 8; unsigned long long initrd_end; *dt++ = 3; Index: kexec/arch/ppc64/kexec-elf-ppc64.c =================================================================== --- kexec/arch/ppc64/kexec-elf-ppc64.c.orig +++ kexec/arch/ppc64/kexec-elf-ppc64.c @@ -89,6 +89,7 @@ int elf_ppc64_load(int argc, char **argv unsigned int my_panic_kernel; unsigned long my_stack, my_backup_start; unsigned long toc_addr; + unsigned int slave_code[256/sizeof (unsigned int)], master_entry; #define OPT_APPEND (OPT_ARCH_MAX+0) #define OPT_RAMDISK (OPT_ARCH_MAX+1) @@ -281,6 +282,15 @@ int elf_ppc64_load(int argc, char **argv elf_rel_set_symbol(&info->rhdr, "dt_offset", &my_dt_offset, sizeof(my_dt_offset)); + /* get slave code from new kernel, put in purgatory */ + elf_rel_get_symbol(&info->rhdr, "purgatory_start", slave_code, + sizeof(slave_code)); + master_entry = slave_code[0]; + memcpy(slave_code, info->segment[0].buf, sizeof(slave_code)); + slave_code[0] = master_entry; + elf_rel_set_symbol(&info->rhdr, "purgatory_start", slave_code, + sizeof(slave_code)); + if (info->kexec_flags & KEXEC_ON_CRASH) { my_panic_kernel = 1; /* Set panic flag */ Index: kexec/arch/ppc64/kexec-elf-rel-ppc64.c =================================================================== --- kexec/arch/ppc64/kexec-elf-rel-ppc64.c.orig +++ kexec/arch/ppc64/kexec-elf-rel-ppc64.c @@ -97,7 +97,7 @@ void machine_apply_elf_rel(struct mem_eh break; case R_PPC64_ADDR16_HA: - *(uint16_t *)location = ((value>>16) & 0xffff); + *(uint16_t *)location = (((value+0x8000)>>16) & 0xffff); break; case R_PPC64_ADDR16_HIGHEST: Index: purgatory/arch/ppc64/v2wrap.S =================================================================== --- purgatory/arch/ppc64/v2wrap.S.orig +++ purgatory/arch/ppc64/v2wrap.S @@ -45,13 +45,22 @@ oris rn,rn,name##@h; \ ori rn,rn,name##@l -# look a bit like a Linux kernel here ... + .machine ppc64 .globl purgatory_start purgatory_start: b master - tweq 0,0 + .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys +slave: b $ + .org purgatory_start + 0x100 # ABI: end of copied region + .size purgatory_start, . - purgatory_start + +# +# 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 +# + master: - or 1,1,1 # low priority to let other thread catchup + or 1,1,1 # low priority to let other threads catchup isync mr 17,3 # save cpu id to r17 mr 15,4 # save physical address in reg15 @@ -66,25 +75,7 @@ master: bl .purgatory nop - b 81f - .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys -slave: - # load slave spin code address and branch into that - LOADADDR(6,slave_spin) - ld 4,0(6) - mtctr 4 - bctr - -spin: .long 1 -slave_spin_code: - lis 5,spin@ha - lwz 5,spin@l(5) - cmpwi 0,5,0 - bne slave_spin_code - ba 0x60 - -81: # master continues here - or 3,3,3 # ok back to high, lets boot + or 3,3,3 # ok now to high priority, lets boot lis 6,0x1 mtctr 6 # delay a bit for slaves to catch up 83: bdnz 83b # before we overwrite 0-100 again @@ -99,30 +90,12 @@ slave_spin_code: 80: LOADADDR(6,kernel) ld 4,0(6) # load the kernel address - - addi 5,4,-8 # prepare copy with update form instructions - li 6,0x100/8 - mtctr 6 - li 6,-8 -85: ldu 7,8(5) - stdu 7,8(6) - bdnz 85b - li 5,0 # r5 will be 0 for kernel - dcbst 0,5 # store dcache, flush icache - dcbst 0,6 # 0 and 0xf8 covers us with 128 byte lines mtctr 4 # prepare branch too - sync - icbi 0,5 - icbi 0,6 - sync - isync - lis 6,spin@ha - li 0,0 - stw 0,spin@l(6) mr 3,16 # restore dt address - bctr # start kernel - -slave_spin: .llong slave_spin_code + lwz 7,0(4) # get the first instruction that we stole + stw 7,0(0) # and put it in the slave loop at 0 + # skip cache flush, do we care? + bctr # start kernel