Older big-endian ppc64 kernels don't include the FIXUP_ENDIAN check, meaning if we kexec from a little-endian kernel the target kernel will fail to boot. Returning to big-endian before we enter the target kernel ensures that the target kernel can boot whether or not it includes FIXUP_ENDIAN.
Signed-off-by: Samuel Mendoza-Jonas <sam...@au1.ibm.com> --- kexec_trampoline.S | 9 ++++++++- kexec_trampoline.h | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/kexec_trampoline.S b/kexec_trampoline.S index a3eb314..29537ab 100644 --- a/kexec_trampoline.S +++ b/kexec_trampoline.S @@ -41,6 +41,8 @@ #define r7 7 #define r8 8 #define r9 9 +#define r10 10 +#define r11 11 #ifdef __powerpc64__ #define LOAD ld @@ -50,8 +52,10 @@ #if defined(__LITTLE_ENDIAN__) #define STWX_BE stwbrx +#define BCTR .long 0x2004804e #elif defined(__BIG_ENDIAN__) #define STWX_BE stwx +#define BCTR bctr #else #error no endianness defined! #endif @@ -89,7 +93,10 @@ start: li r5,0 mtctr r4 - bctr + + RESET_ENDIAN + + BCTR . = KERNEL_ADDR_OFFSET kernel_addr: diff --git a/kexec_trampoline.h b/kexec_trampoline.h index 6485c88..909953b 100644 --- a/kexec_trampoline.h +++ b/kexec_trampoline.h @@ -27,7 +27,20 @@ /* Fixed offset in device tree for storing the physical ID of the boot CPU */ #define DT_CPU_OFFSET 28 -#ifndef __ASSEMBLY__ +#ifdef __ASSEMBLY__ +#define RESET_ENDIAN \ + mfmsr r9; \ + clrldi. r10,r9,63; \ + beq $+36; /* Already big-endian */ \ + bcl 20,31,$+4; \ + mflr r10; \ + addi r10,r10,28; \ + mfmsr r11; \ + xori r11,r11,1; \ + mtsrr0 r10; \ + mtsrr1 r11; \ + rfid; +#else extern char __trampoline_start[]; extern char __trampoline_end[]; @@ -48,6 +61,6 @@ static inline void trampoline_set_device_tree(void *p, unsigned long addr) *v = addr; } -#endif +#endif /* !__ASSEMBLY__ */ #endif -- 2.4.5 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev