1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019,2021 Arm Limited
4 * Original author: Dave Martin <Dave.Martin@arm.com>
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>
15 typedef struct ucontext ucontext_t;
21 #define EXPECTED_TESTS 18
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;
28 static void fdputs(int fd, const char *str)
39 static void putstr(const char *str)
44 static void putnum(unsigned int num)
55 #define puttestname(test_name, trampoline_name) do { \
58 putstr(trampoline_name); \
61 void print_summary(void)
63 putstr("# Totals: pass:");
67 putstr(" xfail:0 xpass:0 skip:");
72 static const char *volatile current_test_name;
73 static const char *volatile current_trampoline_name;
74 static volatile int sigill_expected, sigill_received;
76 static void handler(int n, siginfo_t *si __always_unused,
77 void *uc_ __always_unused)
81 putstr("# \t[SIGILL in ");
82 puttestname(current_test_name, current_trampoline_name);
84 write(1, &"00011011"[((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)
85 >> PSR_BTYPE_SHIFT) * 2], 2);
86 if (!sigill_expected) {
91 puttestname(current_test_name, current_trampoline_name);
92 putstr("(unexpected SIGILL)\n");
97 putstr(" (expected)]\n");
99 /* zap BTYPE so that resuming the faulting code will work */
100 uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;
105 static void __do_test(void (*trampoline)(void (*)(void)),
107 const char *trampoline_name,
116 puttestname(name, trampoline_name);
122 /* Branch Target exceptions should only happen in BTI binaries: */
126 sigill_expected = expect_sigill;
128 current_test_name = name;
129 current_trampoline_name = trampoline_name;
133 if (expect_sigill && !sigill_received) {
142 puttestname(name, trampoline_name);
146 #define do_test(expect_sigill_br_x0, \
147 expect_sigill_br_x16, \
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); \
159 void start(int *argcp)
163 const struct auxv_entry {
167 unsigned long hwcap = 0, hwcap2 = 0;
169 putstr("TAP version 13\n");
171 putnum(EXPECTED_TESTS);
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 */
179 for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {
180 switch (auxv->type) {
192 if (hwcap & HWCAP_PACA)
193 putstr("# HWCAP_PACA present\n");
195 putstr("# HWCAP_PACA not present\n");
197 if (hwcap2 & HWCAP2_BTI) {
198 putstr("# HWCAP2_BTI present\n");
199 if (!(hwcap & HWCAP_PACA))
200 putstr("# Bad hardware? Expect problems.\n");
202 putstr("# HWCAP2_BTI not present\n");
206 putstr("# Test binary");
209 putstr(" built for BTI\n");
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);
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);
227 if (test_num - 1 != EXPECTED_TESTS)
228 putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");