1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2019 ARM Limited */
11 #include <linux/auxvec.h>
14 #include <asm/unistd.h>
16 #include <kselftest.h>
18 #include "test_signals.h"
19 #include "test_signals_utils.h"
20 #include "testcases/testcases.h"
23 extern struct tdescr
*current
;
25 static int sig_copyctx
= SIGTRAP
;
27 static char const *const feats_names
[FMAX_END
] = {
31 #define MAX_FEATS_SZ 128
32 static char feats_string
[MAX_FEATS_SZ
];
34 static inline char *feats_to_string(unsigned long feats
)
36 size_t flen
= MAX_FEATS_SZ
- 1;
38 for (int i
= 0; i
< FMAX_END
; i
++) {
39 if (feats
& (1UL << i
)) {
40 size_t tlen
= strlen(feats_names
[i
]);
44 strncat(feats_string
, feats_names
[i
], flen
);
51 static void unblock_signal(int signum
)
56 sigaddset(&sset
, signum
);
57 sigprocmask(SIG_UNBLOCK
, &sset
, NULL
);
60 static void default_result(struct tdescr
*td
, bool force_exit
)
62 if (td
->result
== KSFT_SKIP
) {
63 fprintf(stderr
, "==>> completed. SKIP.\n");
64 } else if (td
->pass
) {
65 fprintf(stderr
, "==>> completed. PASS(1)\n");
66 td
->result
= KSFT_PASS
;
68 fprintf(stdout
, "==>> completed. FAIL(0)\n");
69 td
->result
= KSFT_FAIL
;
77 * The following handle_signal_* helpers are used by main default_handler
78 * and are meant to return true when signal is handled successfully:
79 * when false is returned instead, it means that the signal was somehow
80 * unexpected in that context and it was NOT handled; default_handler will
81 * take care of such unexpected situations.
84 static bool handle_signal_unsupported(struct tdescr
*td
,
85 siginfo_t
*si
, void *uc
)
90 /* Mangling PC to avoid loops on original SIGILL */
91 ((ucontext_t
*)uc
)->uc_mcontext
.pc
+= 4;
93 if (!td
->initialized
) {
95 "Got SIG_UNSUPP @test_init. Ignore.\n");
98 "-- RX SIG_UNSUPP on unsupported feat...OK\n");
100 default_result(current
, 1);
106 static bool handle_signal_trigger(struct tdescr
*td
,
107 siginfo_t
*si
, void *uc
)
110 /* ->run was asserted NON-NULL in test_setup() already */
116 static bool handle_signal_ok(struct tdescr
*td
,
117 siginfo_t
*si
, void *uc
)
120 * it's a bug in the test code when this assert fail:
121 * if sig_trig was defined, it must have been used before getting here.
123 assert(!td
->sig_trig
|| td
->triggered
);
125 "SIG_OK -- SP:0x%llX si_addr@:%p si_code:%d token@:%p offset:%ld\n",
126 ((ucontext_t
*)uc
)->uc_mcontext
.sp
,
127 si
->si_addr
, si
->si_code
, td
->token
, td
->token
- si
->si_addr
);
129 * fake_sigreturn tests, which have sanity_enabled=1, set, at the very
130 * last time, the token field to the SP address used to place the fake
131 * sigframe: so token==0 means we never made it to the end,
132 * segfaulting well-before, and the test is possibly broken.
134 if (!td
->sanity_disabled
&& !td
->token
) {
136 "current->token ZEROED...test is probably broken!\n");
140 * Trying to narrow down the SEGV to the ones generated by Kernel itself
141 * via arm64_notify_segfault(). This is a best-effort check anyway, and
142 * the si_code check may need to change if this aspect of the kernel
145 if (td
->sig_ok
== SIGSEGV
&& si
->si_code
!= SEGV_ACCERR
) {
147 "si_code != SEGV_ACCERR...test is probably broken!\n");
152 * Some tests can lead to SEGV loops: in such a case we want to
153 * terminate immediately exiting straight away; some others are not
154 * supposed to outlive the signal handler code, due to the content of
155 * the fake sigframe which caused the signal itself.
157 default_result(current
, 1);
162 static bool handle_signal_copyctx(struct tdescr
*td
,
163 siginfo_t
*si
, void *uc
)
165 /* Mangling PC to avoid loops on original BRK instr */
166 ((ucontext_t
*)uc
)->uc_mcontext
.pc
+= 4;
167 memcpy(td
->live_uc
, uc
, td
->live_sz
);
168 ASSERT_GOOD_CONTEXT(td
->live_uc
);
169 td
->live_uc_valid
= 1;
171 "GOOD CONTEXT grabbed from sig_copyctx handler\n");
176 static void default_handler(int signum
, siginfo_t
*si
, void *uc
)
178 if (current
->sig_unsupp
&& signum
== current
->sig_unsupp
&&
179 handle_signal_unsupported(current
, si
, uc
)) {
180 fprintf(stderr
, "Handled SIG_UNSUPP\n");
181 } else if (current
->sig_trig
&& signum
== current
->sig_trig
&&
182 handle_signal_trigger(current
, si
, uc
)) {
183 fprintf(stderr
, "Handled SIG_TRIG\n");
184 } else if (current
->sig_ok
&& signum
== current
->sig_ok
&&
185 handle_signal_ok(current
, si
, uc
)) {
186 fprintf(stderr
, "Handled SIG_OK\n");
187 } else if (signum
== sig_copyctx
&& current
->live_uc
&&
188 handle_signal_copyctx(current
, si
, uc
)) {
189 fprintf(stderr
, "Handled SIG_COPYCTX\n");
191 if (signum
== SIGALRM
&& current
->timeout
) {
192 fprintf(stderr
, "-- Timeout !\n");
195 "-- RX UNEXPECTED SIGNAL: %d\n", signum
);
197 default_result(current
, 1);
201 static int default_setup(struct tdescr
*td
)
205 sa
.sa_sigaction
= default_handler
;
206 sa
.sa_flags
= SA_SIGINFO
| SA_RESTART
;
207 sa
.sa_flags
|= td
->sa_flags
;
208 sigemptyset(&sa
.sa_mask
);
209 /* uncatchable signals naturally skipped ... */
210 for (int sig
= 1; sig
< 32; sig
++)
211 sigaction(sig
, &sa
, NULL
);
213 * RT Signals default disposition is Term but they cannot be
214 * generated by the Kernel in response to our tests; so just catch
215 * them all and report them as UNEXPECTED signals.
217 for (int sig
= SIGRTMIN
; sig
<= SIGRTMAX
; sig
++)
218 sigaction(sig
, &sa
, NULL
);
220 /* just in case...unblock explicitly all we need */
222 unblock_signal(td
->sig_trig
);
224 unblock_signal(td
->sig_ok
);
226 unblock_signal(td
->sig_unsupp
);
229 unblock_signal(SIGALRM
);
232 fprintf(stderr
, "Registered handlers for all signals.\n");
237 static inline int default_trigger(struct tdescr
*td
)
239 return !raise(td
->sig_trig
);
242 int test_init(struct tdescr
*td
)
244 if (td
->sig_trig
== sig_copyctx
) {
246 "Signal %d is RESERVED, cannot be used as a trigger. Aborting\n",
251 unblock_signal(sig_copyctx
);
253 td
->minsigstksz
= getauxval(AT_MINSIGSTKSZ
);
254 if (!td
->minsigstksz
)
255 td
->minsigstksz
= MINSIGSTKSZ
;
256 fprintf(stderr
, "Detected MINSTKSIGSZ:%d\n", td
->minsigstksz
);
258 if (td
->feats_required
) {
259 td
->feats_supported
= 0;
261 * Checking for CPU required features using both the
262 * auxval and the arm64 MRS Emulation to read sysregs.
264 if (getauxval(AT_HWCAP
) & HWCAP_SSBS
)
265 td
->feats_supported
|= FEAT_SSBS
;
268 "Required Features: [%s] supported\n",
269 feats_to_string(td
->feats_required
&
270 td
->feats_supported
));
273 "Required Features: [%s] NOT supported\n",
274 feats_to_string(td
->feats_required
&
275 ~td
->feats_supported
));
278 /* Perform test specific additional initialization */
279 if (td
->init
&& !td
->init(td
)) {
280 fprintf(stderr
, "FAILED Testcase initialization.\n");
284 fprintf(stderr
, "Testcase initialized.\n");
289 int test_setup(struct tdescr
*td
)
291 /* assert core invariants symptom of a rotten testcase */
297 /* Default result is FAIL if test setup fails */
298 td
->result
= KSFT_FAIL
;
300 return td
->setup(td
);
302 return default_setup(td
);
305 int test_run(struct tdescr
*td
)
309 return td
->trigger(td
);
311 return default_trigger(td
);
313 return td
->run(td
, NULL
, NULL
);
317 void test_result(struct tdescr
*td
)
319 if (td
->initialized
&& td
->result
!= KSFT_SKIP
&& td
->check_result
)
320 td
->check_result(td
);
321 default_result(td
, 0);
324 void test_cleanup(struct tdescr
*td
)