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:
parent
c95278a053
commit
e42edf9b9d
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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++) {
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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++) {
|
||||
|
@ -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++) {
|
||||
/*
|
||||
|
@ -27,6 +27,7 @@ static char *path;
|
||||
static int test_exec(void)
|
||||
{
|
||||
SKIP_IF(!have_htm());
|
||||
SKIP_IF(htm_is_synthetic());
|
||||
|
||||
asm __volatile__(
|
||||
"tbegin.;"
|
||||
|
@ -21,6 +21,7 @@
|
||||
int test_fork(void)
|
||||
{
|
||||
SKIP_IF(!have_htm());
|
||||
SKIP_IF(htm_is_synthetic());
|
||||
|
||||
asm __volatile__(
|
||||
"tbegin.;"
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -35,6 +35,7 @@ int tm_signal_stack()
|
||||
int pid;
|
||||
|
||||
SKIP_IF(!have_htm());
|
||||
SKIP_IF(htm_is_synthetic());
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -91,6 +91,7 @@ int tm_vmx_unavail_test()
|
||||
pthread_t *thread;
|
||||
|
||||
SKIP_IF(!have_htm());
|
||||
SKIP_IF(htm_is_synthetic());
|
||||
|
||||
passed = 1;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user