On Tue, Nov 27, 2001 at 05:07:54AM -0700, Matt Porter wrote:
> On Mon, Nov 26, 2001 at 10:17:28PM -0700, Tom Rini wrote:
> >
>

[...]

> That said, the two stage relocator is "The Right Thing To Do(tm)".
> It only needs to be two stage, though when the load point > -Ttext.

        I have fixed the relocate code so it does it in 2 stages ...
first it moves the relocate code, then it relocates the image, either
start first or end first, so it doesn't overwrite itself.

        The code is a bit verbose, but I guess size isn't really an issue
for the boot code.
>
> Why doesn't walnut simply call mktree with the option to load at
> it's -Ttext to avoid the original problem?  That's why I added the
> parameter to mktree and use it on the Spruce build...no need to
> do an extra copy if we control the load point.

        That would be too easy ;)  Besides, I had pretty much finished
the code when I got this email (would have finished it last night, except
that 'mtcr' and 'mtctr' are apparently both valid instructions ;(

        Simon

--
Simon Winwood
IBM T.J. Watson Research Center
-------------- next part --------------
===== arch/ppc/boot/common/relocate.S 1.5 vs edited =====
--- 1.5/arch/ppc/boot/common/relocate.S Mon Nov 19 19:17:42 2001
+++ edited/arch/ppc/boot/common/relocate.S      Tue Nov 27 14:49:50 2001
@@ -22,8 +22,10 @@
 #include <asm/cache.h>
 #include <asm/ppc_asm.h>

+#define GETSYM(reg, sym)       \
+       lis     reg, sym at h; ori      reg, reg, sym at l
+
        .text
-
        /* We get called from the early initialization code.
         * Register 3 has the address where we were loaded,
         * Register 4 contains any residual data passed from the
@@ -39,10 +41,9 @@
        mr      r11, r4

        /* compute the size of the whole image in words. */
-       lis     r4,start at h
-       ori     r4,r4,start at l
-       lis     r5,end at h
-       ori     r5,r5,end at l
+       GETSYM(r4,start)
+       GETSYM(r5,end)
+
        addi    r5,r5,3         /* round up */
        sub     r5,r5,r4        /* end - start */
        srwi    r5,r5,2
@@ -55,33 +56,94 @@
        cmp     cr0,r3,r4
        beq     start_ldr       /* If 0, we don't need to relocate */

-       /*
-        * No matter where we're loaded, move ourselves to -Ttext
-        * address.  Always copy end->start to accomodate images
-        * that cross the -Ttext boundary.
-        *
-        * Note: There are still many ways we can wipe ourselves out
-        * while relocating.  If we are loaded > -Ttext and the
-        * sizeof(zImage[.initrd]) > (load point - -Ttext) then we
-        * will wipe ourselves out.  We need a two stage relocater
-        * to handle this case. -MDP
+       /* Move this code somewhere safe.  This is max(load + size, end)
+        * r8 == load address
         */
-       lis     r4,end at h     /* Load ending address */
-       ori     r4,r4,end at l
-       mr      r5,r7           /* Get the # of longwords again */
-       mtctr   r5              /* Setup for a loop */
-       slwi    r5,r5,2         /* Get size in bytes */
-       add     r3, r3, r5      /* Calculate end of loaded image */
-       li      r6,0
-00:    lwzu    r5,-4(r3)       /* Load and decrement */
-       stwu    r5,-4(r4)       /* Store and decrement */
-       xor     r6,r6,r5        /* Are we done? */
-       bdnz    00b
-       lis     r3,start_ldr at h
-       ori     r3,r3,start_ldr at l
+       GETSYM(r4, start)
+       GETSYM(r5, end)
+
+       sub     r6, r5, r4
+       add     r6, r8, r6      /* r6 == phys(load + size) */
+
+       cmpw    r5, r6
+       bgt     1f
+       b       2f
+1:
+       mr      r6, r5
+2:
+       /* dest is in r6 */
+       /* Ensure alignment --- this code is precautionary */
+       addi    r6, r6, 4
+       li      r5, 0x0003
+       andc    r6, r6, r5
+
+       /* Find physical address and size of do_relocate */
+       GETSYM(r5, do_relocate)
+       GETSYM(r4, do_relocate_end)
+       GETSYM(r3, start)
+
+       /* Size to copy */
+       sub     r4, r4, r5
+       srwi    r4, r4, 2
+
+       /* Src addr to copy (= do_relocate - start + where_loaded) */
+       sub     r3, r5, r3
+       add     r5, r8, r3
+
+       /* Save dest */
+       mr      r3, r6
+
+       /* Do the copy */
+       mtctr   r4
+3:     lwz     r4, 0(r5)
+       stw     r4, 0(r3)
+       addi    r3, r3, 4
+       addi    r5, r5, 4
+       bdnz    3b
+
+       /* This will return to the relocated do_relocate */
+       mtlr    r6
+       b       flush_instruction_cache
+
+do_relocate:
+       /* We have 2 cases --- start < load, or start > load
+        * This determines whether we copy from the end, or the start.
+        * Its easier to have 2 loops than to have paramaterised
+        * loops.  Sigh.
+        */
+       li      r6, 0           /* Clear checksum */
+       mtctr   r7              /* Setup for a loop */
+
+       GETSYM(r4, start)
+       mr      r3, r8          /* Get the load addr */
+
+       cmp     cr0, r4, r3     /* If we need to copy from the end, do so */
+       bgt     do_relocate_from_end
+
+do_relocate_from_start:
+1:     lwz     r5, 0(r3)       /* Load and decrement */
+       stw     r5, 0(r4)       /* Store and decrement */
+       addi    r3, r3, 4
+       addi    r4, r4, 4
+       xor     r6,r6,r5        /* Update checksum */
+       bdnz    1b              /* Are we done? */
+       b       do_relocate_out /* Finished */
+
+do_relocate_from_end:
+       GETSYM(r3, end)
+       slwi    r4, r7, 2
+       add     r4, r8, r4      /* Get the physical end */
+1:     lwzu    r5, -4(r4)
+       stwu    r5, -4(r3)
+       xor     r6, r6, r5
+       bdnz    1b
+
+do_relocate_out:
+       GETSYM(r3,start_ldr)
        mtlr    r3              /* Easiest way to do an absolute jump */
        blr
-
+do_relocate_end:
+
 start_ldr:
 /* Some boards don't boot up with the I-cache enabled.  Do that
  * now because the decompress runs much faster that way.

Reply via email to