~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/arm64/bti/test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (C) 2019,2021  Arm Limited
  4  * Original author: Dave Martin <Dave.Martin@arm.com>
  5  */
  6 
  7 #include "system.h"
  8 
  9 #include <stdbool.h>
 10 #include <stddef.h>
 11 #include <linux/errno.h>
 12 #include <linux/auxvec.h>
 13 #include <linux/signal.h>
 14 #include <asm/sigcontext.h>
 15 #include <asm/ucontext.h>
 16 
 17 typedef struct ucontext ucontext_t;
 18 
 19 #include "btitest.h"
 20 #include "signal.h"
 21 
 22 #define EXPECTED_TESTS 18
 23 
 24 static volatile unsigned int test_num = 1;
 25 static unsigned int test_passed;
 26 static unsigned int test_failed;
 27 static unsigned int test_skipped;
 28 
 29 static void fdputs(int fd, const char *str)
 30 {
 31         size_t len = 0;
 32         const char *p = str;
 33 
 34         while (*p++)
 35                 ++len;
 36 
 37         write(fd, str, len);
 38 }
 39 
 40 static void putstr(const char *str)
 41 {
 42         fdputs(1, str);
 43 }
 44 
 45 static void putnum(unsigned int num)
 46 {
 47         char c;
 48 
 49         if (num / 10)
 50                 putnum(num / 10);
 51 
 52         c = '' + (num % 10);
 53         write(1, &c, 1);
 54 }
 55 
 56 #define puttestname(test_name, trampoline_name) do {    \
 57         putstr(test_name);                              \
 58         putstr("/");                                    \
 59         putstr(trampoline_name);                        \
 60 } while (0)
 61 
 62 void print_summary(void)
 63 {
 64         putstr("# Totals: pass:");
 65         putnum(test_passed);
 66         putstr(" fail:");
 67         putnum(test_failed);
 68         putstr(" xfail:0 xpass:0 skip:");
 69         putnum(test_skipped);
 70         putstr(" error:0\n");
 71 }
 72 
 73 static const char *volatile current_test_name;
 74 static const char *volatile current_trampoline_name;
 75 static volatile int sigill_expected, sigill_received;
 76 
 77 static void handler(int n, siginfo_t *si __always_unused,
 78                     void *uc_ __always_unused)
 79 {
 80         ucontext_t *uc = uc_;
 81 
 82         putstr("# \t[SIGILL in ");
 83         puttestname(current_test_name, current_trampoline_name);
 84         putstr(", BTYPE=");
 85         write(1, &"00011011"[((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)
 86                               >> PSR_BTYPE_SHIFT) * 2], 2);
 87         if (!sigill_expected) {
 88                 putstr("]\n");
 89                 putstr("not ok ");
 90                 putnum(test_num);
 91                 putstr(" ");
 92                 puttestname(current_test_name, current_trampoline_name);
 93                 putstr("(unexpected SIGILL)\n");
 94                 print_summary();
 95                 exit(128 + n);
 96         }
 97 
 98         putstr(" (expected)]\n");
 99         sigill_received = 1;
100         /* zap BTYPE so that resuming the faulting code will work */
101         uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;
102 }
103 
104 /* Does the system have BTI? */
105 static bool have_bti;
106 
107 static void __do_test(void (*trampoline)(void (*)(void)),
108                       void (*fn)(void),
109                       const char *trampoline_name,
110                       const char *name,
111                       int expect_sigill)
112 {
113         /*
114          * Branch Target exceptions should only happen for BTI
115          * binaries running on a system with BTI:
116          */
117         if (!BTI || !have_bti)
118                 expect_sigill = 0;
119 
120         sigill_expected = expect_sigill;
121         sigill_received = 0;
122         current_test_name = name;
123         current_trampoline_name = trampoline_name;
124 
125         trampoline(fn);
126 
127         if (expect_sigill && !sigill_received) {
128                 putstr("not ok ");
129                 test_failed++;
130         } else {
131                 putstr("ok ");
132                 test_passed++;
133         }
134         putnum(test_num++);
135         putstr(" ");
136         puttestname(name, trampoline_name);
137         putstr("\n");
138 }
139 
140 #define do_test(expect_sigill_br_x0,                                    \
141                 expect_sigill_br_x16,                                   \
142                 expect_sigill_blr,                                      \
143                 name)                                                   \
144 do {                                                                    \
145         __do_test(call_using_br_x0, name, "call_using_br_x0", #name,    \
146                   expect_sigill_br_x0);                                 \
147         __do_test(call_using_br_x16, name, "call_using_br_x16", #name,  \
148                   expect_sigill_br_x16);                                \
149         __do_test(call_using_blr, name, "call_using_blr", #name,        \
150                   expect_sigill_blr);                                   \
151 } while (0)
152 
153 void start(int *argcp)
154 {
155         struct sigaction sa;
156         void *const *p;
157         const struct auxv_entry {
158                 unsigned long type;
159                 unsigned long val;
160         } *auxv;
161         unsigned long hwcap = 0, hwcap2 = 0;
162 
163         putstr("TAP version 13\n");
164         putstr("1..");
165         putnum(EXPECTED_TESTS);
166         putstr("\n");
167 
168         /* Gross hack for finding AT_HWCAP2 from the initial process stack: */
169         p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */
170         /* step over environment */
171         while (*p++)
172                 ;
173         for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {
174                 switch (auxv->type) {
175                 case AT_HWCAP:
176                         hwcap = auxv->val;
177                         break;
178                 case AT_HWCAP2:
179                         hwcap2 = auxv->val;
180                         break;
181                 default:
182                         break;
183                 }
184         }
185 
186         if (hwcap & HWCAP_PACA)
187                 putstr("# HWCAP_PACA present\n");
188         else
189                 putstr("# HWCAP_PACA not present\n");
190 
191         if (hwcap2 & HWCAP2_BTI) {
192                 putstr("# HWCAP2_BTI present\n");
193                 if (!(hwcap & HWCAP_PACA))
194                         putstr("# Bad hardware?  Expect problems.\n");
195                 have_bti = true;
196         } else {
197                 putstr("# HWCAP2_BTI not present\n");
198                 have_bti = false;
199         }
200 
201         putstr("# Test binary");
202         if (!BTI)
203                 putstr(" not");
204         putstr(" built for BTI\n");
205 
206         sa.sa_handler = (sighandler_t)(void *)handler;
207         sa.sa_flags = SA_SIGINFO;
208         sigemptyset(&sa.sa_mask);
209         sigaction(SIGILL, &sa, NULL);
210         sigaddset(&sa.sa_mask, SIGILL);
211         sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
212 
213         do_test(1, 1, 1, nohint_func);
214         do_test(1, 1, 1, bti_none_func);
215         do_test(1, 0, 0, bti_c_func);
216         do_test(0, 0, 1, bti_j_func);
217         do_test(0, 0, 0, bti_jc_func);
218         do_test(1, 0, 0, paciasp_func);
219 
220         print_summary();
221 
222         if (test_num - 1 != EXPECTED_TESTS)
223                 putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");
224 
225         if (test_failed)
226                 exit(1);
227         else
228                 exit(0);
229 }
230 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php