Add code to check if the processor is in 64 or 32 bit mode using
only instructions from the 32 bit subset.  If the processor is in
64 bit mode, switch to 32 bit mode by clearing MSR[SF].

Also add a 64 bit procedure descriptor to use as a elf64 entry
point.

Signed-off-by: Milton Miller <[EMAIL PROTECTED]>
--- 
Merged into crt0.S instead of a separate file with a separate entry
point.

Index: kernel/arch/powerpc/boot/crt0.S
===================================================================
--- kernel.orig/arch/powerpc/boot/crt0.S        2007-07-10 03:33:36.000000000 
-0500
+++ kernel/arch/powerpc/boot/crt0.S     2007-07-10 03:39:08.000000000 -0500
@@ -17,11 +17,47 @@
 _zimage_start_opd:
        .long   _zimage_start, 0, 0, 0
 
+       /* a procedure descriptor used when pretending to be elf64_powerpc */
+       .balign 8
+       .globl  _zimage_start_64
+_zimage_start_64:
+       .long   0, _zimage_start        /* big endian, supported reloc ppc32 */
+       .long   0, 0, 0, 0, 0, 0
+
+
        .weak   _zimage_start
        .globl  _zimage_start
 _zimage_start:
        .globl  _zimage_start_lib
 _zimage_start_lib:
+       /* Check if the processor is running in 32 bit mode, using
+        * only 32 bit instructions which should be safe on 32 and
+        * 64 bit processors.
+        *
+        * Subtract the bottom 32 bits of MSR from the full value
+        * recording the result.  Since MSR[SF] is in the high word,
+        * the result will be not-equal iff in 32 bit mode (either
+        * the processor is a 32 bit processor or MSR[SF] = 0).
+        */
+       mfmsr   r0              /* grab whole msr               */
+       rlwinm  r8,r0,0,0,31    /* extract bottom word          */
+       subf.   r8,r8,r0        /* subtract, same?              */
+       beq     0f              /* yes: we are 32 bit mode      */
+
+       /* We are in 64-bit mode.  This program must run in 32 bit
+        * mode.  Assume we are actually running somewhere in the
+        * low 32 bits of the address space, so we can just turn
+        * off MSR[SF] which is bit 0.
+        */
+       .machine push
+       .machine "ppc64"
+       rldicl  r0,r0,0,1
+       sync
+       mtmsrd  r0
+       isync
+       .machine pop
+0:     /* We are now in 32-bit mode */
+
        /* Work out the offset between the address we were linked at
           and the address where we're running. */
        bl      1f
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to