summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/powerpc/alignment/.gitignore4
-rw-r--r--tools/testing/selftests/powerpc/alignment/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/alignment/alignment_handler.c107
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c33
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c53
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h26
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_unaligned.c41
-rw-r--r--tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c43
-rw-r--r--tools/testing/selftests/powerpc/alignment/paste_unaligned.c43
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/futex_bench.c1
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/mmap_bench.c2
-rw-r--r--tools/testing/selftests/powerpc/copyloops/.gitignore17
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile45
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/asm-compat.h0
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/feature-fixups.h0
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h44
-rw-r--r--tools/testing/selftests/powerpc/copyloops/copy_tofrom_user_reference.S24
-rw-r--r--tools/testing/selftests/powerpc/copyloops/exc_validate.c124
-rw-r--r--tools/testing/selftests/powerpc/copyloops/stubs.S19
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c8
-rw-r--r--tools/testing/selftests/powerpc/harness.c18
-rw-r--r--tools/testing/selftests/powerpc/include/utils.h2
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c1
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c1
l---------tools/testing/selftests/powerpc/primitives/asm/asm-const.h1
l---------tools/testing/selftests/powerpc/primitives/asm/feature-fixups.h1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/core-pkey.c4
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c4
-rw-r--r--tools/testing/selftests/powerpc/stringloops/Makefile29
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/cache.h1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h39
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h25
-rw-r--r--tools/testing/selftests/powerpc/stringloops/memcmp.c99
l---------tools/testing/selftests/powerpc/stringloops/memcmp_32.S1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/string.c21
-rw-r--r--tools/testing/selftests/powerpc/stringloops/strlen.c127
l---------tools/testing/selftests/powerpc/stringloops/strlen_32.S1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-sigreturn.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tar.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-vmxcopy.c1
-rw-r--r--tools/testing/selftests/powerpc/utils.c17
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;
+}