1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | /* |
4 | * Copyright 2015, Laurent Dufour, IBM Corp. |
5 | * |
6 | * Test the kernel's signal returning code to check reclaim is done if the |
7 | * sigreturn() is called while in a transaction (suspended since active is |
8 | * already dropped trough the system call path). |
9 | * |
10 | * The kernel must discard the transaction when entering sigreturn, since |
11 | * restoring the potential TM SPRS from the signal frame is requiring to not be |
12 | * in a transaction. |
13 | */ |
14 | |
15 | #include <signal.h> |
16 | #include <stdio.h> |
17 | #include <stdlib.h> |
18 | #include <string.h> |
19 | #include <sys/types.h> |
20 | #include <sys/wait.h> |
21 | #include <unistd.h> |
22 | |
23 | #include "tm.h" |
24 | #include "utils.h" |
25 | |
26 | |
27 | void handler(int sig) |
28 | { |
29 | uint64_t ret; |
30 | |
31 | asm __volatile__( |
32 | "li 3,1 ;" |
33 | "tbegin. ;" |
34 | "beq 1f ;" |
35 | "li 3,0 ;" |
36 | "tsuspend. ;" |
37 | "1: ;" |
38 | "std%X[ret] 3, %[ret] ;" |
39 | : [ret] "=m" (ret) |
40 | : |
41 | : "memory" , "3" , "cr0" ); |
42 | |
43 | if (ret) |
44 | exit(1); |
45 | |
46 | /* |
47 | * We return from the signal handle while in a suspended transaction |
48 | */ |
49 | } |
50 | |
51 | |
52 | int tm_sigreturn(void) |
53 | { |
54 | struct sigaction sa; |
55 | uint64_t ret = 0; |
56 | |
57 | SKIP_IF(!have_htm()); |
58 | SKIP_IF(htm_is_synthetic()); |
59 | SKIP_IF(!is_ppc64le()); |
60 | |
61 | memset(&sa, 0, sizeof(sa)); |
62 | sa.sa_handler = handler; |
63 | sigemptyset(&sa.sa_mask); |
64 | |
65 | if (sigaction(SIGSEGV, &sa, NULL)) |
66 | exit(1); |
67 | |
68 | asm __volatile__( |
69 | "tbegin. ;" |
70 | "beq 1f ;" |
71 | "li 3,0 ;" |
72 | "std 3,0(3) ;" /* trigger SEGV */ |
73 | "li 3,1 ;" |
74 | "std%X[ret] 3,%[ret] ;" |
75 | "tend. ;" |
76 | "b 2f ;" |
77 | "1: ;" |
78 | "li 3,2 ;" |
79 | "std%X[ret] 3,%[ret] ;" |
80 | "2: ;" |
81 | : [ret] "=m" (ret) |
82 | : |
83 | : "memory" , "3" , "cr0" ); |
84 | |
85 | if (ret != 2) |
86 | exit(1); |
87 | |
88 | exit(0); |
89 | } |
90 | |
91 | int main(void) |
92 | { |
93 | return test_harness(tm_sigreturn, "tm_sigreturn" ); |
94 | } |
95 | |