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