1#include <assert.h>
2#include <signal.h>
3#include <string.h>
4#include <sys/mman.h>
5#include <ucontext.h>
6#include <unistd.h>
7
8
9
10
11
12
13
14void illegal_op(void);
15void after_illegal_op(void);
16asm(".globl\tillegal_op\n"
17 "illegal_op:\t.byte\t0x00,0x00\n"
18 "\t.globl\tafter_illegal_op\n"
19 "after_illegal_op:\tbr\t%r14");
20
21void stg(void *dst, unsigned long src);
22asm(".globl\tstg\n"
23 "stg:\tstg\t%r3,0(%r2)\n"
24 "\tbr\t%r14");
25
26void mvc_8(void *dst, void *src);
27asm(".globl\tmvc_8\n"
28 "mvc_8:\tmvc\t0(8,%r2),0(%r3)\n"
29 "\tbr\t%r14");
30
31static void safe_puts(const char *s)
32{
33 write(0, s, strlen(s));
34 write(0, "\n", 1);
35}
36
37enum exception {
38 exception_operation,
39 exception_translation,
40 exception_protection,
41};
42
43static struct {
44 int sig;
45 void *addr;
46 unsigned long psw_addr;
47 enum exception exception;
48} expected;
49
50static void handle_signal(int sig, siginfo_t *info, void *ucontext)
51{
52 void *page;
53 int err;
54
55 if (sig != expected.sig) {
56 safe_puts("[ FAILED ] wrong signal");
57 _exit(1);
58 }
59
60 if (info->si_addr != expected.addr) {
61 safe_puts("[ FAILED ] wrong si_addr");
62 _exit(1);
63 }
64
65 if (((ucontext_t *)ucontext)->uc_mcontext.psw.addr != expected.psw_addr) {
66 safe_puts("[ FAILED ] wrong psw.addr");
67 _exit(1);
68 }
69
70 switch (expected.exception) {
71 case exception_translation:
72 page = mmap(expected.addr, 4096, PROT_READ | PROT_WRITE,
73 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
74 if (page != expected.addr) {
75 safe_puts("[ FAILED ] mmap() failed");
76 _exit(1);
77 }
78 break;
79 case exception_protection:
80 err = mprotect(expected.addr, 4096, PROT_READ | PROT_WRITE);
81 if (err != 0) {
82 safe_puts("[ FAILED ] mprotect() failed");
83 _exit(1);
84 }
85 break;
86 default:
87 break;
88 }
89}
90
91static void check_sigsegv(void *func, enum exception exception,
92 unsigned long val)
93{
94 int prot;
95 unsigned long *page;
96 unsigned long *addr;
97 int err;
98
99 prot = exception == exception_translation ? PROT_NONE : PROT_READ;
100 page = mmap(NULL, 4096, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
101 assert(page != MAP_FAILED);
102 if (exception == exception_translation) {
103
104 err = munmap(page, 4096);
105 assert(err == 0);
106 }
107 addr = page + (val & 0x1ff);
108
109 expected.sig = SIGSEGV;
110 expected.addr = page;
111 expected.psw_addr = (unsigned long)func;
112 expected.exception = exception;
113 if (func == stg) {
114 stg(addr, val);
115 } else {
116 assert(func == mvc_8);
117 mvc_8(addr, &val);
118 }
119 assert(*addr == val);
120
121 err = munmap(page, 4096);
122 assert(err == 0);
123}
124
125int main(void)
126{
127 struct sigaction act;
128 int err;
129
130 memset(&act, 0, sizeof(act));
131 act.sa_sigaction = handle_signal;
132 act.sa_flags = SA_SIGINFO;
133 err = sigaction(SIGILL, &act, NULL);
134 assert(err == 0);
135 err = sigaction(SIGSEGV, &act, NULL);
136 assert(err == 0);
137
138 safe_puts("[ RUN ] Operation exception");
139 expected.sig = SIGILL;
140 expected.addr = illegal_op;
141 expected.psw_addr = (unsigned long)after_illegal_op;
142 expected.exception = exception_operation;
143 illegal_op();
144 safe_puts("[ OK ]");
145
146 safe_puts("[ RUN ] Translation exception from stg");
147 check_sigsegv(stg, exception_translation, 42);
148 safe_puts("[ OK ]");
149
150 safe_puts("[ RUN ] Translation exception from mvc");
151 check_sigsegv(mvc_8, exception_translation, 4242);
152 safe_puts("[ OK ]");
153
154 safe_puts("[ RUN ] Protection exception from stg");
155 check_sigsegv(stg, exception_protection, 424242);
156 safe_puts("[ OK ]");
157
158 safe_puts("[ RUN ] Protection exception from mvc");
159 check_sigsegv(mvc_8, exception_protection, 42424242);
160 safe_puts("[ OK ]");
161
162 safe_puts("[ PASSED ]");
163
164 _exit(0);
165}
166