Commit e42edf9b authored by Jordan Niethe's avatar Jordan Niethe Committed by Michael Ellerman

selftests: Skip TM tests on synthetic TM implementations

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: default avatarJordan Niethe <jniethe5@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210729041317.366612-2-jniethe5@gmail.com
parent c95278a0
...@@ -113,6 +113,7 @@ int ptrace_tm_gpr(void) ...@@ -113,6 +113,7 @@ int ptrace_tm_gpr(void)
int ret, status; int ret, status;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
......
...@@ -119,6 +119,7 @@ int ptrace_tm_spd_gpr(void) ...@@ -119,6 +119,7 @@ int ptrace_tm_spd_gpr(void)
int ret, status; int ret, status;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
......
...@@ -129,6 +129,7 @@ int ptrace_tm_spd_tar(void) ...@@ -129,6 +129,7 @@ int ptrace_tm_spd_tar(void)
int ret, status; int ret, status;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
pid = fork(); pid = fork();
if (pid == 0) if (pid == 0)
......
...@@ -129,6 +129,7 @@ int ptrace_tm_spd_vsx(void) ...@@ -129,6 +129,7 @@ int ptrace_tm_spd_vsx(void)
int ret, status, i; int ret, status, i;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
......
...@@ -114,6 +114,7 @@ int ptrace_tm_spr(void) ...@@ -114,6 +114,7 @@ int ptrace_tm_spr(void)
int ret, status; int ret, status;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT); shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
pid = fork(); pid = fork();
......
...@@ -117,6 +117,7 @@ int ptrace_tm_tar(void) ...@@ -117,6 +117,7 @@ int ptrace_tm_tar(void)
int ret, status; int ret, status;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
pid = fork(); pid = fork();
if (pid == 0) if (pid == 0)
......
...@@ -113,6 +113,7 @@ int ptrace_tm_vsx(void) ...@@ -113,6 +113,7 @@ int ptrace_tm_vsx(void)
int ret, status, i; int ret, status, i;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
......
...@@ -56,6 +56,7 @@ static int test_signal_tm() ...@@ -56,6 +56,7 @@ static int test_signal_tm()
} }
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
for (i = 0; i < MAX_ATTEMPT; i++) { for (i = 0; i < MAX_ATTEMPT; i++) {
/* /*
......
...@@ -27,6 +27,7 @@ static char *path; ...@@ -27,6 +27,7 @@ static char *path;
static int test_exec(void) static int test_exec(void)
{ {
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
asm __volatile__( asm __volatile__(
"tbegin.;" "tbegin.;"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
int test_fork(void) int test_fork(void)
{ {
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
asm __volatile__( asm __volatile__(
"tbegin.;" "tbegin.;"
......
...@@ -33,6 +33,7 @@ int tm_poison_test(void) ...@@ -33,6 +33,7 @@ int tm_poison_test(void)
bool fail_vr = false; bool fail_vr = false;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
cpu = pick_online_cpu(); cpu = pick_online_cpu();
FAIL_IF(cpu < 0); FAIL_IF(cpu < 0);
......
...@@ -40,6 +40,7 @@ int test_body(void) ...@@ -40,6 +40,7 @@ int test_body(void)
uint64_t rv, dscr1 = 1, dscr2, texasr; uint64_t rv, dscr1 = 1, dscr2, texasr;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
printf("Check DSCR TM context switch: "); printf("Check DSCR TM context switch: ");
fflush(stdout); fflush(stdout);
......
...@@ -79,6 +79,7 @@ static int tm_signal_context_chk_fpu() ...@@ -79,6 +79,7 @@ static int tm_signal_context_chk_fpu()
pid_t pid = getpid(); pid_t pid = getpid();
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1; act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
......
...@@ -81,6 +81,7 @@ static int tm_signal_context_chk_gpr() ...@@ -81,6 +81,7 @@ static int tm_signal_context_chk_gpr()
pid_t pid = getpid(); pid_t pid = getpid();
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1; act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
......
...@@ -104,6 +104,7 @@ static int tm_signal_context_chk() ...@@ -104,6 +104,7 @@ static int tm_signal_context_chk()
pid_t pid = getpid(); pid_t pid = getpid();
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1; act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
......
...@@ -153,6 +153,7 @@ static int tm_signal_context_chk() ...@@ -153,6 +153,7 @@ static int tm_signal_context_chk()
pid_t pid = getpid(); pid_t pid = getpid();
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1; act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
......
...@@ -226,6 +226,7 @@ int tm_signal_pagefault(void) ...@@ -226,6 +226,7 @@ int tm_signal_pagefault(void)
stack_t ss; stack_t ss;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
SKIP_IF(!have_userfaultfd()); SKIP_IF(!have_userfaultfd());
setup_uf_mem(); setup_uf_mem();
......
...@@ -32,6 +32,7 @@ int tm_signal_sigreturn_nt(void) ...@@ -32,6 +32,7 @@ int tm_signal_sigreturn_nt(void)
struct sigaction trap_sa; struct sigaction trap_sa;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
trap_sa.sa_flags = SA_SIGINFO; trap_sa.sa_flags = SA_SIGINFO;
trap_sa.sa_sigaction = trap_signal_handler; trap_sa.sa_sigaction = trap_signal_handler;
......
...@@ -35,6 +35,7 @@ int tm_signal_stack() ...@@ -35,6 +35,7 @@ int tm_signal_stack()
int pid; int pid;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
......
...@@ -55,6 +55,7 @@ int tm_sigreturn(void) ...@@ -55,6 +55,7 @@ int tm_sigreturn(void)
uint64_t ret = 0; uint64_t ret = 0;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le()); SKIP_IF(!is_ppc64le());
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
......
...@@ -25,7 +25,6 @@ extern int getppid_tm_suspended(void); ...@@ -25,7 +25,6 @@ extern int getppid_tm_suspended(void);
unsigned retries = 0; unsigned retries = 0;
#define TEST_DURATION 10 /* seconds */ #define TEST_DURATION 10 /* seconds */
#define TM_RETRIES 100
pid_t getppid_tm(bool suspend) pid_t getppid_tm(bool suspend)
{ {
...@@ -67,6 +66,7 @@ int tm_syscall(void) ...@@ -67,6 +66,7 @@ int tm_syscall(void)
struct timeval end, now; struct timeval end, now;
SKIP_IF(!have_htm_nosc()); SKIP_IF(!have_htm_nosc());
SKIP_IF(htm_is_synthetic());
setbuf(stdout, NULL); setbuf(stdout, NULL);
......
...@@ -26,6 +26,7 @@ int test_tar(void) ...@@ -26,6 +26,7 @@ int test_tar(void)
int i; int i;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le()); SKIP_IF(!is_ppc64le());
for (i = 0; i < num_loops; i++) for (i = 0; i < num_loops; i++)
......
...@@ -96,6 +96,7 @@ int test_tmspr() ...@@ -96,6 +96,7 @@ int test_tmspr()
unsigned long i; unsigned long i;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
/* To cause some context switching */ /* To cause some context switching */
thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN); thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
......
...@@ -255,6 +255,7 @@ int tm_trap_test(void) ...@@ -255,6 +255,7 @@ int tm_trap_test(void)
struct sigaction trap_sa; struct sigaction trap_sa;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
trap_sa.sa_flags = SA_SIGINFO; trap_sa.sa_flags = SA_SIGINFO;
trap_sa.sa_sigaction = trap_signal_handler; trap_sa.sa_sigaction = trap_signal_handler;
......
...@@ -344,6 +344,7 @@ int tm_unavailable_test(void) ...@@ -344,6 +344,7 @@ int tm_unavailable_test(void)
cpu_set_t cpuset; cpu_set_t cpuset;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
cpu = pick_online_cpu(); cpu = pick_online_cpu();
FAIL_IF(cpu < 0); FAIL_IF(cpu < 0);
......
...@@ -91,6 +91,7 @@ int tm_vmx_unavail_test() ...@@ -91,6 +91,7 @@ int tm_vmx_unavail_test()
pthread_t *thread; pthread_t *thread;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
passed = 1; passed = 1;
......
...@@ -46,6 +46,7 @@ int test_vmxcopy() ...@@ -46,6 +46,7 @@ int test_vmxcopy()
uint64_t aborted = 0; uint64_t aborted = 0;
SKIP_IF(!have_htm()); SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le()); SKIP_IF(!is_ppc64le());
fd = mkstemp(tmpfile); fd = mkstemp(tmpfile);
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include <asm/tm.h> #include <asm/tm.h>
#include "utils.h" #include "utils.h"
#include "reg.h"
#define TM_RETRIES 100
static inline bool have_htm(void) static inline bool have_htm(void)
{ {
...@@ -31,6 +34,39 @@ static inline bool have_htm_nosc(void) ...@@ -31,6 +34,39 @@ static inline bool have_htm_nosc(void)
#endif #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) static inline long failure_code(void)
{ {
return __builtin_get_texasru() >> 24; return __builtin_get_texasru() >> 24;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment