]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/kern/basic_signal.c
Add tests for affinity syscalls.
[FreeBSD/FreeBSD.git] / tests / sys / kern / basic_signal.c
1 /*-
2  * Copyright (c) 2021 M. Warner Losh <imp@FreeBSD.org>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6
7 #include <atf-c.h>
8 #include <errno.h>
9 #include <signal.h>
10 #include <stdbool.h>
11 #include <stdlib.h>
12
13 #if defined(__aarch64__)
14 #include <machine/armreg.h>
15 #define SET_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_gpregs.gp_spsr |= PSR_SS
16 #define CLR_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_gpregs.gp_spsr &= ~PSR_SS
17 #elif defined(__amd64__)
18 #include <machine/psl.h>
19 #define SET_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_rflags |= PSL_T
20 #define CLR_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_rflags &= ~PSL_T
21 #elif defined(__i386__)
22 #include <machine/psl.h>
23 #define SET_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_eflags |= PSL_T
24 #define CLR_TRACE_FLAG(ucp)     (ucp)->uc_mcontext.mc_eflags &= ~PSL_T
25 #endif
26
27 static volatile sig_atomic_t signal_fired = 0;
28
29 static void
30 sig_handler(int signo, siginfo_t *info __unused, void *ucp __unused)
31 {
32         signal_fired++;
33 }
34
35 ATF_TC(signal_test);
36
37 ATF_TC_HEAD(signal_test, tc)
38 {
39
40         atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal");
41 }
42
43 ATF_TC_BODY(signal_test, tc)
44 {
45         /*
46          * Setup the signal handlers
47          */
48         struct sigaction sa = {
49                 .sa_sigaction = sig_handler,
50                 .sa_flags = SA_SIGINFO,
51         };
52         ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
53         ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
54         ATF_REQUIRE(sigaction(SIGUSR2, &sa, NULL) == 0);
55         ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0);
56
57         /*
58          * Fire SIGUSR1
59          */
60         ATF_CHECK(signal_fired == 0);
61         ATF_REQUIRE(raise(SIGUSR1) == 0);
62         ATF_CHECK(signal_fired == 1);
63
64         /*
65          * Fire SIGUSR2
66          */
67         ATF_REQUIRE(raise(SIGUSR2) == 0);
68         ATF_CHECK(signal_fired == 2);
69
70         /*
71          * Fire SIGALRM after a timeout
72          */
73         ATF_REQUIRE(alarm(1) == 0);
74         ATF_REQUIRE(pause() == -1);
75         ATF_REQUIRE(errno == EINTR);
76         ATF_CHECK(signal_fired == 3);
77 }
78
79 /*
80  * Check setting the machine dependent single step flag works when supported.
81  */
82 #ifdef SET_TRACE_FLAG
83 static volatile sig_atomic_t trap_signal_fired = 0;
84
85 static void
86 trap_sig_handler(int signo, siginfo_t *info __unused, void *_ucp)
87 {
88         ucontext_t *ucp = _ucp;
89
90         if (trap_signal_fired < 9) {
91                 SET_TRACE_FLAG(ucp);
92         } else {
93                 CLR_TRACE_FLAG(ucp);
94         }
95         trap_signal_fired++;
96 }
97
98 ATF_TC(trap_signal_test);
99
100 ATF_TC_HEAD(trap_signal_test, tc)
101 {
102
103         atf_tc_set_md_var(tc, "descr",
104             "Testing signal handler setting the MD single step flag");
105 }
106
107 ATF_TC_BODY(trap_signal_test, tc)
108 {
109         /*
110          * Setup the signal handlers
111          */
112         struct sigaction sa = {
113                 .sa_sigaction = trap_sig_handler,
114                 .sa_flags = SA_SIGINFO,
115         };
116         ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
117         ATF_REQUIRE(sigaction(SIGTRAP, &sa, NULL) == 0);
118
119         /*
120          * Fire SIGTRAP
121          */
122         ATF_CHECK(trap_signal_fired == 0);
123         ATF_REQUIRE(raise(SIGTRAP) == 0);
124         ATF_CHECK(trap_signal_fired == 10);
125 }
126 #endif
127
128 /*
129  * Special tests for 32-bit arm. We can call thumb code (really just t32) from
130  * normal (a32) mode and vice versa. Likewise, signals can interrupt a T32
131  * context with A32 code and vice versa. Make sure these all work with a simple
132  * test that raises the signal and ensures that it executed. No other platform
133  * has these requirements. Also note: we only support thumb2, so there's no T16
134  * vs T32 issues we have to test for.
135  */
136 #ifdef __arm__
137
138 #define a32_isa __attribute__((target("arm")))
139 #define t32_isa __attribute__((target("thumb")))
140
141 static volatile sig_atomic_t t32_fired = 0;
142 static volatile sig_atomic_t a32_fired = 0;
143
144 a32_isa static void
145 sig_a32(int signo, siginfo_t *info __unused, void *ucp __unused)
146 {
147         a32_fired++;
148 }
149
150 t32_isa static void
151 sig_t32(int signo, siginfo_t *info __unused, void *ucp __unused)
152 {
153         t32_fired++;
154 }
155
156
157 ATF_TC(signal_test_T32_to_A32);
158
159 ATF_TC_HEAD(signal_test_T32_to_A32, tc)
160 {
161
162         atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from T32 to A32");
163 }
164
165 t32_isa ATF_TC_BODY(signal_test_T32_to_A32, tc)
166 {
167         /*
168          * Setup the signal handlers
169          */
170         struct sigaction sa = {
171                 .sa_sigaction = sig_a32,
172                 .sa_flags = SA_SIGINFO,
173         };
174         ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
175         ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
176
177         ATF_REQUIRE((((uintptr_t)sig_a32) & 1) == 0); /* Make sure compiled as not thumb */
178
179         ATF_CHECK(a32_fired == 0);
180         ATF_REQUIRE(raise(SIGUSR1) == 0);
181         ATF_CHECK(a32_fired == 1);
182 }
183
184 ATF_TC(signal_test_A32_to_T32);
185
186 ATF_TC_HEAD(signal_test_A32_to_T32, tc)
187 {
188
189         atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from A32 to T32");
190 }
191
192 a32_isa ATF_TC_BODY(signal_test_A32_to_T32, tc)
193 {
194         /*
195          * Setup the signal handlers
196          */
197         struct sigaction sa = {
198                 .sa_sigaction = sig_t32,
199                 .sa_flags = SA_SIGINFO,
200         };
201         ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
202         ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
203
204         ATF_REQUIRE((((uintptr_t)sig_t32) & 1) == 1);   /* Make sure compiled as thumb */
205
206         ATF_CHECK(t32_fired == 0);
207         ATF_REQUIRE(raise(SIGUSR1) == 0);
208         ATF_CHECK(t32_fired == 1);
209 }
210 #endif
211
212 ATF_TP_ADD_TCS(tp)
213 {
214
215         ATF_TP_ADD_TC(tp, signal_test);
216 #ifdef SET_TRACE_FLAG
217         ATF_TP_ADD_TC(tp, trap_signal_test);
218 #endif
219 #ifdef __arm__
220         ATF_TP_ADD_TC(tp, signal_test_T32_to_A32);
221         ATF_TP_ADD_TC(tp, signal_test_A32_to_T32);
222 #endif
223
224         return (atf_no_error());
225 }