selftests: Skip TM tests on synthetic TM implementations
authorJordan Niethe <jniethe5@gmail.com>
Thu, 29 Jul 2021 04:13:17 +0000 (14:13 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 26 Aug 2021 11:21:06 +0000 (21:21 +1000)
Transactional Memory was removed from the architecture in ISA v3.1. For
threads running in P8/P9 compatibility mode on P10 a synthetic TM
implementation is provided. In this implementation, tbegin. always sets
cr0 eq meaning the abort handler is always called. This is not an issue
as users of TM are expected to have a fallback non transactional way to
make forward progress in the abort handler.  The TEXASR indicates if a
transaction failure is due to a synthetic implementation.

Some of the TM self tests need a non-degenerate TM implementation for
their testing to be meaningful so check for a synthetic implementation
and skip the test if so.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210729041317.366612-2-jniethe5@gmail.com
28 files changed:
tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
tools/testing/selftests/powerpc/signal/signal_tm.c
tools/testing/selftests/powerpc/tm/tm-exec.c
tools/testing/selftests/powerpc/tm/tm-fork.c
tools/testing/selftests/powerpc/tm/tm-poison.c
tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c
tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c
tools/testing/selftests/powerpc/tm/tm-signal-stack.c
tools/testing/selftests/powerpc/tm/tm-sigreturn.c
tools/testing/selftests/powerpc/tm/tm-syscall.c
tools/testing/selftests/powerpc/tm/tm-tar.c
tools/testing/selftests/powerpc/tm/tm-tmspr.c
tools/testing/selftests/powerpc/tm/tm-trap.c
tools/testing/selftests/powerpc/tm/tm-unavailable.c
tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
tools/testing/selftests/powerpc/tm/tm.h

index 7df7100..67ca297 100644 (file)
@@ -113,6 +113,7 @@ int ptrace_tm_gpr(void)
        int ret, status;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
        pid = fork();
        if (pid < 0) {
index 8706bea..6f2bce1 100644 (file)
@@ -119,6 +119,7 @@ int ptrace_tm_spd_gpr(void)
        int ret, status;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
        pid = fork();
        if (pid < 0) {
index 2ecfa11..e112a34 100644 (file)
@@ -129,6 +129,7 @@ int ptrace_tm_spd_tar(void)
        int ret, status;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
        pid = fork();
        if (pid == 0)
index 6f7fb51..40133d4 100644 (file)
@@ -129,6 +129,7 @@ int ptrace_tm_spd_vsx(void)
        int ret, status, i;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
 
        for (i = 0; i < 128; i++) {
index 068bfed..880ba6a 100644 (file)
@@ -114,6 +114,7 @@ int ptrace_tm_spr(void)
        int ret, status;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
        shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
        pid = fork();
index 46ef378..d0db6df 100644 (file)
@@ -117,6 +117,7 @@ int ptrace_tm_tar(void)
        int ret, status;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
        pid = fork();
        if (pid == 0)
index 70ca012..4f05ce4 100644 (file)
@@ -113,6 +113,7 @@ int ptrace_tm_vsx(void)
        int ret, status, i;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
 
        for (i = 0; i < 128; i++) {
index 5bf2224..c9cf66a 100644 (file)
@@ -56,6 +56,7 @@ static int test_signal_tm()
        }
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        for (i = 0; i < MAX_ATTEMPT; i++) {
                /*
index 260cfdb..c59919d 100644 (file)
@@ -27,6 +27,7 @@ static char *path;
 static int test_exec(void)
 {
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        asm __volatile__(
                "tbegin.;"
index 6efa5a6..c27b935 100644 (file)
@@ -21,6 +21,7 @@
 int test_fork(void)
 {
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        asm __volatile__(
                "tbegin.;"
index 27c083a..a7bbf03 100644 (file)
@@ -33,6 +33,7 @@ int tm_poison_test(void)
        bool fail_vr = false;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        cpu = pick_online_cpu();
        FAIL_IF(cpu < 0);
index 4cdb839..85c940a 100644 (file)
@@ -40,6 +40,7 @@ int test_body(void)
        uint64_t rv, dscr1 = 1, dscr2, texasr;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        printf("Check DSCR TM context switch: ");
        fflush(stdout);
index 254f912..657d755 100644 (file)
@@ -79,6 +79,7 @@ static int tm_signal_context_chk_fpu()
        pid_t pid = getpid();
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        act.sa_sigaction = signal_usr1;
        sigemptyset(&act.sa_mask);
index 0cc680f..400fa70 100644 (file)
@@ -81,6 +81,7 @@ static int tm_signal_context_chk_gpr()
        pid_t pid = getpid();
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        act.sa_sigaction = signal_usr1;
        sigemptyset(&act.sa_mask);
index b6d5273..d628fd3 100644 (file)
@@ -104,6 +104,7 @@ static int tm_signal_context_chk()
        pid_t pid = getpid();
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        act.sa_sigaction = signal_usr1;
        sigemptyset(&act.sa_mask);
index 8e25e20..9bd8692 100644 (file)
@@ -153,6 +153,7 @@ static int tm_signal_context_chk()
        pid_t pid = getpid();
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        act.sa_sigaction = signal_usr1;
        sigemptyset(&act.sa_mask);
index 5908bc6..0b84c92 100644 (file)
@@ -226,6 +226,7 @@ int tm_signal_pagefault(void)
        stack_t ss;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        SKIP_IF(!have_userfaultfd());
 
        setup_uf_mem();
index 07c3881..06b8019 100644 (file)
@@ -32,6 +32,7 @@ int tm_signal_sigreturn_nt(void)
        struct sigaction trap_sa;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        trap_sa.sa_flags = SA_SIGINFO;
        trap_sa.sa_sigaction = trap_signal_handler;
index cdcf8c5..68807aa 100644 (file)
@@ -35,6 +35,7 @@ int tm_signal_stack()
        int pid;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        pid = fork();
        if (pid < 0)
index 9a6017a..ffe4e55 100644 (file)
@@ -55,6 +55,7 @@ int tm_sigreturn(void)
        uint64_t ret = 0;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        SKIP_IF(!is_ppc64le());
 
        memset(&sa, 0, sizeof(sa));
index becb820..467a6b3 100644 (file)
@@ -25,7 +25,6 @@ extern int getppid_tm_suspended(void);
 unsigned retries = 0;
 
 #define TEST_DURATION 10 /* seconds */
-#define TM_RETRIES 100
 
 pid_t getppid_tm(bool suspend)
 {
@@ -67,6 +66,7 @@ int tm_syscall(void)
        struct timeval end, now;
 
        SKIP_IF(!have_htm_nosc());
+       SKIP_IF(htm_is_synthetic());
 
        setbuf(stdout, NULL);
 
index 03be8c4..f2a9137 100644 (file)
@@ -26,6 +26,7 @@ int test_tar(void)
        int i;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        SKIP_IF(!is_ppc64le());
 
        for (i = 0; i < num_loops; i++)
index 794d574..dd5ddff 100644 (file)
@@ -96,6 +96,7 @@ int test_tmspr()
        unsigned long   i;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        /* To cause some context switching */
        thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
index 1152107..97cb747 100644 (file)
@@ -255,6 +255,7 @@ int tm_trap_test(void)
        struct sigaction trap_sa;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        trap_sa.sa_flags = SA_SIGINFO;
        trap_sa.sa_sigaction = trap_signal_handler;
index a1348a5..6bf1b65 100644 (file)
@@ -344,6 +344,7 @@ int tm_unavailable_test(void)
        cpu_set_t cpuset;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        cpu = pick_online_cpu();
        FAIL_IF(cpu < 0);
index 9ef37a9..34364ed 100644 (file)
@@ -91,6 +91,7 @@ int tm_vmx_unavail_test()
        pthread_t *thread;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
 
        passed = 1;
 
index c1e788a..1640e7e 100644 (file)
@@ -46,6 +46,7 @@ int test_vmxcopy()
        uint64_t aborted = 0;
 
        SKIP_IF(!have_htm());
+       SKIP_IF(htm_is_synthetic());
        SKIP_IF(!is_ppc64le());
 
        fd = mkstemp(tmpfile);
index c5a1e5c..c03c6e7 100644 (file)
@@ -10,6 +10,9 @@
 #include <asm/tm.h>
 
 #include "utils.h"
+#include "reg.h"
+
+#define TM_RETRIES 100
 
 static inline bool have_htm(void)
 {
@@ -31,6 +34,39 @@ static inline bool have_htm_nosc(void)
 #endif
 }
 
+/*
+ * Transactional Memory was removed in ISA 3.1. A synthetic TM implementation
+ * is provided on P10 for threads running in P8/P9 compatibility  mode. The
+ * synthetic implementation immediately fails after tbegin. This failure sets
+ * Bit 7 (Failure Persistent) and Bit 15 (Implementation-specific).
+ */
+static inline bool htm_is_synthetic(void)
+{
+       int i;
+
+       /*
+        * Per the ISA, the Failure Persistent bit may be incorrect. Try a few
+        * times in case we got an Implementation-specific failure on a non ISA
+        * v3.1 system. On these systems the Implementation-specific failure
+        * should not be persistent.
+        */
+       for (i = 0; i < TM_RETRIES; i++) {
+               asm volatile(
+               "tbegin.;"
+               "beq 1f;"
+               "tend.;"
+               "1:"
+               :
+               :
+               : "memory");
+
+               if ((__builtin_get_texasr() & (TEXASR_FP | TEXASR_IC)) !=
+                   (TEXASR_FP | TEXASR_IC))
+                       break;
+       }
+       return i == TM_RETRIES;
+}
+
 static inline long failure_code(void)
 {
        return __builtin_get_texasru() >> 24;