Thread (16 messages) 16 messages, 3 authors, 2016-02-10

Re: [v3, 1/9] selftests/powerpc: Test the preservation of FPU and VMX regs across syscall

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2016-02-10 08:56:04

[offlist]

On Thu, 2016-21-01 at 00:55:41 UTC, Cyril Bur wrote:
Test that the non volatile floating point and Altivec registers get
correctly preserved across the fork() syscall.

fork() works nicely for this purpose, the registers should be the same for
both parent and child
...
quoted hunk ↗ jump to hunk
diff --git a/tools/testing/selftests/powerpc/basic_asm.h b/tools/testing/selftests/powerpc/basic_asm.h
new file mode 100644
index 0000000..27aca79
--- /dev/null
+++ b/tools/testing/selftests/powerpc/basic_asm.h
@@ -0,0 +1,26 @@
+#include <ppc-asm.h>
+#include <asm/unistd.h>
+
+#define LOAD_REG_IMMEDIATE(reg,expr) \
+	lis	reg,(expr)@highest;	\
+	ori	reg,reg,(expr)@higher;	\
+	rldicr	reg,reg,32,31;	\
+	oris	reg,reg,(expr)@high;	\
+	ori	reg,reg,(expr)@l;
+
+#define PUSH_BASIC_STACK(size) \
+	std	2,24(sp); \
+	mflr	r0; \
+	std	r0,16(sp); \
+	mfcr	r0; \
+	stw	r0,8(sp); \
+	stdu	sp,-size(sp);
Unless I'm completely misreading this, that's not ABI compliant.

You are supposed to save LR into your caller's stack frame, but the TOC and CR
go into *your* stack frame.

I know that's not super obvious from the ABI doc.

See for example this code generated by GCC:

extern int global_thing;

int foo(int x, int (*fp)(int x))
{
	int a, b, c;

	a = x;
	b = a + global_thing;
	c = b + 2;

	a = fp(x);

	printf("%d %d %d\n", a, b, c);

	return a;
}

0000000000000000 <foo>:
   0:	00 00 4c 3c 	addis   r2,r12,0
			0: R_PPC64_REL16_HA	.TOC.
   4:	00 00 42 38 	addi    r2,r2,0
			4: R_PPC64_REL16_LO	.TOC.+0x4
   8:	a6 02 08 7c 	mflr    r0
   c:	f0 ff c1 fb 	std     r30,-16(r1)	<- save r30 into (what will be) our stack frame
  10:	f8 ff e1 fb 	std     r31,-8(r1)	<- save r31 into (what will be) our stack frame
  14:	78 23 8c 7c 	mr      r12,r4		<- put fp into r12 because we'll be calling its global entry point
  18:	a6 03 89 7c 	mtctr   r4		<- put fp into CTR
  1c:	00 00 22 3d 	addis   r9,r2,0
			1c: R_PPC64_TOC16_HA	.toc
  20:	00 00 29 e9 	ld      r9,0(r9)
			20: R_PPC64_TOC16_LO_DS	.toc
  24:	10 00 01 f8 	std     r0,16(r1)	<- save r0 (LR) into *our caller's* stack frame
  28:	91 ff 21 f8 	stdu    r1,-112(r1)	<- create our stack frame & store the backchain pointer
  2c:	18 00 41 f8 	std     r2,24(r1)	<- save r2 (TOC) into *our* stack frame
  30:	00 00 e9 83 	lwz     r31,0(r9)
  34:	14 1a ff 7f 	add     r31,r31,r3
  38:	21 04 80 4e 	bctrl			<- call fp, it will get it's TOC pointer using r12
  3c:	18 00 41 e8 	ld      r2,24(r1)	<- restore our r2 (TOC) from *our* stack frame
  40:	02 00 ff 38 	addi    r7,r31,2
  44:	b4 07 e6 7f 	extsw   r6,r31
  48:	b4 07 e7 7c 	extsw   r7,r7
  4c:	78 1b 7e 7c 	mr      r30,r3
  50:	00 00 82 3c 	addis   r4,r2,0
			50: R_PPC64_TOC16_HA	.rodata.str1.8
  54:	78 f3 c5 7f 	mr      r5,r30
  58:	00 00 84 38 	addi    r4,r4,0
			58: R_PPC64_TOC16_LO	.rodata.str1.8
  5c:	01 00 60 38 	li      r3,1
  60:	01 00 00 48 	bl      60 <foo+0x60>
			60: R_PPC64_REL24	__printf_chk
  64:	00 00 00 60 	nop
  68:	70 00 21 38 	addi    r1,r1,112	<- pop our stack frame
  6c:	78 f3 c3 7f 	mr      r3,r30
  70:	10 00 01 e8 	ld      r0,16(r1)	<- restore r0 (LR) from our caller's stack frame
  74:	f0 ff c1 eb 	ld      r30,-16(r1)	<- restore r30 from (what was) our stack frame
  78:	f8 ff e1 eb 	ld      r31,-8(r1)	<- restore r31 from (what was) our stack frame
  7c:	a6 03 08 7c 	mtlr    r0		<- restore LR
  80:	20 00 80 4e 	blr			<- return



So your macro wants to be more like:

#define PUSH_BASIC_STACK(_size) \
	mflr	r0;		\
	std	r0,16(r1);	\
	stdu	r1,-_size(r1);	\
	mfcr	r0;		\
	stw	r0,8(r1);	\
	std	r2,24(r1);

Though untested.

Also you're relying on the caller to ensure size is big enough. So maybe it'd
be better if you ensured that, making the size parameter the *extra* size above
the minimum stack frame. eg:


#define PUSH_BASIC_STACK(_extra) 	\
	mflr	r0;			\
	std	r0,16(r1);		\
	stdu	r1,-(_extra + 32)(r1);	\
	mfcr	r0;			\
	stw	r0,8(r1);		\
	std	r2,24(r1);


cheers
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help