1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2015, Michael Neuling, IBM Corp. |
4 | * |
5 | * Test the kernel's signal return code to ensure that it doesn't |
6 | * crash when both the transactional and suspend MSR bits are set in |
7 | * the signal context. |
8 | * |
9 | * For this test, we send ourselves a SIGUSR1. In the SIGUSR1 handler |
10 | * we modify the signal context to set both MSR TM S and T bits (which |
11 | * is "reserved" by the PowerISA). When we return from the signal |
12 | * handler (implicit sigreturn), the kernel should detect reserved MSR |
13 | * value and send us with a SIGSEGV. |
14 | */ |
15 | |
16 | #include <stdlib.h> |
17 | #include <stdio.h> |
18 | #include <signal.h> |
19 | #include <unistd.h> |
20 | |
21 | #include "utils.h" |
22 | #include "tm.h" |
23 | |
24 | int segv_expected = 0; |
25 | |
26 | void signal_segv(int signum) |
27 | { |
28 | if (segv_expected && (signum == SIGSEGV)) |
29 | _exit(0); |
30 | _exit(1); |
31 | } |
32 | |
33 | void signal_usr1(int signum, siginfo_t *info, void *uc) |
34 | { |
35 | ucontext_t *ucp = uc; |
36 | |
37 | /* Link tm checkpointed context to normal context */ |
38 | ucp->uc_link = ucp; |
39 | /* Set all TM bits so that the context is now invalid */ |
40 | #ifdef __powerpc64__ |
41 | ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32); |
42 | #else |
43 | ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL); |
44 | #endif |
45 | /* Should segv on return becuase of invalid context */ |
46 | segv_expected = 1; |
47 | } |
48 | |
49 | int tm_signal_msr_resv() |
50 | { |
51 | struct sigaction act; |
52 | |
53 | SKIP_IF(!have_htm()); |
54 | |
55 | act.sa_sigaction = signal_usr1; |
56 | sigemptyset(&act.sa_mask); |
57 | act.sa_flags = SA_SIGINFO; |
58 | if (sigaction(SIGUSR1, &act, NULL) < 0) { |
59 | perror("sigaction sigusr1" ); |
60 | exit(1); |
61 | } |
62 | if (signal(SIGSEGV, signal_segv) == SIG_ERR) |
63 | exit(1); |
64 | |
65 | raise(SIGUSR1); |
66 | |
67 | /* We shouldn't get here as we exit in the segv handler */ |
68 | return 1; |
69 | } |
70 | |
71 | int main(void) |
72 | { |
73 | return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv" ); |
74 | } |
75 | |