selftests/powerpc: Import Anton's memcpy / copy_tofrom_user tests
authorMichael Ellerman <mpe@ellerman.id.au>
Tue, 21 Jan 2014 04:22:17 +0000 (15:22 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 7 Mar 2014 04:53:12 +0000 (15:53 +1100)
Turn Anton's memcpy / copy_tofrom_user test into something that can
live in tools/testing/selftests.

It requires one turd in arch/powerpc/lib/memcpy_64.S, but it's pretty
harmless IMHO.

We are sailing very close to the wind with the feature macros. We define
them to nothing, which currently means we get a few extra nops and
include the unaligned calls.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/lib/memcpy_64.S
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/copyloops/Makefile [new file with mode: 0644]
tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h [new file with mode: 0644]
tools/testing/selftests/powerpc/copyloops/asm/processor.h [new file with mode: 0644]
tools/testing/selftests/powerpc/copyloops/copyuser_64.S [new symlink]
tools/testing/selftests/powerpc/copyloops/copyuser_power7.S [new symlink]
tools/testing/selftests/powerpc/copyloops/memcpy_64.S [new symlink]
tools/testing/selftests/powerpc/copyloops/memcpy_power7.S [new symlink]
tools/testing/selftests/powerpc/copyloops/validate.c [new file with mode: 0644]
tools/testing/selftests/powerpc/utils.h

index d2bbbc8d7dc0b045aab751d79264a2f4f959fe61..72ad055168a333ed31ebd5c0c014ff00f6c7436a 100644 (file)
@@ -14,7 +14,9 @@ _GLOBAL(memcpy)
 BEGIN_FTR_SECTION
        std     r3,48(r1)       /* save destination pointer for return value */
 FTR_SECTION_ELSE
+#ifndef SELFTEST
        b       memcpy_power7
+#endif
 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
        PPC_MTOCRF(0x01,r5)
        cmpldi  cr1,r5,16
index bd24ae5aaeab052894d2c998754ec150084c9bba..316194f26ff4ab3131c6b29f939ef2209626f208 100644 (file)
@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
 
 export CC CFLAGS
 
-TARGETS = pmu
+TARGETS = pmu copyloops
 
 endif
 
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
new file mode 100644 (file)
index 0000000..6f2d3be
--- /dev/null
@@ -0,0 +1,29 @@
+# The loops are all 64-bit code
+CFLAGS += -m64
+CFLAGS += -I$(CURDIR)
+CFLAGS += -D SELFTEST
+
+# Use our CFLAGS for the implicit .S rule
+ASFLAGS = $(CFLAGS)
+
+PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
+EXTRA_SOURCES := validate.c ../harness.c
+
+all: $(PROGS)
+
+copyuser_64:     CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
+copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
+memcpy_64:       CPPFLAGS += -D COPY_LOOP=test_memcpy
+memcpy_power7:   CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
+
+$(PROGS): $(EXTRA_SOURCES)
+
+run_tests: all
+       @-for PROG in $(PROGS); do \
+               ./$$PROG; \
+       done;
+
+clean:
+       rm -f $(PROGS) *.o
+
+.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
new file mode 100644 (file)
index 0000000..ccd9c84
--- /dev/null
@@ -0,0 +1,86 @@
+#include <ppc-asm.h>
+
+#define CONFIG_ALTIVEC
+
+#define r1     1
+
+#define vr0     0
+#define vr1     1
+#define vr2     2
+#define vr3     3
+#define vr4     4
+#define vr5     5
+#define vr6     6
+#define vr7     7
+#define vr8     8
+#define vr9     9
+#define vr10    10
+#define vr11    11
+#define vr12    12
+#define vr13    13
+#define vr14    14
+#define vr15    15
+#define vr16    16
+#define vr17    17
+#define vr18    18
+#define vr19    19
+#define vr20    20
+#define vr21    21
+#define vr22    22
+#define vr23    23
+#define vr24    24
+#define vr25    25
+#define vr26    26
+#define vr27    27
+#define vr28    28
+#define vr29    29
+#define vr30    30
+#define vr31    31
+
+#define R14 r14
+#define R15 r15
+#define R16 r16
+#define R17 r17
+#define R18 r18
+#define R19 r19
+#define R20 r20
+#define R21 r21
+#define R22 r22
+
+#define STACKFRAMESIZE 256
+#define STK_PARAM(i)   (48 + ((i)-3)*8)
+#define STK_REG(i)     (112 + ((i)-14)*8)
+
+#define _GLOBAL(A) FUNC_START(test_ ## A)
+
+#define PPC_MTOCRF(A, B)       mtocrf A, B
+
+FUNC_START(enter_vmx_usercopy)
+       li      r3,1
+       blr
+
+FUNC_START(exit_vmx_usercopy)
+       li      r3,0
+       blr
+
+FUNC_START(enter_vmx_copy)
+       li      r3,1
+       blr
+
+FUNC_START(exit_vmx_copy)
+       blr
+
+FUNC_START(memcpy_power7)
+       blr
+
+FUNC_START(__copy_tofrom_user_power7)
+       blr
+
+FUNC_START(__copy_tofrom_user_base)
+       blr
+
+#define BEGIN_FTR_SECTION
+#define FTR_SECTION_ELSE
+#define ALT_FTR_SECTION_END_IFCLR(x)
+#define ALT_FTR_SECTION_END(x, y)
+#define END_FTR_SECTION_IFCLR(x)
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/processor.h b/tools/testing/selftests/powerpc/copyloops/asm/processor.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_64.S b/tools/testing/selftests/powerpc/copyloops/copyuser_64.S
new file mode 120000 (symlink)
index 0000000..f1c418a
--- /dev/null
@@ -0,0 +1 @@
+../../../../../arch/powerpc/lib/copyuser_64.S
\ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S b/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S
new file mode 120000 (symlink)
index 0000000..4786895
--- /dev/null
@@ -0,0 +1 @@
+../../../../../arch/powerpc/lib/copyuser_power7.S
\ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_64.S b/tools/testing/selftests/powerpc/copyloops/memcpy_64.S
new file mode 120000 (symlink)
index 0000000..cce33fb
--- /dev/null
@@ -0,0 +1 @@
+../../../../../arch/powerpc/lib/memcpy_64.S
\ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S b/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S
new file mode 120000 (symlink)
index 0000000..0d6fbfa
--- /dev/null
@@ -0,0 +1 @@
+../../../../../arch/powerpc/lib/memcpy_power7.S
\ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c
new file mode 100644 (file)
index 0000000..1750ff5
--- /dev/null
@@ -0,0 +1,99 @@
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "../utils.h"
+
+#define MAX_LEN 8192
+#define MAX_OFFSET 16
+#define MIN_REDZONE 128
+#define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE)
+#define POISON 0xa5
+
+unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
+
+static void do_one(char *src, char *dst, unsigned long src_off,
+                  unsigned long dst_off, unsigned long len, void *redzone,
+                  void *fill)
+{
+       char *srcp, *dstp;
+       unsigned long ret;
+       unsigned long i;
+
+       srcp = src + MIN_REDZONE + src_off;
+       dstp = dst + MIN_REDZONE + dst_off;
+
+       memset(src, POISON, BUFLEN);
+       memset(dst, POISON, BUFLEN);
+       memcpy(srcp, fill, len);
+
+       ret = COPY_LOOP(dstp, srcp, len);
+       if (ret && ret != (unsigned long)dstp) {
+               printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret);
+               abort();
+       }
+
+       if (memcmp(dstp, srcp, len)) {
+               printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len);
+               printf("src: ");
+               for (i = 0; i < len; i++)
+                       printf("%02x ", srcp[i]);
+               printf("\ndst: ");
+               for (i = 0; i < len; i++)
+                       printf("%02x ", dstp[i]);
+               printf("\n");
+               abort();
+       }
+
+       if (memcmp(dst, redzone, dstp - dst)) {
+               printf("(%p,%p,%ld) redzone before corrupted\n",
+                      dstp, srcp, len);
+               abort();
+       }
+
+       if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) {
+               printf("(%p,%p,%ld) redzone after corrupted\n",
+                      dstp, srcp, len);
+               abort();
+       }
+}
+
+int test_copy_loop(void)
+{
+       char *src, *dst, *redzone, *fill;
+       unsigned long len, src_off, dst_off;
+       unsigned long i;
+
+       src = memalign(BUFLEN, BUFLEN);
+       dst = memalign(BUFLEN, BUFLEN);
+       redzone = malloc(BUFLEN);
+       fill = malloc(BUFLEN);
+
+       if (!src || !dst || !redzone || !fill) {
+               fprintf(stderr, "malloc failed\n");
+               exit(1);
+       }
+
+       memset(redzone, POISON, BUFLEN);
+
+       /* Fill with sequential bytes */
+       for (i = 0; i < BUFLEN; i++)
+               fill[i] = i & 0xff;
+
+       for (len = 1; len < MAX_LEN; len++) {
+               for (src_off = 0; src_off < MAX_OFFSET; src_off++) {
+                       for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) {
+                               do_one(src, dst, src_off, dst_off, len,
+                                      redzone, fill);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int main(void)
+{
+       return test_harness(test_copy_loop, str(COPY_LOOP));
+}
index 5851c4b0f55362e9f2cab9b480c6ebd3b4d0ef30..0de064406dabf5d7589f9cc094f133e12b1798a1 100644 (file)
@@ -31,4 +31,7 @@ do {                                                          \
        }                                                       \
 } while (0)
 
+#define _str(s) #s
+#define str(s) _str(s)
+
 #endif /* _SELFTESTS_POWERPC_UTILS_H */