kselftest/arm64: Add missing stddef.h include to BTI tests
[linux-2.6-microblaze.git] / tools / testing / selftests / arm64 / bti / test.c
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
16 typedef struct ucontext ucontext_t;
17
18 #include "btitest.h"
19 #include "compiler.h"
20 #include "signal.h"
21
22 #define EXPECTED_TESTS 18
23
24 static volatile unsigned int test_num = 1;
25 static unsigned int test_passed;
26 static unsigned int test_failed;
27 static unsigned int test_skipped;
28
29 static 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
40 static void putstr(const char *str)
41 {
42         fdputs(1, str);
43 }
44
45 static 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
62 void 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
73 static const char *volatile current_test_name;
74 static const char *volatile current_trampoline_name;
75 static volatile int sigill_expected, sigill_received;
76
77 static 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
104 static int skip_all;
105
106 static 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)                                                   \
151 do {                                                                    \
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
160 void 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 }