This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PPC32 fix for BZ 357


This patch fixes the bugzilla 357 and adds a stack clobber test to tst-setcontext.c. While I as at it I improved the scheduling and cleaned up the comments.




2004-09-02  Steven Munroe  <sjmunroe@us.ibm.com>

	[BZ #357]
	* stdlib/tst-setcontext.c (test_stack): Added test for stack clobber.
	(main): Call test_stack.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S
	(__getcontext): Push stack frame then save parms in local frame.
	Improve instruction scheduling.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S
	(__swapcontext): Push stack frame then save parms in local frame.
	Improve instruction scheduling.


diff -urN libc23-cvstip-20040830/stdlib/tst-setcontext.c libc23/stdlib/tst-setcontext.c
--- libc23-cvstip-20040830/stdlib/tst-setcontext.c	2002-08-30 22:21:40.000000000 -0500
+++ libc23/stdlib/tst-setcontext.c	2004-09-02 10:10:28.055274880 -0500
@@ -72,6 +72,55 @@
   was_in_f2 = 1;
 }
 
+void 
+test_stack(volatile int a, volatile int b, 
+           volatile int c, volatile int d)
+{
+  volatile int e = 5;
+  volatile int f = 6;
+  ucontext_t uc;
+
+  /* Test for cases where getcontext is clobbering the callers
+     stack, including parameters.  */
+  getcontext(&uc);
+	
+  if (a != 1)
+    {
+      printf ("%s: getcontext clobbers parm a\n", __FUNCTION__);
+      exit (1);
+    }
+	
+  if (b != 2)
+    {
+      printf ("%s: getcontext clobbers parm b\n", __FUNCTION__);
+      exit (1);
+    }
+	
+  if (c != 3)
+    {
+      printf ("%s: getcontext clobbers parm c\n", __FUNCTION__);
+      exit (1);
+    }
+	
+  if (d != 4)
+    {
+      printf ("%s: getcontext clobbers parm d\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (e != 5)
+    {
+      printf ("%s: getcontext clobbers varible e\n", __FUNCTION__);
+      exit (1);
+    }
+	
+  if (f != 6)
+    {
+      printf ("%s: getcontext clobbers variable f\n", __FUNCTION__);
+      exit (1);
+    }
+}
+
 volatile int global;
 
 int
@@ -88,6 +137,8 @@
       printf ("%s: getcontext: %m\n", __FUNCTION__);
       exit (1);
     }
+  
+  test_stack (1, 2, 3, 4);
 
   /* Play some tricks with this context.  */
   if (++global == 1)
diff -urN libc23-cvstip-20040830/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S libc23/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S
--- libc23-cvstip-20040830/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S	2004-06-15 15:02:20.000000000 -0500
+++ libc23/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S	2004-09-02 12:46:16.064221704 -0500
@@ -27,18 +27,22 @@
 
 	.machine	"altivec"
 ENTRY(__getcontext)
+	stwu	r1,-16(r1)
+/* Insure that the _UC_REGS start on a quadword boundary.  */
 	stw	r3,_FRAME_PARM_SAVE1(r1)
 	addi	r3,r3,_UC_REG_SPACE+12
 	clrrwi  r3,r3,4
+
+/* Save the general purpose registers */
 	stw	r0,_UC_GREGS+(PT_R0*4)(r3)
 	mflr	r0
-	stw	r1,_UC_GREGS+(PT_R1*4)(r3)
-	stwu	r1,-16(r1)
+	stw	r2,_UC_GREGS+(PT_R2*4)(r3)
+	stw	r4,_UC_GREGS+(PT_R4*4)(r3)
+/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
+   return address.  */
 	stw	r0,_UC_GREGS+(PT_LNK*4)(r3)
 	stw	r0,_UC_GREGS+(PT_NIP*4)(r3)
 	stw	r0,_FRAME_LR_SAVE+16(r1)
-	stw	r2,_UC_GREGS+(PT_R2*4)(r3)
-	stw	r4,_UC_GREGS+(PT_R4*4)(r3)
 	stw	r5,_UC_GREGS+(PT_R5*4)(r3)
 	stw	r6,_UC_GREGS+(PT_R6*4)(r3)
 	stw	r7,_UC_GREGS+(PT_R7*4)(r3)
@@ -66,23 +70,28 @@
 	stw	r29,_UC_GREGS+(PT_R29*4)(r3)
 	stw	r30,_UC_GREGS+(PT_R30*4)(r3)
 	stw	r31,_UC_GREGS+(PT_R31*4)(r3)
-	mfctr	r0
-	stw	r0,_UC_GREGS+(PT_CTR*4)(r3)
-	mfxer	r0
-	stw	r0,_UC_GREGS+(PT_XER*4)(r3)
-	mfcr	r0
-	stw	r0,_UC_GREGS+(PT_CCR*4)(r3)
-
-	/* Set the return value of getcontext to "success".  R3 is the only
-	   register whose value is not preserved in the saved context.  */
+/* Save the value of R1.  We had to push the stack before we
+   had the address of uc_reg_space.  So compute the address of
+   the callers stack pointer and save it as R1.  */
+	addi	r8,r1,16
 	li	r0,0
+/* Save the count, exception and condition registers.  */
+	mfctr	r11
+	mfxer	r10
+	mfcr	r9
+	stw	r8,_UC_GREGS+(PT_R1*4)(r3)
+	stw	r11,_UC_GREGS+(PT_CTR*4)(r3)
+	stw	r10,_UC_GREGS+(PT_XER*4)(r3)
+	stw	r9,_UC_GREGS+(PT_CCR*4)(r3)
+/* Set the return value of getcontext to "success".  R3 is the only
+   register whose value is not preserved in the saved context.  */
 	stw	r0,_UC_GREGS+(PT_R3*4)(r3)
 
-	/* Zero fill fields that can't be set in user state. */
+/* Zero fill fields that can't be set in user state. */
 	stw	r0,_UC_GREGS+(PT_MSR*4)(r3)
 	stw	r0,_UC_GREGS+(PT_MQ*4)(r3)
 
-	/* Save the floating-point registers */
+/* Save the floating-point registers */
 	stfd	fp0,_UC_FREGS+(0*8)(r3)
 	stfd	fp1,_UC_FREGS+(1*8)(r3)
 	stfd	fp2,_UC_FREGS+(2*8)(r3)
@@ -136,21 +145,31 @@
 	lwz     r7,_dl_hwcap@l(r7)
 #endif
 	andis.	r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
-	beq	L(no_vec)
 
 	la	r10,(_UC_VREGS)(r3)
 	la	r9,(_UC_VREGS+16)(r3)
+	
+	beq	L(no_vec)
+/* address of the combined VSCR/VSAVE quadword.  */	
+	la	r8,(_UC_VREGS+512)(r3)
 
+/* Save the vector registers */
 	stvx  v0,0,r10
 	stvx  v1,0,r9
 	addi  r10,r10,32
 	addi  r9,r9,32
+/* We need to get the Vector Status and Control Register early to avoid
+   store order problems later with the VSAVE register that shares the
+   same quadword.  */
+	mfvscr	v0
 
 	stvx  v2,0,r10
 	stvx  v3,0,r9
 	addi  r10,r10,32
 	addi  r9,r9,32
 
+	stvx	v0,0,r8
+	
 	stvx  v4,0,r10
 	stvx  v5,0,r9
 	addi  r10,r10,32
@@ -216,20 +235,18 @@
 	addi  r10,r10,32
 	addi  r9,r9,32
 
+	mfspr	r0,VRSAVE
 	stvx  v30,0,r10
 	stvx  v31,0,r9
-	addi  r10,r10,32
-	addi  r9,r9,32
 
-	mfvscr	v0
-	mfspr	r0,VRSAVE
-	stvx	v0,0,r10
-	sync
- 	stw	r0,0(r10)
+ 	stw	r0,0(r8)
 
 L(no_vec):
-/* Restore ucontext (parm1) from stack.  */
-	lwz	r12,_FRAME_PARM_SAVE1+16(r1)
+/* We need to set up parms and call sigprocmask which will clobber
+   volatile registers. So before the call we need to retrieve the
+   original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
+   (current R3).  */
+	lwz	r12,_FRAME_PARM_SAVE1(r1)
 	li	r4,0
 	stw	r3,_UC_REGS_PTR(r12)
 	addi	r5,r12,_UC_SIGMASK
diff -urN libc23-cvstip-20040830/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S libc23/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S
--- libc23-cvstip-20040830/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S	2004-06-15 15:02:20.000000000 -0500
+++ libc23/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S	2004-09-02 12:45:43.125302872 -0500
@@ -27,22 +27,23 @@
 
 	.machine	"altivec"
 ENTRY(__swapcontext)
-	/* Save the current context */
+	stwu	r1,-16(r1)
+/* Insure that the _UC_REGS start on a quadword boundary.  */
 	stw	r3,_FRAME_PARM_SAVE1(r1)
 	addi	r3,r3,_UC_REG_SPACE+12
+	stw	r4,_FRAME_PARM_SAVE2(r1)	/* new context pointer */
 	clrrwi  r3,r3,4
+
+/* Save the general purpose registers */
 	stw	r0,_UC_GREGS+(PT_R0*4)(r3)
-	stw	r1,_UC_GREGS+(PT_R1*4)(r3)
 	mflr	r0
-	stwu	r1,-16(r1)
-	stw	r0,20(r1)
-	stw	r31,12(r1)
-	stw	r31,_UC_GREGS+(PT_R31*4)(r3)
-	mr	r31,r4			/* new context pointer */
+	stw	r2,_UC_GREGS+(PT_R2*4)(r3)
+	stw	r4,_UC_GREGS+(PT_R4*4)(r3)			
+/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
+   return address.  */
 	stw	r0,_UC_GREGS+(PT_LNK*4)(r3)
 	stw	r0,_UC_GREGS+(PT_NIP*4)(r3)
-	stw	r2,_UC_GREGS+(PT_R2*4)(r3)
-	stw	r4,_UC_GREGS+(PT_R4*4)(r3)
+	stw	r0,_FRAME_LR_SAVE+16(r1)
 	stw	r5,_UC_GREGS+(PT_R5*4)(r3)
 	stw	r6,_UC_GREGS+(PT_R6*4)(r3)
 	stw	r7,_UC_GREGS+(PT_R7*4)(r3)
@@ -69,16 +70,23 @@
 	stw	r28,_UC_GREGS+(PT_R28*4)(r3)
 	stw	r29,_UC_GREGS+(PT_R29*4)(r3)
 	stw	r30,_UC_GREGS+(PT_R30*4)(r3)
-	mfctr	r0
-	stw	r0,_UC_GREGS+(PT_CTR*4)(r3)
-	mfxer	r0
-	stw	r0,_UC_GREGS+(PT_XER*4)(r3)
-	mfcr	r0
-	stw	r0,_UC_GREGS+(PT_CCR*4)(r3)
-
-	/* Set the return value of swapcontext to "success".  R3 is the only
-	   register whose value is not preserved in the saved context.  */
+	stw	r31,_UC_GREGS+(PT_R31*4)(r3)
+	
+/* Save the value of R1.  We had to push the stack before we
+   had the address of uc_reg_space.  So compute the address of
+   the callers stack pointer and save it as R1.  */
+	addi	r8,r1,16
 	li	r0,0
+/* Save the count, exception and condition registers.  */
+	mfctr	r11
+	mfxer	r10
+	mfcr	r9
+	stw	r8,_UC_GREGS+(PT_R1*4)(r3)
+	stw	r11,_UC_GREGS+(PT_CTR*4)(r3)
+	stw	r10,_UC_GREGS+(PT_XER*4)(r3)
+	stw	r9,_UC_GREGS+(PT_CCR*4)(r3)
+/* Set the return value of getcontext to "success".  R3 is the only
+   register whose value is not preserved in the saved context.  */
 	stw	r0,_UC_GREGS+(PT_R3*4)(r3)
 
 	/* Zero fill fields that can't be set in user state. */
@@ -138,20 +146,30 @@
 	lwz     r7,_dl_hwcap@l(r7)
 #endif
 	andis.	r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
-	beq	L(no_vec)
 
 	la	r10,(_UC_VREGS)(r3)
 	la	r9,(_UC_VREGS+16)(r3)
+	
+	beq	L(no_vec)
+/* address of the combined VSCR/VSAVE quadword.  */	
+	la	r8,(_UC_VREGS+512)(r3)
 
+/* Save the vector registers */
 	stvx  v0,0,r10
 	stvx  v1,0,r9
 	addi  r10,r10,32
 	addi  r9,r9,32
+/* We need to get the Vector Status and Control Register early to avoid
+   store order problems later with the VSAVE register that shares the
+   same quadword.  */
+	mfvscr	v0
 
 	stvx  v2,0,r10
 	stvx  v3,0,r9
 	addi  r10,r10,32
 	addi  r9,r9,32
+	
+	stvx	v0,0,r8
 
 	stvx  v4,0,r10
 	stvx  v5,0,r9
@@ -218,20 +236,15 @@
 	addi  r10,r10,32
 	addi  r9,r9,32
 
+	mfvscr	v0
 	stvx  v30,0,r10
 	stvx  v31,0,r9
-	addi  r10,r10,32
-	addi  r9,r9,32
 
-	mfvscr	v0
-	mfspr	r0,VRSAVE
-	stvx	v0,0,r10
-	sync
- 	stw	r0,0(r10)
+ 	stw	r0,0(r8)
 
 L(no_vec):
 /* Restore ucontext (parm1) from stack.  */
-	lwz	r12,_FRAME_PARM_SAVE1+16(r1)
+	lwz	r12,_FRAME_PARM_SAVE1(r1)
 	li	r4,0
 	stw	r3,_UC_REGS_PTR(r12)
 	addi	r5,r12,_UC_SIGMASK
@@ -251,8 +264,8 @@
 	 * r0, xer, ctr.  We don't restore r2 since it will be used as
 	 * the TLS pointer.
 	 */
-	mr	r4,r31
-	lwz	r31,_UC_REGS_PTR(r31)
+	lwz	r4,_FRAME_PARM_SAVE2(r1)
+	lwz	r31,_UC_REGS_PTR(r4)
 	lwz	r0,_UC_GREGS+(PT_MSR*4)(r31)
 	cmpwi	r0,0
 	bne	L(do_sigret)
@@ -451,8 +464,7 @@
 	bctr
 
 L(error_exit):
-	lwz	r31,12(r1)
-	lwz	r0,20(r1)
+	lwz	r0,_FRAME_LR_SAVE+16(r1)
 	addi	r1,r1,16
 	mtlr	r0
 	blr

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]