powerpc/boot: Add support for 64bit little endian wrapper
authorCédric Le Goater <clg@fr.ibm.com>
Thu, 24 Apr 2014 07:23:39 +0000 (09:23 +0200)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 28 Apr 2014 07:36:21 +0000 (17:36 +1000)
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>
arch/powerpc/boot/Makefile
arch/powerpc/boot/crt0.S
arch/powerpc/boot/ppc_asm.h
arch/powerpc/boot/pseries-head.S
arch/powerpc/boot/wrapper
arch/powerpc/boot/zImage.lds.S
arch/powerpc/platforms/Kconfig.cputype

index bed660d..a33c233 100644 (file)
@@ -22,8 +22,14 @@ all: $(obj)/zImage
 BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                 -fno-strict-aliasing -Os -msoft-float -pipe \
                 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
-                -isystem $(shell $(CROSS32CC) -print-file-name=include) \
-                -mbig-endian
+                -isystem $(shell $(CROSS32CC) -print-file-name=include)
+ifdef CONFIG_PPC64_BOOT_WRAPPER
+BOOTCFLAGS     += -m64
+endif
+ifdef CONFIG_CPU_BIG_ENDIAN
+BOOTCFLAGS     += -mbig-endian
+endif
+
 BOOTAFLAGS     := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 
 ifdef CONFIG_DEBUG_INFO
@@ -142,7 +148,11 @@ $(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: $(srctree)/scripts/dtc
 $(obj)/empty.c:
        @touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds: $(obj)/%: $(srctree)/$(src)/%.S
+       $(CROSS32CC) $(cpp_flags) -E -Wp,-MD,$(depfile) -P -Upowerpc \
+               -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+$(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S
        @cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
index 6892905..14de4f8 100644 (file)
@@ -275,6 +275,7 @@ prom:
        rfid
 
 1:     /* Return from OF */
+       FIXUP_ENDIAN
 
        /* Restore registers and return. */
        rldicl  r1,r1,0,32
index eb0e98b..35ea60c 100644 (file)
 #define SPRN_TBRL      268
 #define SPRN_TBRU      269
 
+#define FIXUP_ENDIAN                                              \
+       tdi   0, 0, 0x48; /* Reverse endian of b . + 8          */ \
+       b     $+36;       /* Skip trampoline if endian is good  */ \
+       .long 0x05009f42; /* bcl 20,31,$+4                      */ \
+       .long 0xa602487d; /* mflr r10                           */ \
+       .long 0x1c004a39; /* addi r10,r10,28                    */ \
+       .long 0xa600607d; /* mfmsr r11                          */ \
+       .long 0x01006b69; /* xori r11,r11,1                     */ \
+       .long 0xa6035a7d; /* mtsrr0 r10                         */ \
+       .long 0xa6037b7d; /* mtsrr1 r11                         */ \
+       .long 0x2400004c  /* rfid                               */
+
 #endif /* _PPC64_PPC_ASM_H */
index 655c3d2..6ef6e02 100644 (file)
@@ -1,5 +1,8 @@
+#include "ppc_asm.h"
+
        .text
 
        .globl _zimage_start
 _zimage_start:
+       FIXUP_ENDIAN
        b _zimage_start_lib
index 5889c44..1948cf8 100755 (executable)
@@ -40,6 +40,7 @@ cacheit=
 binary=
 gzip=.gz
 pie=
+format=
 
 # cross-compilation prefix
 CROSS=
@@ -136,6 +137,14 @@ if [ -z "$kernel" ]; then
     kernel=vmlinux
 fi
 
+elfformat="`${CROSS}objdump -p "$kernel" | grep 'file format' | awk '{print $4}'`"
+case "$elfformat" in
+    elf64-powerpcle)   format=elf64lppc        ;;
+    elf64-powerpc)     format=elf32ppc ;;
+    elf32-powerpc)     format=elf32ppc ;;
+esac
+
+
 platformo=$object/"$platform".o
 lds=$object/zImage.lds
 ext=strip
@@ -154,6 +163,10 @@ of)
 pseries)
     platformo="$object/pseries-head.o $object/of.o $object/epapr.o"
     link_address='0x4000000'
+    if [ "$format" != "elf32ppc" ]; then
+       link_address=
+       pie=-pie
+    fi
     make_space=n
     ;;
 maple)
@@ -379,7 +392,7 @@ if [ "$platform" != "miboot" ]; then
     if [ -n "$link_address" ] ; then
         text_start="-Ttext $link_address"
     fi
-    ${CROSS}ld -m elf32ppc -T $lds $text_start $pie -o "$ofile" \
+    ${CROSS}ld -m $format -T $lds $text_start $pie -o "$ofile" \
        $platformo $tmp $object/wrapper.a
     rm $tmp
 fi
index 2bd8731..861e721 100644 (file)
@@ -1,4 +1,10 @@
+#include <asm-generic/vmlinux.lds.h>
+
+#ifdef CONFIG_PPC64_BOOT_WRAPPER
+OUTPUT_ARCH(powerpc:common64)
+#else
 OUTPUT_ARCH(powerpc:common)
+#endif
 ENTRY(_zimage_start)
 EXTERN(_zimage_start)
 SECTIONS
@@ -16,7 +22,9 @@ SECTIONS
     *(.rodata*)
     *(.data*)
     *(.sdata*)
+#ifndef CONFIG_PPC64_BOOT_WRAPPER
     *(.got2)
+#endif
   }
   .dynsym : { *(.dynsym) }
   .dynstr : { *(.dynstr) }
@@ -27,7 +35,13 @@ SECTIONS
   }
   .hash : { *(.hash) }
   .interp : { *(.interp) }
-  .rela.dyn : { *(.rela*) }
+  .rela.dyn :
+  {
+#ifdef CONFIG_PPC64_BOOT_WRAPPER
+    __rela_dyn_start = .;
+#endif
+    *(.rela*)
+  }
 
   . = ALIGN(8);
   .kernel:dtb :
@@ -53,6 +67,15 @@ SECTIONS
     _initrd_end =  .;
   }
 
+#ifdef CONFIG_PPC64_BOOT_WRAPPER
+  .got :
+  {
+    __toc_start = .;
+    *(.got)
+    *(.toc)
+  }
+#endif
+
   . = ALIGN(4096);
   .bss       :
   {
index d9e2b19..43b65ad 100644 (file)
@@ -422,6 +422,7 @@ config CPU_BIG_ENDIAN
 
 config CPU_LITTLE_ENDIAN
        bool "Build little endian kernel"
+       select PPC64_BOOT_WRAPPER
        help
          Build a little endian kernel.
 
@@ -430,3 +431,7 @@ config CPU_LITTLE_ENDIAN
          little endian powerpc.
 
 endchoice
+
+config PPC64_BOOT_WRAPPER
+       def_bool n
+       depends on CPU_LITTLE_ENDIAN