[parisc-linux] parisc64 kernel and ret1 (gr29) setup

Richard Hirst rhirst@linuxcare.com
Tue, 23 Jan 2001 13:45:45 +0000


On Thu, Dec 21, 2000 at 04:00:06PM +0000, Richard Hirst wrote:
> Hi,
>   I tried calling ptrace() from a 32 bit app on a 64 bit kernel, and
> the kernel crashed.  sys_ptrace needs a 32 bit wrapper, but that is
> a seperate issue (I think).
> 
> It died at sys_ptrace+0x28, where it tried to use ret1.
> (ret1 = 00000000000517a1):

So, I still havn't fixed this, because I added a syscall wrapper for
sys_ptrace() and that masked the problem.  The wrapper didn't try to
use the incoming r29, and it initialised r29 before calling sys_ptrace().

64 bit functions expect r29 to point to a parameter save area.  I've
made changes in my tree to increase FRAME_SIZE from 64 to 128 bytes on
64 bit, and initialise r29 on syscall entry.  I havn't committed it yet.
I was just going to increase to 80 bytes - 64 bytes save area plus
16 for rp and sp - but Willy thought there was a requirement for the
stack to be 64 byte aligned.
Presumably r29 needs initialising on every call from entry.S and syscall.S
to C code, but I'm not over confident about that, so I thought I'd let
others see my diff so far.  Comments?

Richard


Index: arch/parisc/kernel/syscall.S
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/syscall.S,v
retrieving revision 1.49
diff -u -r1.49 syscall.S
--- syscall.S	2001/01/20 04:44:04	1.49
+++ syscall.S	2001/01/23 13:03:29
@@ -23,7 +23,13 @@
 	.level		1.1
 #endif
 	.text
-	
+
+#ifdef __LP64__
+#define FRAME_SIZE	128
+#else
+#define FRAME_SIZE	64
+#endif
+
 	.import syscall_exit,code
 	.import syscall_exit_rfi,code
 	.export linux_gateway_page
@@ -94,11 +100,12 @@
 	STREG	%r27, TASK_PT_SAR(%r1)
 
 	loadgp
-
-	ldo	TASK_SZ_ALGN+64(%r1),%r30	/* set up kernel stack */
 
-#ifndef __LP64__
-	/* no need to save these on stack because in wide mode the first 8
+	ldo	TASK_SZ_ALGN+FRAME_SIZE(%r1),%r30	/* set up kernel stack */
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#else
+	/* no need to save these on stack in wide mode because the first 8
 	 * args are passed in registers */
 	stw     %r22, -52(%r30)                 /* 5th argument */
 	stw     %r21, -56(%r30)                 /* 6th argument */
@@ -170,7 +177,7 @@
 	 * C bit set, a non-straced syscall entry results in C and D clear
 	 * in the saved PSW.
 	 */
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	ssm	0,%r2
 	STREG	%r2,TASK_PT_PSW(%r1)		/* Lower 8 bits only!! */
 	STREG	%r1,TASK_PT_CR30(%r1)
@@ -224,7 +231,7 @@
 	LDIL_FIXUP(%r1)
 	ldo     R%sys_call_table(%r1), %r19
 
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG   TASK_PT_GR20(%r1), %r20
 	LDREG   TASK_PT_GR26(%r1), %r26		/* Restore the users args */
 	LDREG   TASK_PT_GR25(%r1), %r25
@@ -260,10 +267,10 @@
 	makes a direct call to syscall_trace. */
 	
 tracesys_exit:
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	bl	syscall_trace, %r2
 	STREG   %r28,TASK_PT_GR28(%r1)          /* save return value now */
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG   TASK_PT_GR28(%r1), %r28		/* Restore return val. */
 
 	ldil	L%syscall_exit,%r1
@@ -278,7 +285,7 @@
 	ldo	R%tracesys_sigexit(%r2),%r2
 
 tracesys_sigexit:
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	bl	syscall_trace, %r2
 	nop
 
Index: arch/parisc/kernel/entry.S
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/entry.S,v
retrieving revision 1.58
diff -u -r1.58 entry.S
--- entry.S	2001/01/13 09:51:57	1.58
+++ entry.S	2001/01/23 13:03:36
@@ -48,7 +48,7 @@
 #include <asm/signal.h>
 
 #ifdef __LP64__
-#define FRAME_SIZE	64
+#define FRAME_SIZE	128
 #else
 #define FRAME_SIZE	64
 #endif
@@ -1787,7 +1787,7 @@
 
 	/* Set the return value for the child */
 child_return:
-	LDREG	TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+	LDREG	TASK_PT_GR19-TASK_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30),%r2
 	b	wrapper_exit
 	copy	%r0,%r28