Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/basic_signal.c
39536 views
1
/*-
2
* Copyright (c) 2021 M. Warner Losh <[email protected]>
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
}
226
227