diff options
Diffstat (limited to 'tools/testing/selftests')
41 files changed, 733 insertions, 301 deletions
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore index 9d383073b7ad..6d4fd014511c 100644 --- a/tools/testing/selftests/powerpc/alignment/.gitignore +++ b/tools/testing/selftests/powerpc/alignment/.gitignore @@ -1,6 +1,2 @@ -copy_unaligned copy_first_unaligned -paste_unaligned -paste_last_unaligned -copy_paste_unaligned_common alignment_handler diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile index 083a48a008b4..93baacab7693 100644 --- a/tools/testing/selftests/powerpc/alignment/Makefile +++ b/tools/testing/selftests/powerpc/alignment/Makefile @@ -1,6 +1,5 @@ -TEST_GEN_PROGS := copy_unaligned copy_first_unaligned paste_unaligned \ - paste_last_unaligned alignment_handler +TEST_GEN_PROGS := copy_first_unaligned alignment_handler include ../../lib.mk -$(TEST_GEN_PROGS): ../harness.c ../utils.c copy_paste_unaligned_common.c +$(TEST_GEN_PROGS): ../harness.c ../utils.c diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index 0f2698f9fd6d..169a8b9719fb 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -40,6 +40,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -48,6 +49,8 @@ #include <setjmp.h> #include <signal.h> +#include <asm/cputable.h> + #include "utils.h" int bufsize; @@ -191,7 +194,7 @@ int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name) */ int do_test(char *test_name, void (*test_func)(char *, char *)) { - int offset, width, fd, rc = 0, r; + int offset, width, fd, rc, r; void *mem0, *mem1, *ci0, *ci1; printf("\tDoing %s:\t", test_name); @@ -199,8 +202,8 @@ int do_test(char *test_name, void (*test_func)(char *, char *)) fd = open("/dev/fb0", O_RDWR); if (fd < 0) { printf("\n"); - perror("Can't open /dev/fb0"); - SKIP_IF(1); + perror("Can't open /dev/fb0 now?"); + return 1; } ci0 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED, @@ -226,6 +229,7 @@ int do_test(char *test_name, void (*test_func)(char *, char *)) return rc; } + rc = 0; /* offset = 0 no alignment fault, so skip */ for (offset = 1; offset < 16; offset++) { width = 16; /* vsx == 16 bytes */ @@ -244,32 +248,51 @@ int do_test(char *test_name, void (*test_func)(char *, char *)) r |= test_memcpy(mem1, mem0, width, offset, test_func); if (r && !debug) { printf("FAILED: Got signal"); + rc = 1; break; } r |= test_memcmp(mem1, ci1, width, offset, test_name); - rc |= r; if (r && !debug) { printf("FAILED: Wrong Data"); + rc = 1; break; } } - if (!r) + + if (rc == 0) printf("PASSED"); + printf("\n"); munmap(ci0, bufsize); munmap(ci1, bufsize); free(mem0); free(mem1); + close(fd); return rc; } +static bool can_open_fb0(void) +{ + int fd; + + fd = open("/dev/fb0", O_RDWR); + if (fd < 0) + return false; + + close(fd); + return true; +} + int test_alignment_handler_vsx_206(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + printf("VSX: 2.06B\n"); LOAD_VSX_XFORM_TEST(lxvd2x); LOAD_VSX_XFORM_TEST(lxvw4x); @@ -285,6 +308,9 @@ int test_alignment_handler_vsx_207(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07)); + printf("VSX: 2.07B\n"); LOAD_VSX_XFORM_TEST(lxsspx); LOAD_VSX_XFORM_TEST(lxsiwax); @@ -298,6 +324,8 @@ int test_alignment_handler_vsx_300(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); printf("VSX: 3.00B\n"); LOAD_VMX_DFORM_TEST(lxsd); @@ -328,6 +356,8 @@ int test_alignment_handler_integer(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + printf("Integer\n"); LOAD_DFORM_TEST(lbz); LOAD_DFORM_TEST(lbzu); @@ -354,7 +384,6 @@ int test_alignment_handler_integer(void) LOAD_DFORM_TEST(ldu); LOAD_XFORM_TEST(ldx); LOAD_XFORM_TEST(ldux); - LOAD_XFORM_TEST(ldbrx); LOAD_DFORM_TEST(lmw); STORE_DFORM_TEST(stb); STORE_XFORM_TEST(stbx); @@ -374,8 +403,23 @@ int test_alignment_handler_integer(void) STORE_XFORM_TEST(stdx); STORE_DFORM_TEST(stdu); STORE_XFORM_TEST(stdux); - STORE_XFORM_TEST(stdbrx); STORE_DFORM_TEST(stmw); + + return rc; +} + +int test_alignment_handler_integer_206(void) +{ + int rc = 0; + + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + + printf("Integer: 2.06\n"); + + LOAD_XFORM_TEST(ldbrx); + STORE_XFORM_TEST(stdbrx); + return rc; } @@ -383,6 +427,9 @@ int test_alignment_handler_vmx(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)); + printf("VMX\n"); LOAD_VMX_XFORM_TEST(lvx); @@ -408,23 +455,19 @@ int test_alignment_handler_fp(void) { int rc = 0; + SKIP_IF(!can_open_fb0()); + printf("Floating point\n"); LOAD_FLOAT_DFORM_TEST(lfd); LOAD_FLOAT_XFORM_TEST(lfdx); - LOAD_FLOAT_DFORM_TEST(lfdp); - LOAD_FLOAT_XFORM_TEST(lfdpx); LOAD_FLOAT_DFORM_TEST(lfdu); LOAD_FLOAT_XFORM_TEST(lfdux); LOAD_FLOAT_DFORM_TEST(lfs); LOAD_FLOAT_XFORM_TEST(lfsx); LOAD_FLOAT_DFORM_TEST(lfsu); LOAD_FLOAT_XFORM_TEST(lfsux); - LOAD_FLOAT_XFORM_TEST(lfiwzx); - LOAD_FLOAT_XFORM_TEST(lfiwax); STORE_FLOAT_DFORM_TEST(stfd); STORE_FLOAT_XFORM_TEST(stfdx); - STORE_FLOAT_DFORM_TEST(stfdp); - STORE_FLOAT_XFORM_TEST(stfdpx); STORE_FLOAT_DFORM_TEST(stfdu); STORE_FLOAT_XFORM_TEST(stfdux); STORE_FLOAT_DFORM_TEST(stfs); @@ -436,6 +479,38 @@ int test_alignment_handler_fp(void) return rc; } +int test_alignment_handler_fp_205(void) +{ + int rc = 0; + + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05)); + + printf("Floating point: 2.05\n"); + + LOAD_FLOAT_DFORM_TEST(lfdp); + LOAD_FLOAT_XFORM_TEST(lfdpx); + LOAD_FLOAT_XFORM_TEST(lfiwax); + STORE_FLOAT_DFORM_TEST(stfdp); + STORE_FLOAT_XFORM_TEST(stfdpx); + + return rc; +} + +int test_alignment_handler_fp_206(void) +{ + int rc = 0; + + SKIP_IF(!can_open_fb0()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + + printf("Floating point: 2.06\n"); + + LOAD_FLOAT_XFORM_TEST(lfiwzx); + + return rc; +} + void usage(char *prog) { printf("Usage: %s [options]\n", prog); @@ -483,9 +558,15 @@ int main(int argc, char *argv[]) "test_alignment_handler_vsx_300"); rc |= test_harness(test_alignment_handler_integer, "test_alignment_handler_integer"); + rc |= test_harness(test_alignment_handler_integer_206, + "test_alignment_handler_integer_206"); rc |= test_harness(test_alignment_handler_vmx, "test_alignment_handler_vmx"); rc |= test_harness(test_alignment_handler_fp, "test_alignment_handler_fp"); + rc |= test_harness(test_alignment_handler_fp_205, + "test_alignment_handler_fp_205"); + rc |= test_harness(test_alignment_handler_fp_206, + "test_alignment_handler_fp_206"); return rc; } diff --git a/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c index 47b73b3a08bd..5a9589987702 100644 --- a/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c +++ b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c @@ -11,15 +11,46 @@ * */ +#include <signal.h> #include <string.h> #include <unistd.h> #include "utils.h" #include "instructions.h" -#include "copy_paste_unaligned_common.h" unsigned int expected_instruction = PPC_INST_COPY_FIRST; unsigned int instruction_mask = 0xfc2007fe; +void signal_action_handler(int signal_num, siginfo_t *info, void *ptr) +{ + ucontext_t *ctx = ptr; +#ifdef __powerpc64__ + unsigned int *pc = (unsigned int *)ctx->uc_mcontext.gp_regs[PT_NIP]; +#else + unsigned int *pc = (unsigned int *)ctx->uc_mcontext.uc_regs->gregs[PT_NIP]; +#endif + + /* + * Check that the signal was on the correct instruction, using a + * mask because the compiler assigns the register at RB. + */ + if ((*pc & instruction_mask) == expected_instruction) + _exit(0); /* We hit the right instruction */ + + _exit(1); +} + +void setup_signal_handler(void) +{ + struct sigaction signal_action; + + memset(&signal_action, 0, sizeof(signal_action)); + signal_action.sa_sigaction = signal_action_handler; + signal_action.sa_flags = SA_SIGINFO; + sigaction(SIGBUS, &signal_action, NULL); +} + +char cacheline_buf[128] __cacheline_aligned; + int test_copy_first_unaligned(void) { /* Only run this test on a P9 or later */ diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c deleted file mode 100644 index d35fa5f5d2d3..000000000000 --- a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2016, Chris Smart, IBM Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Common code for copy, copy_first, paste and paste_last unaligned - * tests. - * - */ - -#include <signal.h> -#include <string.h> -#include <unistd.h> -#include "utils.h" -#include "instructions.h" -#include "copy_paste_unaligned_common.h" - -unsigned int expected_instruction; -unsigned int instruction_mask; - -char cacheline_buf[128] __cacheline_aligned; - -void signal_action_handler(int signal_num, siginfo_t *info, void *ptr) -{ - ucontext_t *ctx = ptr; -#if defined(__powerpc64__) - unsigned int *pc = (unsigned int *)ctx->uc_mcontext.gp_regs[PT_NIP]; -#else - unsigned int *pc = (unsigned int *)ctx->uc_mcontext.uc_regs->gregs[PT_NIP]; -#endif - - /* - * Check that the signal was on the correct instruction, using a - * mask because the compiler assigns the register at RB. - */ - if ((*pc & instruction_mask) == expected_instruction) - _exit(0); /* We hit the right instruction */ - - _exit(1); -} - -void setup_signal_handler(void) -{ - struct sigaction signal_action; - - memset(&signal_action, 0, sizeof(signal_action)); - signal_action.sa_sigaction = signal_action_handler; - signal_action.sa_flags = SA_SIGINFO; - sigaction(SIGBUS, &signal_action, NULL); -} diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h deleted file mode 100644 index 053899fe506e..000000000000 --- a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2016, Chris Smart, IBM Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Declarations for common code for copy, copy_first, paste and - * paste_last unaligned tests. - * - */ - -#ifndef _SELFTESTS_POWERPC_COPY_PASTE_H -#define _SELFTESTS_POWERPC_COPY_PASTE_H - -#include <signal.h> - -int main(int argc, char *argv[]); -void signal_action_handler(int signal_num, siginfo_t *info, void *ptr); -void setup_signal_handler(void); -extern char cacheline_buf[128] __cacheline_aligned; -extern unsigned int expected_instruction; -extern unsigned int instruction_mask; - -#endif /* _SELFTESTS_POWERPC_COPY_PASTE_H */ diff --git a/tools/testing/selftests/powerpc/alignment/copy_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_unaligned.c deleted file mode 100644 index 3a4e26461554..000000000000 --- a/tools/testing/selftests/powerpc/alignment/copy_unaligned.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2016, Chris Smart, IBM Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Calls to copy which are not 128-byte aligned should be caught - * and sent a SIGBUS. - * - */ - -#include <string.h> -#include <unistd.h> -#include "utils.h" -#include "instructions.h" -#include "copy_paste_unaligned_common.h" - -unsigned int expected_instruction = PPC_INST_COPY; -unsigned int instruction_mask = 0xfc0007fe; - -int test_copy_unaligned(void) -{ - /* Only run this test on a P9 or later */ - SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); - - /* Register our signal handler with SIGBUS */ - setup_signal_handler(); - - /* +1 makes buf unaligned */ - copy(cacheline_buf+1); - - /* We should not get here */ - return 1; -} - -int main(int argc, char *argv[]) -{ - return test_harness(test_copy_unaligned, "test_copy_unaligned"); -} diff --git a/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c deleted file mode 100644 index 6e0ad045fcc3..000000000000 --- a/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016, Chris Smart, IBM Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Calls to paste_last which are not 128-byte aligned should be - * caught and sent a SIGBUS. - * - */ - -#include <string.h> -#include <unistd.h> -#include "utils.h" -#include "instructions.h" -#include "copy_paste_unaligned_common.h" - -unsigned int expected_instruction = PPC_INST_PASTE_LAST; -unsigned int instruction_mask = 0xfc2007ff; - -int test_paste_last_unaligned(void) -{ - /* Only run this test on a P9 or later */ - SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); - - /* Register our signal handler with SIGBUS */ - setup_signal_handler(); - - copy(cacheline_buf); - - /* +1 makes buf unaligned */ - paste_last(cacheline_buf+1); - - /* We should not get here */ - return 1; -} - -int main(int argc, char *argv[]) -{ - return test_harness(test_paste_last_unaligned, "test_paste_last_unaligned"); -} diff --git a/tools/testing/selftests/powerpc/alignment/paste_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_unaligned.c deleted file mode 100644 index 6f982b45e4bd..000000000000 --- a/tools/testing/selftests/powerpc/alignment/paste_unaligned.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016, Chris Smart, IBM Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Calls to paste which are not 128-byte aligned should be caught - * and sent a SIGBUS. - * - */ - -#include <string.h> -#include <unistd.h> -#include "utils.h" -#include "instructions.h" -#include "copy_paste_unaligned_common.h" - -unsigned int expected_instruction = PPC_INST_PASTE; -unsigned int instruction_mask = 0xfc0007fe; - -int test_paste_unaligned(void) -{ - /* Only run this test on a P9 or later */ - SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); - - /* Register our signal handler with SIGBUS */ - setup_signal_handler(); - - copy(cacheline_buf); - - /* +1 makes buf unaligned */ - paste(cacheline_buf+1); - - /* We should not get here */ - return 1; -} - -int main(int argc, char *argv[]) -{ - return test_harness(test_paste_unaligned, "test_paste_unaligned"); -} diff --git a/tools/testing/selftests/powerpc/benchmarks/futex_bench.c b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c index 2fc711d9150d..d58e4dc50fcd 100644 --- a/tools/testing/selftests/powerpc/benchmarks/futex_bench.c +++ b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c @@ -38,5 +38,6 @@ int test_futex(void) int main(void) { + test_harness_set_timeout(300); return test_harness(test_futex, "futex_bench"); } diff --git a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c index 7a0a462a2272..033de0560d99 100644 --- a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c +++ b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c @@ -84,5 +84,7 @@ int main(int argc, char *argv[]) exit(1); } } + + test_harness_set_timeout(300); return test_harness(test_mmap, "mmap_bench"); } diff --git a/tools/testing/selftests/powerpc/copyloops/.gitignore b/tools/testing/selftests/powerpc/copyloops/.gitignore index 25a192f62c4d..ce12cd0e2967 100644 --- a/tools/testing/selftests/powerpc/copyloops/.gitignore +++ b/tools/testing/selftests/powerpc/copyloops/.gitignore @@ -1,4 +1,13 @@ -copyuser_64 -copyuser_power7 -memcpy_64 -memcpy_power7 +copyuser_64_t0 +copyuser_64_t1 +copyuser_64_t2 +copyuser_power7_t0 +copyuser_power7_t1 +memcpy_64_t0 +memcpy_64_t1 +memcpy_64_t2 +memcpy_power7_t0 +memcpy_power7_t1 +copyuser_64_exc_t0 +copyuser_64_exc_t1 +copyuser_64_exc_t2 diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile index eedce3366f64..1cf89a34d97c 100644 --- a/tools/testing/selftests/powerpc/copyloops/Makefile +++ b/tools/testing/selftests/powerpc/copyloops/Makefile @@ -4,18 +4,49 @@ CFLAGS += -m64 CFLAGS += -I$(CURDIR) CFLAGS += -D SELFTEST CFLAGS += -maltivec +CFLAGS += -mcpu=power4 # Use our CFLAGS for the implicit .S rule & set the asm machine type ASFLAGS = $(CFLAGS) -Wa,-mpower4 -TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 -EXTRA_SOURCES := validate.c ../harness.c +TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \ + copyuser_p7_t0 copyuser_p7_t1 \ + memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \ + memcpy_p7_t0 memcpy_p7_t1 \ + copyuser_64_exc_t0 copyuser_64_exc_t1 copyuser_64_exc_t2 + +EXTRA_SOURCES := validate.c ../harness.c stubs.S include ../../lib.mk -$(OUTPUT)/copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base -$(OUTPUT)/copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7 -$(OUTPUT)/memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy -$(OUTPUT)/memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7 +$(OUTPUT)/copyuser_64_t%: copyuser_64.S $(EXTRA_SOURCES) + $(CC) $(CPPFLAGS) $(CFLAGS) \ + -D COPY_LOOP=test___copy_tofrom_user_base \ + -D SELFTEST_CASE=$(subst copyuser_64_t,,$(notdir $@)) \ + -o $@ $^ + +$(OUTPUT)/copyuser_p7_t%: copyuser_power7.S $(EXTRA_SOURCES) + $(CC) $(CPPFLAGS) $(CFLAGS) \ + -D COPY_LOOP=test___copy_tofrom_user_power7 \ + -D SELFTEST_CASE=$(subst copyuser_p7_t,,$(notdir $@)) \ + -o $@ $^ + +# Strictly speaking, we only need the memcpy_64 test cases for big-endian +$(OUTPUT)/memcpy_64_t%: memcpy_64.S $(EXTRA_SOURCES) + $(CC) $(CPPFLAGS) $(CFLAGS) \ + -D COPY_LOOP=test_memcpy \ + -D SELFTEST_CASE=$(subst memcpy_64_t,,$(notdir $@)) \ + -o $@ $^ + +$(OUTPUT)/memcpy_p7_t%: memcpy_power7.S $(EXTRA_SOURCES) + $(CC) $(CPPFLAGS) $(CFLAGS) \ + -D COPY_LOOP=test_memcpy_power7 \ + -D SELFTEST_CASE=$(subst memcpy_p7_t,,$(notdir $@)) \ + -o $@ $^ -$(TEST_GEN_PROGS): $(EXTRA_SOURCES) +$(OUTPUT)/copyuser_64_exc_t%: copyuser_64.S exc_validate.c ../harness.c \ + copy_tofrom_user_reference.S stubs.S + $(CC) $(CPPFLAGS) $(CFLAGS) \ + -D COPY_LOOP=test___copy_tofrom_user_base \ + -D SELFTEST_CASE=$(subst copyuser_64_exc_t,,$(notdir $@)) \ + -o $@ $^ diff --git a/tools/testing/selftests/powerpc/copyloops/asm/asm-compat.h b/tools/testing/selftests/powerpc/copyloops/asm/asm-compat.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/asm/asm-compat.h diff --git a/tools/testing/selftests/powerpc/copyloops/asm/feature-fixups.h b/tools/testing/selftests/powerpc/copyloops/asm/feature-fixups.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/asm/feature-fixups.h diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h index 5ffe04d802c9..0605df807593 100644 --- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h +++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h @@ -1,4 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __SELFTESTS_POWERPC_PPC_ASM_H +#define __SELFTESTS_POWERPC_PPC_ASM_H #include <ppc-asm.h> #define CONFIG_ALTIVEC @@ -26,34 +28,20 @@ #define PPC_MTOCRF(A, B) mtocrf A, B -#define EX_TABLE(x, y) +#define EX_TABLE(x, y) \ + .section __ex_table,"a"; \ + .8byte x, y; \ + .previous -FUNC_START(enter_vmx_usercopy) - li r3,1 - blr +#define BEGIN_FTR_SECTION .if test_feature +#define FTR_SECTION_ELSE .else +#define ALT_FTR_SECTION_END_IFCLR(x) .endif +#define ALT_FTR_SECTION_END_IFSET(x) .endif +#define ALT_FTR_SECTION_END(x, y) .endif +#define END_FTR_SECTION_IFCLR(x) .endif +#define END_FTR_SECTION_IFSET(x) .endif -FUNC_START(exit_vmx_usercopy) - li r3,0 - blr +/* Default to taking the first of any alternative feature sections */ +test_feature = 1 -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) +#endif /* __SELFTESTS_POWERPC_PPC_ASM_H */ diff --git a/tools/testing/selftests/powerpc/copyloops/copy_tofrom_user_reference.S b/tools/testing/selftests/powerpc/copyloops/copy_tofrom_user_reference.S new file mode 100644 index 000000000000..3363b86407d6 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/copy_tofrom_user_reference.S @@ -0,0 +1,24 @@ +#include <asm/ppc_asm.h> + +_GLOBAL(copy_tofrom_user_reference) + cmpdi r5,0 + beq 4f + + mtctr r5 + +1: lbz r6,0(r4) +2: stb r6,0(r3) + addi r3,r3,1 + addi r4,r4,1 + bdnz 1b + +3: mfctr r3 + blr + +4: mr r3,r5 + blr + +.section __ex_table,"a" + .llong 1b,3b + .llong 2b,3b +.text diff --git a/tools/testing/selftests/powerpc/copyloops/exc_validate.c b/tools/testing/selftests/powerpc/copyloops/exc_validate.c new file mode 100644 index 000000000000..c896ea9a763c --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/exc_validate.c @@ -0,0 +1,124 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <sys/mman.h> + +#include "utils.h" + +extern char __start___ex_table[]; +extern char __stop___ex_table[]; + +#if defined(__powerpc64__) +#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] +#elif defined(__powerpc__) +#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP] +#else +#error implement UCONTEXT_NIA +#endif + +static void segv_handler(int signr, siginfo_t *info, void *ptr) +{ + ucontext_t *uc = (ucontext_t *)ptr; + unsigned long addr = (unsigned long)info->si_addr; + unsigned long *ip = &UCONTEXT_NIA(uc); + unsigned long *ex_p = (unsigned long *)__start___ex_table; + + while (ex_p < (unsigned long *)__stop___ex_table) { + unsigned long insn, fixup; + + insn = *ex_p++; + fixup = *ex_p++; + + if (insn == *ip) { + *ip = fixup; + return; + } + } + + printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr); + abort(); +} + +static void setup_segv_handler(void) +{ + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_sigaction = segv_handler; + action.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &action, NULL); +} + +unsigned long COPY_LOOP(void *to, const void *from, unsigned long size); +unsigned long test_copy_tofrom_user_reference(void *to, const void *from, unsigned long size); + +static int total_passed; +static int total_failed; + +static void do_one_test(char *dstp, char *srcp, unsigned long len) +{ + unsigned long got, expected; + + got = COPY_LOOP(dstp, srcp, len); + expected = test_copy_tofrom_user_reference(dstp, srcp, len); + + if (got != expected) { + total_failed++; + printf("FAIL from=%p to=%p len=%ld returned %ld, expected %ld\n", + srcp, dstp, len, got, expected); + //abort(); + } else + total_passed++; +} + +//#define MAX_LEN 512 +#define MAX_LEN 16 + +int test_copy_exception(void) +{ + int page_size; + static char *p, *q; + unsigned long src, dst, len; + + page_size = getpagesize(); + p = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + + if (p == MAP_FAILED) { + perror("mmap"); + exit(1); + } + + memset(p, 0, page_size); + + setup_segv_handler(); + + if (mprotect(p + page_size, page_size, PROT_NONE)) { + perror("mprotect"); + exit(1); + } + + q = p + page_size - MAX_LEN; + + for (src = 0; src < MAX_LEN; src++) { + for (dst = 0; dst < MAX_LEN; dst++) { + for (len = 0; len < MAX_LEN+1; len++) { + // printf("from=%p to=%p len=%ld\n", q+dst, q+src, len); + do_one_test(q+dst, q+src, len); + } + } + } + + printf("Totals:\n"); + printf(" Pass: %d\n", total_passed); + printf(" Fail: %d\n", total_failed); + + return 0; +} + +int main(void) +{ + return test_harness(test_copy_exception, str(COPY_LOOP)); +} diff --git a/tools/testing/selftests/powerpc/copyloops/stubs.S b/tools/testing/selftests/powerpc/copyloops/stubs.S new file mode 100644 index 000000000000..ec8bcf2bf1c2 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/stubs.S @@ -0,0 +1,19 @@ +#include <asm/ppc_asm.h> + +FUNC_START(enter_vmx_usercopy) + li r3,1 + blr + +FUNC_START(exit_vmx_usercopy) + li r3,0 + blr + +FUNC_START(enter_vmx_ops) + li r3,1 + blr + +FUNC_START(exit_vmx_ops) + blr + +FUNC_START(__copy_tofrom_user_base) + blr diff --git a/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c b/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c index 08a8b95e3bc1..c8c240accc0c 100644 --- a/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c +++ b/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c @@ -5,8 +5,8 @@ * verifies that the child is using the changed DSCR using mfspr. * * When using the privilege state SPR, the instructions such as - * mfspr or mtspr are priviledged and the kernel emulates them - * for us. Instructions using problem state SPR can be exuecuted + * mfspr or mtspr are privileged and the kernel emulates them + * for us. Instructions using problem state SPR can be executed * directly without any emulation if the HW supports them. Else * they also get emulated by the kernel. * @@ -19,7 +19,7 @@ */ #include "dscr.h" -static char prog[LEN_MAX]; +static char *prog; static void do_exec(unsigned long parent_dscr) { @@ -104,6 +104,6 @@ int main(int argc, char *argv[]) exit(1); } - strncpy(prog, argv[0], strlen(argv[0])); + prog = argv[0]; return test_harness(dscr_inherit_exec, "dscr_inherit_exec_test"); } diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c index 66d31de60b9a..9d7166dfad1e 100644 --- a/tools/testing/selftests/powerpc/harness.c +++ b/tools/testing/selftests/powerpc/harness.c @@ -85,13 +85,13 @@ wait: return status; } -static void alarm_handler(int signum) +static void sig_handler(int signum) { - /* Jut wake us up from waitpid */ + /* Just wake us up from waitpid */ } -static struct sigaction alarm_action = { - .sa_handler = alarm_handler, +static struct sigaction sig_action = { + .sa_handler = sig_handler, }; void test_harness_set_timeout(uint64_t time) @@ -106,8 +106,14 @@ int test_harness(int (test_function)(void), char *name) test_start(name); test_set_git_version(GIT_VERSION); - if (sigaction(SIGALRM, &alarm_action, NULL)) { - perror("sigaction"); + if (sigaction(SIGINT, &sig_action, NULL)) { + perror("sigaction (sigint)"); + test_error(name); + return 1; + } + + if (sigaction(SIGALRM, &sig_action, NULL)) { + perror("sigaction (sigalrm)"); test_error(name); return 1; } diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h index 735815b3ad7f..c58c370828b4 100644 --- a/tools/testing/selftests/powerpc/include/utils.h +++ b/tools/testing/selftests/powerpc/include/utils.h @@ -48,6 +48,8 @@ static inline bool have_hwcap2(unsigned long ftr2) } #endif +bool is_ppc64le(void); + /* Yes, this is evil */ #define FAIL_IF(x) \ do { \ diff --git a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c index ae9a79086111..35a3426e341c 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c @@ -162,5 +162,6 @@ int instruction_count(void) int main(void) { + test_harness_set_timeout(300); return test_harness(instruction_count, "instruction_count"); } diff --git a/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c index eb8acb78bc6c..2ed7ad33f7a3 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c @@ -98,5 +98,6 @@ static int lost_exception(void) int main(void) { + test_harness_set_timeout(300); return test_harness(lost_exception, "lost_exception"); } diff --git a/tools/testing/selftests/powerpc/primitives/asm/asm-const.h b/tools/testing/selftests/powerpc/primitives/asm/asm-const.h new file mode 120000 index 000000000000..18d8be13e67f --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/asm/asm-const.h @@ -0,0 +1 @@ +../../../../../../arch/powerpc/include/asm/asm-const.h
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/primitives/asm/feature-fixups.h b/tools/testing/selftests/powerpc/primitives/asm/feature-fixups.h new file mode 120000 index 000000000000..8dc6d4d46e8e --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/asm/feature-fixups.h @@ -0,0 +1 @@ +../../../../../../arch/powerpc/include/asm/feature-fixups.h
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/ptrace/core-pkey.c b/tools/testing/selftests/powerpc/ptrace/core-pkey.c index 36bc312b1f5c..e23e2e199eb4 100644 --- a/tools/testing/selftests/powerpc/ptrace/core-pkey.c +++ b/tools/testing/selftests/powerpc/ptrace/core-pkey.c @@ -140,6 +140,10 @@ static int child(struct shared_info *info) if (disable_execute) info->iamr |= 1ul << pkeyshift(pkey1); + else + info->iamr &= ~(1ul << pkeyshift(pkey1)); + + info->iamr &= ~(1ul << pkeyshift(pkey2) | 1ul << pkeyshift(pkey3)); info->uamor |= 3ul << pkeyshift(pkey1) | 3ul << pkeyshift(pkey2); diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c index 5cf631f792cc..bdbbbe8431e0 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c @@ -104,6 +104,10 @@ static int child(struct shared_info *info) if (disable_execute) info->expected_iamr |= 1ul << pkeyshift(pkey1); + else + info->expected_iamr &= ~(1ul << pkeyshift(pkey1)); + + info->expected_iamr &= ~(1ul << pkeyshift(pkey2) | 1ul << pkeyshift(pkey3)); info->expected_uamor |= 3ul << pkeyshift(pkey1) | 3ul << pkeyshift(pkey2); diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile index 1125e489055e..10b35c87a4f4 100644 --- a/tools/testing/selftests/powerpc/stringloops/Makefile +++ b/tools/testing/selftests/powerpc/stringloops/Makefile @@ -1,10 +1,33 @@ # SPDX-License-Identifier: GPL-2.0 # The loops are all 64-bit code -CFLAGS += -m64 CFLAGS += -I$(CURDIR) -TEST_GEN_PROGS := memcmp -EXTRA_SOURCES := memcmp_64.S ../harness.c +EXTRA_SOURCES := ../harness.c + +build_32bit = $(shell if ($(CC) $(CFLAGS) -m32 -o /dev/null memcmp.c >/dev/null 2>&1) then echo "1"; fi) + +TEST_GEN_PROGS := memcmp_64 strlen + +$(OUTPUT)/memcmp_64: memcmp.c +$(OUTPUT)/memcmp_64: CFLAGS += -m64 -maltivec + +ifeq ($(build_32bit),1) +$(OUTPUT)/memcmp_32: memcmp.c +$(OUTPUT)/memcmp_32: CFLAGS += -m32 + +TEST_GEN_PROGS += memcmp_32 +endif + +$(OUTPUT)/strlen: strlen.c string.c + +ifeq ($(build_32bit),1) +$(OUTPUT)/strlen_32: strlen.c +$(OUTPUT)/strlen_32: CFLAGS += -m32 + +TEST_GEN_PROGS += strlen_32 +endif + +ASFLAGS = $(CFLAGS) include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/stringloops/asm/cache.h b/tools/testing/selftests/powerpc/stringloops/asm/cache.h new file mode 100644 index 000000000000..8a2840831122 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/asm/cache.h @@ -0,0 +1 @@ +#define IFETCH_ALIGN_BYTES 4 diff --git a/tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h b/tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h new file mode 100644 index 000000000000..9de413c0c2cb --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * provides masks and opcode images for use by code generation, emulation + * and for instructions that older assemblers might not know about + */ +#ifndef _ASM_POWERPC_PPC_OPCODE_H +#define _ASM_POWERPC_PPC_OPCODE_H + + +# define stringify_in_c(...) __VA_ARGS__ +# define ASM_CONST(x) x + + +#define PPC_INST_VCMPEQUD_RC 0x100000c7 +#define PPC_INST_VCMPEQUB_RC 0x10000006 + +#define __PPC_RC21 (0x1 << 10) + +/* macros to insert fields into opcodes */ +#define ___PPC_RA(a) (((a) & 0x1f) << 16) +#define ___PPC_RB(b) (((b) & 0x1f) << 11) +#define ___PPC_RS(s) (((s) & 0x1f) << 21) +#define ___PPC_RT(t) ___PPC_RS(t) + +#define VCMPEQUD_RC(vrt, vra, vrb) stringify_in_c(.long PPC_INST_VCMPEQUD_RC | \ + ___PPC_RT(vrt) | ___PPC_RA(vra) | \ + ___PPC_RB(vrb) | __PPC_RC21) + +#define VCMPEQUB_RC(vrt, vra, vrb) stringify_in_c(.long PPC_INST_VCMPEQUB_RC | \ + ___PPC_RT(vrt) | ___PPC_RA(vra) | \ + ___PPC_RB(vrb) | __PPC_RC21) + +#endif /* _ASM_POWERPC_PPC_OPCODE_H */ diff --git a/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h index 136242ec4b0e..d2c0a911f55e 100644 --- a/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h +++ b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h @@ -1,4 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _PPC_ASM_H +#define __PPC_ASM_H #include <ppc-asm.h> #ifndef r1 @@ -6,3 +8,26 @@ #endif #define _GLOBAL(A) FUNC_START(test_ ## A) +#define _GLOBAL_TOC(A) FUNC_START(test_ ## A) + +#define CONFIG_ALTIVEC + +#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 BEGIN_FTR_SECTION +#define END_FTR_SECTION_IFSET(val) +#endif diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp.c b/tools/testing/selftests/powerpc/stringloops/memcmp.c index 8250db25b379..b1fa7546957f 100644 --- a/tools/testing/selftests/powerpc/stringloops/memcmp.c +++ b/tools/testing/selftests/powerpc/stringloops/memcmp.c @@ -2,20 +2,40 @@ #include <malloc.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include "utils.h" #define SIZE 256 #define ITERATIONS 10000 +#define LARGE_SIZE (5 * 1024) +#define LARGE_ITERATIONS 1000 +#define LARGE_MAX_OFFSET 32 +#define LARGE_SIZE_START 4096 + +#define MAX_OFFSET_DIFF_S1_S2 48 + +int vmx_count; +int enter_vmx_ops(void) +{ + vmx_count++; + return 1; +} + +void exit_vmx_ops(void) +{ + vmx_count--; +} int test_memcmp(const void *s1, const void *s2, size_t n); /* test all offsets and lengths */ -static void test_one(char *s1, char *s2) +static void test_one(char *s1, char *s2, unsigned long max_offset, + unsigned long size_start, unsigned long max_size) { unsigned long offset, size; - for (offset = 0; offset < SIZE; offset++) { - for (size = 0; size < (SIZE-offset); size++) { + for (offset = 0; offset < max_offset; offset++) { + for (size = size_start; size < (max_size - offset); size++) { int x, y; unsigned long i; @@ -35,70 +55,105 @@ static void test_one(char *s1, char *s2) printf("\n"); abort(); } + + if (vmx_count != 0) { + printf("vmx enter/exit not paired.(offset:%ld size:%ld s1:%p s2:%p vc:%d\n", + offset, size, s1, s2, vmx_count); + printf("\n"); + abort(); + } } } } -static int testcase(void) +static int testcase(bool islarge) { char *s1; char *s2; unsigned long i; - s1 = memalign(128, SIZE); + unsigned long comp_size = (islarge ? LARGE_SIZE : SIZE); + unsigned long alloc_size = comp_size + MAX_OFFSET_DIFF_S1_S2; + int iterations = islarge ? LARGE_ITERATIONS : ITERATIONS; + + s1 = memalign(128, alloc_size); if (!s1) { perror("memalign"); exit(1); } - s2 = memalign(128, SIZE); + s2 = memalign(128, alloc_size); if (!s2) { perror("memalign"); exit(1); } - srandom(1); + srandom(time(0)); - for (i = 0; i < ITERATIONS; i++) { + for (i = 0; i < iterations; i++) { unsigned long j; unsigned long change; + char *rand_s1 = s1; + char *rand_s2 = s2; - for (j = 0; j < SIZE; j++) + for (j = 0; j < alloc_size; j++) s1[j] = random(); - memcpy(s2, s1, SIZE); + rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2; + rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2; + memcpy(rand_s2, rand_s1, comp_size); /* change one byte */ - change = random() % SIZE; - s2[change] = random() & 0xff; - - test_one(s1, s2); + change = random() % comp_size; + rand_s2[change] = random() & 0xff; + + if (islarge) + test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET, + LARGE_SIZE_START, comp_size); + else + test_one(rand_s1, rand_s2, SIZE, 0, comp_size); } - srandom(1); + srandom(time(0)); - for (i = 0; i < ITERATIONS; i++) { + for (i = 0; i < iterations; i++) { unsigned long j; unsigned long change; + char *rand_s1 = s1; + char *rand_s2 = s2; - for (j = 0; j < SIZE; j++) + for (j = 0; j < alloc_size; j++) s1[j] = random(); - memcpy(s2, s1, SIZE); + rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2; + rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2; + memcpy(rand_s2, rand_s1, comp_size); /* change multiple bytes, 1/8 of total */ - for (j = 0; j < SIZE / 8; j++) { - change = random() % SIZE; + for (j = 0; j < comp_size / 8; j++) { + change = random() % comp_size; s2[change] = random() & 0xff; } - test_one(s1, s2); + if (islarge) + test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET, + LARGE_SIZE_START, comp_size); + else + test_one(rand_s1, rand_s2, SIZE, 0, comp_size); } return 0; } +static int testcases(void) +{ + testcase(0); + testcase(1); + return 0; +} + int main(void) { - return test_harness(testcase, "memcmp"); + test_harness_set_timeout(300); + return test_harness(testcases, "memcmp"); } diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp_32.S b/tools/testing/selftests/powerpc/stringloops/memcmp_32.S new file mode 120000 index 000000000000..056f2b3af789 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/memcmp_32.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/memcmp_32.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/stringloops/string.c b/tools/testing/selftests/powerpc/stringloops/string.c new file mode 100644 index 000000000000..45e7775415c7 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/string.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copied from linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include <stddef.h> + +/** + * strlen - Find the length of a string + * @s: The string to be sized + */ +size_t test_strlen(const char *s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} diff --git a/tools/testing/selftests/powerpc/stringloops/strlen.c b/tools/testing/selftests/powerpc/stringloops/strlen.c new file mode 100644 index 000000000000..9055ebc484d0 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/strlen.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <malloc.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "utils.h" + +#define SIZE 256 +#define ITERATIONS 1000 +#define ITERATIONS_BENCH 100000 + +int test_strlen(const void *s); + +/* test all offsets and lengths */ +static void test_one(char *s) +{ + unsigned long offset; + + for (offset = 0; offset < SIZE; offset++) { + int x, y; + unsigned long i; + + y = strlen(s + offset); + x = test_strlen(s + offset); + + if (x != y) { + printf("strlen() returned %d, should have returned %d (%p offset %ld)\n", x, y, s, offset); + + for (i = offset; i < SIZE; i++) + printf("%02x ", s[i]); + printf("\n"); + } + } +} + +static void bench_test(char *s) +{ + struct timespec ts_start, ts_end; + int i; + + clock_gettime(CLOCK_MONOTONIC, &ts_start); + + for (i = 0; i < ITERATIONS_BENCH; i++) + test_strlen(s); + + clock_gettime(CLOCK_MONOTONIC, &ts_end); + + printf("len %3.3d : time = %.6f\n", test_strlen(s), ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9); +} + +static int testcase(void) +{ + char *s; + unsigned long i; + + s = memalign(128, SIZE); + if (!s) { + perror("memalign"); + exit(1); + } + + srandom(1); + + memset(s, 0, SIZE); + for (i = 0; i < SIZE; i++) { + char c; + + do { + c = random() & 0x7f; + } while (!c); + s[i] = c; + test_one(s); + } + + for (i = 0; i < ITERATIONS; i++) { + unsigned long j; + + for (j = 0; j < SIZE; j++) { + char c; + + do { + c = random() & 0x7f; + } while (!c); + s[j] = c; + } + for (j = 0; j < sizeof(long); j++) { + s[SIZE - 1 - j] = 0; + test_one(s); + } + } + + for (i = 0; i < SIZE; i++) { + char c; + + do { + c = random() & 0x7f; + } while (!c); + s[i] = c; + } + + bench_test(s); + + s[16] = 0; + bench_test(s); + + s[8] = 0; + bench_test(s); + + s[4] = 0; + bench_test(s); + + s[3] = 0; + bench_test(s); + + s[2] = 0; + bench_test(s); + + s[1] = 0; + bench_test(s); + + return 0; +} + +int main(void) +{ + return test_harness(testcase, "strlen"); +} diff --git a/tools/testing/selftests/powerpc/stringloops/strlen_32.S b/tools/testing/selftests/powerpc/stringloops/strlen_32.S new file mode 120000 index 000000000000..72b13731b24c --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/strlen_32.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/strlen_32.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/tm/tm-sigreturn.c b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c index 85d63449243b..9a6017a1d769 100644 --- a/tools/testing/selftests/powerpc/tm/tm-sigreturn.c +++ b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c @@ -55,6 +55,7 @@ int tm_sigreturn(void) uint64_t ret = 0; SKIP_IF(!have_htm()); + SKIP_IF(!is_ppc64le()); memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; diff --git a/tools/testing/selftests/powerpc/tm/tm-tar.c b/tools/testing/selftests/powerpc/tm/tm-tar.c index 2d2fcc2b7a60..f31fe5a28ddb 100644 --- a/tools/testing/selftests/powerpc/tm/tm-tar.c +++ b/tools/testing/selftests/powerpc/tm/tm-tar.c @@ -26,6 +26,7 @@ int test_tar(void) int i; SKIP_IF(!have_htm()); + SKIP_IF(!is_ppc64le()); for (i = 0; i < num_loops; i++) { diff --git a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c index 0274de7b11f3..fe52811584ae 100644 --- a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c +++ b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c @@ -46,6 +46,7 @@ int test_vmxcopy() uint64_t aborted = 0; SKIP_IF(!have_htm()); + SKIP_IF(!is_ppc64le()); fd = mkstemp(tmpfile); assert(fd >= 0); diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c index d46916867a6f..aa8fc1e6365b 100644 --- a/tools/testing/selftests/powerpc/utils.c +++ b/tools/testing/selftests/powerpc/utils.c @@ -11,8 +11,10 @@ #include <link.h> #include <sched.h> #include <stdio.h> +#include <string.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/utsname.h> #include <unistd.h> #include "utils.h" @@ -104,3 +106,18 @@ int pick_online_cpu(void) printf("No cpus in affinity mask?!\n"); return -1; } + +bool is_ppc64le(void) +{ + struct utsname uts; + int rc; + + errno = 0; + rc = uname(&uts); + if (rc) { + perror("uname"); + return false; + } + + return strcmp(uts.machine, "ppc64le") == 0; +} |