test.c (5035B)
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 <stddef.h> 10#include <linux/errno.h> 11#include <linux/auxvec.h> 12#include <linux/signal.h> 13#include <asm/sigcontext.h> 14#include <asm/ucontext.h> 15 16typedef struct ucontext ucontext_t; 17 18#include "btitest.h" 19#include "compiler.h" 20#include "signal.h" 21 22#define EXPECTED_TESTS 18 23 24static volatile unsigned int test_num = 1; 25static unsigned int test_passed; 26static unsigned int test_failed; 27static unsigned int test_skipped; 28 29static 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 40static void putstr(const char *str) 41{ 42 fdputs(1, str); 43} 44 45static void putnum(unsigned int num) 46{ 47 char c; 48 49 if (num / 10) 50 putnum(num / 10); 51 52 c = '0' + (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 62void 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 73static const char *volatile current_test_name; 74static const char *volatile current_trampoline_name; 75static volatile int sigill_expected, sigill_received; 76 77static 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 104static int skip_all; 105 106static void __do_test(void (*trampoline)(void (*)(void)), 107 void (*fn)(void), 108 const char *trampoline_name, 109 const char *name, 110 int expect_sigill) 111{ 112 if (skip_all) { 113 test_skipped++; 114 putstr("ok "); 115 putnum(test_num); 116 putstr(" "); 117 puttestname(name, trampoline_name); 118 putstr(" # SKIP\n"); 119 120 return; 121 } 122 123 /* Branch Target exceptions should only happen in BTI binaries: */ 124 if (!BTI) 125 expect_sigill = 0; 126 127 sigill_expected = expect_sigill; 128 sigill_received = 0; 129 current_test_name = name; 130 current_trampoline_name = trampoline_name; 131 132 trampoline(fn); 133 134 if (expect_sigill && !sigill_received) { 135 putstr("not ok "); 136 test_failed++; 137 } else { 138 putstr("ok "); 139 test_passed++; 140 } 141 putnum(test_num++); 142 putstr(" "); 143 puttestname(name, trampoline_name); 144 putstr("\n"); 145} 146 147#define do_test(expect_sigill_br_x0, \ 148 expect_sigill_br_x16, \ 149 expect_sigill_blr, \ 150 name) \ 151do { \ 152 __do_test(call_using_br_x0, name, "call_using_br_x0", #name, \ 153 expect_sigill_br_x0); \ 154 __do_test(call_using_br_x16, name, "call_using_br_x16", #name, \ 155 expect_sigill_br_x16); \ 156 __do_test(call_using_blr, name, "call_using_blr", #name, \ 157 expect_sigill_blr); \ 158} while (0) 159 160void start(int *argcp) 161{ 162 struct sigaction sa; 163 void *const *p; 164 const struct auxv_entry { 165 unsigned long type; 166 unsigned long val; 167 } *auxv; 168 unsigned long hwcap = 0, hwcap2 = 0; 169 170 putstr("TAP version 13\n"); 171 putstr("1.."); 172 putnum(EXPECTED_TESTS); 173 putstr("\n"); 174 175 /* Gross hack for finding AT_HWCAP2 from the initial process stack: */ 176 p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */ 177 /* step over environment */ 178 while (*p++) 179 ; 180 for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) { 181 switch (auxv->type) { 182 case AT_HWCAP: 183 hwcap = auxv->val; 184 break; 185 case AT_HWCAP2: 186 hwcap2 = auxv->val; 187 break; 188 default: 189 break; 190 } 191 } 192 193 if (hwcap & HWCAP_PACA) 194 putstr("# HWCAP_PACA present\n"); 195 else 196 putstr("# HWCAP_PACA not present\n"); 197 198 if (hwcap2 & HWCAP2_BTI) { 199 putstr("# HWCAP2_BTI present\n"); 200 if (!(hwcap & HWCAP_PACA)) 201 putstr("# Bad hardware? Expect problems.\n"); 202 } else { 203 putstr("# HWCAP2_BTI not present\n"); 204 skip_all = 1; 205 } 206 207 putstr("# Test binary"); 208 if (!BTI) 209 putstr(" not"); 210 putstr(" built for BTI\n"); 211 212 sa.sa_handler = (sighandler_t)(void *)handler; 213 sa.sa_flags = SA_SIGINFO; 214 sigemptyset(&sa.sa_mask); 215 sigaction(SIGILL, &sa, NULL); 216 sigaddset(&sa.sa_mask, SIGILL); 217 sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL); 218 219 do_test(1, 1, 1, nohint_func); 220 do_test(1, 1, 1, bti_none_func); 221 do_test(1, 0, 0, bti_c_func); 222 do_test(0, 0, 1, bti_j_func); 223 do_test(0, 0, 0, bti_jc_func); 224 do_test(1, 0, 0, paciasp_func); 225 226 print_summary(); 227 228 if (test_num - 1 != EXPECTED_TESTS) 229 putstr("# WARNING - EXPECTED TEST COUNT WRONG\n"); 230 231 if (test_failed) 232 exit(1); 233 else 234 exit(0); 235}