Commit 93d3921042988317e94b1bcc2e19844efe0b7356

Authored by Cédric Le Goater
Committed by Benjamin Herrenschmidt
1 parent 002c39dba3

powerpc/boot: Define a routine to enter prom

This patch defines a 'prom' routine similar to 'enter_prom' in the
kernel.

The difference is in the MSR which is built before entering prom. Big
endian order is enforced as in the kernel but 32bit mode is not. It
prepares ground for the next patches which will introduce Little endian
order.

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

Showing 2 changed files with 77 additions and 0 deletions Side-by-side Diff

arch/powerpc/boot/crt0.S
... ... @@ -126,4 +126,75 @@
126 126  
127 127 /* Call start */
128 128 b start
  129 +
  130 +#ifdef __powerpc64__
  131 +
  132 +#define PROM_FRAME_SIZE 512
  133 +#define SAVE_GPR(n, base) std n,8*(n)(base)
  134 +#define REST_GPR(n, base) ld n,8*(n)(base)
  135 +#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
  136 +#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
  137 +#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
  138 +#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
  139 +#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
  140 +#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
  141 +#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
  142 +#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
  143 +
  144 +/* prom handles the jump into and return from firmware. The prom args pointer
  145 + is loaded in r3. */
  146 +.globl prom
  147 +prom:
  148 + mflr r0
  149 + std r0,16(r1)
  150 + stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
  151 +
  152 + SAVE_GPR(2, r1)
  153 + SAVE_GPR(13, r1)
  154 + SAVE_8GPRS(14, r1)
  155 + SAVE_10GPRS(22, r1)
  156 + mfcr r10
  157 + std r10,8*32(r1)
  158 + mfmsr r10
  159 + std r10,8*33(r1)
  160 +
  161 + /* remove MSR_LE from msr but keep MSR_SF */
  162 + mfmsr r10
  163 + rldicr r10,r10,0,62
  164 + mtsrr1 r10
  165 +
  166 + /* Load FW address, set LR to label 1, and jump to FW */
  167 + bl 0f
  168 +0: mflr r10
  169 + addi r11,r10,(1f-0b)
  170 + mtlr r11
  171 +
  172 + ld r10,(p_prom-0b)(r10)
  173 + mtsrr0 r10
  174 +
  175 + rfid
  176 +
  177 +1: /* Return from OF */
  178 +
  179 + /* Restore registers and return. */
  180 + rldicl r1,r1,0,32
  181 +
  182 + /* Restore the MSR (back to 64 bits) */
  183 + ld r10,8*(33)(r1)
  184 + mtmsr r10
  185 + isync
  186 +
  187 + /* Restore other registers */
  188 + REST_GPR(2, r1)
  189 + REST_GPR(13, r1)
  190 + REST_8GPRS(14, r1)
  191 + REST_10GPRS(22, r1)
  192 + ld r10,8*32(r1)
  193 + mtcr r10
  194 +
  195 + addi r1,r1,PROM_FRAME_SIZE
  196 + ld r0,16(r1)
  197 + mtlr r0
  198 + blr
  199 +#endif
arch/powerpc/boot/oflib.c
... ... @@ -27,11 +27,17 @@
27 27 __be32 args[10]; /* Input/output arguments. */
28 28 };
29 29  
  30 +#ifdef __powerpc64__
  31 +extern int prom(void *);
  32 +#else
30 33 static int (*prom) (void *);
  34 +#endif
31 35  
32 36 void of_init(void *promptr)
33 37 {
  38 +#ifndef __powerpc64__
34 39 prom = (int (*)(void *))promptr;
  40 +#endif
35 41 }
36 42  
37 43 #define ADDR(x) (u32)(unsigned long)(x)