Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / powerpc / tm / tm-sigreturn.c
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(!is_ppc64le());
59
60         memset(&sa, 0, sizeof(sa));
61         sa.sa_handler = handler;
62         sigemptyset(&sa.sa_mask);
63
64         if (sigaction(SIGSEGV, &sa, NULL))
65                 exit(1);
66
67         asm __volatile__(
68                 "tbegin.                        ;"
69                 "beq            1f              ;"
70                 "li             3,0             ;"
71                 "std            3,0(3)          ;" /* trigger SEGV */
72                 "li             3,1             ;"
73                 "std%X[ret]     3,%[ret]        ;"
74                 "tend.                          ;"
75                 "b              2f              ;"
76                 "1:                             ;"
77                 "li             3,2             ;"
78                 "std%X[ret]     3,%[ret]        ;"
79                 "2:                             ;"
80                 : [ret] "=m"(ret)
81                 :
82                 : "memory", "3", "cr0");
83
84         if (ret != 2)
85                 exit(1);
86
87         exit(0);
88 }
89
90 int main(void)
91 {
92         return test_harness(tm_sigreturn, "tm_sigreturn");
93 }