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