More walnut boottime "fun"
Simon Winwood
sjw at cse.unsw.edu.au
Wed Nov 28 06:18:57 EST 2001
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.
More information about the Linuxppc-embedded
mailing list