Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/boot: Add support for 64bit little endian wrapper

The code is only slightly modified : entry points now use the
FIXUP_ENDIAN trampoline to switch endian order. The 32bit wrapper
is kept for big endian kernels and 64bit is enforced for little
endian kernels with a PPC64_BOOT_WRAPPER config option.

The linker script is generated using the kernel preprocessor flags
to make use of the CONFIG_* definitions and the wrapper script is
modified to take into account the new elf64ppc format.

Finally, the zImage file is compiled as a position independent
executable (-pie) which makes it loadable at any address by the
firmware.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Cédric Le Goater and committed by
Benjamin Herrenschmidt
147c0516 2d9afb36

+72 -5
+13 -3
arch/powerpc/boot/Makefile
··· 22 22 BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ 23 23 -fno-strict-aliasing -Os -msoft-float -pipe \ 24 24 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ 25 - -isystem $(shell $(CROSS32CC) -print-file-name=include) \ 26 - -mbig-endian 25 + -isystem $(shell $(CROSS32CC) -print-file-name=include) 26 + ifdef CONFIG_PPC64_BOOT_WRAPPER 27 + BOOTCFLAGS += -m64 28 + endif 29 + ifdef CONFIG_CPU_BIG_ENDIAN 30 + BOOTCFLAGS += -mbig-endian 31 + endif 32 + 27 33 BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc 28 34 29 35 ifdef CONFIG_DEBUG_INFO ··· 148 142 $(obj)/empty.c: 149 143 @touch $@ 150 144 151 - $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S 145 + $(obj)/zImage.lds: $(obj)/%: $(srctree)/$(src)/%.S 146 + $(CROSS32CC) $(cpp_flags) -E -Wp,-MD,$(depfile) -P -Upowerpc \ 147 + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< 148 + 149 + $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S 152 150 @cp $< $@ 153 151 154 152 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
+1
arch/powerpc/boot/crt0.S
··· 275 275 rfid 276 276 277 277 1: /* Return from OF */ 278 + FIXUP_ENDIAN 278 279 279 280 /* Restore registers and return. */ 280 281 rldicl r1,r1,0,32
+12
arch/powerpc/boot/ppc_asm.h
··· 62 62 #define SPRN_TBRL 268 63 63 #define SPRN_TBRU 269 64 64 65 + #define FIXUP_ENDIAN \ 66 + tdi 0, 0, 0x48; /* Reverse endian of b . + 8 */ \ 67 + b $+36; /* Skip trampoline if endian is good */ \ 68 + .long 0x05009f42; /* bcl 20,31,$+4 */ \ 69 + .long 0xa602487d; /* mflr r10 */ \ 70 + .long 0x1c004a39; /* addi r10,r10,28 */ \ 71 + .long 0xa600607d; /* mfmsr r11 */ \ 72 + .long 0x01006b69; /* xori r11,r11,1 */ \ 73 + .long 0xa6035a7d; /* mtsrr0 r10 */ \ 74 + .long 0xa6037b7d; /* mtsrr1 r11 */ \ 75 + .long 0x2400004c /* rfid */ 76 + 65 77 #endif /* _PPC64_PPC_ASM_H */
+3
arch/powerpc/boot/pseries-head.S
··· 1 + #include "ppc_asm.h" 2 + 1 3 .text 2 4 3 5 .globl _zimage_start 4 6 _zimage_start: 7 + FIXUP_ENDIAN 5 8 b _zimage_start_lib
+14 -1
arch/powerpc/boot/wrapper
··· 40 40 binary= 41 41 gzip=.gz 42 42 pie= 43 + format= 43 44 44 45 # cross-compilation prefix 45 46 CROSS= ··· 137 136 kernel=vmlinux 138 137 fi 139 138 139 + elfformat="`${CROSS}objdump -p "$kernel" | grep 'file format' | awk '{print $4}'`" 140 + case "$elfformat" in 141 + elf64-powerpcle) format=elf64lppc ;; 142 + elf64-powerpc) format=elf32ppc ;; 143 + elf32-powerpc) format=elf32ppc ;; 144 + esac 145 + 146 + 140 147 platformo=$object/"$platform".o 141 148 lds=$object/zImage.lds 142 149 ext=strip ··· 163 154 pseries) 164 155 platformo="$object/pseries-head.o $object/of.o $object/epapr.o" 165 156 link_address='0x4000000' 157 + if [ "$format" != "elf32ppc" ]; then 158 + link_address= 159 + pie=-pie 160 + fi 166 161 make_space=n 167 162 ;; 168 163 maple) ··· 392 379 if [ -n "$link_address" ] ; then 393 380 text_start="-Ttext $link_address" 394 381 fi 395 - ${CROSS}ld -m elf32ppc -T $lds $text_start $pie -o "$ofile" \ 382 + ${CROSS}ld -m $format -T $lds $text_start $pie -o "$ofile" \ 396 383 $platformo $tmp $object/wrapper.a 397 384 rm $tmp 398 385 fi
+24 -1
arch/powerpc/boot/zImage.lds.S
··· 1 + #include <asm-generic/vmlinux.lds.h> 2 + 3 + #ifdef CONFIG_PPC64_BOOT_WRAPPER 4 + OUTPUT_ARCH(powerpc:common64) 5 + #else 1 6 OUTPUT_ARCH(powerpc:common) 7 + #endif 2 8 ENTRY(_zimage_start) 3 9 EXTERN(_zimage_start) 4 10 SECTIONS ··· 22 16 *(.rodata*) 23 17 *(.data*) 24 18 *(.sdata*) 19 + #ifndef CONFIG_PPC64_BOOT_WRAPPER 25 20 *(.got2) 21 + #endif 26 22 } 27 23 .dynsym : { *(.dynsym) } 28 24 .dynstr : { *(.dynstr) } ··· 35 27 } 36 28 .hash : { *(.hash) } 37 29 .interp : { *(.interp) } 38 - .rela.dyn : { *(.rela*) } 30 + .rela.dyn : 31 + { 32 + #ifdef CONFIG_PPC64_BOOT_WRAPPER 33 + __rela_dyn_start = .; 34 + #endif 35 + *(.rela*) 36 + } 39 37 40 38 . = ALIGN(8); 41 39 .kernel:dtb : ··· 66 52 *(.kernel:initrd) 67 53 _initrd_end = .; 68 54 } 55 + 56 + #ifdef CONFIG_PPC64_BOOT_WRAPPER 57 + .got : 58 + { 59 + __toc_start = .; 60 + *(.got) 61 + *(.toc) 62 + } 63 + #endif 69 64 70 65 . = ALIGN(4096); 71 66 .bss :
+5
arch/powerpc/platforms/Kconfig.cputype
··· 422 422 423 423 config CPU_LITTLE_ENDIAN 424 424 bool "Build little endian kernel" 425 + select PPC64_BOOT_WRAPPER 425 426 help 426 427 Build a little endian kernel. 427 428 ··· 431 430 little endian powerpc. 432 431 433 432 endchoice 433 + 434 + config PPC64_BOOT_WRAPPER 435 + def_bool n 436 + depends on CPU_LITTLE_ENDIAN