]>
Commit | Line | Data |
---|---|---|
e793a714 UW |
1 | // s390-signal.h - Catch runtime signals and turn them into exceptions |
2 | // on an s390 based Linux system. | |
3 | ||
d652f226 | 4 | /* Copyright (C) 2002, 2010 Free Software Foundation |
e793a714 UW |
5 | |
6 | This file is part of libgcj. | |
7 | ||
8 | This software is copyrighted work licensed under the terms of the | |
9 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
10 | details. */ | |
11 | ||
12 | ||
13 | #ifndef JAVA_SIGNAL_H | |
14 | #define JAVA_SIGNAL_H 1 | |
15 | ||
16 | #include <signal.h> | |
17 | #include <sys/syscall.h> | |
220a826e UW |
18 | #include <ucontext.h> |
19 | #include <limits.h> | |
e793a714 UW |
20 | |
21 | #define HANDLE_SEGV 1 | |
220a826e | 22 | #define HANDLE_FPE 1 |
e793a714 UW |
23 | |
24 | #define SIGNAL_HANDLER(_name) \ | |
220a826e UW |
25 | static void _name (int, siginfo_t *_si __attribute__((unused)), \ |
26 | ucontext_t *_uc __attribute__((unused))) | |
e793a714 | 27 | |
bbb362e6 UW |
28 | /* We no longer need to fiddle with the PSW address in the signal handler; |
29 | this is now all handled correctly in MD_FALLBACK_FRAME_STATE_FOR. */ | |
30 | #define MAKE_THROW_FRAME(_exception) | |
e793a714 UW |
31 | |
32 | ||
220a826e UW |
33 | /* According to the JVM spec, "if the dividend is the negative integer |
34 | of the smallest magnitude and the divisor is -1, then overflow occurs | |
35 | and the result is equal to the dividend. Despite the overflow, no | |
36 | exception occurs". | |
37 | ||
38 | We handle this by inspecting the instruction which generated the signal, | |
39 | and if dividend and divisor are as above, we simply return from the signal | |
40 | handler. This causes execution to continue after the instruction. | |
41 | Before returning, we the set result registers as expected. */ | |
9602b6a1 | 42 | #define UC_EXTENDED 0x00000001 |
220a826e UW |
43 | |
44 | #define HANDLE_DIVIDE_OVERFLOW \ | |
45 | do \ | |
46 | { \ | |
47 | unsigned char *_eip = (unsigned char *) \ | |
48 | __builtin_extract_return_addr (_si->si_addr); \ | |
49 | unsigned long *_regs = _uc->uc_mcontext.gregs; \ | |
50 | int _r1, _r2, _d2, _x2, _b2; \ | |
9602b6a1 AK |
51 | struct \ |
52 | { \ | |
53 | unsigned long int uc_flags; \ | |
54 | struct ucontext *uc_link; \ | |
55 | stack_t uc_stack; \ | |
56 | mcontext_t uc_mcontext; \ | |
57 | unsigned long sigmask[2]; \ | |
58 | unsigned long ext_regs[16]; \ | |
59 | } *_uc_ext = (typeof(_uc_ext))_uc; \ | |
220a826e UW |
60 | \ |
61 | /* First, a couple of helper routines to decode instructions. */ \ | |
62 | struct _decode \ | |
63 | { \ | |
64 | /* Decode RR instruction format. */ \ | |
65 | static inline int _is_rr (unsigned char *_eip, \ | |
66 | unsigned char _op, \ | |
67 | int *_r1, int *_r2) \ | |
68 | { \ | |
69 | if (_eip[0] == _op) \ | |
70 | { \ | |
71 | *_r1 = _eip[1] >> 4; \ | |
72 | *_r2 = _eip[1] & 0xf; \ | |
73 | return 1; \ | |
74 | } \ | |
75 | return 0; \ | |
76 | } \ | |
77 | \ | |
78 | /* Decode RX instruction format. */ \ | |
79 | static inline int _is_rx (unsigned char *_eip, \ | |
80 | unsigned char _op, \ | |
81 | int *_r1, int *_d2, int *_x2, int *_b2) \ | |
82 | { \ | |
83 | if (_eip[0] == _op) \ | |
84 | { \ | |
85 | *_r1 = _eip[1] >> 4; \ | |
86 | *_x2 = _eip[1] & 0xf; \ | |
87 | *_b2 = _eip[2] >> 4; \ | |
88 | *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3]; \ | |
89 | return 1; \ | |
90 | } \ | |
91 | return 0; \ | |
92 | } \ | |
93 | \ | |
94 | /* Decode RRE instruction format. */ \ | |
95 | static inline int _is_rre (unsigned char *_eip, \ | |
96 | unsigned char _op1, unsigned char _op2,\ | |
97 | int *_r1, int *_r2) \ | |
98 | { \ | |
99 | if (_eip[0] == _op1 && _eip[1] == _op2) \ | |
100 | { \ | |
101 | *_r1 = _eip[3] >> 4; \ | |
102 | *_r2 = _eip[3] & 0xf; \ | |
103 | return 1; \ | |
104 | } \ | |
105 | return 0; \ | |
106 | } \ | |
107 | \ | |
108 | /* Decode RXY instruction format. */ \ | |
109 | static inline int _is_rxy (unsigned char *_eip, \ | |
110 | unsigned char _op1, unsigned char _op2,\ | |
111 | int *_r1, int *_d2, int *_x2, int *_b2)\ | |
112 | { \ | |
113 | if (_eip[0] == _op1 && _eip[5] == _op2) \ | |
114 | { \ | |
115 | *_r1 = _eip[1] >> 4; \ | |
116 | *_x2 = _eip[1] & 0xf; \ | |
117 | *_b2 = _eip[2] >> 4; \ | |
118 | *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3] + (_eip[4] << 12); \ | |
119 | /* We have a 20-bit signed displacement. */ \ | |
120 | *_d2 = (*_d2 ^ 0x80000) - 0x80000; \ | |
121 | return 1; \ | |
122 | } \ | |
123 | return 0; \ | |
124 | } \ | |
125 | \ | |
126 | /* Compute effective address. */ \ | |
127 | static inline unsigned long _eff (unsigned long *_regs, \ | |
128 | long _d, int _x, int _b) \ | |
129 | { \ | |
130 | return _d + (_x? _regs[_x] : 0) + (_b? _regs[_b] : 0); \ | |
131 | } \ | |
220a826e | 132 | \ |
9602b6a1 AK |
133 | static inline int is_long_long_min_p (unsigned long *_regs, \ |
134 | unsigned long *_ext_regs, \ | |
135 | int _r) \ | |
136 | { \ | |
137 | return ((long long)_regs[_r] \ | |
138 | | (long long)_ext_regs[_r] << 32) == \ | |
139 | LONG_LONG_MIN; \ | |
140 | } \ | |
141 | }; \ | |
220a826e UW |
142 | \ |
143 | /* DR r1,r2 */ \ | |
144 | if (_decode::_is_rr (_eip, 0x1d, &_r1, &_r2) \ | |
145 | && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN \ | |
146 | && (int) _regs[_r2] == -1) \ | |
147 | { \ | |
148 | _regs[_r1] &= ~0xffffffff; \ | |
149 | return; \ | |
150 | } \ | |
151 | \ | |
152 | /* D r1,d2(x2,b2) */ \ | |
153 | if (_decode::_is_rx (_eip, 0x5d, &_r1, &_d2, &_x2, &_b2) \ | |
154 | && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN \ | |
155 | && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1) \ | |
156 | { \ | |
157 | _regs[_r1] &= ~0xffffffff; \ | |
158 | return; \ | |
159 | } \ | |
160 | \ | |
161 | /* DSGR r1,r2 */ \ | |
162 | if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2) \ | |
163 | && (long) _regs[_r1+1] == LONG_MIN \ | |
164 | && (long) _regs[_r2] == -1L) \ | |
165 | { \ | |
166 | _regs[_r1] = 0; \ | |
167 | return; \ | |
168 | } \ | |
169 | \ | |
170 | /* DSGFR r1,r2 */ \ | |
171 | if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2) \ | |
172 | && (long) _regs[_r1+1] == LONG_MIN \ | |
173 | && (int) _regs[_r2] == -1) \ | |
174 | { \ | |
175 | _regs[_r1] = 0; \ | |
176 | return; \ | |
177 | } \ | |
178 | \ | |
179 | /* DSG r1,d2(x2,b2) */ \ | |
180 | if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2) \ | |
181 | && (long) _regs[_r1+1] == LONG_MIN \ | |
182 | && *(long *) _decode::_eff (_regs, _d2, _x2, _b2) == -1L) \ | |
183 | { \ | |
184 | _regs[_r1] = 0; \ | |
185 | return; \ | |
186 | } \ | |
187 | \ | |
188 | /* DSGF r1,d2(x2,b2) */ \ | |
189 | if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2) \ | |
190 | && (long) _regs[_r1+1] == LONG_MIN \ | |
191 | && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1) \ | |
192 | { \ | |
193 | _regs[_r1] = 0; \ | |
194 | return; \ | |
195 | } \ | |
9602b6a1 AK |
196 | \ |
197 | /* The extended ucontext contains the upper halfs of the 64bit \ | |
198 | registers in 31bit applications. */ \ | |
199 | if (_uc->uc_flags & 1 == 1) \ | |
200 | { \ | |
201 | /* DSGR r1,r2 */ \ | |
202 | if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2) \ | |
203 | && (int) _regs[_r2] == -1 \ | |
204 | && (int) _uc_ext->ext_regs[_r2] == -1 \ | |
205 | && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \ | |
206 | _r1 + 1)) \ | |
207 | { \ | |
208 | _regs[_r1] = 0; \ | |
209 | _uc_ext->ext_regs[_r1] = 0; \ | |
210 | return; \ | |
211 | } \ | |
212 | \ | |
213 | /* DSGFR r1,r2 */ \ | |
214 | if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2) \ | |
215 | && (int) _regs[_r2] == -1 \ | |
216 | && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \ | |
217 | _r1 + 1)) \ | |
218 | { \ | |
219 | _regs[_r1] = 0; \ | |
220 | _uc_ext->ext_regs[_r1] = 0; \ | |
221 | return; \ | |
222 | } \ | |
223 | \ | |
224 | /* DSG r1,d2(x2,b2) */ \ | |
225 | if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2) \ | |
226 | && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1 \ | |
227 | && *(int *) _decode::_eff (_regs, _d2 + 4, _x2, _b2) == -1 \ | |
228 | && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \ | |
229 | _r1 + 1)) \ | |
230 | { \ | |
231 | _regs[_r1] = 0; \ | |
232 | _uc_ext->ext_regs[_r1] = 0; \ | |
233 | return; \ | |
234 | } \ | |
235 | \ | |
236 | /* DSGF r1,d2(x2,b2) */ \ | |
237 | if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2) \ | |
238 | && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1 \ | |
239 | && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \ | |
240 | _r1 + 1)) \ | |
241 | { \ | |
242 | _regs[_r1] = 0; \ | |
243 | _uc_ext->ext_regs[_r1] = 0; \ | |
244 | return; \ | |
245 | } \ | |
246 | } \ | |
247 | } \ | |
220a826e UW |
248 | while (0) |
249 | ||
e793a714 UW |
250 | /* For an explanation why we cannot simply use sigaction to |
251 | install the handlers, see i386-signal.h. */ | |
252 | ||
253 | /* We use old_kernel_sigaction here because we're calling the kernel | |
254 | directly rather than via glibc. The sigaction structure that the | |
255 | syscall uses is a different shape from the one in userland and not | |
256 | visible to us in a header file so we define it here. */ | |
257 | ||
258 | struct old_s390_kernel_sigaction { | |
220a826e | 259 | void (*k_sa_handler) (int, siginfo_t *, ucontext_t *); |
e793a714 UW |
260 | unsigned long k_sa_mask; |
261 | unsigned long k_sa_flags; | |
262 | void (*sa_restorer) (void); | |
263 | }; | |
264 | ||
265 | #define INIT_SEGV \ | |
266 | do \ | |
267 | { \ | |
e793a714 UW |
268 | struct old_s390_kernel_sigaction kact; \ |
269 | kact.k_sa_handler = catch_segv; \ | |
270 | kact.k_sa_mask = 0; \ | |
bbb362e6 | 271 | kact.k_sa_flags = SA_SIGINFO; \ |
e793a714 UW |
272 | syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \ |
273 | } \ | |
274 | while (0) | |
275 | ||
276 | #define INIT_FPE \ | |
277 | do \ | |
278 | { \ | |
e793a714 UW |
279 | struct old_s390_kernel_sigaction kact; \ |
280 | kact.k_sa_handler = catch_fpe; \ | |
281 | kact.k_sa_mask = 0; \ | |
bbb362e6 | 282 | kact.k_sa_flags = SA_SIGINFO; \ |
e793a714 UW |
283 | syscall (SYS_sigaction, SIGFPE, &kact, NULL); \ |
284 | } \ | |
285 | while (0) | |
286 | ||
287 | #endif /* JAVA_SIGNAL_H */ | |
288 |