Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2019 ARM Limited */
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  * The following handle_signal_* helpers are used by main default_handler
0083  * and are meant to return true when signal is handled successfully:
0084  * when false is returned instead, it means that the signal was somehow
0085  * unexpected in that context and it was NOT handled; default_handler will
0086  * take care of such unexpected situations.
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     /* Mangling PC to avoid loops on original SIGILL */
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     /* ->run was asserted NON-NULL in test_setup() already */
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      * it's a bug in the test code when this assert fail:
0126      * if sig_trig was defined, it must have been used before getting here.
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      * fake_sigreturn tests, which have sanity_enabled=1, set, at the very
0135      * last time, the token field to the SP address used to place the fake
0136      * sigframe: so token==0 means we never made it to the end,
0137      * segfaulting well-before, and the test is possibly broken.
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      * Trying to narrow down the SEGV to the ones generated by Kernel itself
0146      * via arm64_notify_segfault(). This is a best-effort check anyway, and
0147      * the si_code check may need to change if this aspect of the kernel
0148      * ABI changes.
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      * Some tests can lead to SEGV loops: in such a case we want to
0158      * terminate immediately exiting straight away; some others are not
0159      * supposed to outlive the signal handler code, due to the content of
0160      * the fake sigframe which caused the signal itself.
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     /* Mangling PC to avoid loops on original BRK instr */
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     /* uncatchable signals naturally skipped ... */
0215     for (int sig = 1; sig < 32; sig++)
0216         sigaction(sig, &sa, NULL);
0217     /*
0218      * RT Signals default disposition is Term but they cannot be
0219      * generated by the Kernel in response to our tests; so just catch
0220      * them all and report them as UNEXPECTED signals.
0221      */
0222     for (int sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
0223         sigaction(sig, &sa, NULL);
0224 
0225     /* just in case...unblock explicitly all we need */
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     /* just in case */
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          * Checking for CPU required features using both the
0267          * auxval and the arm64 MRS Emulation to read sysregs.
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     /* Perform test specific additional initialization */
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     /* assert core invariants symptom of a rotten testcase */
0320     assert(current);
0321     assert(td);
0322     assert(td->name);
0323     assert(td->run);
0324 
0325     /* Default result is FAIL if test setup fails */
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 }