selftests/powerpc: Add thread based stress test for DSCR sysfs interfaces
authorMichael Ellerman <mpe@ellerman.id.au>
Sun, 7 Jun 2015 09:25:16 +0000 (19:25 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Sun, 7 Jun 2015 09:38:18 +0000 (19:38 +1000)
This patch adds a test to update the system wide DSCR value repeatedly
and then verifies that any thread on any given CPU on the system must be
able to see the same DSCR value whether its is being read through the
problem state based SPR or the privilege state based SPR.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
tools/testing/selftests/powerpc/dscr/Makefile
tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c [new file with mode: 0644]

index de0b53b533d4d551b5fd9fbbd0fffcdb722b9cb1..49327ee84e3a32fc26415afe04f8075e52a8872e 100644 (file)
@@ -1,5 +1,6 @@
 TEST_PROGS := dscr_default_test dscr_explicit_test dscr_user_test      \
-             dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test
+             dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test  \
+             dscr_sysfs_thread_test
 
 dscr_default_test: LDLIBS += -lpthread
 
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_thread_test.c
new file mode 100644 (file)
index 0000000..ad97b59
--- /dev/null
@@ -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");
+}