[parisc-linux-cvs] palo patch

Paul Bame bame@endor.fc.hp.com
Thu, 8 Feb 2001 21:08:45 -0700


Arrange for palo ipl to live at 3/4Mb aka 0x60000 instead of up at 5Mb
as currently is done.  According to PDC docs on pehc (which are violated
by firmware on c3k becaue it loads ipl at 0x29000 when max is stated to
be 0x20000), 3/4Mb is the lowest place ipl can be copied which
won't possibly result in an overlapping copy.  Tricks could be used
to go lower if necessary.

Move the palo stack and heap up to the top of the initial memory module
instead of directly following the palo executable.  This should
theoretically allow for huge ramdisks.

ipl/Makefile:
	Adjust relocation address from 0x00500000 to 0x00060000

ipl/crt0.S:
	Calculate new SP based on initial memory module size

	Implement a (crappy) copy and cache flush in assembly
	to avoid using C for this (C isn't always PIC enough).

ipl/ipl.c:
	Remove the unused ipl copying code

	Change heap initialization

ipl/lib.c:
	Change heap allocator to grow down instead of up

lib/common.h:
	Fix DECLARE_ALIGNED_STRING() macro which was using way too
	much memory which was caught by having the stack at top of RAM.
Index: ipl/Makefile
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/Makefile,v
retrieving revision 1.13
diff -u -r1.13 Makefile
--- Makefile	2001/01/19 04:27:36	1.13
+++ Makefile	2001/02/09 03:51:58
@@ -22,7 +22,7 @@
 VPATH=../lib:.
 
 CFLAGS	= -I. -I../lib -I../include -O2 -fwritable-strings -mdisable-fpregs -Wall
-LDFLAGS  = -N --Ttext 0x500000 -e '$$START$$'
+LDFLAGS  = -N --Ttext 0x60000 -e '$$START$$'
 
 all:	iplelf
 
Index: ipl/crt0.S
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/crt0.S,v
retrieving revision 1.9
diff -u -r1.9 crt0.S
--- crt0.S	2000/07/14 22:30:31	1.9
+++ crt0.S	2001/02/09 03:51:58
@@ -23,9 +23,9 @@
 				; image where we have to preserve the
 				; integrity of this ELF executable file.
 continue:
-	;! nuke the W bit
 	ssm	0,%r0
 
+	;! nuke the W bit
 	.level 2.0
 #define PSW_W_SM 0x200
 	rsm	PSW_W_SM, %r1
@@ -38,38 +38,48 @@
 bbb:
 	ldil	L%($global$), %dp
 	ldo	R%($global$)(%dp), %dp
+
+	/* find size of first memory module -- assume it is well aligned */
+#define IMM_MAX_MEM 0x39c
+	ldil	L%(IMM_MAX_MEM), %r3
+	ldo	R%(IMM_MAX_MEM)(%r3), %r3
+	ldw	0(%r3), %r3
+
+	/* stack is at top of initial mem module */
+#define STACK_SIZE (64 * 1024)
+	ldil	L%(STACK_SIZE), %r4
+	ldo	R%(STACK_SIZE)(%r4), %r4
 
-	;! Initial %sp = align(_end)
-	.import _end, code
-	ldil	L%_end, %sp
-	ldo	R%(_end)(%sp), %sp
-
-	;! At least a double-word-aligned stack is required esp for PDC
-	;! align sp to 2^6 for no particularly good reason
-	addi	63, %sp, %sp
-	depi	0,31,6,%sp
+	sub	%r3, %r4, %sp
+	copy	%sp, %arg2
 
-	;! save %sp in case I test unwind() code at some point
+	/* heap lives just below stack and grows down -- see iplmain() */
+
+	;! save %sp for calling iplmain()
 	copy	%sp, %r10
 
 	;! push a stack frame
 	ldo	64(%sp), %sp
 
-	;! store arg0 from the firmware
+	;! save arg0 from the firmware
 	stw	%arg0, -64(%sp)
-	;! stw	%arg1, -60(%sp)
 
-	ldil	L%$START$, %arg2
-	ldo	R%$START$(%arg2), %arg2
+	ldil	L%$START$, %arg0
+	ldo	R%$START$(%arg0), %arg0
 
-	;! call the C code to copy us to our correct destination
-	.import precopy, code
-	;! precopy(interactive, where-start-is-loaded, where-we-want-it)
-	bl	precopy, %r2
+	/* arg2 = _end - $$START$$ */
+	.import	_end
+	ldil	L%_end, %r5
+	ldo	R%_end(%r5), %r5
+	sub	%r5, %arg0, %arg2
+
+	;! copy us to our correct destination
+	/* memmove($START$, where-loaded, #bytes) */
+	bl	memmove, %r2
 	nop
 
+	/* restore saved arg0 from firmware */
 	ldw	-64(%sp), %arg0
-	;! ldw	-60(%sp), %arg1
 
 	.import iplmain,code
 	;! call iplmain via a register so we can jump from PIC space
@@ -104,15 +114,64 @@
 
 	bv	0(%ret0)
 	nop
+	/* shouldn't ever return */
 ret_kernel:
-
+	nop
+	/* if it does, it won't go past here */
 infinite_loop:
 	b .
 	nop
 
+	.text
+	.export	memmove
+	/* void *memmove(void * dest,const void *src,size_t count)
+	 *
+	 * combines overkill cache flushing with copying because
+	 * this loop is used to copy the bootloader to its final
+	 * location where it will then be executed.  You probably
+	 * shouldn't use this for generic C memory copying.
+	 *
+	 * note that memmove() can handle overlapping copies, but
+	 * that's not currently used because copying a running program
+	 * on top of itself is unwise.
+	 */
+memmove:
+	copy		%arg0, %ret0		/* arg0 must be returned */
+	cmpb,<<,n	%arg1, %arg0, mmreverse
+	ldo		-1(%arg2), %arg2
+	cmpib,=,n	-1, %arg2, mmret	/* if count==0 exit */
+mmloop1:    
+	ldb,ma		1(%arg1), %r19
+	ldo		-1(%arg2), %arg2
+	stb		%r19, 0(%arg0)
+	fdc		0(%arg0)
+	fic		0(%arg0)
+	ldo		1(%arg0), %arg0
+	cmpib,<>	-1, %arg2, mmloop1
+	nop
+	bv,n		%r0(%rp)
+mmreverse:    
+	add,l		%arg0, %arg2, %arg0
+	add,l		%arg1, %arg2, %arg1
+	ldo		-1(%arg2), %arg2
+	ldo		-1(%arg0), %arg0
+	cmpib,=,n	-1, %arg2, mmret
+mmloop2:    
+	ldb,mb		-1( %arg1), %r19
+	ldo		-1(%arg2), %arg2
+	stb		%r19, 0(%arg0)
+	fdc		0(%arg0)
+	fic		0(%arg0)
+	ldo		-1(%arg0), %arg0
+	cmpib,<>	-1, %arg2, mmloop2
+	nop
+mmret:	
+	bv,n		%r0(%rp)
+	nop
+
 	.data
 	.align 4
-	.export $global$,data
+	.export $global$, data
 $global$:
 	.word	4
 	.export commandline,data
Index: ipl/ipl.c
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/ipl.c,v
retrieving revision 1.12
diff -u -r1.12 ipl.c
--- ipl.c	2000/12/13 20:54:37	1.12
+++ ipl.c	2001/02/09 03:51:58
@@ -168,23 +168,6 @@
     return (rd_start != 0);
 }
 
-/* precopy gets called to copy the code from where was loaded to where
- * it was relocated, before iplmain() is called.  It is being executed
- * from a place other than where it is relocated, so beware mystery bugs.
- */
-
-void
-precopy(int is_interactive_notused, char *loaded_start, char *desired_start)
-{
-    extern char _end;
-
-    /* This seems to work even with a bogus %dp */
-    putchar('p');
-    memcpy(desired_start, loaded_start, &_end - desired_start);
-    flush_data_cache(desired_start, &_end - desired_start);
-    putchar('a');
-}
-
 static void
 join(char *out, int argc, char *argv[])
 {
@@ -272,12 +255,12 @@
     /* BSS clear */
     bzero(&_edata, &_end - &_edata);
 
-    /* allow 64k stack -- I use a fair amount of stack variables */
-    malloc_init(initialstackptr + 64 * 1024);
+    /* heap grows down from initial stack pointer */
+    malloc_init(initialstackptr);
 
-    putchar('l');	/* if you get this l and no more, string storage */
+    putchar('p');	/* if you get this p and no more, string storage */
 			/* in $GLOBAL$ is wrong or %dp is wrong */
-    puts("o ipl ");
+    puts("alo ipl ");
     puts(bld_info);
     puts("\r\n");
     if (0) printf("iplmain(%d)\n\r", is_interactive);
Index: ipl/lib.c
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/lib.c,v
retrieving revision 1.3
diff -u -r1.3 lib.c
--- lib.c	2000/07/12 21:20:50	1.3
+++ lib.c	2001/02/09 03:51:58
@@ -27,22 +27,12 @@
 
 char *malloc_aligned(int nbytes, int align)
 {
-    char *new;
-
-    if (__free == 0)
-    {
-	extern char _end;
-	__free = &_end;
-    }
-
+    /* allocate */
+    __free -= nbytes;
     /* align */
-    __free = (char *)(((unsigned)__free + (align - 1)) & ~(align - 1));
-
-    new = __free;
-
-    __free += nbytes;
+    __free = (char *)(((unsigned)__free) & ~(align - 1));
 
-    return new;
+    return __free;
 }
 
 char *malloc(int nbytes)
Index: lib/common.h
===================================================================
RCS file: /home/cvs/parisc/palo/lib/common.h,v
retrieving revision 1.4
diff -u -r1.4 common.h
--- common.h	2000/12/13 20:54:38	1.4
+++ common.h	2001/02/09 03:51:58
@@ -20,7 +20,7 @@
 #define PHYS(virtual)	((virtual) & 0x00ffffff)
 
 #define DECLARE_ALIGNED_STRING(name, length, align) \
-	char _##name[length * align]; \
+	char _##name[length + align]; \
 	char *name = (char *)(((unsigned)_##name + align - 1) & ~(align - 1))
 
 /* This struct is placed at the start of the boot loader executable.  The