master
c 106 lines 2.53 KB
Raw
1 /*
2 * Test that invalid instruction encodings 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 /*
30 * Each test function:
31 * - Sets r0 to something other than SIGILL
32 * - Stores the resume address into resume_pc
33 * - Executes the invalid encoding
34 * - The handler sets r0 = SIGILL and resumes after the faulting packet
35 * - Returns the value in r0
36 */
37
38 /*
39 * Invalid duplex encoding (issue #3291):
40 * - Word 0: 0x0fff6fff = immext(#0xfffbffc0), parse bits = 01
41 * - Word 1: 0x600237b0 = duplex with:
42 * - slot0 = 0x17b0 (invalid S2 subinstruction encoding)
43 * - slot1 = 0x0002 (valid SA1_addi)
44 * - duplex iclass = 7 (S2 for slot0, A for slot1)
45 *
46 * Since slot0 doesn't decode to any valid S2 subinstruction, this packet
47 * should be rejected and raise SIGILL.
48 */
49 static int test_invalid_duplex(void)
50 {
51 int sig;
52
53 asm volatile(
54 "r0 = #0\n"
55 "r1 = ##1f\n"
56 "memw(%1) = r1\n"
57 ".word 0x0fff6fff\n" /* immext(#0xfffbffc0), parse=01 */
58 ".word 0x600237b0\n" /* duplex: slot0=0x17b0 (invalid) */
59 "1:\n"
60 "%0 = r0\n"
61 : "=r"(sig)
62 : "r"(&resume_pc)
63 : "r0", "r1", "memory");
64
65 return sig;
66 }
67
68 /*
69 * Invalid non-duplex encoding:
70 * The encoding 0xffffc000 has parse bits [15:14] = 0b11, making it a
71 * non-duplex instruction and packet end. The remaining bits do not match
72 * any valid normal or HVX instruction encoding, so this should raise SIGILL.
73 */
74 static int test_invalid_nonduplex(void)
75 {
76 int sig;
77
78 asm volatile(
79 "r0 = #0\n"
80 "r1 = ##1f\n"
81 "memw(%1) = r1\n"
82 ".word 0xffffc000\n"
83 "1:\n"
84 "%0 = r0\n"
85 : "=r"(sig)
86 : "r"(&resume_pc)
87 : "r0", "r1", "memory");
88
89 return sig;
90 }
91
92 int main()
93 {
94 struct sigaction act;
95
96 memset(&act, 0, sizeof(act));
97 act.sa_sigaction = handle_sigill;
98 act.sa_flags = SA_SIGINFO;
99 assert(sigaction(SIGILL, &act, NULL) == 0);
100
101 assert(test_invalid_duplex() == SIGILL);
102 assert(test_invalid_nonduplex() == SIGILL);
103
104 puts("PASS");
105 return EXIT_SUCCESS;
106 }