1 // s390-signal.h - Catch runtime signals and turn them into exceptions
2 // on an s390 based Linux system.
3 
4 /* Copyright (C) 2002, 2010  Free Software Foundation
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>
18 #include <ucontext.h>
19 #include <limits.h>
20 
21 #define HANDLE_SEGV 1
22 #define HANDLE_FPE 1
23 
24 #define SIGNAL_HANDLER(_name)	\
25 static void _name (int, siginfo_t *_si __attribute__((unused)), \
26 		   ucontext_t *_uc __attribute__((unused)))
27 
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)
31 
32 
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.  */
42 #define UC_EXTENDED	0x00000001
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;						\
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;					\
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       }									\
132 									\
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   };									\
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     }									\
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  }                                                                      \
248 while (0)
249 
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 {
259 	void (*k_sa_handler) (int, siginfo_t *, ucontext_t *);
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   {							\
268     struct old_s390_kernel_sigaction kact;		\
269     kact.k_sa_handler = catch_segv;			\
270     kact.k_sa_mask = 0;					\
271     kact.k_sa_flags = SA_SIGINFO;			\
272     syscall (SYS_sigaction, SIGSEGV, &kact, NULL);	\
273   }							\
274 while (0)
275 
276 #define INIT_FPE						\
277 do								\
278   {								\
279     struct old_s390_kernel_sigaction kact;			\
280     kact.k_sa_handler = catch_fpe;				\
281     kact.k_sa_mask = 0;						\
282     kact.k_sa_flags = SA_SIGINFO;				\
283     syscall (SYS_sigaction, SIGFPE, &kact, NULL);		\
284   }								\
285 while (0)
286 
287 #endif /* JAVA_SIGNAL_H */
288 
289