blob: 8ea0cbf0e6d527dfc4dd9c54823ba6d8f9b9a370 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
198 int pending;
199
200 /* It's OK to block everything including SIGSEGV, because we won't
201 * run any further guest code before unblocking signals in
202 * process_pending_signals().
203 */
204 sigfillset(&set);
205 sigprocmask(SIG_SETMASK, &set, 0);
206
207 pending = atomic_xchg(&ts->signal_pending, 1);
208
209 return pending;
210}
211
Alex Barcelo1c275922014-03-14 14:36:55 +0000212/* Wrapper for sigprocmask function
213 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100214 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
215 * a signal was already pending and the syscall must be restarted, or
216 * 0 on success.
217 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000218 */
219int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
220{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100221 TaskState *ts = (TaskState *)thread_cpu->opaque;
222
223 if (oldset) {
224 *oldset = ts->signal_mask;
225 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
227 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100228 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000229
Peter Maydell3d3efba2016-05-27 15:51:49 +0100230 if (block_signals()) {
231 return -TARGET_ERESTARTSYS;
232 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000233
234 switch (how) {
235 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000237 break;
238 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100239 for (i = 1; i <= NSIG; ++i) {
240 if (sigismember(set, i)) {
241 sigdelset(&ts->signal_mask, i);
242 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000243 }
244 break;
245 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100246 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000247 break;
248 default:
249 g_assert_not_reached();
250 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100251
252 /* Silently ignore attempts to change blocking status of KILL or STOP */
253 sigdelset(&ts->signal_mask, SIGKILL);
254 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000255 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100256 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000257}
258
Peter Maydell9eede5b2016-05-27 15:51:46 +0100259#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
260 !defined(TARGET_X86_64)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100261/* Just set the guest's signal mask to the specified value; the
262 * caller is assumed to have called block_signals() already.
263 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100264static void set_sigmask(const sigset_t *set)
265{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100266 TaskState *ts = (TaskState *)thread_cpu->opaque;
267
268 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100269}
270#endif
271
bellard9de5e442003-03-23 16:49:39 +0000272/* siginfo conversion */
273
Anthony Liguoric227f092009-10-01 16:12:16 -0500274static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000275 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000276{
Richard Hendersona05c6402012-09-15 11:34:20 -0700277 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100278 int si_code = info->si_code;
279 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000280 tinfo->si_signo = sig;
281 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000282 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700283
Peter Maydella70dadc2016-05-27 15:51:59 +0100284 /* This is awkward, because we have to use a combination of
285 * the si_code and si_signo to figure out which of the union's
286 * members are valid. (Within the host kernel it is always possible
287 * to tell, but the kernel carefully avoids giving userspace the
288 * high 16 bits of si_code, so we don't have the information to
289 * do this the easy way...) We therefore make our best guess,
290 * bearing in mind that a guest can spoof most of the si_codes
291 * via rt_sigqueueinfo() if it likes.
292 *
293 * Once we have made our guess, we record it in the top 16 bits of
294 * the si_code, so that tswap_siginfo() later can use it.
295 * tswap_siginfo() will strip these top bits out before writing
296 * si_code to the guest (sign-extending the lower bits).
297 */
298
299 switch (si_code) {
300 case SI_USER:
301 case SI_TKILL:
302 case SI_KERNEL:
303 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
304 * These are the only unspoofable si_code values.
305 */
306 tinfo->_sifields._kill._pid = info->si_pid;
307 tinfo->_sifields._kill._uid = info->si_uid;
308 si_type = QEMU_SI_KILL;
309 break;
310 default:
311 /* Everything else is spoofable. Make best guess based on signal */
312 switch (sig) {
313 case TARGET_SIGCHLD:
314 tinfo->_sifields._sigchld._pid = info->si_pid;
315 tinfo->_sifields._sigchld._uid = info->si_uid;
316 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100317 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100318 tinfo->_sifields._sigchld._utime = info->si_utime;
319 tinfo->_sifields._sigchld._stime = info->si_stime;
320 si_type = QEMU_SI_CHLD;
321 break;
322 case TARGET_SIGIO:
323 tinfo->_sifields._sigpoll._band = info->si_band;
324 tinfo->_sifields._sigpoll._fd = info->si_fd;
325 si_type = QEMU_SI_POLL;
326 break;
327 default:
328 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
329 tinfo->_sifields._rt._pid = info->si_pid;
330 tinfo->_sifields._rt._uid = info->si_uid;
331 /* XXX: potential problem if 64 bit */
332 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100333 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100334 si_type = QEMU_SI_RT;
335 break;
336 }
337 break;
bellard9de5e442003-03-23 16:49:39 +0000338 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100339
340 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000341}
342
Anthony Liguoric227f092009-10-01 16:12:16 -0500343static void tswap_siginfo(target_siginfo_t *tinfo,
344 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000345{
Peter Maydella70dadc2016-05-27 15:51:59 +0100346 int si_type = extract32(info->si_code, 16, 16);
347 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700348
Peter Maydella70dadc2016-05-27 15:51:59 +0100349 __put_user(info->si_signo, &tinfo->si_signo);
350 __put_user(info->si_errno, &tinfo->si_errno);
351 __put_user(si_code, &tinfo->si_code);
352
353 /* We can use our internal marker of which fields in the structure
354 * are valid, rather than duplicating the guesswork of
355 * host_to_target_siginfo_noswap() here.
356 */
357 switch (si_type) {
358 case QEMU_SI_KILL:
359 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
360 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
361 break;
362 case QEMU_SI_TIMER:
363 __put_user(info->_sifields._timer._timer1,
364 &tinfo->_sifields._timer._timer1);
365 __put_user(info->_sifields._timer._timer2,
366 &tinfo->_sifields._timer._timer2);
367 break;
368 case QEMU_SI_POLL:
369 __put_user(info->_sifields._sigpoll._band,
370 &tinfo->_sifields._sigpoll._band);
371 __put_user(info->_sifields._sigpoll._fd,
372 &tinfo->_sifields._sigpoll._fd);
373 break;
374 case QEMU_SI_FAULT:
375 __put_user(info->_sifields._sigfault._addr,
376 &tinfo->_sifields._sigfault._addr);
377 break;
378 case QEMU_SI_CHLD:
379 __put_user(info->_sifields._sigchld._pid,
380 &tinfo->_sifields._sigchld._pid);
381 __put_user(info->_sifields._sigchld._uid,
382 &tinfo->_sifields._sigchld._uid);
383 __put_user(info->_sifields._sigchld._status,
384 &tinfo->_sifields._sigchld._status);
385 __put_user(info->_sifields._sigchld._utime,
386 &tinfo->_sifields._sigchld._utime);
387 __put_user(info->_sifields._sigchld._stime,
388 &tinfo->_sifields._sigchld._stime);
389 break;
390 case QEMU_SI_RT:
391 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
392 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
393 __put_user(info->_sifields._rt._sigval.sival_ptr,
394 &tinfo->_sifields._rt._sigval.sival_ptr);
395 break;
396 default:
397 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000398 }
399}
400
Anthony Liguoric227f092009-10-01 16:12:16 -0500401void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000402{
403 host_to_target_siginfo_noswap(tinfo, info);
404 tswap_siginfo(tinfo, tinfo);
405}
406
407/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000408/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500409void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000410{
411 info->si_signo = tswap32(tinfo->si_signo);
412 info->si_errno = tswap32(tinfo->si_errno);
413 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000414 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
415 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000416 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200417 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000418}
419
aurel32ca587a82008-12-18 22:44:13 +0000420static int fatal_signal (int sig)
421{
422 switch (sig) {
423 case TARGET_SIGCHLD:
424 case TARGET_SIGURG:
425 case TARGET_SIGWINCH:
426 /* Ignored by default. */
427 return 0;
428 case TARGET_SIGCONT:
429 case TARGET_SIGSTOP:
430 case TARGET_SIGTSTP:
431 case TARGET_SIGTTIN:
432 case TARGET_SIGTTOU:
433 /* Job control signals. */
434 return 0;
435 default:
436 return 1;
437 }
438}
439
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300440/* returns 1 if given signal should dump core if not handled */
441static int core_dump_signal(int sig)
442{
443 switch (sig) {
444 case TARGET_SIGABRT:
445 case TARGET_SIGFPE:
446 case TARGET_SIGILL:
447 case TARGET_SIGQUIT:
448 case TARGET_SIGSEGV:
449 case TARGET_SIGTRAP:
450 case TARGET_SIGBUS:
451 return (1);
452 default:
453 return (0);
454 }
455}
456
bellard31e31b82003-02-18 22:55:36 +0000457void signal_init(void)
458{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100459 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000460 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000461 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000462 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000463 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000464
bellard9e5f5282003-07-13 17:33:54 +0000465 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200466 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000467 if (host_to_target_signal_table[i] == 0)
468 host_to_target_signal_table[i] = i;
469 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200470 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000471 j = host_to_target_signal_table[i];
472 target_to_host_signal_table[j] = i;
473 }
ths3b46e622007-09-17 08:09:54 +0000474
Peter Maydell3d3efba2016-05-27 15:51:49 +0100475 /* Set the signal mask from the host mask. */
476 sigprocmask(0, 0, &ts->signal_mask);
477
bellard9de5e442003-03-23 16:49:39 +0000478 /* set all host signal handlers. ALL signals are blocked during
479 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000480 memset(sigact_table, 0, sizeof(sigact_table));
481
bellard9de5e442003-03-23 16:49:39 +0000482 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000483 act.sa_flags = SA_SIGINFO;
484 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000485 for(i = 1; i <= TARGET_NSIG; i++) {
486 host_sig = target_to_host_signal(i);
487 sigaction(host_sig, NULL, &oact);
488 if (oact.sa_sigaction == (void *)SIG_IGN) {
489 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
490 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
491 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
492 }
493 /* If there's already a handler installed then something has
494 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000495 /* Install some handlers for our own use. We need at least
496 SIGSEGV and SIGBUS, to detect exceptions. We can not just
497 trap all signals because it affects syscall interrupt
498 behavior. But do trap all default-fatal signals. */
499 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000500 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000501 }
bellard31e31b82003-02-18 22:55:36 +0000502}
503
bellard66fb9762003-03-23 01:06:05 +0000504
bellard9de5e442003-03-23 16:49:39 +0000505/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200506static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000507{
Andreas Färber0429a972013-08-26 18:14:44 +0200508 CPUState *cpu = thread_cpu;
509 CPUArchState *env = cpu->env_ptr;
510 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300511 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000512 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100513
Riku Voipio66393fb2009-12-04 15:16:32 +0200514 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100515 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200516 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000517
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300518 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200519 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300520 stop_all_tasks();
521 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200522 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300523 }
524 if (core_dumped) {
525 /* we already dumped the core of target process, we don't want
526 * a coredump of qemu itself */
527 struct rlimit nodump;
528 getrlimit(RLIMIT_CORE, &nodump);
529 nodump.rlim_cur=0;
530 setrlimit(RLIMIT_CORE, &nodump);
531 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200532 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300533 }
534
Stefan Weil0c587512011-04-28 17:20:32 +0200535 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000536 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
537 * a negative value. To get the proper exit code we need to
538 * actually die from an uncaught signal. Here the default signal
539 * handler is installed, we send ourself a signal and we wait for
540 * it to arrive. */
541 sigfillset(&act.sa_mask);
542 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000543 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000544 sigaction(host_sig, &act, NULL);
545
546 /* For some reason raise(host_sig) doesn't send the signal when
547 * statically linked on x86-64. */
548 kill(getpid(), host_sig);
549
550 /* Make sure the signal isn't masked (just reuse the mask inside
551 of act) */
552 sigdelset(&act.sa_mask, host_sig);
553 sigsuspend(&act.sa_mask);
554
555 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000556 abort();
bellard66fb9762003-03-23 01:06:05 +0000557}
558
bellard9de5e442003-03-23 16:49:39 +0000559/* queue a signal so that it will be send to the virtual CPU as soon
560 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100561int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000562{
Andreas Färber0429a972013-08-26 18:14:44 +0200563 CPUState *cpu = ENV_GET_CPU(env);
564 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000565
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100566 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000567
Peter Maydella70dadc2016-05-27 15:51:59 +0100568 /* Currently all callers define siginfo structures which
569 * use the _sifields._sigfault union member, so we can
570 * set the type here. If that changes we should push this
571 * out so the si_type is passed in by callers.
572 */
573 info->si_code = deposit32(info->si_code, 16, 16, QEMU_SI_FAULT);
574
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100575 ts->sync_signal.info = *info;
576 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100577 /* signal that a new signal is pending */
578 atomic_set(&ts->signal_pending, 1);
579 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000580}
581
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100582#ifndef HAVE_SAFE_SYSCALL
583static inline void rewind_if_in_safe_syscall(void *puc)
584{
585 /* Default version: never rewind */
586}
587#endif
588
ths5fafdf22007-09-16 21:08:06 +0000589static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000590 void *puc)
591{
Andreas Färbera2247f82013-06-09 19:47:04 +0200592 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100593 CPUState *cpu = ENV_GET_CPU(env);
594 TaskState *ts = cpu->opaque;
595
bellard9de5e442003-03-23 16:49:39 +0000596 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500597 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100598 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100599 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000600
601 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000602 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000603 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000604 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000605 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000606 return;
607 }
608
609 /* get target signal number */
610 sig = host_to_target_signal(host_signum);
611 if (sig < 1 || sig > TARGET_NSIG)
612 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100613 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100614
615 rewind_if_in_safe_syscall(puc);
616
bellard9de5e442003-03-23 16:49:39 +0000617 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100618 k = &ts->sigtab[sig - 1];
619 k->info = tinfo;
620 k->pending = sig;
621 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100622
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100623 /* Block host signals until target signal handler entered. We
624 * can't block SIGSEGV or SIGBUS while we're executing guest
625 * code in case the guest code provokes one in the window between
626 * now and it getting out to the main loop. Signals will be
627 * unblocked again in process_pending_signals().
628 */
629 sigfillset(&uc->uc_sigmask);
630 sigdelset(&uc->uc_sigmask, SIGSEGV);
631 sigdelset(&uc->uc_sigmask, SIGBUS);
632
633 /* interrupt the virtual CPU as soon as possible */
634 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000635}
636
ths0da46a62007-10-20 20:23:07 +0000637/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000638/* compare linux/kernel/signal.c:do_sigaltstack() */
639abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000640{
641 int ret;
642 struct target_sigaltstack oss;
643
644 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000645 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000646 {
647 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
648 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
649 __put_user(sas_ss_flags(sp), &oss.ss_flags);
650 }
651
bellard579a97f2007-11-11 14:26:47 +0000652 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000653 {
bellard579a97f2007-11-11 14:26:47 +0000654 struct target_sigaltstack *uss;
655 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500656 size_t minstacksize = TARGET_MINSIGSTKSZ;
657
658#if defined(TARGET_PPC64)
659 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
660 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
661 if (get_ppc64_abi(image) > 1) {
662 minstacksize = 4096;
663 }
664#endif
thsa04e1342007-09-27 13:57:58 +0000665
ths0da46a62007-10-20 20:23:07 +0000666 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300667 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000668 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300669 }
670 __get_user(ss.ss_sp, &uss->ss_sp);
671 __get_user(ss.ss_size, &uss->ss_size);
672 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000673 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000674
ths0da46a62007-10-20 20:23:07 +0000675 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000676 if (on_sig_stack(sp))
677 goto out;
678
ths0da46a62007-10-20 20:23:07 +0000679 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000680 if (ss.ss_flags != TARGET_SS_DISABLE
681 && ss.ss_flags != TARGET_SS_ONSTACK
682 && ss.ss_flags != 0)
683 goto out;
684
685 if (ss.ss_flags == TARGET_SS_DISABLE) {
686 ss.ss_size = 0;
687 ss.ss_sp = 0;
688 } else {
ths0da46a62007-10-20 20:23:07 +0000689 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500690 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000691 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500692 }
thsa04e1342007-09-27 13:57:58 +0000693 }
694
695 target_sigaltstack_used.ss_sp = ss.ss_sp;
696 target_sigaltstack_used.ss_size = ss.ss_size;
697 }
698
bellard579a97f2007-11-11 14:26:47 +0000699 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000700 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000701 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000702 goto out;
thsa04e1342007-09-27 13:57:58 +0000703 }
704
705 ret = 0;
706out:
707 return ret;
708}
709
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100710/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000711int do_sigaction(int sig, const struct target_sigaction *act,
712 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000713{
pbrook624f7972008-05-31 16:11:38 +0000714 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000715 struct sigaction act1;
716 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000717 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000718
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100719 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
720 return -TARGET_EINVAL;
721 }
722
723 if (block_signals()) {
724 return -TARGET_ERESTARTSYS;
725 }
726
bellard66fb9762003-03-23 01:06:05 +0000727 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000728 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800729 __put_user(k->_sa_handler, &oact->_sa_handler);
730 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000731#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800732 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000733#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800734 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000735 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000736 }
737 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000738 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800739 __get_user(k->_sa_handler, &act->_sa_handler);
740 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000741#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800742 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000743#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800744 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000745 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000746
747 /* we update the host linux signal state */
748 host_sig = target_to_host_signal(sig);
749 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
750 sigfillset(&act1.sa_mask);
751 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000752 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000753 act1.sa_flags |= SA_RESTART;
754 /* NOTE: it is important to update the host kernel signal
755 ignore state to avoid getting unexpected interrupted
756 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000757 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000758 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000759 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000760 if (fatal_signal (sig))
761 act1.sa_sigaction = host_signal_handler;
762 else
763 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000764 } else {
765 act1.sa_sigaction = host_signal_handler;
766 }
ths0da46a62007-10-20 20:23:07 +0000767 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000768 }
bellard66fb9762003-03-23 01:06:05 +0000769 }
ths0da46a62007-10-20 20:23:07 +0000770 return ret;
bellard66fb9762003-03-23 01:06:05 +0000771}
bellard31e31b82003-02-18 22:55:36 +0000772
bellard459a4012007-11-11 19:45:10 +0000773#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000774
775/* from the Linux kernel */
776
777struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100778 uint16_t significand[4];
779 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000780};
781
782struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100783 uint16_t significand[4];
784 uint16_t exponent;
785 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000786};
787
788struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100789 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000790};
791
792struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100793 /* Regular FPU environment */
794 abi_ulong cw;
795 abi_ulong sw;
796 abi_ulong tag;
797 abi_ulong ipoff;
798 abi_ulong cssel;
799 abi_ulong dataoff;
800 abi_ulong datasel;
801 struct target_fpreg _st[8];
802 uint16_t status;
803 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000804
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100805 /* FXSR FPU environment */
806 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
807 abi_ulong mxcsr;
808 abi_ulong reserved;
809 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
810 struct target_xmmreg _xmm[8];
811 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000812};
813
814#define X86_FXSR_MAGIC 0x0000
815
816struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100817 uint16_t gs, __gsh;
818 uint16_t fs, __fsh;
819 uint16_t es, __esh;
820 uint16_t ds, __dsh;
821 abi_ulong edi;
822 abi_ulong esi;
823 abi_ulong ebp;
824 abi_ulong esp;
825 abi_ulong ebx;
826 abi_ulong edx;
827 abi_ulong ecx;
828 abi_ulong eax;
829 abi_ulong trapno;
830 abi_ulong err;
831 abi_ulong eip;
832 uint16_t cs, __csh;
833 abi_ulong eflags;
834 abi_ulong esp_at_signal;
835 uint16_t ss, __ssh;
836 abi_ulong fpstate; /* pointer */
837 abi_ulong oldmask;
838 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000839};
840
bellard66fb9762003-03-23 01:06:05 +0000841struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100842 abi_ulong tuc_flags;
843 abi_ulong tuc_link;
844 target_stack_t tuc_stack;
845 struct target_sigcontext tuc_mcontext;
846 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000847};
848
849struct sigframe
850{
blueswir1992f48a2007-10-14 16:27:31 +0000851 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000852 int sig;
853 struct target_sigcontext sc;
854 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000855 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000856 char retcode[8];
857};
858
859struct rt_sigframe
860{
blueswir1992f48a2007-10-14 16:27:31 +0000861 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000862 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000863 abi_ulong pinfo;
864 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000865 struct target_siginfo info;
866 struct target_ucontext uc;
867 struct target_fpstate fpstate;
868 char retcode[8];
869};
870
871/*
872 * Set up a signal frame.
873 */
874
bellard66fb9762003-03-23 01:06:05 +0000875/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300876static void setup_sigcontext(struct target_sigcontext *sc,
877 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
878 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000879{
Andreas Färber27103422013-08-26 08:31:06 +0200880 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200881 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000882
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100883 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300884 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
885 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
886 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
887 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
888 __put_user(env->regs[R_EDI], &sc->edi);
889 __put_user(env->regs[R_ESI], &sc->esi);
890 __put_user(env->regs[R_EBP], &sc->ebp);
891 __put_user(env->regs[R_ESP], &sc->esp);
892 __put_user(env->regs[R_EBX], &sc->ebx);
893 __put_user(env->regs[R_EDX], &sc->edx);
894 __put_user(env->regs[R_ECX], &sc->ecx);
895 __put_user(env->regs[R_EAX], &sc->eax);
896 __put_user(cs->exception_index, &sc->trapno);
897 __put_user(env->error_code, &sc->err);
898 __put_user(env->eip, &sc->eip);
899 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
900 __put_user(env->eflags, &sc->eflags);
901 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
902 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000903
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100904 cpu_x86_fsave(env, fpstate_addr, 1);
905 fpstate->status = fpstate->sw;
906 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300907 __put_user(magic, &fpstate->magic);
908 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000909
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100910 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300911 __put_user(mask, &sc->oldmask);
912 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000913}
914
915/*
916 * Determine which stack to use..
917 */
918
bellard579a97f2007-11-11 14:26:47 +0000919static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000920get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000921{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100922 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000923
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100924 /* Default to using normal stack */
925 esp = env->regs[R_ESP];
926 /* This is the X/Open sanctioned signal stack switching. */
927 if (ka->sa_flags & TARGET_SA_ONSTACK) {
928 if (sas_ss_flags(esp) == 0) {
929 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000930 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100931 } else {
bellard66fb9762003-03-23 01:06:05 +0000932
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100933 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000934 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100935 !(ka->sa_flags & TARGET_SA_RESTORER) &&
936 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000937 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100938 }
939 }
940 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000941}
942
bellard579a97f2007-11-11 14:26:47 +0000943/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000944static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100945 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000946{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100947 abi_ulong frame_addr;
948 struct sigframe *frame;
949 int i;
bellard66fb9762003-03-23 01:06:05 +0000950
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100951 frame_addr = get_sigframe(ka, env, sizeof(*frame));
952 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000953
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100954 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
955 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000956
Peter Maydellb6e2c932015-01-08 12:19:43 +0000957 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000958
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100959 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
960 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000961
Riku Voipio7df2fa32014-04-23 10:34:53 +0300962 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
963 __put_user(set->sig[i], &frame->extramask[i - 1]);
964 }
bellard66fb9762003-03-23 01:06:05 +0000965
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100966 /* Set up to return from userspace. If provided, use a stub
967 already in userspace. */
968 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300969 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100970 } else {
971 uint16_t val16;
972 abi_ulong retcode_addr;
973 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300974 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100975 /* This is popl %eax ; movl $,%eax ; int $0x80 */
976 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300977 __put_user(val16, (uint16_t *)(frame->retcode+0));
978 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100979 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300980 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100981 }
bellard66fb9762003-03-23 01:06:05 +0000982
bellard66fb9762003-03-23 01:06:05 +0000983
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100984 /* Set up registers for signal handler */
985 env->regs[R_ESP] = frame_addr;
986 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000987
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100988 cpu_x86_load_seg(env, R_DS, __USER_DS);
989 cpu_x86_load_seg(env, R_ES, __USER_DS);
990 cpu_x86_load_seg(env, R_SS, __USER_DS);
991 cpu_x86_load_seg(env, R_CS, __USER_CS);
992 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +0000993
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100994 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000995
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100996 return;
bellard66fb9762003-03-23 01:06:05 +0000997
998give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100999 if (sig == TARGET_SIGSEGV) {
1000 ka->_sa_handler = TARGET_SIG_DFL;
1001 }
1002 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001003}
1004
bellard579a97f2007-11-11 14:26:47 +00001005/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001006static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001007 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001008 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001009{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001010 abi_ulong frame_addr, addr;
1011 struct rt_sigframe *frame;
1012 int i;
bellard66fb9762003-03-23 01:06:05 +00001013
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001014 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1015 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001016
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001017 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1018 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001019
Peter Maydellb6e2c932015-01-08 12:19:43 +00001020 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001021 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001022 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001023 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001024 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +00001025 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +00001026
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001027 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001028 __put_user(0, &frame->uc.tuc_flags);
1029 __put_user(0, &frame->uc.tuc_link);
1030 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1031 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1032 &frame->uc.tuc_stack.ss_flags);
1033 __put_user(target_sigaltstack_used.ss_size,
1034 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001035 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1036 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1037
Riku Voipio0188fad2014-04-23 13:34:15 +03001038 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1039 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1040 }
bellard66fb9762003-03-23 01:06:05 +00001041
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001042 /* Set up to return from userspace. If provided, use a stub
1043 already in userspace. */
1044 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001045 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001046 } else {
1047 uint16_t val16;
1048 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001049 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001050 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001051 __put_user(0xb8, (char *)(frame->retcode+0));
1052 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001053 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001054 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001055 }
bellard66fb9762003-03-23 01:06:05 +00001056
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001057 /* Set up registers for signal handler */
1058 env->regs[R_ESP] = frame_addr;
1059 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001060
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001061 cpu_x86_load_seg(env, R_DS, __USER_DS);
1062 cpu_x86_load_seg(env, R_ES, __USER_DS);
1063 cpu_x86_load_seg(env, R_SS, __USER_DS);
1064 cpu_x86_load_seg(env, R_CS, __USER_CS);
1065 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001066
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001067 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001068
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001069 return;
bellard66fb9762003-03-23 01:06:05 +00001070
1071give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001072 if (sig == TARGET_SIGSEGV) {
1073 ka->_sa_handler = TARGET_SIG_DFL;
1074 }
1075 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001076}
1077
1078static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001079restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001080{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001081 unsigned int err = 0;
1082 abi_ulong fpstate_addr;
1083 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001084
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001085 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1086 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1087 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1088 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001089
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001090 env->regs[R_EDI] = tswapl(sc->edi);
1091 env->regs[R_ESI] = tswapl(sc->esi);
1092 env->regs[R_EBP] = tswapl(sc->ebp);
1093 env->regs[R_ESP] = tswapl(sc->esp);
1094 env->regs[R_EBX] = tswapl(sc->ebx);
1095 env->regs[R_EDX] = tswapl(sc->edx);
1096 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001097 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001098 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001099
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001100 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1101 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001102
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001103 tmpflags = tswapl(sc->eflags);
1104 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1105 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001106
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001107 fpstate_addr = tswapl(sc->fpstate);
1108 if (fpstate_addr != 0) {
1109 if (!access_ok(VERIFY_READ, fpstate_addr,
1110 sizeof(struct target_fpstate)))
1111 goto badframe;
1112 cpu_x86_frstor(env, fpstate_addr, 1);
1113 }
bellard66fb9762003-03-23 01:06:05 +00001114
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001115 return err;
bellard66fb9762003-03-23 01:06:05 +00001116badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001117 return 1;
bellard66fb9762003-03-23 01:06:05 +00001118}
1119
1120long do_sigreturn(CPUX86State *env)
1121{
bellard579a97f2007-11-11 14:26:47 +00001122 struct sigframe *frame;
1123 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001124 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001125 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001126 int i;
bellard66fb9762003-03-23 01:06:05 +00001127
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001128 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001129 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1130 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001131 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001132 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001133 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001134 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001135 }
bellard66fb9762003-03-23 01:06:05 +00001136
bellard92319442004-06-19 16:58:13 +00001137 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001138 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001139
bellard66fb9762003-03-23 01:06:05 +00001140 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001141 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001142 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001143 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001144 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001145
1146badframe:
bellard579a97f2007-11-11 14:26:47 +00001147 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001148 force_sig(TARGET_SIGSEGV);
1149 return 0;
1150}
1151
1152long do_rt_sigreturn(CPUX86State *env)
1153{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001154 abi_ulong frame_addr;
1155 struct rt_sigframe *frame;
1156 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001157
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001158 frame_addr = env->regs[R_ESP] - 4;
1159 trace_user_do_rt_sigreturn(env, frame_addr);
1160 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1161 goto badframe;
1162 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001163 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001164
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001165 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001166 goto badframe;
1167 }
bellard66fb9762003-03-23 01:06:05 +00001168
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001169 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1170 get_sp_from_cpustate(env)) == -EFAULT) {
1171 goto badframe;
1172 }
thsa04e1342007-09-27 13:57:58 +00001173
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001174 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001175 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001176
1177badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001178 unlock_user_struct(frame, frame_addr, 0);
1179 force_sig(TARGET_SIGSEGV);
1180 return 0;
bellard66fb9762003-03-23 01:06:05 +00001181}
1182
Andreas Schwab1744aea2013-09-03 20:12:16 +01001183#elif defined(TARGET_AARCH64)
1184
1185struct target_sigcontext {
1186 uint64_t fault_address;
1187 /* AArch64 registers */
1188 uint64_t regs[31];
1189 uint64_t sp;
1190 uint64_t pc;
1191 uint64_t pstate;
1192 /* 4K reserved for FP/SIMD state and future expansion */
1193 char __reserved[4096] __attribute__((__aligned__(16)));
1194};
1195
1196struct target_ucontext {
1197 abi_ulong tuc_flags;
1198 abi_ulong tuc_link;
1199 target_stack_t tuc_stack;
1200 target_sigset_t tuc_sigmask;
1201 /* glibc uses a 1024-bit sigset_t */
1202 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1203 /* last for future expansion */
1204 struct target_sigcontext tuc_mcontext;
1205};
1206
1207/*
1208 * Header to be used at the beginning of structures extending the user
1209 * context. Such structures must be placed after the rt_sigframe on the stack
1210 * and be 16-byte aligned. The last structure must be a dummy one with the
1211 * magic and size set to 0.
1212 */
1213struct target_aarch64_ctx {
1214 uint32_t magic;
1215 uint32_t size;
1216};
1217
1218#define TARGET_FPSIMD_MAGIC 0x46508001
1219
1220struct target_fpsimd_context {
1221 struct target_aarch64_ctx head;
1222 uint32_t fpsr;
1223 uint32_t fpcr;
1224 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1225};
1226
1227/*
1228 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1229 * user space as it will change with the addition of new context. User space
1230 * should check the magic/size information.
1231 */
1232struct target_aux_context {
1233 struct target_fpsimd_context fpsimd;
1234 /* additional context to be added before "end" */
1235 struct target_aarch64_ctx end;
1236};
1237
1238struct target_rt_sigframe {
1239 struct target_siginfo info;
1240 struct target_ucontext uc;
1241 uint64_t fp;
1242 uint64_t lr;
1243 uint32_t tramp[2];
1244};
1245
1246static int target_setup_sigframe(struct target_rt_sigframe *sf,
1247 CPUARMState *env, target_sigset_t *set)
1248{
1249 int i;
1250 struct target_aux_context *aux =
1251 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1252
1253 /* set up the stack frame for unwinding */
1254 __put_user(env->xregs[29], &sf->fp);
1255 __put_user(env->xregs[30], &sf->lr);
1256
1257 for (i = 0; i < 31; i++) {
1258 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1259 }
1260 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1261 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001262 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001263
Peter Maydell7af03922014-05-01 18:36:17 +01001264 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001265
1266 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1267 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1268 }
1269
1270 for (i = 0; i < 32; i++) {
1271#ifdef TARGET_WORDS_BIGENDIAN
1272 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1273 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1274#else
1275 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1276 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1277#endif
1278 }
Will Newtone0ee1382014-01-04 22:15:48 +00001279 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1280 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001281 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1282 __put_user(sizeof(struct target_fpsimd_context),
1283 &aux->fpsimd.head.size);
1284
1285 /* set the "end" magic */
1286 __put_user(0, &aux->end.magic);
1287 __put_user(0, &aux->end.size);
1288
1289 return 0;
1290}
1291
1292static int target_restore_sigframe(CPUARMState *env,
1293 struct target_rt_sigframe *sf)
1294{
1295 sigset_t set;
1296 int i;
1297 struct target_aux_context *aux =
1298 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001299 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001300 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001301
1302 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001303 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001304
1305 for (i = 0; i < 31; i++) {
1306 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1307 }
1308
1309 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1310 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001311 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1312 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001313
1314 __get_user(magic, &aux->fpsimd.head.magic);
1315 __get_user(size, &aux->fpsimd.head.size);
1316
1317 if (magic != TARGET_FPSIMD_MAGIC
1318 || size != sizeof(struct target_fpsimd_context)) {
1319 return 1;
1320 }
1321
Peter Maydell4cf23482014-03-02 19:36:38 +00001322 for (i = 0; i < 32; i++) {
1323#ifdef TARGET_WORDS_BIGENDIAN
1324 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1325 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1326#else
1327 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1328 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1329#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001330 }
Will Newtone0ee1382014-01-04 22:15:48 +00001331 __get_user(fpsr, &aux->fpsimd.fpsr);
1332 vfp_set_fpsr(env, fpsr);
1333 __get_user(fpcr, &aux->fpsimd.fpcr);
1334 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001335
1336 return 0;
1337}
1338
1339static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1340{
1341 abi_ulong sp;
1342
1343 sp = env->xregs[31];
1344
1345 /*
1346 * This is the X/Open sanctioned signal stack switching.
1347 */
Riku Voipiob545f632014-07-15 17:01:55 +03001348 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001349 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1350 }
1351
1352 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1353
1354 return sp;
1355}
1356
1357static void target_setup_frame(int usig, struct target_sigaction *ka,
1358 target_siginfo_t *info, target_sigset_t *set,
1359 CPUARMState *env)
1360{
1361 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001362 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001363
1364 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001365 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001366 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1367 goto give_sigsegv;
1368 }
1369
1370 __put_user(0, &frame->uc.tuc_flags);
1371 __put_user(0, &frame->uc.tuc_link);
1372
1373 __put_user(target_sigaltstack_used.ss_sp,
1374 &frame->uc.tuc_stack.ss_sp);
1375 __put_user(sas_ss_flags(env->xregs[31]),
1376 &frame->uc.tuc_stack.ss_flags);
1377 __put_user(target_sigaltstack_used.ss_size,
1378 &frame->uc.tuc_stack.ss_size);
1379 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001380 if (ka->sa_flags & TARGET_SA_RESTORER) {
1381 return_addr = ka->sa_restorer;
1382 } else {
1383 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1384 __put_user(0xd2801168, &frame->tramp[0]);
1385 __put_user(0xd4000001, &frame->tramp[1]);
1386 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1387 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001388 env->xregs[0] = usig;
1389 env->xregs[31] = frame_addr;
1390 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1391 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001392 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001393 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001394 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001395 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1396 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1397 }
1398
1399 unlock_user_struct(frame, frame_addr, 1);
1400 return;
1401
1402 give_sigsegv:
1403 unlock_user_struct(frame, frame_addr, 1);
1404 force_sig(TARGET_SIGSEGV);
1405}
1406
1407static void setup_rt_frame(int sig, struct target_sigaction *ka,
1408 target_siginfo_t *info, target_sigset_t *set,
1409 CPUARMState *env)
1410{
1411 target_setup_frame(sig, ka, info, set, env);
1412}
1413
1414static void setup_frame(int sig, struct target_sigaction *ka,
1415 target_sigset_t *set, CPUARMState *env)
1416{
1417 target_setup_frame(sig, ka, 0, set, env);
1418}
1419
1420long do_rt_sigreturn(CPUARMState *env)
1421{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001422 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001423 abi_ulong frame_addr = env->xregs[31];
1424
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001425 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001426 if (frame_addr & 15) {
1427 goto badframe;
1428 }
1429
1430 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1431 goto badframe;
1432 }
1433
1434 if (target_restore_sigframe(env, frame)) {
1435 goto badframe;
1436 }
1437
1438 if (do_sigaltstack(frame_addr +
1439 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1440 0, get_sp_from_cpustate(env)) == -EFAULT) {
1441 goto badframe;
1442 }
1443
1444 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001445 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001446
1447 badframe:
1448 unlock_user_struct(frame, frame_addr, 0);
1449 force_sig(TARGET_SIGSEGV);
1450 return 0;
1451}
1452
1453long do_sigreturn(CPUARMState *env)
1454{
1455 return do_rt_sigreturn(env);
1456}
1457
bellard43fff232003-07-09 19:31:39 +00001458#elif defined(TARGET_ARM)
1459
1460struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001461 abi_ulong trap_no;
1462 abi_ulong error_code;
1463 abi_ulong oldmask;
1464 abi_ulong arm_r0;
1465 abi_ulong arm_r1;
1466 abi_ulong arm_r2;
1467 abi_ulong arm_r3;
1468 abi_ulong arm_r4;
1469 abi_ulong arm_r5;
1470 abi_ulong arm_r6;
1471 abi_ulong arm_r7;
1472 abi_ulong arm_r8;
1473 abi_ulong arm_r9;
1474 abi_ulong arm_r10;
1475 abi_ulong arm_fp;
1476 abi_ulong arm_ip;
1477 abi_ulong arm_sp;
1478 abi_ulong arm_lr;
1479 abi_ulong arm_pc;
1480 abi_ulong arm_cpsr;
1481 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001482};
1483
pbrooka745ec62008-05-06 15:36:17 +00001484struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001485 abi_ulong tuc_flags;
1486 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001487 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001488 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001489 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001490};
1491
pbrooka745ec62008-05-06 15:36:17 +00001492struct target_ucontext_v2 {
1493 abi_ulong tuc_flags;
1494 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001495 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001496 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001497 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001498 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001499 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1500};
1501
Peter Maydell0d871bd2010-11-24 15:20:05 +00001502struct target_user_vfp {
1503 uint64_t fpregs[32];
1504 abi_ulong fpscr;
1505};
1506
1507struct target_user_vfp_exc {
1508 abi_ulong fpexc;
1509 abi_ulong fpinst;
1510 abi_ulong fpinst2;
1511};
1512
1513struct target_vfp_sigframe {
1514 abi_ulong magic;
1515 abi_ulong size;
1516 struct target_user_vfp ufp;
1517 struct target_user_vfp_exc ufp_exc;
1518} __attribute__((__aligned__(8)));
1519
Peter Maydell08e11252010-11-24 15:20:07 +00001520struct target_iwmmxt_sigframe {
1521 abi_ulong magic;
1522 abi_ulong size;
1523 uint64_t regs[16];
1524 /* Note that not all the coprocessor control registers are stored here */
1525 uint32_t wcssf;
1526 uint32_t wcasf;
1527 uint32_t wcgr0;
1528 uint32_t wcgr1;
1529 uint32_t wcgr2;
1530 uint32_t wcgr3;
1531} __attribute__((__aligned__(8)));
1532
Peter Maydell0d871bd2010-11-24 15:20:05 +00001533#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001534#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001535
pbrooka8c33202008-05-07 23:22:46 +00001536struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001537{
1538 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001539 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1540 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001541};
1542
pbrooka8c33202008-05-07 23:22:46 +00001543struct sigframe_v2
1544{
1545 struct target_ucontext_v2 uc;
1546 abi_ulong retcode;
1547};
1548
pbrooka745ec62008-05-06 15:36:17 +00001549struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001550{
bellardf8b0aa22007-11-11 23:03:42 +00001551 abi_ulong pinfo;
1552 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001553 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001554 struct target_ucontext_v1 uc;
1555 abi_ulong retcode;
1556};
1557
1558struct rt_sigframe_v2
1559{
1560 struct target_siginfo info;
1561 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001562 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001563};
1564
1565#define TARGET_CONFIG_CPU_32 1
1566
1567/*
1568 * For ARM syscalls, we encode the syscall number into the instruction.
1569 */
1570#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1571#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1572
1573/*
1574 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1575 * need two 16-bit instructions.
1576 */
1577#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1578#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1579
blueswir1992f48a2007-10-14 16:27:31 +00001580static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001581 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1582 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1583};
1584
1585
Andreas Färber05390242012-02-25 03:37:53 +01001586static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001587{
1588 return 1;
1589}
1590
pbrooka8c33202008-05-07 23:22:46 +00001591static void
bellard43fff232003-07-09 19:31:39 +00001592setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001593 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001594{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001595 __put_user(env->regs[0], &sc->arm_r0);
1596 __put_user(env->regs[1], &sc->arm_r1);
1597 __put_user(env->regs[2], &sc->arm_r2);
1598 __put_user(env->regs[3], &sc->arm_r3);
1599 __put_user(env->regs[4], &sc->arm_r4);
1600 __put_user(env->regs[5], &sc->arm_r5);
1601 __put_user(env->regs[6], &sc->arm_r6);
1602 __put_user(env->regs[7], &sc->arm_r7);
1603 __put_user(env->regs[8], &sc->arm_r8);
1604 __put_user(env->regs[9], &sc->arm_r9);
1605 __put_user(env->regs[10], &sc->arm_r10);
1606 __put_user(env->regs[11], &sc->arm_fp);
1607 __put_user(env->regs[12], &sc->arm_ip);
1608 __put_user(env->regs[13], &sc->arm_sp);
1609 __put_user(env->regs[14], &sc->arm_lr);
1610 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001611#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001612 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001613#endif
1614
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001615 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1616 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1617 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1618 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001619}
1620
bellard579a97f2007-11-11 14:26:47 +00001621static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001622get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001623{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001624 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001625
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001626 /*
1627 * This is the X/Open sanctioned signal stack switching.
1628 */
1629 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1630 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1631 }
1632 /*
1633 * ATPCS B01 mandates 8-byte alignment
1634 */
1635 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001636}
1637
Riku Voipio0188fad2014-04-23 13:34:15 +03001638static void
Andreas Färber05390242012-02-25 03:37:53 +01001639setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001640 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001641{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001642 abi_ulong handler = ka->_sa_handler;
1643 abi_ulong retcode;
1644 int thumb = handler & 1;
1645 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001646
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001647 cpsr &= ~CPSR_IT;
1648 if (thumb) {
1649 cpsr |= CPSR_T;
1650 } else {
1651 cpsr &= ~CPSR_T;
1652 }
bellard43fff232003-07-09 19:31:39 +00001653
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001654 if (ka->sa_flags & TARGET_SA_RESTORER) {
1655 retcode = ka->sa_restorer;
1656 } else {
1657 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001658
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001659 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1660 idx += 2;
1661 }
bellard43fff232003-07-09 19:31:39 +00001662
Riku Voipio0188fad2014-04-23 13:34:15 +03001663 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001664
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001665 retcode = rc_addr + thumb;
1666 }
bellard43fff232003-07-09 19:31:39 +00001667
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001668 env->regs[0] = usig;
1669 env->regs[13] = frame_addr;
1670 env->regs[14] = retcode;
1671 env->regs[15] = handler & (thumb ? ~1 : ~3);
1672 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001673}
1674
Andreas Färber05390242012-02-25 03:37:53 +01001675static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001676{
1677 int i;
1678 struct target_vfp_sigframe *vfpframe;
1679 vfpframe = (struct target_vfp_sigframe *)regspace;
1680 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1681 __put_user(sizeof(*vfpframe), &vfpframe->size);
1682 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001683 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001684 }
1685 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1686 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1687 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1688 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1689 return (abi_ulong*)(vfpframe+1);
1690}
1691
Andreas Färber05390242012-02-25 03:37:53 +01001692static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1693 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001694{
1695 int i;
1696 struct target_iwmmxt_sigframe *iwmmxtframe;
1697 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1698 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1699 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1700 for (i = 0; i < 16; i++) {
1701 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1702 }
1703 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1704 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1705 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1706 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1707 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1708 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1709 return (abi_ulong*)(iwmmxtframe+1);
1710}
1711
pbrooka8c33202008-05-07 23:22:46 +00001712static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001713 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001714{
pbrooka8c33202008-05-07 23:22:46 +00001715 struct target_sigaltstack stack;
1716 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001717 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001718
1719 /* Clear all the bits of the ucontext we don't use. */
1720 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1721
1722 memset(&stack, 0, sizeof(stack));
1723 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1724 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1725 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1726 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1727
1728 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001729 /* Save coprocessor signal frame. */
1730 regspace = uc->tuc_regspace;
1731 if (arm_feature(env, ARM_FEATURE_VFP)) {
1732 regspace = setup_sigframe_v2_vfp(regspace, env);
1733 }
Peter Maydell08e11252010-11-24 15:20:07 +00001734 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1735 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1736 }
1737
Peter Maydell0d871bd2010-11-24 15:20:05 +00001738 /* Write terminating magic word */
1739 __put_user(0, regspace);
1740
pbrooka8c33202008-05-07 23:22:46 +00001741 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1742 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1743 }
1744}
1745
1746/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001747static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001748 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001749{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001750 struct sigframe_v1 *frame;
1751 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1752 int i;
bellard43fff232003-07-09 19:31:39 +00001753
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001754 trace_user_setup_frame(regs, frame_addr);
1755 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1756 return;
1757 }
bellard579a97f2007-11-11 14:26:47 +00001758
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001759 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001760
Riku Voipio0188fad2014-04-23 13:34:15 +03001761 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1762 __put_user(set->sig[i], &frame->extramask[i - 1]);
1763 }
bellard43fff232003-07-09 19:31:39 +00001764
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001765 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1766 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001767
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001768 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001769}
1770
pbrook624f7972008-05-31 16:11:38 +00001771static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001772 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001773{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001774 struct sigframe_v2 *frame;
1775 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001776
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001777 trace_user_setup_frame(regs, frame_addr);
1778 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1779 return;
1780 }
pbrooka8c33202008-05-07 23:22:46 +00001781
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001782 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001783
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001784 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1785 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001786
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001787 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001788}
1789
pbrook624f7972008-05-31 16:11:38 +00001790static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001791 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001792{
1793 if (get_osversion() >= 0x020612) {
1794 setup_frame_v2(usig, ka, set, regs);
1795 } else {
1796 setup_frame_v1(usig, ka, set, regs);
1797 }
bellard43fff232003-07-09 19:31:39 +00001798}
1799
bellard579a97f2007-11-11 14:26:47 +00001800/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001801static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001802 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001803 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001804{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001805 struct rt_sigframe_v1 *frame;
1806 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1807 struct target_sigaltstack stack;
1808 int i;
1809 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001810
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001811 trace_user_setup_rt_frame(env, frame_addr);
1812 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1813 return /* 1 */;
1814 }
bellardedf779f2004-02-22 13:40:13 +00001815
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001816 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1817 __put_user(info_addr, &frame->pinfo);
1818 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1819 __put_user(uc_addr, &frame->puc);
1820 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001821
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001822 /* Clear all the bits of the ucontext we don't use. */
1823 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001824
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001825 memset(&stack, 0, sizeof(stack));
1826 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1827 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1828 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1829 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001830
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001831 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1832 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1833 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1834 }
bellard43fff232003-07-09 19:31:39 +00001835
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001836 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1837 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001838
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001839 env->regs[1] = info_addr;
1840 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001841
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001842 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001843}
1844
pbrook624f7972008-05-31 16:11:38 +00001845static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001846 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001847 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001848{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001849 struct rt_sigframe_v2 *frame;
1850 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1851 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001852
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001853 trace_user_setup_rt_frame(env, frame_addr);
1854 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1855 return /* 1 */;
1856 }
pbrooka745ec62008-05-06 15:36:17 +00001857
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001858 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1859 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1860 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001861
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001862 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001863
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001864 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1865 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001866
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001867 env->regs[1] = info_addr;
1868 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001869
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001870 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001871}
1872
pbrook624f7972008-05-31 16:11:38 +00001873static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001874 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001875 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001876{
1877 if (get_osversion() >= 0x020612) {
1878 setup_rt_frame_v2(usig, ka, info, set, env);
1879 } else {
1880 setup_rt_frame_v1(usig, ka, info, set, env);
1881 }
1882}
1883
bellard43fff232003-07-09 19:31:39 +00001884static int
Andreas Färber05390242012-02-25 03:37:53 +01001885restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001886{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001887 int err = 0;
1888 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001889
Riku Voipio1d8b5122014-04-23 10:26:05 +03001890 __get_user(env->regs[0], &sc->arm_r0);
1891 __get_user(env->regs[1], &sc->arm_r1);
1892 __get_user(env->regs[2], &sc->arm_r2);
1893 __get_user(env->regs[3], &sc->arm_r3);
1894 __get_user(env->regs[4], &sc->arm_r4);
1895 __get_user(env->regs[5], &sc->arm_r5);
1896 __get_user(env->regs[6], &sc->arm_r6);
1897 __get_user(env->regs[7], &sc->arm_r7);
1898 __get_user(env->regs[8], &sc->arm_r8);
1899 __get_user(env->regs[9], &sc->arm_r9);
1900 __get_user(env->regs[10], &sc->arm_r10);
1901 __get_user(env->regs[11], &sc->arm_fp);
1902 __get_user(env->regs[12], &sc->arm_ip);
1903 __get_user(env->regs[13], &sc->arm_sp);
1904 __get_user(env->regs[14], &sc->arm_lr);
1905 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001906#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001907 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001908 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001909#endif
1910
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001911 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001912
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001913 return err;
bellard43fff232003-07-09 19:31:39 +00001914}
1915
Andreas Färber05390242012-02-25 03:37:53 +01001916static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001917{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001918 abi_ulong frame_addr;
1919 struct sigframe_v1 *frame = NULL;
1920 target_sigset_t set;
1921 sigset_t host_set;
1922 int i;
bellard43fff232003-07-09 19:31:39 +00001923
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001924 /*
1925 * Since we stacked the signal on a 64-bit boundary,
1926 * then 'sp' should be word aligned here. If it's
1927 * not, then the user is trying to mess with us.
1928 */
1929 frame_addr = env->regs[13];
1930 trace_user_do_sigreturn(env, frame_addr);
1931 if (frame_addr & 7) {
1932 goto badframe;
1933 }
Peter Maydell978fae92013-07-29 12:00:32 +01001934
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001935 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1936 goto badframe;
1937 }
bellard43fff232003-07-09 19:31:39 +00001938
Riku Voipiof5f601a2014-04-23 13:00:17 +03001939 __get_user(set.sig[0], &frame->sc.oldmask);
1940 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1941 __get_user(set.sig[i], &frame->extramask[i - 1]);
1942 }
bellard43fff232003-07-09 19:31:39 +00001943
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001944 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001945 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00001946
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001947 if (restore_sigcontext(env, &frame->sc)) {
1948 goto badframe;
1949 }
bellard43fff232003-07-09 19:31:39 +00001950
1951#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001952 /* Send SIGTRAP if we're single-stepping */
1953 if (ptrace_cancel_bpt(current))
1954 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00001955#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001956 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001957 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00001958
1959badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001960 force_sig(TARGET_SIGSEGV /* , current */);
1961 return 0;
bellard43fff232003-07-09 19:31:39 +00001962}
1963
Andreas Färber05390242012-02-25 03:37:53 +01001964static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001965{
1966 int i;
1967 abi_ulong magic, sz;
1968 uint32_t fpscr, fpexc;
1969 struct target_vfp_sigframe *vfpframe;
1970 vfpframe = (struct target_vfp_sigframe *)regspace;
1971
1972 __get_user(magic, &vfpframe->magic);
1973 __get_user(sz, &vfpframe->size);
1974 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1975 return 0;
1976 }
1977 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001978 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001979 }
1980 __get_user(fpscr, &vfpframe->ufp.fpscr);
1981 vfp_set_fpscr(env, fpscr);
1982 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1983 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1984 * and the exception flag is cleared
1985 */
1986 fpexc |= (1 << 30);
1987 fpexc &= ~((1 << 31) | (1 << 28));
1988 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1989 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1990 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1991 return (abi_ulong*)(vfpframe + 1);
1992}
1993
Andreas Färber05390242012-02-25 03:37:53 +01001994static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1995 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001996{
1997 int i;
1998 abi_ulong magic, sz;
1999 struct target_iwmmxt_sigframe *iwmmxtframe;
2000 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2001
2002 __get_user(magic, &iwmmxtframe->magic);
2003 __get_user(sz, &iwmmxtframe->size);
2004 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2005 return 0;
2006 }
2007 for (i = 0; i < 16; i++) {
2008 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2009 }
2010 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2011 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2012 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2013 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2014 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2015 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2016 return (abi_ulong*)(iwmmxtframe + 1);
2017}
2018
Andreas Färber05390242012-02-25 03:37:53 +01002019static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00002020 struct target_ucontext_v2 *uc)
2021{
2022 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002023 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002024
2025 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002026 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002027
2028 if (restore_sigcontext(env, &uc->tuc_mcontext))
2029 return 1;
2030
Peter Maydell5f9099d2010-11-24 15:20:06 +00002031 /* Restore coprocessor signal frame */
2032 regspace = uc->tuc_regspace;
2033 if (arm_feature(env, ARM_FEATURE_VFP)) {
2034 regspace = restore_sigframe_v2_vfp(env, regspace);
2035 if (!regspace) {
2036 return 1;
2037 }
2038 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002039 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2040 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2041 if (!regspace) {
2042 return 1;
2043 }
2044 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002045
pbrooka8c33202008-05-07 23:22:46 +00002046 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2047 return 1;
2048
2049#if 0
2050 /* Send SIGTRAP if we're single-stepping */
2051 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002052 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002053#endif
2054
2055 return 0;
2056}
2057
Andreas Färber05390242012-02-25 03:37:53 +01002058static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002059{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002060 abi_ulong frame_addr;
2061 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002062
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002063 /*
2064 * Since we stacked the signal on a 64-bit boundary,
2065 * then 'sp' should be word aligned here. If it's
2066 * not, then the user is trying to mess with us.
2067 */
2068 frame_addr = env->regs[13];
2069 trace_user_do_sigreturn(env, frame_addr);
2070 if (frame_addr & 7) {
2071 goto badframe;
2072 }
Peter Maydell978fae92013-07-29 12:00:32 +01002073
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002074 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2075 goto badframe;
2076 }
pbrooka8c33202008-05-07 23:22:46 +00002077
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002078 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2079 goto badframe;
2080 }
pbrooka8c33202008-05-07 23:22:46 +00002081
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002082 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002083 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002084
2085badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002086 unlock_user_struct(frame, frame_addr, 0);
2087 force_sig(TARGET_SIGSEGV /* , current */);
2088 return 0;
pbrooka8c33202008-05-07 23:22:46 +00002089}
2090
Andreas Färber05390242012-02-25 03:37:53 +01002091long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002092{
2093 if (get_osversion() >= 0x020612) {
2094 return do_sigreturn_v2(env);
2095 } else {
2096 return do_sigreturn_v1(env);
2097 }
2098}
2099
Andreas Färber05390242012-02-25 03:37:53 +01002100static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002101{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002102 abi_ulong frame_addr;
2103 struct rt_sigframe_v1 *frame = NULL;
2104 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002105
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002106 /*
2107 * Since we stacked the signal on a 64-bit boundary,
2108 * then 'sp' should be word aligned here. If it's
2109 * not, then the user is trying to mess with us.
2110 */
2111 frame_addr = env->regs[13];
2112 trace_user_do_rt_sigreturn(env, frame_addr);
2113 if (frame_addr & 7) {
2114 goto badframe;
2115 }
Peter Maydell978fae92013-07-29 12:00:32 +01002116
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002117 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2118 goto badframe;
2119 }
bellard43fff232003-07-09 19:31:39 +00002120
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002121 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002122 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002124 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2125 goto badframe;
2126 }
bellard43fff232003-07-09 19:31:39 +00002127
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002128 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2129 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002130
bellard43fff232003-07-09 19:31:39 +00002131#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002132 /* Send SIGTRAP if we're single-stepping */
2133 if (ptrace_cancel_bpt(current))
2134 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002135#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002136 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002137 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002138
2139badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002140 unlock_user_struct(frame, frame_addr, 0);
2141 force_sig(TARGET_SIGSEGV /* , current */);
2142 return 0;
bellard43fff232003-07-09 19:31:39 +00002143}
2144
Andreas Färber05390242012-02-25 03:37:53 +01002145static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002146{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002147 abi_ulong frame_addr;
2148 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002149
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002150 /*
2151 * Since we stacked the signal on a 64-bit boundary,
2152 * then 'sp' should be word aligned here. If it's
2153 * not, then the user is trying to mess with us.
2154 */
2155 frame_addr = env->regs[13];
2156 trace_user_do_rt_sigreturn(env, frame_addr);
2157 if (frame_addr & 7) {
2158 goto badframe;
2159 }
Peter Maydell978fae92013-07-29 12:00:32 +01002160
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002161 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2162 goto badframe;
2163 }
pbrooka745ec62008-05-06 15:36:17 +00002164
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002165 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2166 goto badframe;
2167 }
pbrooka745ec62008-05-06 15:36:17 +00002168
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002169 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002170 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002171
2172badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002173 unlock_user_struct(frame, frame_addr, 0);
2174 force_sig(TARGET_SIGSEGV /* , current */);
2175 return 0;
pbrooka745ec62008-05-06 15:36:17 +00002176}
2177
Andreas Färber05390242012-02-25 03:37:53 +01002178long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002179{
2180 if (get_osversion() >= 0x020612) {
2181 return do_rt_sigreturn_v2(env);
2182 } else {
2183 return do_rt_sigreturn_v1(env);
2184 }
2185}
2186
bellard6d5e2162004-09-30 22:04:13 +00002187#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002188
bellard6d5e2162004-09-30 22:04:13 +00002189#define __SUNOS_MAXWIN 31
2190
2191/* This is what SunOS does, so shall I. */
2192struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002193 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002194
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002195 abi_ulong sigc_mask; /* sigmask to restore */
2196 abi_ulong sigc_sp; /* stack pointer */
2197 abi_ulong sigc_pc; /* program counter */
2198 abi_ulong sigc_npc; /* next program counter */
2199 abi_ulong sigc_psr; /* for condition codes etc */
2200 abi_ulong sigc_g1; /* User uses these two registers */
2201 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002202
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002203 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002204 * at the time of the signal.
2205 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002206 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002207
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002208 /* stack ptrs for each regwin buf */
2209 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002210
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002211 /* Windows to restore after signal */
2212 struct {
2213 abi_ulong locals[8];
2214 abi_ulong ins[8];
2215 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002216};
2217/* A Sparc stack frame */
2218struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002219 abi_ulong locals[8];
2220 abi_ulong ins[8];
2221 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002222 * since we never need to access them ourselves.
2223 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002224 char *structptr;
2225 abi_ulong xargs[6];
2226 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002227};
2228
2229typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002230 struct {
2231 abi_ulong psr;
2232 abi_ulong pc;
2233 abi_ulong npc;
2234 abi_ulong y;
2235 abi_ulong u_regs[16]; /* globals and ins */
2236 } si_regs;
2237 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002238} __siginfo_t;
2239
2240typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002241 abi_ulong si_float_regs[32];
2242 unsigned long si_fsr;
2243 unsigned long si_fpqdepth;
2244 struct {
2245 unsigned long *insn_addr;
2246 unsigned long insn;
2247 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002248} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002249
2250
2251struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002252 struct sparc_stackf ss;
2253 __siginfo_t info;
2254 abi_ulong fpu_save;
2255 abi_ulong insns[2] __attribute__ ((aligned (8)));
2256 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2257 abi_ulong extra_size; /* Should be 0 */
2258 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002259};
2260struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 struct sparc_stackf ss;
2262 siginfo_t info;
2263 abi_ulong regs[20];
2264 sigset_t mask;
2265 abi_ulong fpu_save;
2266 unsigned int insns[2];
2267 stack_t stack;
2268 unsigned int extra_size; /* Should be 0 */
2269 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002270};
2271
bellarde80cfcf2004-12-19 23:18:01 +00002272#define UREG_O0 16
2273#define UREG_O6 22
2274#define UREG_I0 0
2275#define UREG_I1 1
2276#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002277#define UREG_I3 3
2278#define UREG_I4 4
2279#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002280#define UREG_I6 6
2281#define UREG_I7 7
2282#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002283#define UREG_FP UREG_I6
2284#define UREG_SP UREG_O6
2285
pbrook624f7972008-05-31 16:11:38 +00002286static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002287 CPUSPARCState *env,
2288 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002289{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002290 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002292 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002293
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002294 /* This is the X/Open sanctioned signal stack switching. */
2295 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2296 if (!on_sig_stack(sp)
2297 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2298 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2299 }
2300 }
2301 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002302}
2303
2304static int
Andreas Färber05390242012-02-25 03:37:53 +01002305setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002306{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002307 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002308
Riku Voipio1d8b5122014-04-23 10:26:05 +03002309 __put_user(env->psr, &si->si_regs.psr);
2310 __put_user(env->pc, &si->si_regs.pc);
2311 __put_user(env->npc, &si->si_regs.npc);
2312 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002313 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002314 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002315 }
2316 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002317 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002318 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002319 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002320 return err;
bellard6d5e2162004-09-30 22:04:13 +00002321}
bellarde80cfcf2004-12-19 23:18:01 +00002322
bellard80a9d032005-01-03 23:31:27 +00002323#if 0
bellard6d5e2162004-09-30 22:04:13 +00002324static int
2325setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002326 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002327{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002328 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002329
Riku Voipio1d8b5122014-04-23 10:26:05 +03002330 __put_user(mask, &sc->sigc_mask);
2331 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2332 __put_user(env->pc, &sc->sigc_pc);
2333 __put_user(env->npc, &sc->sigc_npc);
2334 __put_user(env->psr, &sc->sigc_psr);
2335 __put_user(env->gregs[1], &sc->sigc_g1);
2336 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002337
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002338 return err;
bellard6d5e2162004-09-30 22:04:13 +00002339}
bellard80a9d032005-01-03 23:31:27 +00002340#endif
bellard6d5e2162004-09-30 22:04:13 +00002341#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2342
pbrook624f7972008-05-31 16:11:38 +00002343static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002344 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002345{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002346 abi_ulong sf_addr;
2347 struct target_signal_frame *sf;
2348 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002349
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002350 /* 1. Make sure everything is clean */
2351 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002352
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002353 sigframe_size = NF_ALIGNEDSZ;
2354 sf_addr = get_sigframe(ka, env, sigframe_size);
2355 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002356
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002357 sf = lock_user(VERIFY_WRITE, sf_addr,
2358 sizeof(struct target_signal_frame), 0);
2359 if (!sf) {
2360 goto sigsegv;
2361 }
bellard6d5e2162004-09-30 22:04:13 +00002362#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002363 if (invalid_frame_pointer(sf, sigframe_size))
2364 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002365#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002366 /* 2. Save the current process state */
2367 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002368 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002369
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002370 //save_fpu_state(regs, &sf->fpu_state);
2371 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002372
Riku Voipio1d8b5122014-04-23 10:26:05 +03002373 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002374 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002375 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002376 }
bellard6d5e2162004-09-30 22:04:13 +00002377
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002378 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002379 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002380 }
2381 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002382 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002383 }
2384 if (err)
2385 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002386
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002387 /* 3. signal handler back-trampoline and parameters */
2388 env->regwptr[UREG_FP] = sf_addr;
2389 env->regwptr[UREG_I0] = sig;
2390 env->regwptr[UREG_I1] = sf_addr +
2391 offsetof(struct target_signal_frame, info);
2392 env->regwptr[UREG_I2] = sf_addr +
2393 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002394
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002395 /* 4. signal handler */
2396 env->pc = ka->_sa_handler;
2397 env->npc = (env->pc + 4);
2398 /* 5. return to kernel instructions */
2399 if (ka->sa_restorer) {
2400 env->regwptr[UREG_I7] = ka->sa_restorer;
2401 } else {
2402 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002403
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002404 env->regwptr[UREG_I7] = sf_addr +
2405 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002406
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002407 /* mov __NR_sigreturn, %g1 */
2408 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002409 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002410
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002411 /* t 0x10 */
2412 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002413 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002414 if (err)
2415 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002416
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002417 /* Flush instruction space. */
2418 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2419 // tb_flush(env);
2420 }
2421 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2422 return;
bellard459a4012007-11-11 19:45:10 +00002423#if 0
2424sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002425 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002426#endif
bellard6d5e2162004-09-30 22:04:13 +00002427sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002428 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2429 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002430}
bellard6d5e2162004-09-30 22:04:13 +00002431
pbrook624f7972008-05-31 16:11:38 +00002432static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002433 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002434 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002435{
2436 fprintf(stderr, "setup_rt_frame: not implemented\n");
2437}
2438
Andreas Färber05390242012-02-25 03:37:53 +01002439long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002440{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002441 abi_ulong sf_addr;
2442 struct target_signal_frame *sf;
2443 uint32_t up_psr, pc, npc;
2444 target_sigset_t set;
2445 sigset_t host_set;
2446 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002447
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002448 sf_addr = env->regwptr[UREG_FP];
2449 trace_user_do_sigreturn(env, sf_addr);
2450 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2451 goto segv_and_exit;
2452 }
bellard6d5e2162004-09-30 22:04:13 +00002453
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002454 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002455
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002456 if (sf_addr & 3)
2457 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002458
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002459 __get_user(pc, &sf->info.si_regs.pc);
2460 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002461
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002462 if ((pc | npc) & 3) {
2463 goto segv_and_exit;
2464 }
bellard6d5e2162004-09-30 22:04:13 +00002465
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002466 /* 2. Restore the state */
2467 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002468
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002469 /* User can only change condition codes and FPU enabling in %psr. */
2470 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2471 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002472
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002473 env->pc = pc;
2474 env->npc = npc;
2475 __get_user(env->y, &sf->info.si_regs.y);
2476 for (i=0; i < 8; i++) {
2477 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2478 }
2479 for (i=0; i < 8; i++) {
2480 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2481 }
bellard6d5e2162004-09-30 22:04:13 +00002482
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002483 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002484 * __get_user(fpu_save, &sf->fpu_save);
2485 * if (fpu_save)
2486 * err |= restore_fpu_state(env, fpu_save);
2487 */
bellard6d5e2162004-09-30 22:04:13 +00002488
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002489 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002490 * the races which exist anyways.
2491 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002492 __get_user(set.sig[0], &sf->info.si_mask);
2493 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2494 __get_user(set.sig[i], &sf->extramask[i - 1]);
2495 }
bellarde80cfcf2004-12-19 23:18:01 +00002496
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002497 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002498 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002499
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002500 if (err) {
2501 goto segv_and_exit;
2502 }
2503 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002504 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002505
2506segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002507 unlock_user_struct(sf, sf_addr, 0);
2508 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002509}
2510
Andreas Färber05390242012-02-25 03:37:53 +01002511long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002512{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002513 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002514 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002515 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002516}
2517
bellard459a4012007-11-11 19:45:10 +00002518#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002519#define MC_TSTATE 0
2520#define MC_PC 1
2521#define MC_NPC 2
2522#define MC_Y 3
2523#define MC_G1 4
2524#define MC_G2 5
2525#define MC_G3 6
2526#define MC_G4 7
2527#define MC_G5 8
2528#define MC_G6 9
2529#define MC_G7 10
2530#define MC_O0 11
2531#define MC_O1 12
2532#define MC_O2 13
2533#define MC_O3 14
2534#define MC_O4 15
2535#define MC_O5 16
2536#define MC_O6 17
2537#define MC_O7 18
2538#define MC_NGREG 19
2539
Anthony Liguoric227f092009-10-01 16:12:16 -05002540typedef abi_ulong target_mc_greg_t;
2541typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002542
2543struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002544 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002545 uint32_t mcfq_insn;
2546};
2547
2548struct target_mc_fpu {
2549 union {
2550 uint32_t sregs[32];
2551 uint64_t dregs[32];
2552 //uint128_t qregs[16];
2553 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002554 abi_ulong mcfpu_fsr;
2555 abi_ulong mcfpu_fprs;
2556 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002557 struct target_mc_fq *mcfpu_fq;
2558 unsigned char mcfpu_qcnt;
2559 unsigned char mcfpu_qentsz;
2560 unsigned char mcfpu_enab;
2561};
Anthony Liguoric227f092009-10-01 16:12:16 -05002562typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002563
2564typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002565 target_mc_gregset_t mc_gregs;
2566 target_mc_greg_t mc_fp;
2567 target_mc_greg_t mc_i7;
2568 target_mc_fpu_t mc_fpregs;
2569} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002570
2571struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002572 struct target_ucontext *tuc_link;
2573 abi_ulong tuc_flags;
2574 target_sigset_t tuc_sigmask;
2575 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002576};
2577
2578/* A V9 register window */
2579struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002580 abi_ulong locals[8];
2581 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002582};
2583
2584#define TARGET_STACK_BIAS 2047
2585
2586/* {set, get}context() needed for 64-bit SparcLinux userland. */
2587void sparc64_set_context(CPUSPARCState *env)
2588{
bellard459a4012007-11-11 19:45:10 +00002589 abi_ulong ucp_addr;
2590 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002591 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002592 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002593 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002594 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002595
bellard459a4012007-11-11 19:45:10 +00002596 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002597 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002598 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002599 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002600 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002601 __get_user(pc, &((*grp)[MC_PC]));
2602 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002603 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002604 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002605 }
blueswir15bfb56b2007-10-05 17:01:51 +00002606 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002607 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002608 sigset_t set;
2609
2610 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002611 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002612 } else {
bellard459a4012007-11-11 19:45:10 +00002613 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002614 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002615 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002616 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002617 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002618 }
blueswir15bfb56b2007-10-05 17:01:51 +00002619 }
2620 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002621 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002622 }
2623 env->pc = pc;
2624 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002625 __get_user(env->y, &((*grp)[MC_Y]));
2626 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002627 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002628 cpu_put_ccr(env, tstate >> 32);
2629 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002630 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2631 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2632 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2633 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2634 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2635 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2636 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2637 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2638 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2639 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2640 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2641 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2642 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2643 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2644 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002645
Riku Voipio1d8b5122014-04-23 10:26:05 +03002646 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2647 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002648
bellard459a4012007-11-11 19:45:10 +00002649 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002650 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2651 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002652 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002653 }
2654 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2655 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002656 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002657 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002658 /* FIXME this does not match how the kernel handles the FPU in
2659 * its sparc64_set_context implementation. In particular the FPU
2660 * is only restored if fenab is non-zero in:
2661 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2662 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002663 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002664 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002665 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2666 for (i = 0; i < 64; i++, src++) {
2667 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002668 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002669 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002670 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002671 }
2672 }
bellard459a4012007-11-11 19:45:10 +00002673 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002674 __get_user(env->fsr,
2675 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2676 __get_user(env->gsr,
2677 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002678 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002679 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002680do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002681 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002682 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002683}
2684
2685void sparc64_get_context(CPUSPARCState *env)
2686{
bellard459a4012007-11-11 19:45:10 +00002687 abi_ulong ucp_addr;
2688 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002689 target_mc_gregset_t *grp;
2690 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002691 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002692 int err;
2693 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002694 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002695 sigset_t set;
2696
bellard459a4012007-11-11 19:45:10 +00002697 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002698 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002699 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002700 }
bellard459a4012007-11-11 19:45:10 +00002701
Aurelien Jarno60e99242010-03-29 02:12:51 +02002702 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002703 grp = &mcp->mc_gregs;
2704
2705 /* Skip over the trap instruction, first. */
2706 env->pc = env->npc;
2707 env->npc += 4;
2708
Peter Maydell3d3efba2016-05-27 15:51:49 +01002709 /* If we're only reading the signal mask then do_sigprocmask()
2710 * is guaranteed not to fail, which is important because we don't
2711 * have any way to signal a failure or restart this operation since
2712 * this is not a normal syscall.
2713 */
2714 err = do_sigprocmask(0, NULL, &set);
2715 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002716 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002717 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002718 __put_user(target_set.sig[0],
2719 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002720 } else {
2721 abi_ulong *src, *dst;
2722 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002723 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002724 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002725 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002726 }
blueswir15bfb56b2007-10-05 17:01:51 +00002727 if (err)
2728 goto do_sigsegv;
2729 }
2730
bellard459a4012007-11-11 19:45:10 +00002731 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002732 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2733 __put_user(env->pc, &((*grp)[MC_PC]));
2734 __put_user(env->npc, &((*grp)[MC_NPC]));
2735 __put_user(env->y, &((*grp)[MC_Y]));
2736 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2737 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2738 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2739 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2740 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2741 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2742 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2743 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2744 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2745 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2746 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2747 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2748 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2749 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2750 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002751
bellard459a4012007-11-11 19:45:10 +00002752 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2753 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002754 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2755 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002756 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002757 }
2758 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2759 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002760 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002761 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002762 __put_user(fp, &(mcp->mc_fp));
2763 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002764
bellard459a4012007-11-11 19:45:10 +00002765 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002766 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2767 for (i = 0; i < 64; i++, dst++) {
2768 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002769 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002770 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002771 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002772 }
2773 }
bellard459a4012007-11-11 19:45:10 +00002774 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002775 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2776 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2777 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002778
2779 if (err)
2780 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002781 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002782 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002783do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002784 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002785 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002786}
2787#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002788#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002789
Richard Hendersonff970902013-02-10 10:30:42 -08002790# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002791struct target_sigcontext {
2792 uint32_t sc_regmask; /* Unused */
2793 uint32_t sc_status;
2794 uint64_t sc_pc;
2795 uint64_t sc_regs[32];
2796 uint64_t sc_fpregs[32];
2797 uint32_t sc_ownedfp; /* Unused */
2798 uint32_t sc_fpc_csr;
2799 uint32_t sc_fpc_eir; /* Unused */
2800 uint32_t sc_used_math;
2801 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002802 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002803 uint64_t sc_mdhi;
2804 uint64_t sc_mdlo;
2805 target_ulong sc_hi1; /* Was sc_cause */
2806 target_ulong sc_lo1; /* Was sc_badvaddr */
2807 target_ulong sc_hi2; /* Was sc_sigset[4] */
2808 target_ulong sc_lo2;
2809 target_ulong sc_hi3;
2810 target_ulong sc_lo3;
2811};
Richard Hendersonff970902013-02-10 10:30:42 -08002812# else /* N32 || N64 */
2813struct target_sigcontext {
2814 uint64_t sc_regs[32];
2815 uint64_t sc_fpregs[32];
2816 uint64_t sc_mdhi;
2817 uint64_t sc_hi1;
2818 uint64_t sc_hi2;
2819 uint64_t sc_hi3;
2820 uint64_t sc_mdlo;
2821 uint64_t sc_lo1;
2822 uint64_t sc_lo2;
2823 uint64_t sc_lo3;
2824 uint64_t sc_pc;
2825 uint32_t sc_fpc_csr;
2826 uint32_t sc_used_math;
2827 uint32_t sc_dsp;
2828 uint32_t sc_reserved;
2829};
2830# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002831
2832struct sigframe {
2833 uint32_t sf_ass[4]; /* argument save space for o32 */
2834 uint32_t sf_code[2]; /* signal trampoline */
2835 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002836 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002837};
2838
pbrook0b1bcb02009-04-21 01:41:10 +00002839struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002840 target_ulong tuc_flags;
2841 target_ulong tuc_link;
2842 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002843 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002844 struct target_sigcontext tuc_mcontext;
2845 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002846};
2847
2848struct target_rt_sigframe {
2849 uint32_t rs_ass[4]; /* argument save space for o32 */
2850 uint32_t rs_code[2]; /* signal trampoline */
2851 struct target_siginfo rs_info;
2852 struct target_ucontext rs_uc;
2853};
2854
bellard106ec872006-06-27 21:08:10 +00002855/* Install trampoline to jump back from signal handler */
2856static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2857{
Richard Henderson084d0492013-02-10 10:30:44 -08002858 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002859
2860 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002861 * Set up the return code ...
2862 *
2863 * li v0, __NR__foo_sigreturn
2864 * syscall
2865 */
bellard106ec872006-06-27 21:08:10 +00002866
Riku Voipio1d8b5122014-04-23 10:26:05 +03002867 __put_user(0x24020000 + syscall, tramp + 0);
2868 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002869 return err;
2870}
2871
Riku Voipio41ecc722014-04-23 11:01:00 +03002872static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002873 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002874{
Richard Henderson084d0492013-02-10 10:30:44 -08002875 int i;
bellard106ec872006-06-27 21:08:10 +00002876
Riku Voipio1d8b5122014-04-23 10:26:05 +03002877 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002878 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002879
Richard Henderson084d0492013-02-10 10:30:44 -08002880 __put_user(0, &sc->sc_regs[0]);
2881 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002882 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002883 }
bellard106ec872006-06-27 21:08:10 +00002884
Riku Voipio1d8b5122014-04-23 10:26:05 +03002885 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2886 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002887
Richard Henderson084d0492013-02-10 10:30:44 -08002888 /* Rather than checking for dsp existence, always copy. The storage
2889 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002890 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2891 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2892 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2893 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2894 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2895 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002896 {
2897 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002898 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002899 }
Richard Henderson084d0492013-02-10 10:30:44 -08002900
Riku Voipio1d8b5122014-04-23 10:26:05 +03002901 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002902
2903 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002904 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002905 }
bellard106ec872006-06-27 21:08:10 +00002906}
2907
Riku Voipio016d2e12014-04-23 11:19:48 +03002908static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002909restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002910{
Richard Henderson084d0492013-02-10 10:30:44 -08002911 int i;
bellard106ec872006-06-27 21:08:10 +00002912
Riku Voipio1d8b5122014-04-23 10:26:05 +03002913 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002914
Riku Voipio1d8b5122014-04-23 10:26:05 +03002915 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2916 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002917
Richard Henderson084d0492013-02-10 10:30:44 -08002918 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002919 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002920 }
2921
Riku Voipio1d8b5122014-04-23 10:26:05 +03002922 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2923 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2924 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2925 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2926 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2927 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002928 {
2929 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002930 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002931 cpu_wrdsp(dsp, 0x3ff, regs);
2932 }
2933
2934 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002935 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002936 }
bellard106ec872006-06-27 21:08:10 +00002937}
Richard Hendersonff970902013-02-10 10:30:42 -08002938
bellard106ec872006-06-27 21:08:10 +00002939/*
2940 * Determine which stack to use..
2941 */
bellard579a97f2007-11-11 14:26:47 +00002942static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002943get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002944{
2945 unsigned long sp;
2946
2947 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002948 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002949
2950 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002951 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002952 * above the user stack, 16-bytes before the next lowest
2953 * 16 byte boundary. Try to avoid trashing it.
2954 */
2955 sp -= 32;
2956
bellard106ec872006-06-27 21:08:10 +00002957 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002958 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002959 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2960 }
bellard106ec872006-06-27 21:08:10 +00002961
bellard579a97f2007-11-11 14:26:47 +00002962 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002963}
2964
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002965static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2966{
2967 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2968 env->hflags &= ~MIPS_HFLAG_M16;
2969 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2970 env->active_tc.PC &= ~(target_ulong) 1;
2971 }
2972}
2973
Richard Hendersonff970902013-02-10 10:30:42 -08002974# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002975/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002976static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002977 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002978{
2979 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002980 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002981 int i;
2982
bellard579a97f2007-11-11 14:26:47 +00002983 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002984 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002985 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2986 goto give_sigsegv;
2987 }
bellard106ec872006-06-27 21:08:10 +00002988
2989 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2990
Riku Voipio41ecc722014-04-23 11:01:00 +03002991 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002992
2993 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002994 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002995 }
2996
2997 /*
2998 * Arguments to signal handler:
2999 *
3000 * a0 = signal number
3001 * a1 = 0 (should be cause)
3002 * a2 = pointer to struct sigcontext
3003 *
3004 * $25 and PC point to the signal handler, $29 points to the
3005 * struct sigframe.
3006 */
thsb5dc7732008-06-27 10:02:35 +00003007 regs->active_tc.gpr[ 4] = sig;
3008 regs->active_tc.gpr[ 5] = 0;
3009 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3010 regs->active_tc.gpr[29] = frame_addr;
3011 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003012 /* The original kernel code sets CP0_EPC to the handler
3013 * since it returns to userland using eret
3014 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003015 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003016 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003017 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003018 return;
3019
3020give_sigsegv:
3021 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003022}
3023
Andreas Färber05390242012-02-25 03:37:53 +01003024long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003025{
ths388bb212007-05-13 13:58:00 +00003026 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003027 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003028 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003029 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003030 int i;
bellard106ec872006-06-27 21:08:10 +00003031
thsb5dc7732008-06-27 10:02:35 +00003032 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003033 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003034 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003035 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003036
ths388bb212007-05-13 13:58:00 +00003037 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003038 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003039 }
bellard106ec872006-06-27 21:08:10 +00003040
ths388bb212007-05-13 13:58:00 +00003041 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003042 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003043
Riku Voipio016d2e12014-04-23 11:19:48 +03003044 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003045
3046#if 0
ths388bb212007-05-13 13:58:00 +00003047 /*
3048 * Don't let your children do this ...
3049 */
3050 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003051 "move\t$29, %0\n\t"
3052 "j\tsyscall_exit"
3053 :/* no outputs */
3054 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003055 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003056#endif
ths3b46e622007-09-17 08:09:54 +00003057
thsb5dc7732008-06-27 10:02:35 +00003058 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003059 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003060 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003061 * maybe a problem with nested signals ? */
3062 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003063 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003064
3065badframe:
ths388bb212007-05-13 13:58:00 +00003066 force_sig(TARGET_SIGSEGV/*, current*/);
3067 return 0;
bellard106ec872006-06-27 21:08:10 +00003068}
Richard Hendersonff970902013-02-10 10:30:42 -08003069# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003070
pbrook624f7972008-05-31 16:11:38 +00003071static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003072 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003073 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003074{
pbrook0b1bcb02009-04-21 01:41:10 +00003075 struct target_rt_sigframe *frame;
3076 abi_ulong frame_addr;
3077 int i;
3078
3079 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003080 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003081 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3082 goto give_sigsegv;
3083 }
pbrook0b1bcb02009-04-21 01:41:10 +00003084
3085 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3086
Peter Maydellf6c7a052015-01-08 12:19:48 +00003087 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003088
Aurelien Jarno60e99242010-03-29 02:12:51 +02003089 __put_user(0, &frame->rs_uc.tuc_flags);
3090 __put_user(0, &frame->rs_uc.tuc_link);
3091 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3092 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003093 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003094 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003095
Aurelien Jarno60e99242010-03-29 02:12:51 +02003096 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003097
3098 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003099 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003100 }
3101
3102 /*
3103 * Arguments to signal handler:
3104 *
3105 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003106 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003107 * a2 = pointer to struct ucontext
3108 *
3109 * $25 and PC point to the signal handler, $29 points to the
3110 * struct sigframe.
3111 */
3112 env->active_tc.gpr[ 4] = sig;
3113 env->active_tc.gpr[ 5] = frame_addr
3114 + offsetof(struct target_rt_sigframe, rs_info);
3115 env->active_tc.gpr[ 6] = frame_addr
3116 + offsetof(struct target_rt_sigframe, rs_uc);
3117 env->active_tc.gpr[29] = frame_addr;
3118 env->active_tc.gpr[31] = frame_addr
3119 + offsetof(struct target_rt_sigframe, rs_code);
3120 /* The original kernel code sets CP0_EPC to the handler
3121 * since it returns to userland using eret
3122 * we cannot do this here, and we must set PC directly */
3123 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003124 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003125 unlock_user_struct(frame, frame_addr, 1);
3126 return;
3127
3128give_sigsegv:
3129 unlock_user_struct(frame, frame_addr, 1);
3130 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003131}
3132
Andreas Färber05390242012-02-25 03:37:53 +01003133long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003134{
pbrook0b1bcb02009-04-21 01:41:10 +00003135 struct target_rt_sigframe *frame;
3136 abi_ulong frame_addr;
3137 sigset_t blocked;
3138
pbrook0b1bcb02009-04-21 01:41:10 +00003139 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003140 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003141 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3142 goto badframe;
3143 }
pbrook0b1bcb02009-04-21 01:41:10 +00003144
Aurelien Jarno60e99242010-03-29 02:12:51 +02003145 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003146 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003147
Riku Voipio016d2e12014-04-23 11:19:48 +03003148 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003149
3150 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003151 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3152 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003153 goto badframe;
3154
3155 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003156 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003157 /* I am not sure this is right, but it seems to work
3158 * maybe a problem with nested signals ? */
3159 env->CP0_EPC = 0;
3160 return -TARGET_QEMU_ESIGRETURN;
3161
3162badframe:
3163 force_sig(TARGET_SIGSEGV/*, current*/);
3164 return 0;
bellard106ec872006-06-27 21:08:10 +00003165}
bellard6d5e2162004-09-30 22:04:13 +00003166
thsc3b5bc82007-12-02 06:31:25 +00003167#elif defined(TARGET_SH4)
3168
3169/*
3170 * code and data structures from linux kernel:
3171 * include/asm-sh/sigcontext.h
3172 * arch/sh/kernel/signal.c
3173 */
3174
3175struct target_sigcontext {
3176 target_ulong oldmask;
3177
3178 /* CPU registers */
3179 target_ulong sc_gregs[16];
3180 target_ulong sc_pc;
3181 target_ulong sc_pr;
3182 target_ulong sc_sr;
3183 target_ulong sc_gbr;
3184 target_ulong sc_mach;
3185 target_ulong sc_macl;
3186
3187 /* FPU registers */
3188 target_ulong sc_fpregs[16];
3189 target_ulong sc_xfpregs[16];
3190 unsigned int sc_fpscr;
3191 unsigned int sc_fpul;
3192 unsigned int sc_ownedfp;
3193};
3194
3195struct target_sigframe
3196{
3197 struct target_sigcontext sc;
3198 target_ulong extramask[TARGET_NSIG_WORDS-1];
3199 uint16_t retcode[3];
3200};
3201
3202
3203struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003204 target_ulong tuc_flags;
3205 struct target_ucontext *tuc_link;
3206 target_stack_t tuc_stack;
3207 struct target_sigcontext tuc_mcontext;
3208 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003209};
3210
3211struct target_rt_sigframe
3212{
3213 struct target_siginfo info;
3214 struct target_ucontext uc;
3215 uint16_t retcode[3];
3216};
3217
3218
3219#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3220#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3221
pbrook624f7972008-05-31 16:11:38 +00003222static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003223 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003224{
pbrook624f7972008-05-31 16:11:38 +00003225 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003226 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3227 }
3228
3229 return (sp - frame_size) & -8ul;
3230}
3231
Riku Voipio41ecc722014-04-23 11:01:00 +03003232static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003233 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003234{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003235 int i;
thsc3b5bc82007-12-02 06:31:25 +00003236
Riku Voipio1d8b5122014-04-23 10:26:05 +03003237#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003238 COPY(gregs[0]); COPY(gregs[1]);
3239 COPY(gregs[2]); COPY(gregs[3]);
3240 COPY(gregs[4]); COPY(gregs[5]);
3241 COPY(gregs[6]); COPY(gregs[7]);
3242 COPY(gregs[8]); COPY(gregs[9]);
3243 COPY(gregs[10]); COPY(gregs[11]);
3244 COPY(gregs[12]); COPY(gregs[13]);
3245 COPY(gregs[14]); COPY(gregs[15]);
3246 COPY(gbr); COPY(mach);
3247 COPY(macl); COPY(pr);
3248 COPY(sr); COPY(pc);
3249#undef COPY
3250
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003251 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003252 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003253 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003254 __put_user(regs->fpscr, &sc->sc_fpscr);
3255 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003256
3257 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003258 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003259}
3260
Timothy E Baldwinba412492016-05-12 18:47:35 +01003261static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003262{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003263 int i;
thsc3b5bc82007-12-02 06:31:25 +00003264
Riku Voipio1d8b5122014-04-23 10:26:05 +03003265#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003266 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003267 COPY(gregs[2]); COPY(gregs[3]);
3268 COPY(gregs[4]); COPY(gregs[5]);
3269 COPY(gregs[6]); COPY(gregs[7]);
3270 COPY(gregs[8]); COPY(gregs[9]);
3271 COPY(gregs[10]); COPY(gregs[11]);
3272 COPY(gregs[12]); COPY(gregs[13]);
3273 COPY(gregs[14]); COPY(gregs[15]);
3274 COPY(gbr); COPY(mach);
3275 COPY(macl); COPY(pr);
3276 COPY(sr); COPY(pc);
3277#undef COPY
3278
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003279 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003280 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003281 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003282 __get_user(regs->fpscr, &sc->sc_fpscr);
3283 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003284
3285 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003286}
3287
pbrook624f7972008-05-31 16:11:38 +00003288static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003289 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003290{
3291 struct target_sigframe *frame;
3292 abi_ulong frame_addr;
3293 int i;
thsc3b5bc82007-12-02 06:31:25 +00003294
3295 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003296 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003297 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3298 goto give_sigsegv;
3299 }
thsc3b5bc82007-12-02 06:31:25 +00003300
Riku Voipio41ecc722014-04-23 11:01:00 +03003301 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003302
3303 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003304 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003305 }
3306
3307 /* Set up to return from userspace. If provided, use a stub
3308 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003309 if (ka->sa_flags & TARGET_SA_RESTORER) {
3310 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003311 } else {
3312 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003313 abi_ulong retcode_addr = frame_addr +
3314 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003315 __put_user(MOVW(2), &frame->retcode[0]);
3316 __put_user(TRAP_NOARG, &frame->retcode[1]);
3317 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003318 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003319 }
3320
thsc3b5bc82007-12-02 06:31:25 +00003321 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003322 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003323 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003324 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003325 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003326 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003327
3328 unlock_user_struct(frame, frame_addr, 1);
3329 return;
3330
3331give_sigsegv:
3332 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003333 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003334}
3335
pbrook624f7972008-05-31 16:11:38 +00003336static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003337 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003338 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003339{
3340 struct target_rt_sigframe *frame;
3341 abi_ulong frame_addr;
3342 int i;
thsc3b5bc82007-12-02 06:31:25 +00003343
3344 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003345 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003346 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3347 goto give_sigsegv;
3348 }
thsc3b5bc82007-12-02 06:31:25 +00003349
Peter Maydellf6c7a052015-01-08 12:19:48 +00003350 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003351
3352 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003353 __put_user(0, &frame->uc.tuc_flags);
3354 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3355 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3356 &frame->uc.tuc_stack.ss_sp);
3357 __put_user(sas_ss_flags(regs->gregs[15]),
3358 &frame->uc.tuc_stack.ss_flags);
3359 __put_user(target_sigaltstack_used.ss_size,
3360 &frame->uc.tuc_stack.ss_size);
3361 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003362 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003363 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003364 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003365 }
3366
3367 /* Set up to return from userspace. If provided, use a stub
3368 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003369 if (ka->sa_flags & TARGET_SA_RESTORER) {
3370 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003371 } else {
3372 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003373 abi_ulong retcode_addr = frame_addr +
3374 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003375 __put_user(MOVW(2), &frame->retcode[0]);
3376 __put_user(TRAP_NOARG, &frame->retcode[1]);
3377 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003378 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003379 }
3380
thsc3b5bc82007-12-02 06:31:25 +00003381 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003382 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003383 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003384 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3385 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003386 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003387
3388 unlock_user_struct(frame, frame_addr, 1);
3389 return;
3390
3391give_sigsegv:
3392 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003393 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003394}
3395
Andreas Färber05390242012-02-25 03:37:53 +01003396long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003397{
3398 struct target_sigframe *frame;
3399 abi_ulong frame_addr;
3400 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003401 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003402 int i;
3403 int err = 0;
3404
thsc3b5bc82007-12-02 06:31:25 +00003405 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003406 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003407 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3408 goto badframe;
3409 }
thsc3b5bc82007-12-02 06:31:25 +00003410
Riku Voipio1d8b5122014-04-23 10:26:05 +03003411 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003412 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003413 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003414 }
3415
3416 if (err)
3417 goto badframe;
3418
3419 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003420 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003421
Timothy E Baldwinba412492016-05-12 18:47:35 +01003422 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003423
3424 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003425 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003426
3427badframe:
3428 unlock_user_struct(frame, frame_addr, 0);
3429 force_sig(TARGET_SIGSEGV);
3430 return 0;
3431}
3432
Andreas Färber05390242012-02-25 03:37:53 +01003433long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003434{
3435 struct target_rt_sigframe *frame;
3436 abi_ulong frame_addr;
3437 sigset_t blocked;
3438
thsc3b5bc82007-12-02 06:31:25 +00003439 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003440 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003441 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3442 goto badframe;
3443 }
thsc3b5bc82007-12-02 06:31:25 +00003444
Aurelien Jarno60e99242010-03-29 02:12:51 +02003445 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003446 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003447
Timothy E Baldwinba412492016-05-12 18:47:35 +01003448 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003449
3450 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003451 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3452 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003453 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003454 }
thsc3b5bc82007-12-02 06:31:25 +00003455
3456 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003457 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003458
3459badframe:
3460 unlock_user_struct(frame, frame_addr, 0);
3461 force_sig(TARGET_SIGSEGV);
3462 return 0;
3463}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003464#elif defined(TARGET_MICROBLAZE)
3465
3466struct target_sigcontext {
3467 struct target_pt_regs regs; /* needs to be first */
3468 uint32_t oldmask;
3469};
3470
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003471struct target_stack_t {
3472 abi_ulong ss_sp;
3473 int ss_flags;
3474 unsigned int ss_size;
3475};
3476
3477struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003478 abi_ulong tuc_flags;
3479 abi_ulong tuc_link;
3480 struct target_stack_t tuc_stack;
3481 struct target_sigcontext tuc_mcontext;
3482 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003483};
3484
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003485/* Signal frames. */
3486struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003487 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003488 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3489 uint32_t tramp[2];
3490};
3491
3492struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003493 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003494 struct ucontext uc;
3495 uint32_t tramp[2];
3496};
3497
Andreas Färber05390242012-02-25 03:37:53 +01003498static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003499{
3500 __put_user(env->regs[0], &sc->regs.r0);
3501 __put_user(env->regs[1], &sc->regs.r1);
3502 __put_user(env->regs[2], &sc->regs.r2);
3503 __put_user(env->regs[3], &sc->regs.r3);
3504 __put_user(env->regs[4], &sc->regs.r4);
3505 __put_user(env->regs[5], &sc->regs.r5);
3506 __put_user(env->regs[6], &sc->regs.r6);
3507 __put_user(env->regs[7], &sc->regs.r7);
3508 __put_user(env->regs[8], &sc->regs.r8);
3509 __put_user(env->regs[9], &sc->regs.r9);
3510 __put_user(env->regs[10], &sc->regs.r10);
3511 __put_user(env->regs[11], &sc->regs.r11);
3512 __put_user(env->regs[12], &sc->regs.r12);
3513 __put_user(env->regs[13], &sc->regs.r13);
3514 __put_user(env->regs[14], &sc->regs.r14);
3515 __put_user(env->regs[15], &sc->regs.r15);
3516 __put_user(env->regs[16], &sc->regs.r16);
3517 __put_user(env->regs[17], &sc->regs.r17);
3518 __put_user(env->regs[18], &sc->regs.r18);
3519 __put_user(env->regs[19], &sc->regs.r19);
3520 __put_user(env->regs[20], &sc->regs.r20);
3521 __put_user(env->regs[21], &sc->regs.r21);
3522 __put_user(env->regs[22], &sc->regs.r22);
3523 __put_user(env->regs[23], &sc->regs.r23);
3524 __put_user(env->regs[24], &sc->regs.r24);
3525 __put_user(env->regs[25], &sc->regs.r25);
3526 __put_user(env->regs[26], &sc->regs.r26);
3527 __put_user(env->regs[27], &sc->regs.r27);
3528 __put_user(env->regs[28], &sc->regs.r28);
3529 __put_user(env->regs[29], &sc->regs.r29);
3530 __put_user(env->regs[30], &sc->regs.r30);
3531 __put_user(env->regs[31], &sc->regs.r31);
3532 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3533}
3534
Andreas Färber05390242012-02-25 03:37:53 +01003535static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003536{
3537 __get_user(env->regs[0], &sc->regs.r0);
3538 __get_user(env->regs[1], &sc->regs.r1);
3539 __get_user(env->regs[2], &sc->regs.r2);
3540 __get_user(env->regs[3], &sc->regs.r3);
3541 __get_user(env->regs[4], &sc->regs.r4);
3542 __get_user(env->regs[5], &sc->regs.r5);
3543 __get_user(env->regs[6], &sc->regs.r6);
3544 __get_user(env->regs[7], &sc->regs.r7);
3545 __get_user(env->regs[8], &sc->regs.r8);
3546 __get_user(env->regs[9], &sc->regs.r9);
3547 __get_user(env->regs[10], &sc->regs.r10);
3548 __get_user(env->regs[11], &sc->regs.r11);
3549 __get_user(env->regs[12], &sc->regs.r12);
3550 __get_user(env->regs[13], &sc->regs.r13);
3551 __get_user(env->regs[14], &sc->regs.r14);
3552 __get_user(env->regs[15], &sc->regs.r15);
3553 __get_user(env->regs[16], &sc->regs.r16);
3554 __get_user(env->regs[17], &sc->regs.r17);
3555 __get_user(env->regs[18], &sc->regs.r18);
3556 __get_user(env->regs[19], &sc->regs.r19);
3557 __get_user(env->regs[20], &sc->regs.r20);
3558 __get_user(env->regs[21], &sc->regs.r21);
3559 __get_user(env->regs[22], &sc->regs.r22);
3560 __get_user(env->regs[23], &sc->regs.r23);
3561 __get_user(env->regs[24], &sc->regs.r24);
3562 __get_user(env->regs[25], &sc->regs.r25);
3563 __get_user(env->regs[26], &sc->regs.r26);
3564 __get_user(env->regs[27], &sc->regs.r27);
3565 __get_user(env->regs[28], &sc->regs.r28);
3566 __get_user(env->regs[29], &sc->regs.r29);
3567 __get_user(env->regs[30], &sc->regs.r30);
3568 __get_user(env->regs[31], &sc->regs.r31);
3569 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3570}
3571
3572static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003573 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003574{
3575 abi_ulong sp = env->regs[1];
3576
Riku Voipiob545f632014-07-15 17:01:55 +03003577 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003578 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003579 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003580
3581 return ((sp - frame_size) & -8UL);
3582}
3583
3584static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003585 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003586{
3587 struct target_signal_frame *frame;
3588 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003589 int i;
3590
3591 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003592 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003593 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3594 goto badframe;
3595
3596 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003597 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003598
3599 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003600 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003601 }
3602
Richard Hendersonf711df62010-11-22 14:57:52 -08003603 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003604
3605 /* Set up to return from userspace. If provided, use a stub
3606 already in userspace. */
3607 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3608 if (ka->sa_flags & TARGET_SA_RESTORER) {
3609 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3610 } else {
3611 uint32_t t;
3612 /* Note, these encodings are _big endian_! */
3613 /* addi r12, r0, __NR_sigreturn */
3614 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003615 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003616 /* brki r14, 0x8 */
3617 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003618 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003619
3620 /* Return from sighandler will jump to the tramp.
3621 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003622 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3623 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003624 }
3625
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003626 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003627 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003628 /* Signal handler args: */
3629 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003630 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003631 /* arg 1: sigcontext */
3632 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003633
3634 /* Offset of 4 to handle microblaze rtid r14, 0 */
3635 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3636
3637 unlock_user_struct(frame, frame_addr, 1);
3638 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003639badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003640 force_sig(TARGET_SIGSEGV);
3641}
3642
3643static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003644 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003645 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003646{
3647 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3648}
3649
Andreas Färber05390242012-02-25 03:37:53 +01003650long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003651{
3652 struct target_signal_frame *frame;
3653 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003654 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003655 sigset_t set;
3656 int i;
3657
3658 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003659 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003660 /* Make sure the guest isn't playing games. */
3661 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3662 goto badframe;
3663
3664 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003665 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003666 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003667 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003668 }
3669 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003670 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003671
Richard Hendersonf711df62010-11-22 14:57:52 -08003672 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003673 /* We got here through a sigreturn syscall, our path back is via an
3674 rtb insn so setup r14 for that. */
3675 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003676
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003677 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003678 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003679badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003680 force_sig(TARGET_SIGSEGV);
3681}
3682
Andreas Färber05390242012-02-25 03:37:53 +01003683long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003684{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003685 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003686 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3687 return -TARGET_ENOSYS;
3688}
3689
edgar_iglb6d3abd2008-02-28 11:29:27 +00003690#elif defined(TARGET_CRIS)
3691
3692struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003693 struct target_pt_regs regs; /* needs to be first */
3694 uint32_t oldmask;
3695 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003696};
3697
3698/* Signal frames. */
3699struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003700 struct target_sigcontext sc;
3701 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3702 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003703};
3704
3705struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003706 siginfo_t *pinfo;
3707 void *puc;
3708 siginfo_t info;
3709 struct ucontext uc;
3710 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003711};
3712
Andreas Färber05390242012-02-25 03:37:53 +01003713static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003714{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003715 __put_user(env->regs[0], &sc->regs.r0);
3716 __put_user(env->regs[1], &sc->regs.r1);
3717 __put_user(env->regs[2], &sc->regs.r2);
3718 __put_user(env->regs[3], &sc->regs.r3);
3719 __put_user(env->regs[4], &sc->regs.r4);
3720 __put_user(env->regs[5], &sc->regs.r5);
3721 __put_user(env->regs[6], &sc->regs.r6);
3722 __put_user(env->regs[7], &sc->regs.r7);
3723 __put_user(env->regs[8], &sc->regs.r8);
3724 __put_user(env->regs[9], &sc->regs.r9);
3725 __put_user(env->regs[10], &sc->regs.r10);
3726 __put_user(env->regs[11], &sc->regs.r11);
3727 __put_user(env->regs[12], &sc->regs.r12);
3728 __put_user(env->regs[13], &sc->regs.r13);
3729 __put_user(env->regs[14], &sc->usp);
3730 __put_user(env->regs[15], &sc->regs.acr);
3731 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3732 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3733 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003734}
edgar_igl9664d922008-03-03 22:23:53 +00003735
Andreas Färber05390242012-02-25 03:37:53 +01003736static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003737{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003738 __get_user(env->regs[0], &sc->regs.r0);
3739 __get_user(env->regs[1], &sc->regs.r1);
3740 __get_user(env->regs[2], &sc->regs.r2);
3741 __get_user(env->regs[3], &sc->regs.r3);
3742 __get_user(env->regs[4], &sc->regs.r4);
3743 __get_user(env->regs[5], &sc->regs.r5);
3744 __get_user(env->regs[6], &sc->regs.r6);
3745 __get_user(env->regs[7], &sc->regs.r7);
3746 __get_user(env->regs[8], &sc->regs.r8);
3747 __get_user(env->regs[9], &sc->regs.r9);
3748 __get_user(env->regs[10], &sc->regs.r10);
3749 __get_user(env->regs[11], &sc->regs.r11);
3750 __get_user(env->regs[12], &sc->regs.r12);
3751 __get_user(env->regs[13], &sc->regs.r13);
3752 __get_user(env->regs[14], &sc->usp);
3753 __get_user(env->regs[15], &sc->regs.acr);
3754 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3755 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3756 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003757}
3758
Andreas Färber05390242012-02-25 03:37:53 +01003759static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003760{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003761 abi_ulong sp;
3762 /* Align the stack downwards to 4. */
3763 sp = (env->regs[R_SP] & ~3);
3764 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003765}
3766
pbrook624f7972008-05-31 16:11:38 +00003767static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003768 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003769{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003770 struct target_signal_frame *frame;
3771 abi_ulong frame_addr;
3772 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003773
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003774 frame_addr = get_sigframe(env, sizeof *frame);
3775 trace_user_setup_frame(env, frame_addr);
3776 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3777 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003778
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003779 /*
3780 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3781 * use this trampoline anymore but it sets it up for GDB.
3782 * In QEMU, using the trampoline simplifies things a bit so we use it.
3783 *
3784 * This is movu.w __NR_sigreturn, r9; break 13;
3785 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003786 __put_user(0x9c5f, frame->retcode+0);
3787 __put_user(TARGET_NR_sigreturn,
3788 frame->retcode + 1);
3789 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003790
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003791 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003792 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003793
Riku Voipio0188fad2014-04-23 13:34:15 +03003794 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3795 __put_user(set->sig[i], &frame->extramask[i - 1]);
3796 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003797
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003798 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003799
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003800 /* Move the stack and setup the arguments for the handler. */
3801 env->regs[R_SP] = frame_addr;
3802 env->regs[10] = sig;
3803 env->pc = (unsigned long) ka->_sa_handler;
3804 /* Link SRP so the guest returns through the trampoline. */
3805 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003806
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003807 unlock_user_struct(frame, frame_addr, 1);
3808 return;
3809badframe:
3810 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003811}
3812
pbrook624f7972008-05-31 16:11:38 +00003813static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003814 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003815 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003816{
3817 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3818}
3819
Andreas Färber05390242012-02-25 03:37:53 +01003820long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003821{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003822 struct target_signal_frame *frame;
3823 abi_ulong frame_addr;
3824 target_sigset_t target_set;
3825 sigset_t set;
3826 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003827
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003828 frame_addr = env->regs[R_SP];
3829 trace_user_do_sigreturn(env, frame_addr);
3830 /* Make sure the guest isn't playing games. */
3831 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3832 goto badframe;
3833 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003834
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003835 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003836 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003837 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003838 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003839 }
3840 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003841 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003842
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003843 restore_sigcontext(&frame->sc, env);
3844 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003845 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003846badframe:
3847 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003848}
3849
Andreas Färber05390242012-02-25 03:37:53 +01003850long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003851{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003852 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003853 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3854 return -TARGET_ENOSYS;
3855}
thsc3b5bc82007-12-02 06:31:25 +00003856
Jia Liud9627832012-07-20 15:50:52 +08003857#elif defined(TARGET_OPENRISC)
3858
3859struct target_sigcontext {
3860 struct target_pt_regs regs;
3861 abi_ulong oldmask;
3862 abi_ulong usp;
3863};
3864
3865struct target_ucontext {
3866 abi_ulong tuc_flags;
3867 abi_ulong tuc_link;
3868 target_stack_t tuc_stack;
3869 struct target_sigcontext tuc_mcontext;
3870 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3871};
3872
3873struct target_rt_sigframe {
3874 abi_ulong pinfo;
3875 uint64_t puc;
3876 struct target_siginfo info;
3877 struct target_sigcontext sc;
3878 struct target_ucontext uc;
3879 unsigned char retcode[16]; /* trampoline code */
3880};
3881
3882/* This is the asm-generic/ucontext.h version */
3883#if 0
3884static int restore_sigcontext(CPUOpenRISCState *regs,
3885 struct target_sigcontext *sc)
3886{
3887 unsigned int err = 0;
3888 unsigned long old_usp;
3889
3890 /* Alwys make any pending restarted system call return -EINTR */
3891 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3892
3893 /* restore the regs from &sc->regs (same as sc, since regs is first)
3894 * (sc is already checked for VERIFY_READ since the sigframe was
3895 * checked in sys_sigreturn previously)
3896 */
3897
3898 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3899 goto badframe;
3900 }
3901
3902 /* make sure the U-flag is set so user-mode cannot fool us */
3903
3904 regs->sr &= ~SR_SM;
3905
3906 /* restore the old USP as it was before we stacked the sc etc.
3907 * (we cannot just pop the sigcontext since we aligned the sp and
3908 * stuff after pushing it)
3909 */
3910
Riku Voipio1d8b5122014-04-23 10:26:05 +03003911 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003912 phx_signal("old_usp 0x%lx", old_usp);
3913
3914 __PHX__ REALLY /* ??? */
3915 wrusp(old_usp);
3916 regs->gpr[1] = old_usp;
3917
3918 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3919 * after this completes, but we don't use that mechanism. maybe we can
3920 * use it now ?
3921 */
3922
3923 return err;
3924
3925badframe:
3926 return 1;
3927}
3928#endif
3929
3930/* Set up a signal frame. */
3931
Riku Voipio41ecc722014-04-23 11:01:00 +03003932static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003933 CPUOpenRISCState *regs,
3934 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003935{
Jia Liud9627832012-07-20 15:50:52 +08003936 unsigned long usp = regs->gpr[1];
3937
3938 /* copy the regs. they are first in sc so we can use sc directly */
3939
Riku Voipio1d8b5122014-04-23 10:26:05 +03003940 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003941
3942 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3943 the signal handler. The frametype will be restored to its previous
3944 value in restore_sigcontext. */
3945 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3946
3947 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003948 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003949 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003950}
3951
3952static inline unsigned long align_sigframe(unsigned long sp)
3953{
3954 unsigned long i;
3955 i = sp & ~3UL;
3956 return i;
3957}
3958
3959static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3960 CPUOpenRISCState *regs,
3961 size_t frame_size)
3962{
3963 unsigned long sp = regs->gpr[1];
3964 int onsigstack = on_sig_stack(sp);
3965
3966 /* redzone */
3967 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003968 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003969 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3970 }
3971
3972 sp = align_sigframe(sp - frame_size);
3973
3974 /*
3975 * If we are on the alternate signal stack and would overflow it, don't.
3976 * Return an always-bogus address instead so we will die with SIGSEGV.
3977 */
3978
3979 if (onsigstack && !likely(on_sig_stack(sp))) {
3980 return -1L;
3981 }
3982
3983 return sp;
3984}
3985
Jia Liud9627832012-07-20 15:50:52 +08003986static void setup_rt_frame(int sig, struct target_sigaction *ka,
3987 target_siginfo_t *info,
3988 target_sigset_t *set, CPUOpenRISCState *env)
3989{
3990 int err = 0;
3991 abi_ulong frame_addr;
3992 unsigned long return_ip;
3993 struct target_rt_sigframe *frame;
3994 abi_ulong info_addr, uc_addr;
3995
Jia Liud9627832012-07-20 15:50:52 +08003996 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003997 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08003998 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3999 goto give_sigsegv;
4000 }
4001
4002 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004003 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004004 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004005 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004006
4007 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004008 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004009 }
4010
4011 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004012 __put_user(0, &frame->uc.tuc_flags);
4013 __put_user(0, &frame->uc.tuc_link);
4014 __put_user(target_sigaltstack_used.ss_sp,
4015 &frame->uc.tuc_stack.ss_sp);
4016 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
4017 __put_user(target_sigaltstack_used.ss_size,
4018 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004019 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004020
4021 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4022
Jia Liud9627832012-07-20 15:50:52 +08004023 /* trampoline - the desired return ip is the retcode itself */
4024 return_ip = (unsigned long)&frame->retcode;
4025 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004026 __put_user(0xa960, (short *)(frame->retcode + 0));
4027 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4028 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4029 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004030
4031 if (err) {
4032 goto give_sigsegv;
4033 }
4034
4035 /* TODO what is the current->exec_domain stuff and invmap ? */
4036
4037 /* Set up registers for signal handler */
4038 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
4039 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
4040 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
4041 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
4042 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
4043
4044 /* actually move the usp to reflect the stacked frame */
4045 env->gpr[1] = (unsigned long)frame;
4046
4047 return;
4048
4049give_sigsegv:
4050 unlock_user_struct(frame, frame_addr, 1);
4051 if (sig == TARGET_SIGSEGV) {
4052 ka->_sa_handler = TARGET_SIG_DFL;
4053 }
4054 force_sig(TARGET_SIGSEGV);
4055}
4056
4057long do_sigreturn(CPUOpenRISCState *env)
4058{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004059 trace_user_do_sigreturn(env, 0);
4060 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004061 return -TARGET_ENOSYS;
4062}
4063
4064long do_rt_sigreturn(CPUOpenRISCState *env)
4065{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004066 trace_user_do_rt_sigreturn(env, 0);
4067 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004068 return -TARGET_ENOSYS;
4069}
4070/* TARGET_OPENRISC */
4071
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004072#elif defined(TARGET_S390X)
4073
4074#define __NUM_GPRS 16
4075#define __NUM_FPRS 16
4076#define __NUM_ACRS 16
4077
4078#define S390_SYSCALL_SIZE 2
4079#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4080
4081#define _SIGCONTEXT_NSIG 64
4082#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4083#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4084#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4085#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4086#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4087
4088typedef struct {
4089 target_psw_t psw;
4090 target_ulong gprs[__NUM_GPRS];
4091 unsigned int acrs[__NUM_ACRS];
4092} target_s390_regs_common;
4093
4094typedef struct {
4095 unsigned int fpc;
4096 double fprs[__NUM_FPRS];
4097} target_s390_fp_regs;
4098
4099typedef struct {
4100 target_s390_regs_common regs;
4101 target_s390_fp_regs fpregs;
4102} target_sigregs;
4103
4104struct target_sigcontext {
4105 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4106 target_sigregs *sregs;
4107};
4108
4109typedef struct {
4110 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4111 struct target_sigcontext sc;
4112 target_sigregs sregs;
4113 int signo;
4114 uint8_t retcode[S390_SYSCALL_SIZE];
4115} sigframe;
4116
4117struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004118 target_ulong tuc_flags;
4119 struct target_ucontext *tuc_link;
4120 target_stack_t tuc_stack;
4121 target_sigregs tuc_mcontext;
4122 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004123};
4124
4125typedef struct {
4126 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4127 uint8_t retcode[S390_SYSCALL_SIZE];
4128 struct target_siginfo info;
4129 struct target_ucontext uc;
4130} rt_sigframe;
4131
4132static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004133get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004134{
4135 abi_ulong sp;
4136
4137 /* Default to using normal stack */
4138 sp = env->regs[15];
4139
4140 /* This is the X/Open sanctioned signal stack switching. */
4141 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4142 if (!sas_ss_flags(sp)) {
4143 sp = target_sigaltstack_used.ss_sp +
4144 target_sigaltstack_used.ss_size;
4145 }
4146 }
4147
4148 /* This is the legacy signal stack switching. */
4149 else if (/* FIXME !user_mode(regs) */ 0 &&
4150 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4151 ka->sa_restorer) {
4152 sp = (abi_ulong) ka->sa_restorer;
4153 }
4154
4155 return (sp - frame_size) & -8ul;
4156}
4157
Andreas Färber05390242012-02-25 03:37:53 +01004158static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004159{
4160 int i;
4161 //save_access_regs(current->thread.acrs); FIXME
4162
4163 /* Copy a 'clean' PSW mask to the user to avoid leaking
4164 information about whether PER is currently on. */
4165 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4166 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4167 for (i = 0; i < 16; i++) {
4168 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4169 }
4170 for (i = 0; i < 16; i++) {
4171 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4172 }
4173 /*
4174 * We have to store the fp registers to current->thread.fp_regs
4175 * to merge them with the emulated registers.
4176 */
4177 //save_fp_regs(&current->thread.fp_regs); FIXME
4178 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004179 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004180 }
4181}
4182
4183static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004184 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004185{
4186 sigframe *frame;
4187 abi_ulong frame_addr;
4188
4189 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004190 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004191 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004192 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004193 }
4194
Riku Voipio0188fad2014-04-23 13:34:15 +03004195 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004196
4197 save_sigregs(env, &frame->sregs);
4198
4199 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4200 (abi_ulong *)&frame->sc.sregs);
4201
4202 /* Set up to return from userspace. If provided, use a stub
4203 already in userspace. */
4204 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004205 env->regs[14] = (unsigned long)
4206 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004207 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004208 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4209 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004210 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4211 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004212 }
4213
4214 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004215 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004216
4217 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004218 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004219 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4220
4221 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004222 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004223
4224 /* We forgot to include these in the sigcontext.
4225 To avoid breaking binary compatibility, they are passed as args. */
4226 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4227 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4228
4229 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004230 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004231 unlock_user_struct(frame, frame_addr, 1);
4232 return;
4233
4234give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004235 force_sig(TARGET_SIGSEGV);
4236}
4237
4238static void setup_rt_frame(int sig, struct target_sigaction *ka,
4239 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004240 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004241{
4242 int i;
4243 rt_sigframe *frame;
4244 abi_ulong frame_addr;
4245
4246 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004247 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004248 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4249 goto give_sigsegv;
4250 }
4251
Peter Maydellf6c7a052015-01-08 12:19:48 +00004252 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004253
4254 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004255 __put_user(0, &frame->uc.tuc_flags);
4256 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4257 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004258 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004259 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004260 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4261 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004262 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4263 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004264 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004265 }
4266
4267 /* Set up to return from userspace. If provided, use a stub
4268 already in userspace. */
4269 if (ka->sa_flags & TARGET_SA_RESTORER) {
4270 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4271 } else {
4272 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004273 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4274 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004275 }
4276
4277 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004278 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004279
4280 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004281 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004282 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4283
4284 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004285 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4286 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004287 return;
4288
4289give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004290 force_sig(TARGET_SIGSEGV);
4291}
4292
4293static int
Andreas Färber05390242012-02-25 03:37:53 +01004294restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004295{
4296 int err = 0;
4297 int i;
4298
4299 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004300 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004301 }
4302
Riku Voipio1d8b5122014-04-23 10:26:05 +03004303 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004304 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4305 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004306 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004307 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4308
4309 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004310 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004311 }
4312 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004313 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004314 }
4315
4316 return err;
4317}
4318
Andreas Färber05390242012-02-25 03:37:53 +01004319long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004320{
4321 sigframe *frame;
4322 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004323 target_sigset_t target_set;
4324 sigset_t set;
4325
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004326 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004327 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4328 goto badframe;
4329 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004330 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004331
4332 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004333 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004334
4335 if (restore_sigregs(env, &frame->sregs)) {
4336 goto badframe;
4337 }
4338
4339 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004340 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004341
4342badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004343 force_sig(TARGET_SIGSEGV);
4344 return 0;
4345}
4346
Andreas Färber05390242012-02-25 03:37:53 +01004347long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004348{
4349 rt_sigframe *frame;
4350 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004351 sigset_t set;
4352
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004353 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004354 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4355 goto badframe;
4356 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004357 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004358
Peter Maydell9eede5b2016-05-27 15:51:46 +01004359 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004360
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004361 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004362 goto badframe;
4363 }
4364
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004365 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004366 get_sp_from_cpustate(env)) == -EFAULT) {
4367 goto badframe;
4368 }
4369 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004370 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004371
4372badframe:
4373 unlock_user_struct(frame, frame_addr, 0);
4374 force_sig(TARGET_SIGSEGV);
4375 return 0;
4376}
4377
Tom Musta61e75fe2014-06-30 08:13:38 -05004378#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004379
4380/* Size of dummy stack frame allocated when calling signal handler.
4381 See arch/powerpc/include/asm/ptrace.h. */
4382#if defined(TARGET_PPC64)
4383#define SIGNAL_FRAMESIZE 128
4384#else
4385#define SIGNAL_FRAMESIZE 64
4386#endif
4387
Tom Musta61e75fe2014-06-30 08:13:38 -05004388/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4389 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4390struct target_mcontext {
4391 target_ulong mc_gregs[48];
4392 /* Includes fpscr. */
4393 uint64_t mc_fregs[33];
4394 target_ulong mc_pad[2];
4395 /* We need to handle Altivec and SPE at the same time, which no
4396 kernel needs to do. Fortunately, the kernel defines this bit to
4397 be Altivec-register-large all the time, rather than trying to
4398 twiddle it based on the specific platform. */
4399 union {
4400 /* SPE vector registers. One extra for SPEFSCR. */
4401 uint32_t spe[33];
4402 /* Altivec vector registers. The packing of VSCR and VRSAVE
4403 varies depending on whether we're PPC64 or not: PPC64 splits
4404 them apart; PPC32 stuffs them together. */
4405#if defined(TARGET_PPC64)
4406#define QEMU_NVRREG 34
4407#else
4408#define QEMU_NVRREG 33
4409#endif
4410 ppc_avr_t altivec[QEMU_NVRREG];
4411#undef QEMU_NVRREG
4412 } mc_vregs __attribute__((__aligned__(16)));
4413};
4414
Nathan Froydbcd49332009-05-12 19:13:18 -07004415/* See arch/powerpc/include/asm/sigcontext.h. */
4416struct target_sigcontext {
4417 target_ulong _unused[4];
4418 int32_t signal;
4419#if defined(TARGET_PPC64)
4420 int32_t pad0;
4421#endif
4422 target_ulong handler;
4423 target_ulong oldmask;
4424 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004425#if defined(TARGET_PPC64)
4426 struct target_mcontext mcontext;
4427#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004428};
4429
4430/* Indices for target_mcontext.mc_gregs, below.
4431 See arch/powerpc/include/asm/ptrace.h for details. */
4432enum {
4433 TARGET_PT_R0 = 0,
4434 TARGET_PT_R1 = 1,
4435 TARGET_PT_R2 = 2,
4436 TARGET_PT_R3 = 3,
4437 TARGET_PT_R4 = 4,
4438 TARGET_PT_R5 = 5,
4439 TARGET_PT_R6 = 6,
4440 TARGET_PT_R7 = 7,
4441 TARGET_PT_R8 = 8,
4442 TARGET_PT_R9 = 9,
4443 TARGET_PT_R10 = 10,
4444 TARGET_PT_R11 = 11,
4445 TARGET_PT_R12 = 12,
4446 TARGET_PT_R13 = 13,
4447 TARGET_PT_R14 = 14,
4448 TARGET_PT_R15 = 15,
4449 TARGET_PT_R16 = 16,
4450 TARGET_PT_R17 = 17,
4451 TARGET_PT_R18 = 18,
4452 TARGET_PT_R19 = 19,
4453 TARGET_PT_R20 = 20,
4454 TARGET_PT_R21 = 21,
4455 TARGET_PT_R22 = 22,
4456 TARGET_PT_R23 = 23,
4457 TARGET_PT_R24 = 24,
4458 TARGET_PT_R25 = 25,
4459 TARGET_PT_R26 = 26,
4460 TARGET_PT_R27 = 27,
4461 TARGET_PT_R28 = 28,
4462 TARGET_PT_R29 = 29,
4463 TARGET_PT_R30 = 30,
4464 TARGET_PT_R31 = 31,
4465 TARGET_PT_NIP = 32,
4466 TARGET_PT_MSR = 33,
4467 TARGET_PT_ORIG_R3 = 34,
4468 TARGET_PT_CTR = 35,
4469 TARGET_PT_LNK = 36,
4470 TARGET_PT_XER = 37,
4471 TARGET_PT_CCR = 38,
4472 /* Yes, there are two registers with #39. One is 64-bit only. */
4473 TARGET_PT_MQ = 39,
4474 TARGET_PT_SOFTE = 39,
4475 TARGET_PT_TRAP = 40,
4476 TARGET_PT_DAR = 41,
4477 TARGET_PT_DSISR = 42,
4478 TARGET_PT_RESULT = 43,
4479 TARGET_PT_REGS_COUNT = 44
4480};
4481
Nathan Froydbcd49332009-05-12 19:13:18 -07004482
4483struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004484 target_ulong tuc_flags;
4485 target_ulong tuc_link; /* struct ucontext __user * */
4486 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004487#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004488 int32_t tuc_pad[7];
4489 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004490 points to uc_mcontext field */
4491#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004492 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004493#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004494 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004495 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004496#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004497 int32_t tuc_maskext[30];
4498 int32_t tuc_pad2[3];
4499 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004500#endif
4501};
4502
4503/* See arch/powerpc/kernel/signal_32.c. */
4504struct target_sigframe {
4505 struct target_sigcontext sctx;
4506 struct target_mcontext mctx;
4507 int32_t abigap[56];
4508};
4509
Tom Musta61e75fe2014-06-30 08:13:38 -05004510#if defined(TARGET_PPC64)
4511
4512#define TARGET_TRAMP_SIZE 6
4513
4514struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004515 /* sys_rt_sigreturn requires the ucontext be the first field */
4516 struct target_ucontext uc;
4517 target_ulong _unused[2];
4518 uint32_t trampoline[TARGET_TRAMP_SIZE];
4519 target_ulong pinfo; /* struct siginfo __user * */
4520 target_ulong puc; /* void __user * */
4521 struct target_siginfo info;
4522 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4523 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004524} __attribute__((aligned(16)));
4525
4526#else
4527
Nathan Froydbcd49332009-05-12 19:13:18 -07004528struct target_rt_sigframe {
4529 struct target_siginfo info;
4530 struct target_ucontext uc;
4531 int32_t abigap[56];
4532};
4533
Tom Musta61e75fe2014-06-30 08:13:38 -05004534#endif
4535
Tom Musta8d6ab332014-06-30 08:13:39 -05004536#if defined(TARGET_PPC64)
4537
4538struct target_func_ptr {
4539 target_ulong entry;
4540 target_ulong toc;
4541};
4542
4543#endif
4544
Nathan Froydbcd49332009-05-12 19:13:18 -07004545/* We use the mc_pad field for the signal return trampoline. */
4546#define tramp mc_pad
4547
4548/* See arch/powerpc/kernel/signal.c. */
4549static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004550 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004551 int frame_size)
4552{
4553 target_ulong oldsp, newsp;
4554
4555 oldsp = env->gpr[1];
4556
4557 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004558 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004559 oldsp = (target_sigaltstack_used.ss_sp
4560 + target_sigaltstack_used.ss_size);
4561 }
4562
4563 newsp = (oldsp - frame_size) & ~0xFUL;
4564
4565 return newsp;
4566}
4567
Tom Musta76781082014-06-30 08:13:37 -05004568static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004569{
4570 target_ulong msr = env->msr;
4571 int i;
4572 target_ulong ccr = 0;
4573
4574 /* In general, the kernel attempts to be intelligent about what it
4575 needs to save for Altivec/FP/SPE registers. We don't care that
4576 much, so we just go ahead and save everything. */
4577
4578 /* Save general registers. */
4579 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004580 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004581 }
Riku Voipioc650c002014-04-23 13:53:45 +03004582 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4583 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4584 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4585 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004586
4587 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4588 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4589 }
Riku Voipioc650c002014-04-23 13:53:45 +03004590 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004591
4592 /* Save Altivec registers if necessary. */
4593 if (env->insns_flags & PPC_ALTIVEC) {
4594 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004595 ppc_avr_t *avr = &env->avr[i];
4596 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004597
Riku Voipioc650c002014-04-23 13:53:45 +03004598 __put_user(avr->u64[0], &vreg->u64[0]);
4599 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004600 }
4601 /* Set MSR_VR in the saved MSR value to indicate that
4602 frame->mc_vregs contains valid data. */
4603 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004604 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4605 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004606 }
4607
4608 /* Save floating point registers. */
4609 if (env->insns_flags & PPC_FLOAT) {
4610 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004611 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004612 }
Riku Voipioc650c002014-04-23 13:53:45 +03004613 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004614 }
4615
4616 /* Save SPE registers. The kernel only saves the high half. */
4617 if (env->insns_flags & PPC_SPE) {
4618#if defined(TARGET_PPC64)
4619 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004620 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004621 }
4622#else
4623 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004624 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004625 }
4626#endif
4627 /* Set MSR_SPE in the saved MSR value to indicate that
4628 frame->mc_vregs contains valid data. */
4629 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004630 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004631 }
4632
4633 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004634 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004635}
Nathan Froydbcd49332009-05-12 19:13:18 -07004636
Tom Musta76781082014-06-30 08:13:37 -05004637static void encode_trampoline(int sigret, uint32_t *tramp)
4638{
Nathan Froydbcd49332009-05-12 19:13:18 -07004639 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4640 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004641 __put_user(0x38000000 | sigret, &tramp[0]);
4642 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004643 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004644}
4645
Riku Voipioc650c002014-04-23 13:53:45 +03004646static void restore_user_regs(CPUPPCState *env,
4647 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004648{
4649 target_ulong save_r2 = 0;
4650 target_ulong msr;
4651 target_ulong ccr;
4652
4653 int i;
4654
4655 if (!sig) {
4656 save_r2 = env->gpr[2];
4657 }
4658
4659 /* Restore general registers. */
4660 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004661 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004662 }
Riku Voipioc650c002014-04-23 13:53:45 +03004663 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4664 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4665 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4666 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4667 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004668
4669 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4670 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4671 }
4672
4673 if (!sig) {
4674 env->gpr[2] = save_r2;
4675 }
4676 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004677 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004678
4679 /* If doing signal return, restore the previous little-endian mode. */
4680 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004681 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07004682
4683 /* Restore Altivec registers if necessary. */
4684 if (env->insns_flags & PPC_ALTIVEC) {
4685 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004686 ppc_avr_t *avr = &env->avr[i];
4687 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004688
Riku Voipioc650c002014-04-23 13:53:45 +03004689 __get_user(avr->u64[0], &vreg->u64[0]);
4690 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004691 }
4692 /* Set MSR_VEC in the saved MSR value to indicate that
4693 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004694 __get_user(env->spr[SPR_VRSAVE],
4695 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004696 }
4697
4698 /* Restore floating point registers. */
4699 if (env->insns_flags & PPC_FLOAT) {
4700 uint64_t fpscr;
4701 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004702 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004703 }
Riku Voipioc650c002014-04-23 13:53:45 +03004704 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004705 env->fpscr = (uint32_t) fpscr;
4706 }
4707
4708 /* Save SPE registers. The kernel only saves the high half. */
4709 if (env->insns_flags & PPC_SPE) {
4710#if defined(TARGET_PPC64)
4711 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4712 uint32_t hi;
4713
Riku Voipioc650c002014-04-23 13:53:45 +03004714 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004715 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4716 }
4717#else
4718 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004719 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004720 }
4721#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004722 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004723 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004724}
4725
4726static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004727 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004728{
4729 struct target_sigframe *frame;
4730 struct target_sigcontext *sc;
4731 target_ulong frame_addr, newsp;
4732 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004733#if defined(TARGET_PPC64)
4734 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4735#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004736
4737 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004738 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004739 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4740 goto sigsegv;
4741 sc = &frame->sctx;
4742
Riku Voipio1d8b5122014-04-23 10:26:05 +03004743 __put_user(ka->_sa_handler, &sc->handler);
4744 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004745#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004746 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004747#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004748 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004749#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004750 __put_user(h2g(&frame->mctx), &sc->regs);
4751 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004752
4753 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004754 save_user_regs(env, &frame->mctx);
4755
4756 /* Construct the trampoline code on the stack. */
4757 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004758
4759 /* The kernel checks for the presence of a VDSO here. We don't
4760 emulate a vdso, so use a sigreturn system call. */
4761 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4762
4763 /* Turn off all fp exceptions. */
4764 env->fpscr = 0;
4765
4766 /* Create a stack frame for the caller of the handler. */
4767 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004768 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004769
4770 if (err)
4771 goto sigsegv;
4772
4773 /* Set up registers for signal handler. */
4774 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004775 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004776 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004777
4778#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004779 if (get_ppc64_abi(image) < 2) {
4780 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4781 struct target_func_ptr *handler =
4782 (struct target_func_ptr *)g2h(ka->_sa_handler);
4783 env->nip = tswapl(handler->entry);
4784 env->gpr[2] = tswapl(handler->toc);
4785 } else {
4786 /* ELFv2 PPC64 function pointers are entry points, but R12
4787 * must also be set */
4788 env->nip = tswapl((target_ulong) ka->_sa_handler);
4789 env->gpr[12] = env->nip;
4790 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004791#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004792 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004793#endif
4794
Nathan Froydbcd49332009-05-12 19:13:18 -07004795 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004796 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004797
4798 unlock_user_struct(frame, frame_addr, 1);
4799 return;
4800
4801sigsegv:
4802 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004803 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004804}
4805
4806static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004807 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004808 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004809{
4810 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004811 uint32_t *trampptr = 0;
4812 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004813 target_ulong rt_sf_addr, newsp = 0;
4814 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004815#if defined(TARGET_PPC64)
4816 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4817#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004818
4819 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4820 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4821 goto sigsegv;
4822
Peter Maydellf6c7a052015-01-08 12:19:48 +00004823 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004824
Riku Voipio1d8b5122014-04-23 10:26:05 +03004825 __put_user(0, &rt_sf->uc.tuc_flags);
4826 __put_user(0, &rt_sf->uc.tuc_link);
4827 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4828 &rt_sf->uc.tuc_stack.ss_sp);
4829 __put_user(sas_ss_flags(env->gpr[1]),
4830 &rt_sf->uc.tuc_stack.ss_flags);
4831 __put_user(target_sigaltstack_used.ss_size,
4832 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004833#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004834 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4835 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004836#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004837 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004838 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004839 }
4840
Tom Musta61e75fe2014-06-30 08:13:38 -05004841#if defined(TARGET_PPC64)
4842 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4843 trampptr = &rt_sf->trampoline[0];
4844#else
4845 mctx = &rt_sf->uc.tuc_mcontext;
4846 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4847#endif
4848
4849 save_user_regs(env, mctx);
4850 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004851
4852 /* The kernel checks for the presence of a VDSO here. We don't
4853 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004854 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004855
4856 /* Turn off all fp exceptions. */
4857 env->fpscr = 0;
4858
4859 /* Create a stack frame for the caller of the handler. */
4860 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004861 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004862
4863 if (err)
4864 goto sigsegv;
4865
4866 /* Set up registers for signal handler. */
4867 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004868 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004869 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4870 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4871 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004872
4873#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004874 if (get_ppc64_abi(image) < 2) {
4875 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4876 struct target_func_ptr *handler =
4877 (struct target_func_ptr *)g2h(ka->_sa_handler);
4878 env->nip = tswapl(handler->entry);
4879 env->gpr[2] = tswapl(handler->toc);
4880 } else {
4881 /* ELFv2 PPC64 function pointers are entry points, but R12
4882 * must also be set */
4883 env->nip = tswapl((target_ulong) ka->_sa_handler);
4884 env->gpr[12] = env->nip;
4885 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004886#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004887 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004888#endif
4889
Nathan Froydbcd49332009-05-12 19:13:18 -07004890 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004891 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004892
4893 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4894 return;
4895
4896sigsegv:
4897 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004898 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004899
4900}
4901
Andreas Färber05390242012-02-25 03:37:53 +01004902long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004903{
4904 struct target_sigcontext *sc = NULL;
4905 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004906 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004907 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004908 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004909
4910 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4911 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4912 goto sigsegv;
4913
4914#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004915 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004916#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004917 __get_user(set.sig[0], &sc->oldmask);
4918 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004919#endif
4920 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004921 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07004922
Riku Voipiof5f601a2014-04-23 13:00:17 +03004923 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004924 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4925 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004926 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004927
4928 unlock_user_struct(sr, sr_addr, 1);
4929 unlock_user_struct(sc, sc_addr, 1);
4930 return -TARGET_QEMU_ESIGRETURN;
4931
4932sigsegv:
4933 unlock_user_struct(sr, sr_addr, 1);
4934 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004935 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004936 return 0;
4937}
4938
4939/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004940static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004941{
4942 struct target_mcontext *mcp;
4943 target_ulong mcp_addr;
4944 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004945 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004946
Aurelien Jarno60e99242010-03-29 02:12:51 +02004947 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004948 sizeof (set)))
4949 return 1;
4950
Tom Musta19774ec2014-06-30 08:13:40 -05004951#if defined(TARGET_PPC64)
4952 mcp_addr = h2g(ucp) +
4953 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4954#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004955 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004956#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004957
4958 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4959 return 1;
4960
4961 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004962 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03004963 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004964
4965 unlock_user_struct(mcp, mcp_addr, 1);
4966 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004967}
4968
Andreas Färber05390242012-02-25 03:37:53 +01004969long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004970{
4971 struct target_rt_sigframe *rt_sf = NULL;
4972 target_ulong rt_sf_addr;
4973
4974 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4975 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4976 goto sigsegv;
4977
4978 if (do_setcontext(&rt_sf->uc, env, 1))
4979 goto sigsegv;
4980
4981 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004982 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004983 0, env->gpr[1]);
4984
4985 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4986 return -TARGET_QEMU_ESIGRETURN;
4987
4988sigsegv:
4989 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004990 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004991 return 0;
4992}
4993
Laurent Vivier492a8742009-08-03 16:12:17 +02004994#elif defined(TARGET_M68K)
4995
4996struct target_sigcontext {
4997 abi_ulong sc_mask;
4998 abi_ulong sc_usp;
4999 abi_ulong sc_d0;
5000 abi_ulong sc_d1;
5001 abi_ulong sc_a0;
5002 abi_ulong sc_a1;
5003 unsigned short sc_sr;
5004 abi_ulong sc_pc;
5005};
5006
5007struct target_sigframe
5008{
5009 abi_ulong pretcode;
5010 int sig;
5011 int code;
5012 abi_ulong psc;
5013 char retcode[8];
5014 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5015 struct target_sigcontext sc;
5016};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005017
Anthony Liguoric227f092009-10-01 16:12:16 -05005018typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005019#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005020typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005021
5022typedef struct target_fpregset {
5023 int f_fpcntl[3];
5024 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005025} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005026
5027struct target_mcontext {
5028 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005029 target_gregset_t gregs;
5030 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005031};
5032
5033#define TARGET_MCONTEXT_VERSION 2
5034
5035struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005036 abi_ulong tuc_flags;
5037 abi_ulong tuc_link;
5038 target_stack_t tuc_stack;
5039 struct target_mcontext tuc_mcontext;
5040 abi_long tuc_filler[80];
5041 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005042};
5043
5044struct target_rt_sigframe
5045{
5046 abi_ulong pretcode;
5047 int sig;
5048 abi_ulong pinfo;
5049 abi_ulong puc;
5050 char retcode[8];
5051 struct target_siginfo info;
5052 struct target_ucontext uc;
5053};
Laurent Vivier492a8742009-08-03 16:12:17 +02005054
Riku Voipio41ecc722014-04-23 11:01:00 +03005055static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005056 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005057{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005058 __put_user(mask, &sc->sc_mask);
5059 __put_user(env->aregs[7], &sc->sc_usp);
5060 __put_user(env->dregs[0], &sc->sc_d0);
5061 __put_user(env->dregs[1], &sc->sc_d1);
5062 __put_user(env->aregs[0], &sc->sc_a0);
5063 __put_user(env->aregs[1], &sc->sc_a1);
5064 __put_user(env->sr, &sc->sc_sr);
5065 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005066}
5067
Riku Voipio016d2e12014-04-23 11:19:48 +03005068static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005069restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005070{
Laurent Vivier492a8742009-08-03 16:12:17 +02005071 int temp;
5072
Riku Voipio1d8b5122014-04-23 10:26:05 +03005073 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005074 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005075 __get_user(env->dregs[1], &sc->sc_d1);
5076 __get_user(env->aregs[0], &sc->sc_a0);
5077 __get_user(env->aregs[1], &sc->sc_a1);
5078 __get_user(env->pc, &sc->sc_pc);
5079 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005080 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005081}
5082
5083/*
5084 * Determine which stack to use..
5085 */
5086static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005087get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5088 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005089{
5090 unsigned long sp;
5091
5092 sp = regs->aregs[7];
5093
5094 /* This is the X/Open sanctioned signal stack switching. */
5095 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5096 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5097 }
5098
5099 return ((sp - frame_size) & -8UL);
5100}
5101
5102static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005103 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005104{
5105 struct target_sigframe *frame;
5106 abi_ulong frame_addr;
5107 abi_ulong retcode_addr;
5108 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005109 int i;
5110
5111 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005112 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005113 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5114 goto give_sigsegv;
5115 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005116
Riku Voipio1d8b5122014-04-23 10:26:05 +03005117 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005118
5119 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005120 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005121
Riku Voipio41ecc722014-04-23 11:01:00 +03005122 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005123
5124 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005125 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005126 }
5127
5128 /* Set up to return from userspace. */
5129
5130 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005131 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005132
5133 /* moveq #,d0; trap #0 */
5134
Riku Voipio1d8b5122014-04-23 10:26:05 +03005135 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005136 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005137
Laurent Vivier492a8742009-08-03 16:12:17 +02005138 /* Set up to return from userspace */
5139
5140 env->aregs[7] = frame_addr;
5141 env->pc = ka->_sa_handler;
5142
5143 unlock_user_struct(frame, frame_addr, 1);
5144 return;
5145
5146give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005147 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005148}
5149
Laurent Vivier71811552009-08-03 16:12:18 +02005150static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005151 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005152{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005153 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005154
Riku Voipio1d8b5122014-04-23 10:26:05 +03005155 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5156 __put_user(env->dregs[0], &gregs[0]);
5157 __put_user(env->dregs[1], &gregs[1]);
5158 __put_user(env->dregs[2], &gregs[2]);
5159 __put_user(env->dregs[3], &gregs[3]);
5160 __put_user(env->dregs[4], &gregs[4]);
5161 __put_user(env->dregs[5], &gregs[5]);
5162 __put_user(env->dregs[6], &gregs[6]);
5163 __put_user(env->dregs[7], &gregs[7]);
5164 __put_user(env->aregs[0], &gregs[8]);
5165 __put_user(env->aregs[1], &gregs[9]);
5166 __put_user(env->aregs[2], &gregs[10]);
5167 __put_user(env->aregs[3], &gregs[11]);
5168 __put_user(env->aregs[4], &gregs[12]);
5169 __put_user(env->aregs[5], &gregs[13]);
5170 __put_user(env->aregs[6], &gregs[14]);
5171 __put_user(env->aregs[7], &gregs[15]);
5172 __put_user(env->pc, &gregs[16]);
5173 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005174
Riku Voipio1d8b5122014-04-23 10:26:05 +03005175 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005176}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005177
Andreas Färber05390242012-02-25 03:37:53 +01005178static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005179 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005180{
5181 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005182 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005183
Riku Voipio1d8b5122014-04-23 10:26:05 +03005184 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005185 if (temp != TARGET_MCONTEXT_VERSION)
5186 goto badframe;
5187
5188 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005189 __get_user(env->dregs[0], &gregs[0]);
5190 __get_user(env->dregs[1], &gregs[1]);
5191 __get_user(env->dregs[2], &gregs[2]);
5192 __get_user(env->dregs[3], &gregs[3]);
5193 __get_user(env->dregs[4], &gregs[4]);
5194 __get_user(env->dregs[5], &gregs[5]);
5195 __get_user(env->dregs[6], &gregs[6]);
5196 __get_user(env->dregs[7], &gregs[7]);
5197 __get_user(env->aregs[0], &gregs[8]);
5198 __get_user(env->aregs[1], &gregs[9]);
5199 __get_user(env->aregs[2], &gregs[10]);
5200 __get_user(env->aregs[3], &gregs[11]);
5201 __get_user(env->aregs[4], &gregs[12]);
5202 __get_user(env->aregs[5], &gregs[13]);
5203 __get_user(env->aregs[6], &gregs[14]);
5204 __get_user(env->aregs[7], &gregs[15]);
5205 __get_user(env->pc, &gregs[16]);
5206 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005207 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5208
Riku Voipio1d8b5122014-04-23 10:26:05 +03005209 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005210
5211badframe:
5212 return 1;
5213}
5214
Laurent Vivier492a8742009-08-03 16:12:17 +02005215static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005216 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005217 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005218{
Laurent Vivier71811552009-08-03 16:12:18 +02005219 struct target_rt_sigframe *frame;
5220 abi_ulong frame_addr;
5221 abi_ulong retcode_addr;
5222 abi_ulong info_addr;
5223 abi_ulong uc_addr;
5224 int err = 0;
5225 int i;
5226
5227 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005228 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005229 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5230 goto give_sigsegv;
5231 }
Laurent Vivier71811552009-08-03 16:12:18 +02005232
Riku Voipio1d8b5122014-04-23 10:26:05 +03005233 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005234
5235 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005236 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005237
5238 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005239 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005240
Peter Maydellf6c7a052015-01-08 12:19:48 +00005241 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005242
5243 /* Create the ucontext */
5244
Riku Voipio1d8b5122014-04-23 10:26:05 +03005245 __put_user(0, &frame->uc.tuc_flags);
5246 __put_user(0, &frame->uc.tuc_link);
5247 __put_user(target_sigaltstack_used.ss_sp,
5248 &frame->uc.tuc_stack.ss_sp);
5249 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005250 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005251 __put_user(target_sigaltstack_used.ss_size,
5252 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005253 err |= target_rt_setup_ucontext(&frame->uc, env);
5254
5255 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005256 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005257
5258 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005259 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005260 }
5261
5262 /* Set up to return from userspace. */
5263
5264 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005265 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005266
5267 /* moveq #,d0; notb d0; trap #0 */
5268
Riku Voipio1d8b5122014-04-23 10:26:05 +03005269 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005270 (uint32_t *)(frame->retcode + 0));
5271 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005272
5273 if (err)
5274 goto give_sigsegv;
5275
5276 /* Set up to return from userspace */
5277
5278 env->aregs[7] = frame_addr;
5279 env->pc = ka->_sa_handler;
5280
5281 unlock_user_struct(frame, frame_addr, 1);
5282 return;
5283
5284give_sigsegv:
5285 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005286 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005287}
5288
Andreas Färber05390242012-02-25 03:37:53 +01005289long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005290{
5291 struct target_sigframe *frame;
5292 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005293 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005294 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005295 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005296
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005297 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005298 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5299 goto badframe;
5300
5301 /* set blocked signals */
5302
Riku Voipiof5f601a2014-04-23 13:00:17 +03005303 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005304
5305 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005306 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005307 }
5308
5309 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005310 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005311
5312 /* restore registers */
5313
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005314 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005315
5316 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005317 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005318
5319badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005320 force_sig(TARGET_SIGSEGV);
5321 return 0;
5322}
5323
Andreas Färber05390242012-02-25 03:37:53 +01005324long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005325{
Laurent Vivier71811552009-08-03 16:12:18 +02005326 struct target_rt_sigframe *frame;
5327 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005328 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005329 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005330
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005331 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005332 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5333 goto badframe;
5334
5335 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005336 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005337
5338 /* restore registers */
5339
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005340 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005341 goto badframe;
5342
5343 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005344 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005345 0, get_sp_from_cpustate(env)) == -EFAULT)
5346 goto badframe;
5347
5348 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005349 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005350
5351badframe:
5352 unlock_user_struct(frame, frame_addr, 0);
5353 force_sig(TARGET_SIGSEGV);
5354 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005355}
5356
Richard Henderson6049f4f2009-12-27 18:30:03 -08005357#elif defined(TARGET_ALPHA)
5358
5359struct target_sigcontext {
5360 abi_long sc_onstack;
5361 abi_long sc_mask;
5362 abi_long sc_pc;
5363 abi_long sc_ps;
5364 abi_long sc_regs[32];
5365 abi_long sc_ownedfp;
5366 abi_long sc_fpregs[32];
5367 abi_ulong sc_fpcr;
5368 abi_ulong sc_fp_control;
5369 abi_ulong sc_reserved1;
5370 abi_ulong sc_reserved2;
5371 abi_ulong sc_ssize;
5372 abi_ulong sc_sbase;
5373 abi_ulong sc_traparg_a0;
5374 abi_ulong sc_traparg_a1;
5375 abi_ulong sc_traparg_a2;
5376 abi_ulong sc_fp_trap_pc;
5377 abi_ulong sc_fp_trigger_sum;
5378 abi_ulong sc_fp_trigger_inst;
5379};
5380
5381struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005382 abi_ulong tuc_flags;
5383 abi_ulong tuc_link;
5384 abi_ulong tuc_osf_sigmask;
5385 target_stack_t tuc_stack;
5386 struct target_sigcontext tuc_mcontext;
5387 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005388};
5389
5390struct target_sigframe {
5391 struct target_sigcontext sc;
5392 unsigned int retcode[3];
5393};
5394
5395struct target_rt_sigframe {
5396 target_siginfo_t info;
5397 struct target_ucontext uc;
5398 unsigned int retcode[3];
5399};
5400
5401#define INSN_MOV_R30_R16 0x47fe0410
5402#define INSN_LDI_R0 0x201f0000
5403#define INSN_CALLSYS 0x00000083
5404
Riku Voipio41ecc722014-04-23 11:01:00 +03005405static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005406 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005407{
Riku Voipio41ecc722014-04-23 11:01:00 +03005408 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005409
Riku Voipio1d8b5122014-04-23 10:26:05 +03005410 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5411 __put_user(set->sig[0], &sc->sc_mask);
5412 __put_user(env->pc, &sc->sc_pc);
5413 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005414
5415 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005416 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005417 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005418 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005419
5420 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005421 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005422 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005423 __put_user(0, &sc->sc_fpregs[31]);
5424 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005425
Riku Voipio1d8b5122014-04-23 10:26:05 +03005426 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5427 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5428 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005429}
5430
Riku Voipio016d2e12014-04-23 11:19:48 +03005431static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005432 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005433{
5434 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005435 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005436
Riku Voipio1d8b5122014-04-23 10:26:05 +03005437 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005438
5439 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005440 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005441 }
5442 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005443 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005444 }
5445
Riku Voipio1d8b5122014-04-23 10:26:05 +03005446 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005447 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005448}
5449
5450static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005451 CPUAlphaState *env,
5452 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005453{
5454 abi_ulong sp = env->ir[IR_SP];
5455
5456 /* This is the X/Open sanctioned signal stack switching. */
5457 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5458 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5459 }
5460 return (sp - framesize) & -32;
5461}
5462
5463static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005464 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005465{
5466 abi_ulong frame_addr, r26;
5467 struct target_sigframe *frame;
5468 int err = 0;
5469
5470 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005471 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005472 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5473 goto give_sigsegv;
5474 }
5475
Riku Voipio41ecc722014-04-23 11:01:00 +03005476 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005477
5478 if (ka->sa_restorer) {
5479 r26 = ka->sa_restorer;
5480 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005481 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5482 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5483 &frame->retcode[1]);
5484 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005485 /* imb() */
5486 r26 = frame_addr;
5487 }
5488
5489 unlock_user_struct(frame, frame_addr, 1);
5490
5491 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005492give_sigsegv:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005493 if (sig == TARGET_SIGSEGV) {
5494 ka->_sa_handler = TARGET_SIG_DFL;
5495 }
5496 force_sig(TARGET_SIGSEGV);
5497 }
5498
5499 env->ir[IR_RA] = r26;
5500 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5501 env->ir[IR_A0] = sig;
5502 env->ir[IR_A1] = 0;
5503 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5504 env->ir[IR_SP] = frame_addr;
5505}
5506
5507static void setup_rt_frame(int sig, struct target_sigaction *ka,
5508 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005509 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005510{
5511 abi_ulong frame_addr, r26;
5512 struct target_rt_sigframe *frame;
5513 int i, err = 0;
5514
5515 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005516 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005517 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5518 goto give_sigsegv;
5519 }
5520
Peter Maydellf6c7a052015-01-08 12:19:48 +00005521 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005522
Riku Voipio1d8b5122014-04-23 10:26:05 +03005523 __put_user(0, &frame->uc.tuc_flags);
5524 __put_user(0, &frame->uc.tuc_link);
5525 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5526 __put_user(target_sigaltstack_used.ss_sp,
5527 &frame->uc.tuc_stack.ss_sp);
5528 __put_user(sas_ss_flags(env->ir[IR_SP]),
5529 &frame->uc.tuc_stack.ss_flags);
5530 __put_user(target_sigaltstack_used.ss_size,
5531 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005532 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005533 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005534 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005535 }
5536
5537 if (ka->sa_restorer) {
5538 r26 = ka->sa_restorer;
5539 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005540 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5541 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5542 &frame->retcode[1]);
5543 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005544 /* imb(); */
5545 r26 = frame_addr;
5546 }
5547
5548 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005549give_sigsegv:
5550 if (sig == TARGET_SIGSEGV) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005551 ka->_sa_handler = TARGET_SIG_DFL;
5552 }
5553 force_sig(TARGET_SIGSEGV);
5554 }
5555
5556 env->ir[IR_RA] = r26;
5557 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5558 env->ir[IR_A0] = sig;
5559 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5560 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5561 env->ir[IR_SP] = frame_addr;
5562}
5563
Andreas Färber05390242012-02-25 03:37:53 +01005564long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005565{
5566 struct target_sigcontext *sc;
5567 abi_ulong sc_addr = env->ir[IR_A0];
5568 target_sigset_t target_set;
5569 sigset_t set;
5570
5571 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5572 goto badframe;
5573 }
5574
5575 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005576 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005577
5578 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005579 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005580
Riku Voipio016d2e12014-04-23 11:19:48 +03005581 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005582 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005583 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005584
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005585badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005586 force_sig(TARGET_SIGSEGV);
5587}
5588
Andreas Färber05390242012-02-25 03:37:53 +01005589long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005590{
5591 abi_ulong frame_addr = env->ir[IR_A0];
5592 struct target_rt_sigframe *frame;
5593 sigset_t set;
5594
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005595 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005596 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5597 goto badframe;
5598 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005599 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005600 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005601
Riku Voipio016d2e12014-04-23 11:19:48 +03005602 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005603 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005604 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005605 0, env->ir[IR_SP]) == -EFAULT) {
5606 goto badframe;
5607 }
5608
5609 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005610 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005611
5612
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005613badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005614 unlock_user_struct(frame, frame_addr, 0);
5615 force_sig(TARGET_SIGSEGV);
5616}
5617
Chen Gangbf0f60a2015-09-27 08:10:18 +08005618#elif defined(TARGET_TILEGX)
5619
5620struct target_sigcontext {
5621 union {
5622 /* General-purpose registers. */
5623 abi_ulong gregs[56];
5624 struct {
5625 abi_ulong __gregs[53];
5626 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5627 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5628 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5629 };
5630 };
5631 abi_ulong pc; /* Program counter. */
5632 abi_ulong ics; /* In Interrupt Critical Section? */
5633 abi_ulong faultnum; /* Fault number. */
5634 abi_ulong pad[5];
5635};
5636
5637struct target_ucontext {
5638 abi_ulong tuc_flags;
5639 abi_ulong tuc_link;
5640 target_stack_t tuc_stack;
5641 struct target_sigcontext tuc_mcontext;
5642 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5643};
5644
5645struct target_rt_sigframe {
5646 unsigned char save_area[16]; /* caller save area */
5647 struct target_siginfo info;
5648 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08005649 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08005650};
5651
Chen Gangf1d9d102016-03-29 21:53:49 +08005652#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5653#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5654
5655
Chen Gangbf0f60a2015-09-27 08:10:18 +08005656static void setup_sigcontext(struct target_sigcontext *sc,
5657 CPUArchState *env, int signo)
5658{
5659 int i;
5660
5661 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5662 __put_user(env->regs[i], &sc->gregs[i]);
5663 }
5664
5665 __put_user(env->pc, &sc->pc);
5666 __put_user(0, &sc->ics);
5667 __put_user(signo, &sc->faultnum);
5668}
5669
5670static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5671{
5672 int i;
5673
5674 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5675 __get_user(env->regs[i], &sc->gregs[i]);
5676 }
5677
5678 __get_user(env->pc, &sc->pc);
5679}
5680
5681static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5682 size_t frame_size)
5683{
5684 unsigned long sp = env->regs[TILEGX_R_SP];
5685
5686 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5687 return -1UL;
5688 }
5689
5690 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5691 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5692 }
5693
5694 sp -= frame_size;
5695 sp &= -16UL;
5696 return sp;
5697}
5698
5699static void setup_rt_frame(int sig, struct target_sigaction *ka,
5700 target_siginfo_t *info,
5701 target_sigset_t *set, CPUArchState *env)
5702{
5703 abi_ulong frame_addr;
5704 struct target_rt_sigframe *frame;
5705 unsigned long restorer;
5706
5707 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005708 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005709 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5710 goto give_sigsegv;
5711 }
5712
5713 /* Always write at least the signal number for the stack backtracer. */
5714 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5715 /* At sigreturn time, restore the callee-save registers too. */
5716 tswap_siginfo(&frame->info, info);
5717 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5718 } else {
5719 __put_user(info->si_signo, &frame->info.si_signo);
5720 }
5721
5722 /* Create the ucontext. */
5723 __put_user(0, &frame->uc.tuc_flags);
5724 __put_user(0, &frame->uc.tuc_link);
5725 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5726 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5727 &frame->uc.tuc_stack.ss_flags);
5728 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5729 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5730
Chen Gangbf0f60a2015-09-27 08:10:18 +08005731 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08005732 restorer = (unsigned long) ka->sa_restorer;
5733 } else {
5734 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5735 __put_user(INSN_SWINT1, &frame->retcode[1]);
5736 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005737 }
5738 env->pc = (unsigned long) ka->_sa_handler;
5739 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5740 env->regs[TILEGX_R_LR] = restorer;
5741 env->regs[0] = (unsigned long) sig;
5742 env->regs[1] = (unsigned long) &frame->info;
5743 env->regs[2] = (unsigned long) &frame->uc;
5744 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5745
5746 unlock_user_struct(frame, frame_addr, 1);
5747 return;
5748
5749give_sigsegv:
5750 if (sig == TARGET_SIGSEGV) {
5751 ka->_sa_handler = TARGET_SIG_DFL;
5752 }
5753 force_sig(TARGET_SIGSEGV /* , current */);
5754}
5755
5756long do_rt_sigreturn(CPUTLGState *env)
5757{
5758 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5759 struct target_rt_sigframe *frame;
5760 sigset_t set;
5761
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005762 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005763 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5764 goto badframe;
5765 }
5766 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005767 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005768
5769 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5770 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5771 uc.tuc_stack),
5772 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5773 goto badframe;
5774 }
5775
5776 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005777 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005778
5779
5780 badframe:
5781 unlock_user_struct(frame, frame_addr, 0);
5782 force_sig(TARGET_SIGSEGV);
5783}
5784
bellardb346ff42003-06-15 20:05:50 +00005785#else
5786
pbrook624f7972008-05-31 16:11:38 +00005787static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005788 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005789{
5790 fprintf(stderr, "setup_frame: not implemented\n");
5791}
5792
pbrook624f7972008-05-31 16:11:38 +00005793static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005794 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005795 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005796{
5797 fprintf(stderr, "setup_rt_frame: not implemented\n");
5798}
5799
Andreas Färber9349b4f2012-03-14 01:38:32 +01005800long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005801{
5802 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005803 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005804}
5805
Andreas Färber9349b4f2012-03-14 01:38:32 +01005806long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005807{
5808 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005809 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005810}
5811
bellard66fb9762003-03-23 01:06:05 +00005812#endif
5813
Peter Maydelleb552502016-05-27 15:51:43 +01005814static void handle_pending_signal(CPUArchState *cpu_env, int sig)
5815{
5816 CPUState *cpu = ENV_GET_CPU(cpu_env);
5817 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005818 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01005819 target_sigset_t target_old_set;
5820 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01005821 TaskState *ts = cpu->opaque;
5822 struct emulated_sigtable *k = &ts->sigtab[sig - 1];
5823
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005824 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005825 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005826 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005827
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005828 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005829 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005830 sa = NULL;
5831 handler = TARGET_SIG_IGN;
5832 } else {
5833 sa = &sigact_table[sig - 1];
5834 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005835 }
bellard66fb9762003-03-23 01:06:05 +00005836
bellard66fb9762003-03-23 01:06:05 +00005837 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005838 /* default handler : ignore some signal. The other are job control or fatal */
5839 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5840 kill(getpid(),SIGSTOP);
5841 } else if (sig != TARGET_SIGCHLD &&
5842 sig != TARGET_SIGURG &&
5843 sig != TARGET_SIGWINCH &&
5844 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005845 force_sig(sig);
5846 }
5847 } else if (handler == TARGET_SIG_IGN) {
5848 /* ignore sig */
5849 } else if (handler == TARGET_SIG_ERR) {
5850 force_sig(sig);
5851 } else {
bellard9de5e442003-03-23 16:49:39 +00005852 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005853 sigset_t *blocked_set;
5854
pbrook624f7972008-05-31 16:11:38 +00005855 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005856 /* SA_NODEFER indicates that the current signal should not be
5857 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005858 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005859 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005860
bellard9de5e442003-03-23 16:49:39 +00005861 /* save the previous blocked signal state to restore it at the
5862 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005863 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
5864
5865 /* block signals in the handler */
5866 blocked_set = ts->in_sigsuspend ?
5867 &ts->sigsuspend_mask : &ts->signal_mask;
5868 sigorset(&ts->signal_mask, blocked_set, &set);
5869 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00005870
bellardbc8a22c2003-03-30 21:02:40 +00005871 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005872#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005873 {
5874 CPUX86State *env = cpu_env;
5875 if (env->eflags & VM_MASK)
5876 save_v86_state(env);
5877 }
5878#endif
bellard9de5e442003-03-23 16:49:39 +00005879 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005880#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005881 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005882 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005883 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005884#else
pbrook624f7972008-05-31 16:11:38 +00005885 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005886 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005887 else
pbrook624f7972008-05-31 16:11:38 +00005888 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005889#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01005890 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00005891 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01005892 }
bellard31e31b82003-02-18 22:55:36 +00005893 }
bellard31e31b82003-02-18 22:55:36 +00005894}
Peter Maydelle902d582016-05-27 15:51:44 +01005895
5896void process_pending_signals(CPUArchState *cpu_env)
5897{
5898 CPUState *cpu = ENV_GET_CPU(cpu_env);
5899 int sig;
5900 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005901 sigset_t set;
5902 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01005903
Peter Maydell3d3efba2016-05-27 15:51:49 +01005904 while (atomic_read(&ts->signal_pending)) {
5905 /* FIXME: This is not threadsafe. */
5906 sigfillset(&set);
5907 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01005908
Timothy E Baldwin655ed672016-05-27 15:51:53 +01005909 sig = ts->sync_signal.pending;
5910 if (sig) {
5911 /* Synchronous signals are forced,
5912 * see force_sig_info() and callers in Linux
5913 * Note that not all of our queue_signal() calls in QEMU correspond
5914 * to force_sig_info() calls in Linux (some are send_sig_info()).
5915 * However it seems like a kernel bug to me to allow the process
5916 * to block a synchronous signal since it could then just end up
5917 * looping round and round indefinitely.
5918 */
5919 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
5920 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
5921 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
5922 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
5923 }
5924
5925 handle_pending_signal(cpu_env, sig);
5926 }
5927
Peter Maydell3d3efba2016-05-27 15:51:49 +01005928 for (sig = 1; sig <= TARGET_NSIG; sig++) {
5929 blocked_set = ts->in_sigsuspend ?
5930 &ts->sigsuspend_mask : &ts->signal_mask;
5931
5932 if (ts->sigtab[sig - 1].pending &&
5933 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01005934 target_to_host_signal_table[sig]))) {
Peter Maydell3d3efba2016-05-27 15:51:49 +01005935 handle_pending_signal(cpu_env, sig);
5936 /* Restart scan from the beginning */
5937 sig = 1;
5938 }
Peter Maydelle902d582016-05-27 15:51:44 +01005939 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01005940
5941 /* if no signal is pending, unblock signals and recheck (the act
5942 * of unblocking might cause us to take another host signal which
5943 * will set signal_pending again).
5944 */
5945 atomic_set(&ts->signal_pending, 0);
5946 ts->in_sigsuspend = 0;
5947 set = ts->signal_mask;
5948 sigdelset(&set, SIGSEGV);
5949 sigdelset(&set, SIGBUS);
5950 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01005951 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01005952 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01005953}