xref: /openbmc/qemu/tests/tcg/aarch64/bti-2.c (revision 802427bcdae1ad2eceea8a8877ecad835e3f8fde)
1*1d9ac91bSRichard Henderson /*
2*1d9ac91bSRichard Henderson  * Branch target identification, basic notskip cases.
3*1d9ac91bSRichard Henderson  */
4*1d9ac91bSRichard Henderson 
5*1d9ac91bSRichard Henderson #include <stdio.h>
6*1d9ac91bSRichard Henderson #include <signal.h>
7*1d9ac91bSRichard Henderson #include <string.h>
8*1d9ac91bSRichard Henderson #include <unistd.h>
9*1d9ac91bSRichard Henderson #include <sys/mman.h>
10*1d9ac91bSRichard Henderson 
11*1d9ac91bSRichard Henderson #ifndef PROT_BTI
12*1d9ac91bSRichard Henderson #define PROT_BTI  0x10
13*1d9ac91bSRichard Henderson #endif
14*1d9ac91bSRichard Henderson 
skip2_sigill(int sig,siginfo_t * info,void * vuc)15*1d9ac91bSRichard Henderson static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
16*1d9ac91bSRichard Henderson {
17*1d9ac91bSRichard Henderson     ucontext_t *uc = vuc;
18*1d9ac91bSRichard Henderson     uc->uc_mcontext.pc += 8;
19*1d9ac91bSRichard Henderson     uc->uc_mcontext.pstate = 1;
20*1d9ac91bSRichard Henderson }
21*1d9ac91bSRichard Henderson 
22*1d9ac91bSRichard Henderson #define NOP       "nop"
23*1d9ac91bSRichard Henderson #define BTI_N     "hint #32"
24*1d9ac91bSRichard Henderson #define BTI_C     "hint #34"
25*1d9ac91bSRichard Henderson #define BTI_J     "hint #36"
26*1d9ac91bSRichard Henderson #define BTI_JC    "hint #38"
27*1d9ac91bSRichard Henderson 
28*1d9ac91bSRichard Henderson #define BTYPE_1(DEST)    \
29*1d9ac91bSRichard Henderson     "mov x1, #1\n\t"     \
30*1d9ac91bSRichard Henderson     "adr x16, 1f\n\t"    \
31*1d9ac91bSRichard Henderson     "br x16\n"           \
32*1d9ac91bSRichard Henderson "1: " DEST "\n\t"        \
33*1d9ac91bSRichard Henderson     "mov x1, #0"
34*1d9ac91bSRichard Henderson 
35*1d9ac91bSRichard Henderson #define BTYPE_2(DEST)    \
36*1d9ac91bSRichard Henderson     "mov x1, #1\n\t"     \
37*1d9ac91bSRichard Henderson     "adr x16, 1f\n\t"    \
38*1d9ac91bSRichard Henderson     "blr x16\n"          \
39*1d9ac91bSRichard Henderson "1: " DEST "\n\t"        \
40*1d9ac91bSRichard Henderson     "mov x1, #0"
41*1d9ac91bSRichard Henderson 
42*1d9ac91bSRichard Henderson #define BTYPE_3(DEST)    \
43*1d9ac91bSRichard Henderson     "mov x1, #1\n\t"     \
44*1d9ac91bSRichard Henderson     "adr x15, 1f\n\t"    \
45*1d9ac91bSRichard Henderson     "br x15\n"           \
46*1d9ac91bSRichard Henderson "1: " DEST "\n\t"        \
47*1d9ac91bSRichard Henderson     "mov x1, #0"
48*1d9ac91bSRichard Henderson 
49*1d9ac91bSRichard Henderson #define TEST(WHICH, DEST, EXPECT) \
50*1d9ac91bSRichard Henderson     WHICH(DEST) "\n"              \
51*1d9ac91bSRichard Henderson     ".if " #EXPECT "\n\t"         \
52*1d9ac91bSRichard Henderson     "eor x1, x1," #EXPECT "\n"    \
53*1d9ac91bSRichard Henderson     ".endif\n\t"                  \
54*1d9ac91bSRichard Henderson     "add x0, x0, x1\n\t"
55*1d9ac91bSRichard Henderson 
56*1d9ac91bSRichard Henderson asm("\n"
57*1d9ac91bSRichard Henderson "test_begin:\n\t"
58*1d9ac91bSRichard Henderson     BTI_C "\n\t"
59*1d9ac91bSRichard Henderson     "mov x2, x30\n\t"
60*1d9ac91bSRichard Henderson     "mov x0, #0\n\t"
61*1d9ac91bSRichard Henderson 
62*1d9ac91bSRichard Henderson     TEST(BTYPE_1, NOP, 1)
63*1d9ac91bSRichard Henderson     TEST(BTYPE_1, BTI_N, 1)
64*1d9ac91bSRichard Henderson     TEST(BTYPE_1, BTI_C, 0)
65*1d9ac91bSRichard Henderson     TEST(BTYPE_1, BTI_J, 0)
66*1d9ac91bSRichard Henderson     TEST(BTYPE_1, BTI_JC, 0)
67*1d9ac91bSRichard Henderson 
68*1d9ac91bSRichard Henderson     TEST(BTYPE_2, NOP, 1)
69*1d9ac91bSRichard Henderson     TEST(BTYPE_2, BTI_N, 1)
70*1d9ac91bSRichard Henderson     TEST(BTYPE_2, BTI_C, 0)
71*1d9ac91bSRichard Henderson     TEST(BTYPE_2, BTI_J, 1)
72*1d9ac91bSRichard Henderson     TEST(BTYPE_2, BTI_JC, 0)
73*1d9ac91bSRichard Henderson 
74*1d9ac91bSRichard Henderson     TEST(BTYPE_3, NOP, 1)
75*1d9ac91bSRichard Henderson     TEST(BTYPE_3, BTI_N, 1)
76*1d9ac91bSRichard Henderson     TEST(BTYPE_3, BTI_C, 1)
77*1d9ac91bSRichard Henderson     TEST(BTYPE_3, BTI_J, 0)
78*1d9ac91bSRichard Henderson     TEST(BTYPE_3, BTI_JC, 0)
79*1d9ac91bSRichard Henderson 
80*1d9ac91bSRichard Henderson     "ret x2\n"
81*1d9ac91bSRichard Henderson "test_end:"
82*1d9ac91bSRichard Henderson );
83*1d9ac91bSRichard Henderson 
main()84*1d9ac91bSRichard Henderson int main()
85*1d9ac91bSRichard Henderson {
86*1d9ac91bSRichard Henderson     struct sigaction sa;
87*1d9ac91bSRichard Henderson     void *tb, *te;
88*1d9ac91bSRichard Henderson 
89*1d9ac91bSRichard Henderson     void *p = mmap(0, getpagesize(),
90*1d9ac91bSRichard Henderson                    PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
91*1d9ac91bSRichard Henderson                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
92*1d9ac91bSRichard Henderson     if (p == MAP_FAILED) {
93*1d9ac91bSRichard Henderson         perror("mmap");
94*1d9ac91bSRichard Henderson         return 1;
95*1d9ac91bSRichard Henderson     }
96*1d9ac91bSRichard Henderson 
97*1d9ac91bSRichard Henderson     memset(&sa, 0, sizeof(sa));
98*1d9ac91bSRichard Henderson     sa.sa_sigaction = skip2_sigill;
99*1d9ac91bSRichard Henderson     sa.sa_flags = SA_SIGINFO;
100*1d9ac91bSRichard Henderson     if (sigaction(SIGILL, &sa, NULL) < 0) {
101*1d9ac91bSRichard Henderson         perror("sigaction");
102*1d9ac91bSRichard Henderson         return 1;
103*1d9ac91bSRichard Henderson     }
104*1d9ac91bSRichard Henderson 
105*1d9ac91bSRichard Henderson     /*
106*1d9ac91bSRichard Henderson      * ??? With "extern char test_begin[]", some compiler versions
107*1d9ac91bSRichard Henderson      * will use :got references, and some linker versions will
108*1d9ac91bSRichard Henderson      * resolve this reference to a static symbol incorrectly.
109*1d9ac91bSRichard Henderson      * Bypass this error by using a pc-relative reference directly.
110*1d9ac91bSRichard Henderson      */
111*1d9ac91bSRichard Henderson     asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te));
112*1d9ac91bSRichard Henderson 
113*1d9ac91bSRichard Henderson     memcpy(p, tb, te - tb);
114*1d9ac91bSRichard Henderson 
115*1d9ac91bSRichard Henderson     return ((int (*)(void))p)();
116*1d9ac91bSRichard Henderson }
117