summaryrefslogtreecommitdiffstats
path: root/kernel/tools/testing/selftests/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/tools/testing/selftests/powerpc')
-rw-r--r--kernel/tools/testing/selftests/powerpc/Makefile12
-rw-r--r--kernel/tools/testing/selftests/powerpc/benchmarks/.gitignore1
-rw-r--r--kernel/tools/testing/selftests/powerpc/benchmarks/Makefile12
-rw-r--r--kernel/tools/testing/selftests/powerpc/benchmarks/gettimeofday.c31
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/.gitignore7
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/Makefile14
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr.h127
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_default_test.c127
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c71
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c117
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c95
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c97
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c80
-rw-r--r--kernel/tools/testing/selftests/powerpc/dscr/dscr_user_test.c61
-rw-r--r--kernel/tools/testing/selftests/powerpc/mm/Makefile3
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c11
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.h1
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c2
-rw-r--r--kernel/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c9
-rw-r--r--kernel/tools/testing/selftests/powerpc/switch_endian/Makefile14
-rw-r--r--kernel/tools/testing/selftests/powerpc/syscalls/.gitignore1
-rw-r--r--kernel/tools/testing/selftests/powerpc/syscalls/Makefile12
-rw-r--r--kernel/tools/testing/selftests/powerpc/syscalls/ipc.h47
-rw-r--r--kernel/tools/testing/selftests/powerpc/syscalls/ipc_unmuxed.c61
-rw-r--r--kernel/tools/testing/selftests/powerpc/tm/Makefile4
-rw-r--r--kernel/tools/testing/selftests/powerpc/tm/tm-syscall.c13
-rw-r--r--kernel/tools/testing/selftests/powerpc/vphn/Makefile13
48 files changed, 1062 insertions, 23 deletions
diff --git a/kernel/tools/testing/selftests/powerpc/Makefile b/kernel/tools/testing/selftests/powerpc/Makefile
index 5ad042345..0c2706bda 100644
--- a/kernel/tools/testing/selftests/powerpc/Makefile
+++ b/kernel/tools/testing/selftests/powerpc/Makefile
@@ -12,7 +12,17 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
export CFLAGS
-SUB_DIRS = pmu copyloops mm tm primitives stringloops vphn switch_endian
+SUB_DIRS = benchmarks \
+ copyloops \
+ dscr \
+ mm \
+ pmu \
+ primitives \
+ stringloops \
+ switch_endian \
+ syscalls \
+ tm \
+ vphn
endif
diff --git a/kernel/tools/testing/selftests/powerpc/benchmarks/.gitignore b/kernel/tools/testing/selftests/powerpc/benchmarks/.gitignore
new file mode 100644
index 000000000..b4709ea58
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/benchmarks/.gitignore
@@ -0,0 +1 @@
+gettimeofday
diff --git a/kernel/tools/testing/selftests/powerpc/benchmarks/Makefile b/kernel/tools/testing/selftests/powerpc/benchmarks/Makefile
new file mode 100644
index 000000000..5fa487020
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -0,0 +1,12 @@
+TEST_PROGS := gettimeofday
+
+CFLAGS += -O2
+
+all: $(TEST_PROGS)
+
+$(TEST_PROGS): ../harness.c
+
+include ../../lib.mk
+
+clean:
+ rm -f $(TEST_PROGS) *.o
diff --git a/kernel/tools/testing/selftests/powerpc/benchmarks/gettimeofday.c b/kernel/tools/testing/selftests/powerpc/benchmarks/gettimeofday.c
new file mode 100644
index 000000000..3af3c21e8
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/benchmarks/gettimeofday.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015, Anton Blanchard, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#include <sys/time.h>
+#include <stdio.h>
+
+#include "utils.h"
+
+static int test_gettimeofday(void)
+{
+ int i;
+
+ struct timeval tv_start, tv_end;
+
+ gettimeofday(&tv_start, NULL);
+
+ for(i = 0; i < 100000000; i++) {
+ gettimeofday(&tv_end, NULL);
+ }
+
+ printf("time = %.6f\n", tv_end.tv_sec - tv_start.tv_sec + (tv_end.tv_usec - tv_start.tv_usec) * 1e-6);
+
+ return 0;
+}
+
+int main(void)
+{
+ return test_harness(test_gettimeofday, "gettimeofday");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/.gitignore b/kernel/tools/testing/selftests/powerpc/dscr/.gitignore
new file mode 100644
index 000000000..b585c6c15
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/.gitignore
@@ -0,0 +1,7 @@
+dscr_default_test
+dscr_explicit_test
+dscr_inherit_exec_test
+dscr_inherit_test
+dscr_sysfs_test
+dscr_sysfs_thread_test
+dscr_user_test
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/Makefile b/kernel/tools/testing/selftests/powerpc/dscr/Makefile
new file mode 100644
index 000000000..49327ee84
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/Makefile
@@ -0,0 +1,14 @@
+TEST_PROGS := dscr_default_test dscr_explicit_test dscr_user_test \
+ dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test \
+ dscr_sysfs_thread_test
+
+dscr_default_test: LDLIBS += -lpthread
+
+all: $(TEST_PROGS)
+
+$(TEST_PROGS): ../harness.c
+
+include ../../lib.mk
+
+clean:
+ rm -f $(TEST_PROGS) *.o
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr.h b/kernel/tools/testing/selftests/powerpc/dscr/dscr.h
new file mode 100644
index 000000000..a36af1b2c
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr.h
@@ -0,0 +1,127 @@
+/*
+ * POWER Data Stream Control Register (DSCR)
+ *
+ * This header file contains helper functions and macros
+ * required for all the DSCR related test cases.
+ *
+ * Copyright 2012, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#ifndef _SELFTESTS_POWERPC_DSCR_DSCR_H
+#define _SELFTESTS_POWERPC_DSCR_DSCR_H
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include "utils.h"
+
+#define SPRN_DSCR 0x11 /* Privilege state SPR */
+#define SPRN_DSCR_USR 0x03 /* Problem state SPR */
+#define THREADS 100 /* Max threads */
+#define COUNT 100 /* Max iterations */
+#define DSCR_MAX 16 /* Max DSCR value */
+#define LEN_MAX 100 /* Max name length */
+
+#define DSCR_DEFAULT "/sys/devices/system/cpu/dscr_default"
+#define CPU_PATH "/sys/devices/system/cpu/"
+
+#define rmb() asm volatile("lwsync":::"memory")
+#define wmb() asm volatile("lwsync":::"memory")
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+/* Prilvilege state DSCR access */
+inline unsigned long get_dscr(void)
+{
+ unsigned long ret;
+
+ asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR));
+
+ return ret;
+}
+
+inline void set_dscr(unsigned long val)
+{
+ asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
+}
+
+/* Problem state DSCR access */
+inline unsigned long get_dscr_usr(void)
+{
+ unsigned long ret;
+
+ asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR_USR));
+
+ return ret;
+}
+
+inline void set_dscr_usr(unsigned long val)
+{
+ asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_USR));
+}
+
+/* Default DSCR access */
+unsigned long get_default_dscr(void)
+{
+ int fd = -1, ret;
+ char buf[16];
+ unsigned long val;
+
+ if (fd == -1) {
+ fd = open(DSCR_DEFAULT, O_RDONLY);
+ if (fd == -1) {
+ perror("open() failed");
+ exit(1);
+ }
+ }
+ memset(buf, 0, sizeof(buf));
+ lseek(fd, 0, SEEK_SET);
+ ret = read(fd, buf, sizeof(buf));
+ if (ret == -1) {
+ perror("read() failed");
+ exit(1);
+ }
+ sscanf(buf, "%lx", &val);
+ close(fd);
+ return val;
+}
+
+void set_default_dscr(unsigned long val)
+{
+ int fd = -1, ret;
+ char buf[16];
+
+ if (fd == -1) {
+ fd = open(DSCR_DEFAULT, O_RDWR);
+ if (fd == -1) {
+ perror("open() failed");
+ exit(1);
+ }
+ }
+ sprintf(buf, "%lx\n", val);
+ ret = write(fd, buf, strlen(buf));
+ if (ret == -1) {
+ perror("write() failed");
+ exit(1);
+ }
+ close(fd);
+}
+
+double uniform_deviate(int seed)
+{
+ return seed * (1.0 / (RAND_MAX + 1.0));
+}
+#endif /* _SELFTESTS_POWERPC_DSCR_DSCR_H */
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
new file mode 100644
index 000000000..df17c3bab
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
@@ -0,0 +1,127 @@
+/*
+ * POWER Data Stream Control Register (DSCR) default test
+ *
+ * This test modifies the system wide default DSCR through
+ * it's sysfs interface and then verifies that all threads
+ * see the correct changed DSCR value immediately.
+ *
+ * Copyright 2012, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+static unsigned long dscr; /* System DSCR default */
+static unsigned long sequence;
+static unsigned long result[THREADS];
+
+static void *do_test(void *in)
+{
+ unsigned long thread = (unsigned long)in;
+ unsigned long i;
+
+ for (i = 0; i < COUNT; i++) {
+ unsigned long d, cur_dscr, cur_dscr_usr;
+ unsigned long s1, s2;
+
+ s1 = ACCESS_ONCE(sequence);
+ if (s1 & 1)
+ continue;
+ rmb();
+
+ d = dscr;
+ cur_dscr = get_dscr();
+ cur_dscr_usr = get_dscr_usr();
+
+ rmb();
+ s2 = sequence;
+
+ if (s1 != s2)
+ continue;
+
+ if (cur_dscr != d) {
+ fprintf(stderr, "thread %ld kernel DSCR should be %ld "
+ "but is %ld\n", thread, d, cur_dscr);
+ result[thread] = 1;
+ pthread_exit(&result[thread]);
+ }
+
+ if (cur_dscr_usr != d) {
+ fprintf(stderr, "thread %ld user DSCR should be %ld "
+ "but is %ld\n", thread, d, cur_dscr_usr);
+ result[thread] = 1;
+ pthread_exit(&result[thread]);
+ }
+ }
+ result[thread] = 0;
+ pthread_exit(&result[thread]);
+}
+
+int dscr_default(void)
+{
+ pthread_t threads[THREADS];
+ unsigned long i, *status[THREADS];
+ unsigned long orig_dscr_default;
+
+ orig_dscr_default = get_default_dscr();
+
+ /* Initial DSCR default */
+ dscr = 1;
+ set_default_dscr(dscr);
+
+ /* Spawn all testing threads */
+ for (i = 0; i < THREADS; i++) {
+ if (pthread_create(&threads[i], NULL, do_test, (void *)i)) {
+ perror("pthread_create() failed");
+ goto fail;
+ }
+ }
+
+ srand(getpid());
+
+ /* Keep changing the DSCR default */
+ for (i = 0; i < COUNT; i++) {
+ double ret = uniform_deviate(rand());
+
+ if (ret < 0.0001) {
+ sequence++;
+ wmb();
+
+ dscr++;
+ if (dscr > DSCR_MAX)
+ dscr = 0;
+
+ set_default_dscr(dscr);
+
+ wmb();
+ sequence++;
+ }
+ }
+
+ /* Individual testing thread exit status */
+ for (i = 0; i < THREADS; i++) {
+ if (pthread_join(threads[i], (void **)&(status[i]))) {
+ perror("pthread_join() failed");
+ goto fail;
+ }
+
+ if (*status[i]) {
+ printf("%ldth thread failed to join with %ld status\n",
+ i, *status[i]);
+ goto fail;
+ }
+ }
+ set_default_dscr(orig_dscr_default);
+ return 0;
+fail:
+ set_default_dscr(orig_dscr_default);
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_default, "dscr_default_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
new file mode 100644
index 000000000..ad9c3ec26
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
@@ -0,0 +1,71 @@
+/*
+ * POWER Data Stream Control Register (DSCR) explicit test
+ *
+ * This test modifies the DSCR value using mtspr instruction and
+ * verifies the change with mfspr instruction. It uses both the
+ * privilege state SPR and the problem state SPR for this purpose.
+ *
+ * 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
+ * directly without any emulation if the HW supports them. Else
+ * they also get emulated by the kernel.
+ *
+ * Copyright 2012, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+int dscr_explicit(void)
+{
+ unsigned long i, dscr = 0;
+
+ srand(getpid());
+ set_dscr(dscr);
+
+ for (i = 0; i < COUNT; i++) {
+ unsigned long cur_dscr, cur_dscr_usr;
+ double ret = uniform_deviate(rand());
+
+ if (ret < 0.001) {
+ dscr++;
+ if (dscr > DSCR_MAX)
+ dscr = 0;
+
+ set_dscr(dscr);
+ }
+
+ cur_dscr = get_dscr();
+ if (cur_dscr != dscr) {
+ fprintf(stderr, "Kernel DSCR should be %ld but "
+ "is %ld\n", dscr, cur_dscr);
+ return 1;
+ }
+
+ ret = uniform_deviate(rand());
+ if (ret < 0.001) {
+ dscr++;
+ if (dscr > DSCR_MAX)
+ dscr = 0;
+
+ set_dscr_usr(dscr);
+ }
+
+ cur_dscr_usr = get_dscr_usr();
+ if (cur_dscr_usr != dscr) {
+ fprintf(stderr, "User DSCR should be %ld but "
+ "is %ld\n", dscr, cur_dscr_usr);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_explicit, "dscr_explicit_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
new file mode 100644
index 000000000..8265504de
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
@@ -0,0 +1,117 @@
+/*
+ * POWER Data Stream Control Register (DSCR) fork exec test
+ *
+ * This testcase modifies the DSCR using mtspr, forks & execs and
+ * 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
+ * directly without any emulation if the HW supports them. Else
+ * they also get emulated by the kernel.
+ *
+ * Copyright 2012, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+static char prog[LEN_MAX];
+
+static void do_exec(unsigned long parent_dscr)
+{
+ unsigned long cur_dscr, cur_dscr_usr;
+
+ cur_dscr = get_dscr();
+ cur_dscr_usr = get_dscr_usr();
+
+ if (cur_dscr != parent_dscr) {
+ fprintf(stderr, "Parent DSCR %ld was not inherited "
+ "over exec (kernel value)\n", parent_dscr);
+ exit(1);
+ }
+
+ if (cur_dscr_usr != parent_dscr) {
+ fprintf(stderr, "Parent DSCR %ld was not inherited "
+ "over exec (user value)\n", parent_dscr);
+ exit(1);
+ }
+ exit(0);
+}
+
+int dscr_inherit_exec(void)
+{
+ unsigned long i, dscr = 0;
+ pid_t pid;
+
+ for (i = 0; i < COUNT; i++) {
+ dscr++;
+ if (dscr > DSCR_MAX)
+ dscr = 0;
+
+ if (dscr == get_default_dscr())
+ continue;
+
+ if (i % 2 == 0)
+ set_dscr_usr(dscr);
+ else
+ set_dscr(dscr);
+
+ /*
+ * XXX: Force a context switch out so that DSCR
+ * current value is copied into the thread struct
+ * which is required for the child to inherit the
+ * changed value.
+ */
+ sleep(1);
+
+ pid = fork();
+ if (pid == -1) {
+ perror("fork() failed");
+ exit(1);
+ } else if (pid) {
+ int status;
+
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid() failed");
+ exit(1);
+ }
+
+ if (!WIFEXITED(status)) {
+ fprintf(stderr, "Child didn't exit cleanly\n");
+ exit(1);
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ fprintf(stderr, "Child didn't exit cleanly\n");
+ return 1;
+ }
+ } else {
+ char dscr_str[16];
+
+ sprintf(dscr_str, "%ld", dscr);
+ execlp(prog, prog, "exec", dscr_str, NULL);
+ exit(1);
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc == 3 && !strcmp(argv[1], "exec")) {
+ unsigned long parent_dscr;
+
+ parent_dscr = atoi(argv[2]);
+ do_exec(parent_dscr);
+ } else if (argc != 1) {
+ fprintf(stderr, "Usage: %s\n", argv[0]);
+ exit(1);
+ }
+
+ strncpy(prog, argv[0], strlen(argv[0]));
+ return test_harness(dscr_inherit_exec, "dscr_inherit_exec_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
new file mode 100644
index 000000000..4e414caf7
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
@@ -0,0 +1,95 @@
+/*
+ * POWER Data Stream Control Register (DSCR) fork test
+ *
+ * This testcase modifies the DSCR using mtspr, forks and then
+ * verifies that the child process has the correct changed DSCR
+ * value 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
+ * directly without any emulation if the HW supports them. Else
+ * they also get emulated by the kernel.
+ *
+ * Copyright 2012, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+int dscr_inherit(void)
+{
+ unsigned long i, dscr = 0;
+ pid_t pid;
+
+ srand(getpid());
+ set_dscr(dscr);
+
+ for (i = 0; i < COUNT; i++) {
+ unsigned long cur_dscr, cur_dscr_usr;
+
+ dscr++;
+ if (dscr > DSCR_MAX)
+ dscr = 0;
+
+ if (i % 2 == 0)
+ set_dscr_usr(dscr);
+ else
+ set_dscr(dscr);
+
+ /*
+ * XXX: Force a context switch out so that DSCR
+ * current value is copied into the thread struct
+ * which is required for the child to inherit the
+ * changed value.
+ */
+ sleep(1);
+
+ pid = fork();
+ if (pid == -1) {
+ perror("fork() failed");
+ exit(1);
+ } else if (pid) {
+ int status;
+
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid() failed");
+ exit(1);
+ }
+
+ if (!WIFEXITED(status)) {
+ fprintf(stderr, "Child didn't exit cleanly\n");
+ exit(1);
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ fprintf(stderr, "Child didn't exit cleanly\n");
+ return 1;
+ }
+ } else {
+ cur_dscr = get_dscr();
+ if (cur_dscr != dscr) {
+ fprintf(stderr, "Kernel DSCR should be %ld "
+ "but is %ld\n", dscr, cur_dscr);
+ exit(1);
+ }
+
+ cur_dscr_usr = get_dscr_usr();
+ if (cur_dscr_usr != dscr) {
+ fprintf(stderr, "User DSCR should be %ld "
+ "but is %ld\n", dscr, cur_dscr_usr);
+ exit(1);
+ }
+ exit(0);
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_inherit, "dscr_inherit_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
new file mode 100644
index 000000000..17fb1b43c
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
@@ -0,0 +1,97 @@
+/*
+ * POWER Data Stream Control Register (DSCR) sysfs interface test
+ *
+ * This test updates to system wide DSCR default through the sysfs interface
+ * and then verifies that all the CPU specific DSCR defaults are updated as
+ * well verified from their sysfs interfaces.
+ *
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+static int check_cpu_dscr_default(char *file, unsigned long val)
+{
+ char buf[10];
+ int fd, rc;
+
+ fd = open(file, O_RDWR);
+ if (fd == -1) {
+ perror("open() failed");
+ return 1;
+ }
+
+ rc = read(fd, buf, sizeof(buf));
+ if (rc == -1) {
+ perror("read() failed");
+ return 1;
+ }
+ close(fd);
+
+ buf[rc] = '\0';
+ if (strtol(buf, NULL, 16) != val) {
+ printf("DSCR match failed: %ld (system) %ld (cpu)\n",
+ val, strtol(buf, NULL, 16));
+ return 1;
+ }
+ return 0;
+}
+
+static int check_all_cpu_dscr_defaults(unsigned long val)
+{
+ DIR *sysfs;
+ struct dirent *dp;
+ char file[LEN_MAX];
+
+ sysfs = opendir(CPU_PATH);
+ if (!sysfs) {
+ perror("opendir() failed");
+ return 1;
+ }
+
+ while ((dp = readdir(sysfs))) {
+ if (!(dp->d_type & DT_DIR))
+ continue;
+ if (!strcmp(dp->d_name, "cpuidle"))
+ continue;
+ if (!strstr(dp->d_name, "cpu"))
+ continue;
+
+ sprintf(file, "%s%s/dscr", CPU_PATH, dp->d_name);
+ if (access(file, F_OK))
+ continue;
+
+ if (check_cpu_dscr_default(file, val))
+ return 1;
+ }
+ closedir(sysfs);
+ return 0;
+}
+
+int dscr_sysfs(void)
+{
+ unsigned long orig_dscr_default;
+ int i, j;
+
+ orig_dscr_default = get_default_dscr();
+ for (i = 0; i < COUNT; i++) {
+ for (j = 0; j < DSCR_MAX; j++) {
+ set_default_dscr(j);
+ if (check_all_cpu_dscr_defaults(j))
+ goto fail;
+ }
+ }
+ set_default_dscr(orig_dscr_default);
+ return 0;
+fail:
+ set_default_dscr(orig_dscr_default);
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_sysfs, "dscr_sysfs_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c
new file mode 100644
index 000000000..ad97b592e
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c
@@ -0,0 +1,80 @@
+/*
+ * POWER Data Stream Control Register (DSCR) sysfs thread test
+ *
+ * This test updates the system wide DSCR default value through
+ * sysfs interface which should then update all the CPU specific
+ * DSCR default values which must also be then visible to threads
+ * executing on individual CPUs on the system.
+ *
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#define _GNU_SOURCE
+#include "dscr.h"
+
+static int test_thread_dscr(unsigned long val)
+{
+ unsigned long cur_dscr, cur_dscr_usr;
+
+ cur_dscr = get_dscr();
+ cur_dscr_usr = get_dscr_usr();
+
+ if (val != cur_dscr) {
+ printf("[cpu %d] Kernel DSCR should be %ld but is %ld\n",
+ sched_getcpu(), val, cur_dscr);
+ return 1;
+ }
+
+ if (val != cur_dscr_usr) {
+ printf("[cpu %d] User DSCR should be %ld but is %ld\n",
+ sched_getcpu(), val, cur_dscr_usr);
+ return 1;
+ }
+ return 0;
+}
+
+static int check_cpu_dscr_thread(unsigned long val)
+{
+ cpu_set_t mask;
+ int cpu;
+
+ for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
+ CPU_ZERO(&mask);
+ CPU_SET(cpu, &mask);
+ if (sched_setaffinity(0, sizeof(mask), &mask))
+ continue;
+
+ if (test_thread_dscr(val))
+ return 1;
+ }
+ return 0;
+
+}
+
+int dscr_sysfs_thread(void)
+{
+ unsigned long orig_dscr_default;
+ int i, j;
+
+ orig_dscr_default = get_default_dscr();
+ for (i = 0; i < COUNT; i++) {
+ for (j = 0; j < DSCR_MAX; j++) {
+ set_default_dscr(j);
+ if (check_cpu_dscr_thread(j))
+ goto fail;
+ }
+ }
+ set_default_dscr(orig_dscr_default);
+ return 0;
+fail:
+ set_default_dscr(orig_dscr_default);
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_sysfs_thread, "dscr_sysfs_thread_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/dscr/dscr_user_test.c b/kernel/tools/testing/selftests/powerpc/dscr/dscr_user_test.c
new file mode 100644
index 000000000..77d16b5e7
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/dscr/dscr_user_test.c
@@ -0,0 +1,61 @@
+/*
+ * POWER Data Stream Control Register (DSCR) SPR test
+ *
+ * This test modifies the DSCR value through both the SPR number
+ * based mtspr instruction and then makes sure that the same is
+ * reflected through mfspr instruction using either of the SPR
+ * numbers.
+ *
+ * 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
+ * directly without any emulation if the HW supports them. Else
+ * they also get emulated by the kernel.
+ *
+ * Copyright 2013, Anton Blanchard, IBM Corporation.
+ * Copyright 2015, Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include "dscr.h"
+
+static int check_dscr(char *str)
+{
+ unsigned long cur_dscr, cur_dscr_usr;
+
+ cur_dscr = get_dscr();
+ cur_dscr_usr = get_dscr_usr();
+ if (cur_dscr != cur_dscr_usr) {
+ printf("%s set, kernel get %lx != user get %lx\n",
+ str, cur_dscr, cur_dscr_usr);
+ return 1;
+ }
+ return 0;
+}
+
+int dscr_user(void)
+{
+ int i;
+
+ check_dscr("");
+
+ for (i = 0; i < COUNT; i++) {
+ set_dscr(i);
+ if (check_dscr("kernel"))
+ return 1;
+ }
+
+ for (i = 0; i < COUNT; i++) {
+ set_dscr_usr(i);
+ if (check_dscr("user"))
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_harness(dscr_user, "dscr_user_test");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/mm/Makefile b/kernel/tools/testing/selftests/powerpc/mm/Makefile
index 41cc3ed66..ee179e223 100644
--- a/kernel/tools/testing/selftests/powerpc/mm/Makefile
+++ b/kernel/tools/testing/selftests/powerpc/mm/Makefile
@@ -2,8 +2,9 @@ noarg:
$(MAKE) -C ../
TEST_PROGS := hugetlb_vs_thp_test subpage_prot
+TEST_FILES := tempfile
-all: $(TEST_PROGS) tempfile
+all: $(TEST_PROGS) $(TEST_FILES)
$(TEST_PROGS): ../harness.c
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c
index 66ea765c0..94110b1dc 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c
@@ -63,6 +63,8 @@ int back_to_back_ebbs(void)
{
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c
index 0f0423dba..ac18cf617 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c
@@ -20,6 +20,8 @@ int close_clears_pmcc(void)
{
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c
index d3ed64d5d..f0632e7fd 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c
@@ -43,6 +43,8 @@ int cpu_event_pinned_vs_ebb(void)
int cpu, rc;
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
FAIL_IF(bind_to_cpu(cpu));
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c
index 8b972c2aa..33e56a234 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c
@@ -41,6 +41,8 @@ int cpu_event_vs_ebb(void)
int cpu, rc;
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
FAIL_IF(bind_to_cpu(cpu));
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c
index 8590fc1bf..7c57a8d79 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c
@@ -16,6 +16,8 @@ int cycles(void)
{
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c
index 754b3f200..ecf5ee328 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c
@@ -56,6 +56,8 @@ int cycles_with_freeze(void)
uint64_t val;
bool fc_cleared;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c
index d43029b08..c0faba520 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c
@@ -26,6 +26,8 @@ int cycles_with_mmcr2(void)
int i;
bool bad_mmcr2;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index d7a72ce69..9729d9f90 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <linux/auxvec.h>
#include "trace.h"
#include "reg.h"
@@ -319,6 +320,16 @@ void ebb_global_disable(void)
mb();
}
+bool ebb_is_supported(void)
+{
+#ifdef PPC_FEATURE2_EBB
+ /* EBB requires at least POWER8 */
+ return ((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_EBB);
+#else
+ return false;
+#endif
+}
+
void event_ebb_init(struct event *e)
{
e->attr.config |= (1ull << 63);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.h b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
index e44eee5d9..f87e761f8 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
@@ -52,6 +52,7 @@ void standard_ebb_callee(void);
int ebb_event_enable(struct event *e);
void ebb_global_enable(void);
void ebb_global_disable(void);
+bool ebb_is_supported(void);
void ebb_freeze_pmcs(void);
void ebb_unfreeze_pmcs(void);
void event_ebb_init(struct event *e);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c
index c45f94814..1e7b7fe23 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c
@@ -47,6 +47,8 @@ int ebb_on_child(void)
struct event event;
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
FAIL_IF(pipe(read_pipe.fds) == -1);
FAIL_IF(pipe(write_pipe.fds) == -1);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c
index 11acf1d55..a991d2ea8 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c
@@ -54,6 +54,8 @@ int ebb_on_willing_child(void)
struct event event;
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
FAIL_IF(pipe(read_pipe.fds) == -1);
FAIL_IF(pipe(write_pipe.fds) == -1);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c
index be4dd5a4e..af20a2b36 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c
@@ -41,6 +41,8 @@ int ebb_vs_cpu_event(void)
int cpu, rc;
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
FAIL_IF(bind_to_cpu(cpu));
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c
index 7e78153f0..7762ab26e 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c
@@ -16,6 +16,8 @@ int event_attributes(void)
{
struct event event, leader;
+ SKIP_IF(!ebb_is_supported());
+
event_init(&event, 0x1001e);
event_leader_ebb_init(&event);
/* Expected to succeed */
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c
index 9e7af6e76..167135bd9 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c
@@ -44,6 +44,8 @@ int fork_cleanup(void)
{
pid_t pid;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
index f8190fa29..5da355135 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
@@ -111,6 +111,8 @@ int instruction_count(void)
struct event event;
uint64_t overhead;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x400FA, "PM_RUN_INST_CMPL");
event_leader_ebb_init(&event);
event.attr.exclude_kernel = 1;
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c
index 0c9dd9b2e..eb8acb78b 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c
@@ -23,6 +23,8 @@ static int test_body(void)
int i, orig_period, max_period;
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
/* We use PMC4 to make sure the kernel switches all counters correctly */
event_init_named(&event, 0x40002, "instructions");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c
index 67d78af32..6ff8c8ff2 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c
@@ -18,6 +18,8 @@ int multi_counter(void)
struct event events[6];
int i, group_fd;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&events[0], 0x1001C, "PM_CMPLU_STALL_THRD");
event_init_named(&events[1], 0x2D016, "PM_CMPLU_STALL_FXU");
event_init_named(&events[2], 0x30006, "PM_CMPLU_STALL_OTHER_CMPL");
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c
index b8dc371f9..037cb6154 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c
@@ -79,6 +79,8 @@ int multi_ebb_procs(void)
pid_t pids[NR_CHILDREN];
int cpu, rc, i;
+ SKIP_IF(!ebb_is_supported());
+
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
FAIL_IF(bind_to_cpu(cpu));
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c
index 2f9bf8edf..8341d7778 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c
@@ -19,6 +19,8 @@ static int no_handler_test(void)
u64 val;
int i;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c
index 986500fd2..c5fa64790 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c
@@ -58,6 +58,8 @@ static int test_body(void)
{
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
event_init_named(&event, 0x1001e, "cycles");
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
index a503fa70c..c22860ab9 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
@@ -49,6 +49,8 @@ int pmc56_overflow(void)
{
struct event event;
+ SKIP_IF(!ebb_is_supported());
+
/* Use PMC2 so we set PMCjCE, which enables PMC5/6 */
event_init(&event, 0x2001e);
event_leader_ebb_init(&event);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
index 0cae66f65..5b1188f10 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
@@ -18,6 +18,8 @@ int reg_access(void)
{
uint64_t val, expected;
+ SKIP_IF(!ebb_is_supported());
+
expected = 0x8000000100000000ull;
mtspr(SPRN_BESCR, expected);
val = mfspr(SPRN_BESCR);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c
index d56607e4f..1846f4e84 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c
@@ -42,6 +42,8 @@ int task_event_pinned_vs_ebb(void)
pid_t pid;
int rc;
+ SKIP_IF(!ebb_is_supported());
+
FAIL_IF(pipe(read_pipe.fds) == -1);
FAIL_IF(pipe(write_pipe.fds) == -1);
diff --git a/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c b/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c
index eba32196d..e3bc6e92a 100644
--- a/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c
+++ b/kernel/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c
@@ -40,6 +40,8 @@ int task_event_vs_ebb(void)
pid_t pid;
int rc;
+ SKIP_IF(!ebb_is_supported());
+
FAIL_IF(pipe(read_pipe.fds) == -1);
FAIL_IF(pipe(write_pipe.fds) == -1);
diff --git a/kernel/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/kernel/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
index d1b647509..6cae06117 100644
--- a/kernel/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
+++ b/kernel/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
@@ -25,10 +25,19 @@
#define FIXUP_SECTION ".ex_fixup"
+static inline unsigned long __fls(unsigned long x);
+
#include "word-at-a-time.h"
#include "utils.h"
+static inline unsigned long __fls(unsigned long x)
+{
+ int lz;
+
+ asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
+ return sizeof(unsigned long) - 1 - lz;
+}
static int page_size;
static char *mem_region;
diff --git a/kernel/tools/testing/selftests/powerpc/switch_endian/Makefile b/kernel/tools/testing/selftests/powerpc/switch_endian/Makefile
index 081473db2..e21d10674 100644
--- a/kernel/tools/testing/selftests/powerpc/switch_endian/Makefile
+++ b/kernel/tools/testing/selftests/powerpc/switch_endian/Makefile
@@ -1,9 +1,8 @@
-CC := $(CROSS_COMPILE)gcc
-PROGS := switch_endian_test
+TEST_PROGS := switch_endian_test
ASFLAGS += -O2 -Wall -g -nostdlib -m64
-all: $(PROGS)
+all: $(TEST_PROGS)
switch_endian_test: check-reversed.S
@@ -13,12 +12,7 @@ check-reversed.o: check.o
check-reversed.S: check-reversed.o
hexdump -v -e '/1 ".byte 0x%02X\n"' $< > $@
-run_tests: all
- @-for PROG in $(PROGS); do \
- ./$$PROG; \
- done;
+include ../../lib.mk
clean:
- rm -f $(PROGS) *.o check-reversed.S
-
-.PHONY: all run_tests clean
+ rm -f $(TEST_PROGS) *.o check-reversed.S
diff --git a/kernel/tools/testing/selftests/powerpc/syscalls/.gitignore b/kernel/tools/testing/selftests/powerpc/syscalls/.gitignore
new file mode 100644
index 000000000..f0f3fcc9d
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/syscalls/.gitignore
@@ -0,0 +1 @@
+ipc_unmuxed
diff --git a/kernel/tools/testing/selftests/powerpc/syscalls/Makefile b/kernel/tools/testing/selftests/powerpc/syscalls/Makefile
new file mode 100644
index 000000000..b35c7945b
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/syscalls/Makefile
@@ -0,0 +1,12 @@
+TEST_PROGS := ipc_unmuxed
+
+CFLAGS += -I../../../../../usr/include
+
+all: $(TEST_PROGS)
+
+$(TEST_PROGS): ../harness.c
+
+include ../../lib.mk
+
+clean:
+ rm -f $(TEST_PROGS) *.o
diff --git a/kernel/tools/testing/selftests/powerpc/syscalls/ipc.h b/kernel/tools/testing/selftests/powerpc/syscalls/ipc.h
new file mode 100644
index 000000000..fbebc022e
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/syscalls/ipc.h
@@ -0,0 +1,47 @@
+#ifdef __NR_semop
+DO_TEST(semop, __NR_semop)
+#endif
+
+#ifdef __NR_semget
+DO_TEST(semget, __NR_semget)
+#endif
+
+#ifdef __NR_semctl
+DO_TEST(semctl, __NR_semctl)
+#endif
+
+#ifdef __NR_semtimedop
+DO_TEST(semtimedop, __NR_semtimedop)
+#endif
+
+#ifdef __NR_msgsnd
+DO_TEST(msgsnd, __NR_msgsnd)
+#endif
+
+#ifdef __NR_msgrcv
+DO_TEST(msgrcv, __NR_msgrcv)
+#endif
+
+#ifdef __NR_msgget
+DO_TEST(msgget, __NR_msgget)
+#endif
+
+#ifdef __NR_msgctl
+DO_TEST(msgctl, __NR_msgctl)
+#endif
+
+#ifdef __NR_shmat
+DO_TEST(shmat, __NR_shmat)
+#endif
+
+#ifdef __NR_shmdt
+DO_TEST(shmdt, __NR_shmdt)
+#endif
+
+#ifdef __NR_shmget
+DO_TEST(shmget, __NR_shmget)
+#endif
+
+#ifdef __NR_shmctl
+DO_TEST(shmctl, __NR_shmctl)
+#endif
diff --git a/kernel/tools/testing/selftests/powerpc/syscalls/ipc_unmuxed.c b/kernel/tools/testing/selftests/powerpc/syscalls/ipc_unmuxed.c
new file mode 100644
index 000000000..2ac02706f
--- /dev/null
+++ b/kernel/tools/testing/selftests/powerpc/syscalls/ipc_unmuxed.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015, Michael Ellerman, IBM Corp.
+ *
+ * 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.
+ *
+ * This test simply tests that certain syscalls are implemented. It doesn't
+ * actually exercise their logic in any way.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "utils.h"
+
+
+#define DO_TEST(_name, _num) \
+static int test_##_name(void) \
+{ \
+ int rc; \
+ printf("Testing " #_name); \
+ errno = 0; \
+ rc = syscall(_num, -1, 0, 0, 0, 0, 0); \
+ printf("\treturned %d, errno %d\n", rc, errno); \
+ return errno == ENOSYS; \
+}
+
+#include "ipc.h"
+#undef DO_TEST
+
+static int ipc_unmuxed(void)
+{
+ int tests_done = 0;
+
+#define DO_TEST(_name, _num) \
+ FAIL_IF(test_##_name()); \
+ tests_done++;
+
+#include "ipc.h"
+#undef DO_TEST
+
+ /*
+ * If we ran no tests then it means none of the syscall numbers were
+ * defined, possibly because we were built against old headers. But it
+ * means we didn't really test anything, so instead of passing mark it
+ * as a skip to give the user a clue.
+ */
+ SKIP_IF(tests_done == 0);
+
+ return 0;
+}
+
+int main(void)
+{
+ return test_harness(ipc_unmuxed, "ipc_unmuxed");
+}
diff --git a/kernel/tools/testing/selftests/powerpc/tm/Makefile b/kernel/tools/testing/selftests/powerpc/tm/Makefile
index 6bff955e1..4bea62a31 100644
--- a/kernel/tools/testing/selftests/powerpc/tm/Makefile
+++ b/kernel/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,11 +1,11 @@
-TEST_PROGS := tm-resched-dscr
+TEST_PROGS := tm-resched-dscr tm-syscall
all: $(TEST_PROGS)
$(TEST_PROGS): ../harness.c
tm-syscall: tm-syscall-asm.S
-tm-syscall: CFLAGS += -mhtm
+tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
include ../../lib.mk
diff --git a/kernel/tools/testing/selftests/powerpc/tm/tm-syscall.c b/kernel/tools/testing/selftests/powerpc/tm/tm-syscall.c
index 3ed8d4b25..e835bf7ec 100644
--- a/kernel/tools/testing/selftests/powerpc/tm/tm-syscall.c
+++ b/kernel/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -77,12 +77,23 @@ pid_t getppid_tm(bool suspend)
exit(-1);
}
+static inline bool have_htm_nosc(void)
+{
+#ifdef PPC_FEATURE2_HTM_NOSC
+ return ((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_HTM_NOSC);
+#else
+ printf("PPC_FEATURE2_HTM_NOSC not defined, can't check AT_HWCAP2\n");
+ return false;
+#endif
+}
+
int tm_syscall(void)
{
unsigned count = 0;
struct timeval end, now;
- SKIP_IF(!((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_HTM));
+ SKIP_IF(!have_htm_nosc());
+
setbuf(stdout, NULL);
printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
diff --git a/kernel/tools/testing/selftests/powerpc/vphn/Makefile b/kernel/tools/testing/selftests/powerpc/vphn/Makefile
index e539f775f..a485f2e28 100644
--- a/kernel/tools/testing/selftests/powerpc/vphn/Makefile
+++ b/kernel/tools/testing/selftests/powerpc/vphn/Makefile
@@ -1,15 +1,12 @@
-PROG := test-vphn
+TEST_PROGS := test-vphn
CFLAGS += -m64
-all: $(PROG)
+all: $(TEST_PROGS)
-$(PROG): ../harness.c
+$(TEST_PROGS): ../harness.c
-run_tests: all
- ./$(PROG)
+include ../../lib.mk
clean:
- rm -f $(PROG)
-
-.PHONY: all run_tests clean
+ rm -f $(TEST_PROGS)