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