0001
0002
0003
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <signal.h>
0007 #include <string.h>
0008 #include <unistd.h>
0009 #include <assert.h>
0010 #include <sys/auxv.h>
0011 #include <linux/auxvec.h>
0012 #include <ucontext.h>
0013
0014 #include <asm/unistd.h>
0015
0016 #include <kselftest.h>
0017
0018 #include "test_signals.h"
0019 #include "test_signals_utils.h"
0020 #include "testcases/testcases.h"
0021
0022
0023 extern struct tdescr *current;
0024
0025 static int sig_copyctx = SIGTRAP;
0026
0027 static char const *const feats_names[FMAX_END] = {
0028 " SSBS ",
0029 " SVE ",
0030 " SME ",
0031 " FA64 ",
0032 };
0033
0034 #define MAX_FEATS_SZ 128
0035 static char feats_string[MAX_FEATS_SZ];
0036
0037 static inline char *feats_to_string(unsigned long feats)
0038 {
0039 size_t flen = MAX_FEATS_SZ - 1;
0040
0041 feats_string[0] = '\0';
0042
0043 for (int i = 0; i < FMAX_END; i++) {
0044 if (feats & (1UL << i)) {
0045 size_t tlen = strlen(feats_names[i]);
0046
0047 assert(flen > tlen);
0048 flen -= tlen;
0049 strncat(feats_string, feats_names[i], flen);
0050 }
0051 }
0052
0053 return feats_string;
0054 }
0055
0056 static void unblock_signal(int signum)
0057 {
0058 sigset_t sset;
0059
0060 sigemptyset(&sset);
0061 sigaddset(&sset, signum);
0062 sigprocmask(SIG_UNBLOCK, &sset, NULL);
0063 }
0064
0065 static void default_result(struct tdescr *td, bool force_exit)
0066 {
0067 if (td->result == KSFT_SKIP) {
0068 fprintf(stderr, "==>> completed. SKIP.\n");
0069 } else if (td->pass) {
0070 fprintf(stderr, "==>> completed. PASS(1)\n");
0071 td->result = KSFT_PASS;
0072 } else {
0073 fprintf(stdout, "==>> completed. FAIL(0)\n");
0074 td->result = KSFT_FAIL;
0075 }
0076
0077 if (force_exit)
0078 exit(td->result);
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 static bool handle_signal_unsupported(struct tdescr *td,
0090 siginfo_t *si, void *uc)
0091 {
0092 if (feats_ok(td))
0093 return false;
0094
0095
0096 ((ucontext_t *)uc)->uc_mcontext.pc += 4;
0097
0098 if (!td->initialized) {
0099 fprintf(stderr,
0100 "Got SIG_UNSUPP @test_init. Ignore.\n");
0101 } else {
0102 fprintf(stderr,
0103 "-- RX SIG_UNSUPP on unsupported feat...OK\n");
0104 td->pass = 1;
0105 default_result(current, 1);
0106 }
0107
0108 return true;
0109 }
0110
0111 static bool handle_signal_trigger(struct tdescr *td,
0112 siginfo_t *si, void *uc)
0113 {
0114 td->triggered = 1;
0115
0116 td->run(td, si, uc);
0117
0118 return true;
0119 }
0120
0121 static bool handle_signal_ok(struct tdescr *td,
0122 siginfo_t *si, void *uc)
0123 {
0124
0125
0126
0127
0128 assert(!td->sig_trig || td->triggered);
0129 fprintf(stderr,
0130 "SIG_OK -- SP:0x%llX si_addr@:%p si_code:%d token@:%p offset:%ld\n",
0131 ((ucontext_t *)uc)->uc_mcontext.sp,
0132 si->si_addr, si->si_code, td->token, td->token - si->si_addr);
0133
0134
0135
0136
0137
0138
0139 if (!td->sanity_disabled && !td->token) {
0140 fprintf(stdout,
0141 "current->token ZEROED...test is probably broken!\n");
0142 abort();
0143 }
0144
0145
0146
0147
0148
0149
0150 if (td->sig_ok == SIGSEGV && si->si_code != SEGV_ACCERR) {
0151 fprintf(stdout,
0152 "si_code != SEGV_ACCERR...test is probably broken!\n");
0153 abort();
0154 }
0155 td->pass = 1;
0156
0157
0158
0159
0160
0161
0162 default_result(current, 1);
0163
0164 return true;
0165 }
0166
0167 static bool handle_signal_copyctx(struct tdescr *td,
0168 siginfo_t *si, void *uc)
0169 {
0170
0171 ((ucontext_t *)uc)->uc_mcontext.pc += 4;
0172 memcpy(td->live_uc, uc, td->live_sz);
0173 ASSERT_GOOD_CONTEXT(td->live_uc);
0174 td->live_uc_valid = 1;
0175 fprintf(stderr,
0176 "GOOD CONTEXT grabbed from sig_copyctx handler\n");
0177
0178 return true;
0179 }
0180
0181 static void default_handler(int signum, siginfo_t *si, void *uc)
0182 {
0183 if (current->sig_unsupp && signum == current->sig_unsupp &&
0184 handle_signal_unsupported(current, si, uc)) {
0185 fprintf(stderr, "Handled SIG_UNSUPP\n");
0186 } else if (current->sig_trig && signum == current->sig_trig &&
0187 handle_signal_trigger(current, si, uc)) {
0188 fprintf(stderr, "Handled SIG_TRIG\n");
0189 } else if (current->sig_ok && signum == current->sig_ok &&
0190 handle_signal_ok(current, si, uc)) {
0191 fprintf(stderr, "Handled SIG_OK\n");
0192 } else if (signum == sig_copyctx && current->live_uc &&
0193 handle_signal_copyctx(current, si, uc)) {
0194 fprintf(stderr, "Handled SIG_COPYCTX\n");
0195 } else {
0196 if (signum == SIGALRM && current->timeout) {
0197 fprintf(stderr, "-- Timeout !\n");
0198 } else {
0199 fprintf(stderr,
0200 "-- RX UNEXPECTED SIGNAL: %d\n", signum);
0201 }
0202 default_result(current, 1);
0203 }
0204 }
0205
0206 static int default_setup(struct tdescr *td)
0207 {
0208 struct sigaction sa;
0209
0210 sa.sa_sigaction = default_handler;
0211 sa.sa_flags = SA_SIGINFO | SA_RESTART;
0212 sa.sa_flags |= td->sa_flags;
0213 sigemptyset(&sa.sa_mask);
0214
0215 for (int sig = 1; sig < 32; sig++)
0216 sigaction(sig, &sa, NULL);
0217
0218
0219
0220
0221
0222 for (int sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
0223 sigaction(sig, &sa, NULL);
0224
0225
0226 if (td->sig_trig)
0227 unblock_signal(td->sig_trig);
0228 if (td->sig_ok)
0229 unblock_signal(td->sig_ok);
0230 if (td->sig_unsupp)
0231 unblock_signal(td->sig_unsupp);
0232
0233 if (td->timeout) {
0234 unblock_signal(SIGALRM);
0235 alarm(td->timeout);
0236 }
0237 fprintf(stderr, "Registered handlers for all signals.\n");
0238
0239 return 1;
0240 }
0241
0242 static inline int default_trigger(struct tdescr *td)
0243 {
0244 return !raise(td->sig_trig);
0245 }
0246
0247 int test_init(struct tdescr *td)
0248 {
0249 if (td->sig_trig == sig_copyctx) {
0250 fprintf(stdout,
0251 "Signal %d is RESERVED, cannot be used as a trigger. Aborting\n",
0252 sig_copyctx);
0253 return 0;
0254 }
0255
0256 unblock_signal(sig_copyctx);
0257
0258 td->minsigstksz = getauxval(AT_MINSIGSTKSZ);
0259 if (!td->minsigstksz)
0260 td->minsigstksz = MINSIGSTKSZ;
0261 fprintf(stderr, "Detected MINSTKSIGSZ:%d\n", td->minsigstksz);
0262
0263 if (td->feats_required || td->feats_incompatible) {
0264 td->feats_supported = 0;
0265
0266
0267
0268
0269 if (getauxval(AT_HWCAP) & HWCAP_SSBS)
0270 td->feats_supported |= FEAT_SSBS;
0271 if (getauxval(AT_HWCAP) & HWCAP_SVE)
0272 td->feats_supported |= FEAT_SVE;
0273 if (getauxval(AT_HWCAP2) & HWCAP2_SME)
0274 td->feats_supported |= FEAT_SME;
0275 if (getauxval(AT_HWCAP2) & HWCAP2_SME_FA64)
0276 td->feats_supported |= FEAT_SME_FA64;
0277 if (feats_ok(td)) {
0278 if (td->feats_required & td->feats_supported)
0279 fprintf(stderr,
0280 "Required Features: [%s] supported\n",
0281 feats_to_string(td->feats_required &
0282 td->feats_supported));
0283 if (!(td->feats_incompatible & td->feats_supported))
0284 fprintf(stderr,
0285 "Incompatible Features: [%s] absent\n",
0286 feats_to_string(td->feats_incompatible));
0287 } else {
0288 if ((td->feats_required & td->feats_supported) !=
0289 td->feats_supported)
0290 fprintf(stderr,
0291 "Required Features: [%s] NOT supported\n",
0292 feats_to_string(td->feats_required &
0293 ~td->feats_supported));
0294 if (td->feats_incompatible & td->feats_supported)
0295 fprintf(stderr,
0296 "Incompatible Features: [%s] supported\n",
0297 feats_to_string(td->feats_incompatible &
0298 ~td->feats_supported));
0299
0300
0301 td->result = KSFT_SKIP;
0302 return 0;
0303 }
0304 }
0305
0306
0307 if (td->init && !td->init(td)) {
0308 fprintf(stderr, "FAILED Testcase initialization.\n");
0309 return 0;
0310 }
0311 td->initialized = 1;
0312 fprintf(stderr, "Testcase initialized.\n");
0313
0314 return 1;
0315 }
0316
0317 int test_setup(struct tdescr *td)
0318 {
0319
0320 assert(current);
0321 assert(td);
0322 assert(td->name);
0323 assert(td->run);
0324
0325
0326 td->result = KSFT_FAIL;
0327 if (td->setup)
0328 return td->setup(td);
0329 else
0330 return default_setup(td);
0331 }
0332
0333 int test_run(struct tdescr *td)
0334 {
0335 if (td->trigger)
0336 return td->trigger(td);
0337 else if (td->sig_trig)
0338 return default_trigger(td);
0339 else
0340 return td->run(td, NULL, NULL);
0341 }
0342
0343 void test_result(struct tdescr *td)
0344 {
0345 if (td->initialized && td->result != KSFT_SKIP && td->check_result)
0346 td->check_result(td);
0347 default_result(td, 0);
0348 }
0349
0350 void test_cleanup(struct tdescr *td)
0351 {
0352 if (td->cleanup)
0353 td->cleanup(td);
0354 }