diff options
Diffstat (limited to 'kernel/tools/testing/selftests/powerpc/copyloops')
9 files changed, 188 insertions, 0 deletions
diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/.gitignore b/kernel/tools/testing/selftests/powerpc/copyloops/.gitignore new file mode 100644 index 000000000..25a192f62 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/.gitignore @@ -0,0 +1,4 @@ +copyuser_64 +copyuser_power7 +memcpy_64 +memcpy_power7 diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/Makefile b/kernel/tools/testing/selftests/powerpc/copyloops/Makefile new file mode 100644 index 000000000..384843ea0 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/Makefile @@ -0,0 +1,25 @@ +# The loops are all 64-bit code +CFLAGS += -m64 +CFLAGS += -I$(CURDIR) +CFLAGS += -D SELFTEST +CFLAGS += -maltivec + +# Use our CFLAGS for the implicit .S rule +ASFLAGS = $(CFLAGS) + +TEST_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 +EXTRA_SOURCES := validate.c ../harness.c + +all: $(TEST_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 + +$(TEST_PROGS): $(EXTRA_SOURCES) + +include ../../lib.mk + +clean: + rm -f $(TEST_PROGS) *.o diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/kernel/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h new file mode 100644 index 000000000..50ae7d209 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h @@ -0,0 +1,56 @@ +#include <ppc-asm.h> + +#define CONFIG_ALTIVEC + +#define r1 1 + +#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 R29 r29 +#define R30 r30 +#define R31 r31 + +#define STACKFRAMESIZE 256 +#define STK_REG(i) (112 + ((i)-14)*8) + +#define _GLOBAL(A) FUNC_START(test_ ## A) +#define _GLOBAL_TOC(A) _GLOBAL(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/kernel/tools/testing/selftests/powerpc/copyloops/asm/processor.h b/kernel/tools/testing/selftests/powerpc/copyloops/asm/processor.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/asm/processor.h diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_64.S b/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_64.S new file mode 120000 index 000000000..f1c418a25 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_64.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/copyuser_64.S
\ No newline at end of file diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S b/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S new file mode 120000 index 000000000..478689598 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/copyuser_power7.S
\ No newline at end of file diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_64.S b/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_64.S new file mode 120000 index 000000000..cce33fb6f --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_64.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/memcpy_64.S
\ No newline at end of file diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S b/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S new file mode 120000 index 000000000..0d6fbfaf3 --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/memcpy_power7.S
\ No newline at end of file diff --git a/kernel/tools/testing/selftests/powerpc/copyloops/validate.c b/kernel/tools/testing/selftests/powerpc/copyloops/validate.c new file mode 100644 index 000000000..1750ff57e --- /dev/null +++ b/kernel/tools/testing/selftests/powerpc/copyloops/validate.c @@ -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)); +} |