master
c 143 lines 3.42 KB
Raw
1 /*
2 * Test that invalid slot assignments are properly rejected.
3 *
4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include <assert.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 static void *resume_pc;
16
17 static void handle_sigill(int sig, siginfo_t *info, void *puc)
18 {
19 ucontext_t *uc = (ucontext_t *)puc;
20
21 if (sig != SIGILL) {
22 _exit(EXIT_FAILURE);
23 }
24
25 uc->uc_mcontext.r0 = SIGILL;
26 uc->uc_mcontext.pc = (unsigned long)resume_pc;
27 }
28
29 char mem[8] __attribute__((aligned(8)));
30
31 /*
32 * Invalid packet with 2 instructions at slot 0:
33 * - Word 0: 0xa1804100 = memw(r0) = r1
34 * - Word 1: 0x28032804 = { r3 = #0; r4 = #0 }
35 *
36 * This should raise SIGILL due to the invalid slot assignment.
37 */
38 static int test_invalid_slots(void)
39 {
40 int sig;
41
42 asm volatile(
43 "r0 = #0\n"
44 "r1 = ##1f\n"
45 "memw(%1) = r1\n"
46 "r0 = #mem\n"
47 ".word 0xa1804100\n" /* { memw(r0) = r1; */
48 ".word 0x28032804\n" /* r3 = #0; r4 = #0 } */
49 "1:\n"
50 "%0 = r0\n"
51 : "=r"(sig)
52 : "r"(&resume_pc)
53 : "r0", "r1", "r3", "r4", "memory");
54
55 return sig;
56 }
57
58 /* Load then indirect jump, load encoded first: no high slot left for jump. */
59 static int test_invalid_slots_highslot(void)
60 {
61 int sig;
62
63 asm volatile(
64 "r0 = #0\n"
65 "r1 = ##1f\n"
66 "memw(%1) = r1\n"
67 "r3 = #mem\n"
68 ".word 0x91834006\n" /* { r6 = memw(r3+#0); */
69 ".word 0x529fc000\n" /* jumpr r31 } */
70 "1:\n"
71 "%0 = r0\n"
72 : "=r"(sig)
73 : "r"(&resume_pc)
74 : "r0", "r1", "r3", "r6", "memory");
75
76 return sig;
77 }
78
79 /*
80 * Three predicate-logical ops: each is restricted to slots 2 and 3, so the
81 * fourth-and-fifth-slot-free packet still has only two slots for three ops.
82 * No change-of-flow is involved, so the only reason to reject it is the slot
83 * conflict.
84 */
85 static int test_invalid_slots_crslot23(void)
86 {
87 int sig;
88
89 asm volatile(
90 "r0 = #0\n"
91 "r1 = ##1f\n"
92 "memw(%1) = r1\n"
93 ".word 0x6b024100\n" /* { p0 = and(p1, p2); */
94 ".word 0x6b224103\n" /* p3 = or(p1, p2); */
95 ".word 0x6b42c301\n" /* p1 = xor(p2, p3) } */
96 "1:\n"
97 "%0 = r0\n"
98 : "=r"(sig)
99 : "r"(&resume_pc)
100 : "r0", "r1", "p0", "p1", "p3", "memory");
101
102 return sig;
103 }
104
105 /* Three transfers plus a duplex: five ops for four slots. */
106 static int test_invalid_slots_five(void)
107 {
108 int sig;
109
110 asm volatile(
111 "r0 = #0\n"
112 "r1 = ##1f\n"
113 "memw(%1) = r1\n"
114 ".word 0x78004020\n" /* { r0 = #1; */
115 ".word 0x78004041\n" /* r1 = #2; */
116 ".word 0x78004062\n" /* r2 = #3; */
117 ".word 0x28452856\n" /* r5 = #4; r6 = #5 } */
118 "1:\n"
119 "%0 = r0\n"
120 : "=r"(sig)
121 : "r"(&resume_pc)
122 : "r0", "r1", "r2", "r5", "r6", "memory");
123
124 return sig;
125 }
126
127 int main()
128 {
129 struct sigaction act;
130
131 memset(&act, 0, sizeof(act));
132 act.sa_sigaction = handle_sigill;
133 act.sa_flags = SA_SIGINFO;
134 assert(sigaction(SIGILL, &act, NULL) == 0);
135
136 assert(test_invalid_slots() == SIGILL);
137 assert(test_invalid_slots_highslot() == SIGILL);
138 assert(test_invalid_slots_crslot23() == SIGILL);
139 assert(test_invalid_slots_five() == SIGILL);
140
141 puts("PASS");
142 return EXIT_SUCCESS;
143 }