mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-23 06:14:42 +08:00
e42edf9b9d
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
78 lines
1.7 KiB
C
78 lines
1.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright 2015, Michael Neuling, IBM Corp.
|
|
*
|
|
* Test the kernel's signal delievery code to ensure that we don't
|
|
* trelaim twice in the kernel signal delivery code. This can happen
|
|
* if we trigger a signal when in a transaction and the stack pointer
|
|
* is bogus.
|
|
*
|
|
* This test case registers a SEGV handler, sets the stack pointer
|
|
* (r1) to NULL, starts a transaction and then generates a SEGV. The
|
|
* SEGV should be handled but we exit here as the stack pointer is
|
|
* invalid and hance we can't sigreturn. We only need to check that
|
|
* this flow doesn't crash the kernel.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
|
|
#include "utils.h"
|
|
#include "tm.h"
|
|
|
|
void signal_segv(int signum)
|
|
{
|
|
/* This should never actually run since stack is foobar */
|
|
exit(1);
|
|
}
|
|
|
|
int tm_signal_stack()
|
|
{
|
|
int pid;
|
|
|
|
SKIP_IF(!have_htm());
|
|
SKIP_IF(htm_is_synthetic());
|
|
|
|
pid = fork();
|
|
if (pid < 0)
|
|
exit(1);
|
|
|
|
if (pid) { /* Parent */
|
|
/*
|
|
* It's likely the whole machine will crash here so if
|
|
* the child ever exits, we are good.
|
|
*/
|
|
wait(NULL);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* The flow here is:
|
|
* 1) register a signal handler (so signal delievery occurs)
|
|
* 2) make stack pointer (r1) = NULL
|
|
* 3) start transaction
|
|
* 4) cause segv
|
|
*/
|
|
if (signal(SIGSEGV, signal_segv) == SIG_ERR)
|
|
exit(1);
|
|
asm volatile("li 1, 0 ;" /* stack ptr == NULL */
|
|
"1:"
|
|
"tbegin.;"
|
|
"beq 1b ;" /* retry forever */
|
|
"tsuspend.;"
|
|
"ld 2, 0(1) ;" /* trigger segv" */
|
|
: : : "memory");
|
|
|
|
/* This should never get here due to above segv */
|
|
return 1;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
return test_harness(tm_signal_stack, "tm_signal_stack");
|
|
}
|