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: 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
This commit is contained in:
Jordan Niethe 2021-07-29 14:13:17 +10:00 committed by Michael Ellerman
parent c95278a053
commit e42edf9b9d
28 changed files with 63 additions and 1 deletions

View 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) {

View 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) {

View 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)

View 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++) {

View 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();

View 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)

View 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++) {

View 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++) {
/*

View 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.;"

View File

@ -21,6 +21,7 @@
int test_fork(void)
{
SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
asm __volatile__(
"tbegin.;"

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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();

View 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;

View 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)

View 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));

View 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);

View 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++)

View 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);

View 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;

View 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);

View File

@ -91,6 +91,7 @@ int tm_vmx_unavail_test()
pthread_t *thread;
SKIP_IF(!have_htm());
SKIP_IF(htm_is_synthetic());
passed = 1;

View 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);

View 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;