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