selftests/powerpc: Import Anton's memcpy / copy_tofrom_user tests

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>
This commit is contained in:
Michael Ellerman 2014-01-21 15:22:17 +11:00 committed by Benjamin Herrenschmidt
parent 55672ecfa2
commit 22d651dcef
11 changed files with 224 additions and 1 deletions

View 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

View 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

View File

@ -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

View File

@ -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)

View File

@ -0,0 +1 @@
../../../../../arch/powerpc/lib/copyuser_64.S

View File

@ -0,0 +1 @@
../../../../../arch/powerpc/lib/copyuser_power7.S

View File

@ -0,0 +1 @@
../../../../../arch/powerpc/lib/memcpy_64.S

View File

@ -0,0 +1 @@
../../../../../arch/powerpc/lib/memcpy_power7.S

View File

@ -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));
}

View File

@ -31,4 +31,7 @@ do { \
} \
} while (0)
#define _str(s) #s
#define str(s) _str(s)
#endif /* _SELFTESTS_POWERPC_UTILS_H */