1*f50a7f3dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225007a69SMichael Neuling /*
325007a69SMichael Neuling * Copyright 2015, Michael Neuling, IBM Corp.
425007a69SMichael Neuling *
525007a69SMichael Neuling * Test the kernel's signal return code to ensure that it doesn't
625007a69SMichael Neuling * crash when both the transactional and suspend MSR bits are set in
725007a69SMichael Neuling * the signal context.
825007a69SMichael Neuling *
925007a69SMichael Neuling * For this test, we send ourselves a SIGUSR1. In the SIGUSR1 handler
1025007a69SMichael Neuling * we modify the signal context to set both MSR TM S and T bits (which
1125007a69SMichael Neuling * is "reserved" by the PowerISA). When we return from the signal
1225007a69SMichael Neuling * handler (implicit sigreturn), the kernel should detect reserved MSR
1325007a69SMichael Neuling * value and send us with a SIGSEGV.
1425007a69SMichael Neuling */
1525007a69SMichael Neuling
1625007a69SMichael Neuling #include <stdlib.h>
1725007a69SMichael Neuling #include <stdio.h>
1825007a69SMichael Neuling #include <signal.h>
1925007a69SMichael Neuling #include <unistd.h>
2025007a69SMichael Neuling
2125007a69SMichael Neuling #include "utils.h"
2225007a69SMichael Neuling #include "tm.h"
2325007a69SMichael Neuling
2425007a69SMichael Neuling int segv_expected = 0;
2525007a69SMichael Neuling
signal_segv(int signum)2625007a69SMichael Neuling void signal_segv(int signum)
2725007a69SMichael Neuling {
2825007a69SMichael Neuling if (segv_expected && (signum == SIGSEGV))
2925007a69SMichael Neuling _exit(0);
3025007a69SMichael Neuling _exit(1);
3125007a69SMichael Neuling }
3225007a69SMichael Neuling
signal_usr1(int signum,siginfo_t * info,void * uc)3325007a69SMichael Neuling void signal_usr1(int signum, siginfo_t *info, void *uc)
3425007a69SMichael Neuling {
3525007a69SMichael Neuling ucontext_t *ucp = uc;
3625007a69SMichael Neuling
3725007a69SMichael Neuling /* Link tm checkpointed context to normal context */
3825007a69SMichael Neuling ucp->uc_link = ucp;
3925007a69SMichael Neuling /* Set all TM bits so that the context is now invalid */
4025007a69SMichael Neuling #ifdef __powerpc64__
4125007a69SMichael Neuling ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32);
4225007a69SMichael Neuling #else
43501e279cSMichael Ellerman ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL);
4425007a69SMichael Neuling #endif
4525007a69SMichael Neuling /* Should segv on return becuase of invalid context */
4625007a69SMichael Neuling segv_expected = 1;
4725007a69SMichael Neuling }
4825007a69SMichael Neuling
tm_signal_msr_resv()4925007a69SMichael Neuling int tm_signal_msr_resv()
5025007a69SMichael Neuling {
5125007a69SMichael Neuling struct sigaction act;
5225007a69SMichael Neuling
5325007a69SMichael Neuling SKIP_IF(!have_htm());
5425007a69SMichael Neuling
5525007a69SMichael Neuling act.sa_sigaction = signal_usr1;
5625007a69SMichael Neuling sigemptyset(&act.sa_mask);
5725007a69SMichael Neuling act.sa_flags = SA_SIGINFO;
5825007a69SMichael Neuling if (sigaction(SIGUSR1, &act, NULL) < 0) {
5925007a69SMichael Neuling perror("sigaction sigusr1");
6025007a69SMichael Neuling exit(1);
6125007a69SMichael Neuling }
6225007a69SMichael Neuling if (signal(SIGSEGV, signal_segv) == SIG_ERR)
6325007a69SMichael Neuling exit(1);
6425007a69SMichael Neuling
6525007a69SMichael Neuling raise(SIGUSR1);
6625007a69SMichael Neuling
6725007a69SMichael Neuling /* We shouldn't get here as we exit in the segv handler */
6825007a69SMichael Neuling return 1;
6925007a69SMichael Neuling }
7025007a69SMichael Neuling
main(void)7125007a69SMichael Neuling int main(void)
7225007a69SMichael Neuling {
7325007a69SMichael Neuling return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv");
7425007a69SMichael Neuling }
75