1
2
3
4
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
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
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
176 p = (void *const *)argcp + 1 + *argcp + 1;
177
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}
236