blob: 900ee3515a5719fa8935f45b39ee369ce6e18287 [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;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydell9eede5b2016-05-27 15:51:46 +0100256#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
257 !defined(TARGET_X86_64)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100258/* Just set the guest's signal mask to the specified value; the
259 * caller is assumed to have called block_signals() already.
260 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100261static void set_sigmask(const sigset_t *set)
262{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100263 TaskState *ts = (TaskState *)thread_cpu->opaque;
264
265 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100266}
267#endif
268
bellard9de5e442003-03-23 16:49:39 +0000269/* siginfo conversion */
270
Anthony Liguoric227f092009-10-01 16:12:16 -0500271static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000272 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000273{
Richard Hendersona05c6402012-09-15 11:34:20 -0700274 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100275 int si_code = info->si_code;
276 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000279 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700280
Peter Maydell55d72a72016-06-13 11:22:05 +0100281 /* This memset serves two purposes:
282 * (1) ensure we don't leak random junk to the guest later
283 * (2) placate false positives from gcc about fields
284 * being used uninitialized if it chooses to inline both this
285 * function and tswap_siginfo() into host_to_target_siginfo().
286 */
287 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
288
Peter Maydella70dadc2016-05-27 15:51:59 +0100289 /* This is awkward, because we have to use a combination of
290 * the si_code and si_signo to figure out which of the union's
291 * members are valid. (Within the host kernel it is always possible
292 * to tell, but the kernel carefully avoids giving userspace the
293 * high 16 bits of si_code, so we don't have the information to
294 * do this the easy way...) We therefore make our best guess,
295 * bearing in mind that a guest can spoof most of the si_codes
296 * via rt_sigqueueinfo() if it likes.
297 *
298 * Once we have made our guess, we record it in the top 16 bits of
299 * the si_code, so that tswap_siginfo() later can use it.
300 * tswap_siginfo() will strip these top bits out before writing
301 * si_code to the guest (sign-extending the lower bits).
302 */
303
304 switch (si_code) {
305 case SI_USER:
306 case SI_TKILL:
307 case SI_KERNEL:
308 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
309 * These are the only unspoofable si_code values.
310 */
311 tinfo->_sifields._kill._pid = info->si_pid;
312 tinfo->_sifields._kill._uid = info->si_uid;
313 si_type = QEMU_SI_KILL;
314 break;
315 default:
316 /* Everything else is spoofable. Make best guess based on signal */
317 switch (sig) {
318 case TARGET_SIGCHLD:
319 tinfo->_sifields._sigchld._pid = info->si_pid;
320 tinfo->_sifields._sigchld._uid = info->si_uid;
321 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100322 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100323 tinfo->_sifields._sigchld._utime = info->si_utime;
324 tinfo->_sifields._sigchld._stime = info->si_stime;
325 si_type = QEMU_SI_CHLD;
326 break;
327 case TARGET_SIGIO:
328 tinfo->_sifields._sigpoll._band = info->si_band;
329 tinfo->_sifields._sigpoll._fd = info->si_fd;
330 si_type = QEMU_SI_POLL;
331 break;
332 default:
333 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
334 tinfo->_sifields._rt._pid = info->si_pid;
335 tinfo->_sifields._rt._uid = info->si_uid;
336 /* XXX: potential problem if 64 bit */
337 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100338 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100339 si_type = QEMU_SI_RT;
340 break;
341 }
342 break;
bellard9de5e442003-03-23 16:49:39 +0000343 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100344
345 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000346}
347
Anthony Liguoric227f092009-10-01 16:12:16 -0500348static void tswap_siginfo(target_siginfo_t *tinfo,
349 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000350{
Peter Maydella70dadc2016-05-27 15:51:59 +0100351 int si_type = extract32(info->si_code, 16, 16);
352 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700353
Peter Maydella70dadc2016-05-27 15:51:59 +0100354 __put_user(info->si_signo, &tinfo->si_signo);
355 __put_user(info->si_errno, &tinfo->si_errno);
356 __put_user(si_code, &tinfo->si_code);
357
358 /* We can use our internal marker of which fields in the structure
359 * are valid, rather than duplicating the guesswork of
360 * host_to_target_siginfo_noswap() here.
361 */
362 switch (si_type) {
363 case QEMU_SI_KILL:
364 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
365 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
366 break;
367 case QEMU_SI_TIMER:
368 __put_user(info->_sifields._timer._timer1,
369 &tinfo->_sifields._timer._timer1);
370 __put_user(info->_sifields._timer._timer2,
371 &tinfo->_sifields._timer._timer2);
372 break;
373 case QEMU_SI_POLL:
374 __put_user(info->_sifields._sigpoll._band,
375 &tinfo->_sifields._sigpoll._band);
376 __put_user(info->_sifields._sigpoll._fd,
377 &tinfo->_sifields._sigpoll._fd);
378 break;
379 case QEMU_SI_FAULT:
380 __put_user(info->_sifields._sigfault._addr,
381 &tinfo->_sifields._sigfault._addr);
382 break;
383 case QEMU_SI_CHLD:
384 __put_user(info->_sifields._sigchld._pid,
385 &tinfo->_sifields._sigchld._pid);
386 __put_user(info->_sifields._sigchld._uid,
387 &tinfo->_sifields._sigchld._uid);
388 __put_user(info->_sifields._sigchld._status,
389 &tinfo->_sifields._sigchld._status);
390 __put_user(info->_sifields._sigchld._utime,
391 &tinfo->_sifields._sigchld._utime);
392 __put_user(info->_sifields._sigchld._stime,
393 &tinfo->_sifields._sigchld._stime);
394 break;
395 case QEMU_SI_RT:
396 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
397 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
398 __put_user(info->_sifields._rt._sigval.sival_ptr,
399 &tinfo->_sifields._rt._sigval.sival_ptr);
400 break;
401 default:
402 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000403 }
404}
405
Anthony Liguoric227f092009-10-01 16:12:16 -0500406void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000407{
Peter Maydell55d72a72016-06-13 11:22:05 +0100408 target_siginfo_t tgt_tmp;
409 host_to_target_siginfo_noswap(&tgt_tmp, info);
410 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000411}
412
413/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000414/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500415void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000416{
Peter Maydell90c0f082016-05-27 15:52:01 +0100417 /* This conversion is used only for the rt_sigqueueinfo syscall,
418 * and so we know that the _rt fields are the valid ones.
419 */
420 abi_ulong sival_ptr;
421
422 __get_user(info->si_signo, &tinfo->si_signo);
423 __get_user(info->si_errno, &tinfo->si_errno);
424 __get_user(info->si_code, &tinfo->si_code);
425 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
426 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
427 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
428 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000429}
430
aurel32ca587a82008-12-18 22:44:13 +0000431static int fatal_signal (int sig)
432{
433 switch (sig) {
434 case TARGET_SIGCHLD:
435 case TARGET_SIGURG:
436 case TARGET_SIGWINCH:
437 /* Ignored by default. */
438 return 0;
439 case TARGET_SIGCONT:
440 case TARGET_SIGSTOP:
441 case TARGET_SIGTSTP:
442 case TARGET_SIGTTIN:
443 case TARGET_SIGTTOU:
444 /* Job control signals. */
445 return 0;
446 default:
447 return 1;
448 }
449}
450
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451/* returns 1 if given signal should dump core if not handled */
452static int core_dump_signal(int sig)
453{
454 switch (sig) {
455 case TARGET_SIGABRT:
456 case TARGET_SIGFPE:
457 case TARGET_SIGILL:
458 case TARGET_SIGQUIT:
459 case TARGET_SIGSEGV:
460 case TARGET_SIGTRAP:
461 case TARGET_SIGBUS:
462 return (1);
463 default:
464 return (0);
465 }
466}
467
bellard31e31b82003-02-18 22:55:36 +0000468void signal_init(void)
469{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100470 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000471 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000472 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000473 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000474 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000475
bellard9e5f5282003-07-13 17:33:54 +0000476 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200477 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000478 if (host_to_target_signal_table[i] == 0)
479 host_to_target_signal_table[i] = i;
480 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200481 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000482 j = host_to_target_signal_table[i];
483 target_to_host_signal_table[j] = i;
484 }
ths3b46e622007-09-17 08:09:54 +0000485
Peter Maydell3d3efba2016-05-27 15:51:49 +0100486 /* Set the signal mask from the host mask. */
487 sigprocmask(0, 0, &ts->signal_mask);
488
bellard9de5e442003-03-23 16:49:39 +0000489 /* set all host signal handlers. ALL signals are blocked during
490 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000491 memset(sigact_table, 0, sizeof(sigact_table));
492
bellard9de5e442003-03-23 16:49:39 +0000493 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000494 act.sa_flags = SA_SIGINFO;
495 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000496 for(i = 1; i <= TARGET_NSIG; i++) {
497 host_sig = target_to_host_signal(i);
498 sigaction(host_sig, NULL, &oact);
499 if (oact.sa_sigaction == (void *)SIG_IGN) {
500 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
501 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
502 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
503 }
504 /* If there's already a handler installed then something has
505 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000506 /* Install some handlers for our own use. We need at least
507 SIGSEGV and SIGBUS, to detect exceptions. We can not just
508 trap all signals because it affects syscall interrupt
509 behavior. But do trap all default-fatal signals. */
510 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000511 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000512 }
bellard31e31b82003-02-18 22:55:36 +0000513}
514
Peter Maydellc4b35742016-07-28 16:44:50 +0100515#if !(defined(TARGET_X86_64) || defined(TARGET_UNICORE32))
Peter Maydellc599d4d2016-07-28 16:44:49 +0100516/* Force a synchronously taken signal. The kernel force_sig() function
517 * also forces the signal to "not blocked, not ignored", but for QEMU
518 * that work is done in process_pending_signals().
519 */
520static void force_sig(int sig)
521{
522 CPUState *cpu = thread_cpu;
523 CPUArchState *env = cpu->env_ptr;
524 target_siginfo_t info;
525
526 info.si_signo = sig;
527 info.si_errno = 0;
528 info.si_code = TARGET_SI_KERNEL;
529 info._sifields._kill._pid = 0;
530 info._sifields._kill._uid = 0;
531 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
532}
Peter Maydell09391662016-07-28 16:44:47 +0100533
534/* Force a SIGSEGV if we couldn't write to memory trying to set
535 * up the signal frame. oldsig is the signal we were trying to handle
536 * at the point of failure.
537 */
538static void force_sigsegv(int oldsig)
539{
Peter Maydell09391662016-07-28 16:44:47 +0100540 if (oldsig == SIGSEGV) {
541 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100542 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100543 */
544 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
545 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100546 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100547}
548#endif
bellard66fb9762003-03-23 01:06:05 +0000549
bellard9de5e442003-03-23 16:49:39 +0000550/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100551static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000552{
Andreas Färber0429a972013-08-26 18:14:44 +0200553 CPUState *cpu = thread_cpu;
554 CPUArchState *env = cpu->env_ptr;
555 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300556 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000557 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100558
Riku Voipio66393fb2009-12-04 15:16:32 +0200559 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100560 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200561 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000562
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300563 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200564 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300565 stop_all_tasks();
566 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200567 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 }
569 if (core_dumped) {
570 /* we already dumped the core of target process, we don't want
571 * a coredump of qemu itself */
572 struct rlimit nodump;
573 getrlimit(RLIMIT_CORE, &nodump);
574 nodump.rlim_cur=0;
575 setrlimit(RLIMIT_CORE, &nodump);
576 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200577 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300578 }
579
Stefan Weil0c587512011-04-28 17:20:32 +0200580 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000581 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
582 * a negative value. To get the proper exit code we need to
583 * actually die from an uncaught signal. Here the default signal
584 * handler is installed, we send ourself a signal and we wait for
585 * it to arrive. */
586 sigfillset(&act.sa_mask);
587 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000588 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000589 sigaction(host_sig, &act, NULL);
590
591 /* For some reason raise(host_sig) doesn't send the signal when
592 * statically linked on x86-64. */
593 kill(getpid(), host_sig);
594
595 /* Make sure the signal isn't masked (just reuse the mask inside
596 of act) */
597 sigdelset(&act.sa_mask, host_sig);
598 sigsuspend(&act.sa_mask);
599
600 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000601 abort();
bellard66fb9762003-03-23 01:06:05 +0000602}
603
bellard9de5e442003-03-23 16:49:39 +0000604/* queue a signal so that it will be send to the virtual CPU as soon
605 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100606int queue_signal(CPUArchState *env, int sig, int si_type,
607 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000608{
Andreas Färber0429a972013-08-26 18:14:44 +0200609 CPUState *cpu = ENV_GET_CPU(env);
610 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000611
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100612 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000613
Peter Maydell9d2803f2016-07-28 16:44:46 +0100614 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100615
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100616 ts->sync_signal.info = *info;
617 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100618 /* signal that a new signal is pending */
619 atomic_set(&ts->signal_pending, 1);
620 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000621}
622
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100623#ifndef HAVE_SAFE_SYSCALL
624static inline void rewind_if_in_safe_syscall(void *puc)
625{
626 /* Default version: never rewind */
627}
628#endif
629
ths5fafdf22007-09-16 21:08:06 +0000630static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000631 void *puc)
632{
Andreas Färbera2247f82013-06-09 19:47:04 +0200633 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100634 CPUState *cpu = ENV_GET_CPU(env);
635 TaskState *ts = cpu->opaque;
636
bellard9de5e442003-03-23 16:49:39 +0000637 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500638 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100639 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100640 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000641
642 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000643 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000644 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000645 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000646 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000647 return;
648 }
649
650 /* get target signal number */
651 sig = host_to_target_signal(host_signum);
652 if (sig < 1 || sig > TARGET_NSIG)
653 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100654 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100655
656 rewind_if_in_safe_syscall(puc);
657
bellard9de5e442003-03-23 16:49:39 +0000658 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100659 k = &ts->sigtab[sig - 1];
660 k->info = tinfo;
661 k->pending = sig;
662 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100663
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100664 /* Block host signals until target signal handler entered. We
665 * can't block SIGSEGV or SIGBUS while we're executing guest
666 * code in case the guest code provokes one in the window between
667 * now and it getting out to the main loop. Signals will be
668 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100669 *
670 * WARNING: we cannot use sigfillset() here because the uc_sigmask
671 * field is a kernel sigset_t, which is much smaller than the
672 * libc sigset_t which sigfillset() operates on. Using sigfillset()
673 * would write 0xff bytes off the end of the structure and trash
674 * data on the struct.
675 * We can't use sizeof(uc->uc_sigmask) either, because the libc
676 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100677 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100678 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100679 sigdelset(&uc->uc_sigmask, SIGSEGV);
680 sigdelset(&uc->uc_sigmask, SIGBUS);
681
682 /* interrupt the virtual CPU as soon as possible */
683 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000684}
685
ths0da46a62007-10-20 20:23:07 +0000686/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000687/* compare linux/kernel/signal.c:do_sigaltstack() */
688abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000689{
690 int ret;
691 struct target_sigaltstack oss;
692
693 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000694 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000695 {
696 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
697 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
698 __put_user(sas_ss_flags(sp), &oss.ss_flags);
699 }
700
bellard579a97f2007-11-11 14:26:47 +0000701 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000702 {
bellard579a97f2007-11-11 14:26:47 +0000703 struct target_sigaltstack *uss;
704 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500705 size_t minstacksize = TARGET_MINSIGSTKSZ;
706
707#if defined(TARGET_PPC64)
708 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
709 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
710 if (get_ppc64_abi(image) > 1) {
711 minstacksize = 4096;
712 }
713#endif
thsa04e1342007-09-27 13:57:58 +0000714
ths0da46a62007-10-20 20:23:07 +0000715 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300716 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000717 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300718 }
719 __get_user(ss.ss_sp, &uss->ss_sp);
720 __get_user(ss.ss_size, &uss->ss_size);
721 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000722 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000723
ths0da46a62007-10-20 20:23:07 +0000724 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000725 if (on_sig_stack(sp))
726 goto out;
727
ths0da46a62007-10-20 20:23:07 +0000728 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000729 if (ss.ss_flags != TARGET_SS_DISABLE
730 && ss.ss_flags != TARGET_SS_ONSTACK
731 && ss.ss_flags != 0)
732 goto out;
733
734 if (ss.ss_flags == TARGET_SS_DISABLE) {
735 ss.ss_size = 0;
736 ss.ss_sp = 0;
737 } else {
ths0da46a62007-10-20 20:23:07 +0000738 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500739 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000740 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500741 }
thsa04e1342007-09-27 13:57:58 +0000742 }
743
744 target_sigaltstack_used.ss_sp = ss.ss_sp;
745 target_sigaltstack_used.ss_size = ss.ss_size;
746 }
747
bellard579a97f2007-11-11 14:26:47 +0000748 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000749 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000750 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000751 goto out;
thsa04e1342007-09-27 13:57:58 +0000752 }
753
754 ret = 0;
755out:
756 return ret;
757}
758
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100759/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000760int do_sigaction(int sig, const struct target_sigaction *act,
761 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000762{
pbrook624f7972008-05-31 16:11:38 +0000763 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000764 struct sigaction act1;
765 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000766 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000767
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100768 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
769 return -TARGET_EINVAL;
770 }
771
772 if (block_signals()) {
773 return -TARGET_ERESTARTSYS;
774 }
775
bellard66fb9762003-03-23 01:06:05 +0000776 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000777 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800778 __put_user(k->_sa_handler, &oact->_sa_handler);
779 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000780#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000782#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800783 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000784 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000785 }
786 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000787 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800788 __get_user(k->_sa_handler, &act->_sa_handler);
789 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000790#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000792#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800793 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000794 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000795
796 /* we update the host linux signal state */
797 host_sig = target_to_host_signal(sig);
798 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
799 sigfillset(&act1.sa_mask);
800 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000801 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000802 act1.sa_flags |= SA_RESTART;
803 /* NOTE: it is important to update the host kernel signal
804 ignore state to avoid getting unexpected interrupted
805 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000806 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000807 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000808 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000809 if (fatal_signal (sig))
810 act1.sa_sigaction = host_signal_handler;
811 else
812 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000813 } else {
814 act1.sa_sigaction = host_signal_handler;
815 }
ths0da46a62007-10-20 20:23:07 +0000816 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000817 }
bellard66fb9762003-03-23 01:06:05 +0000818 }
ths0da46a62007-10-20 20:23:07 +0000819 return ret;
bellard66fb9762003-03-23 01:06:05 +0000820}
bellard31e31b82003-02-18 22:55:36 +0000821
bellard459a4012007-11-11 19:45:10 +0000822#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000823
824/* from the Linux kernel */
825
826struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100827 uint16_t significand[4];
828 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000829};
830
831struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100832 uint16_t significand[4];
833 uint16_t exponent;
834 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000835};
836
837struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100838 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000839};
840
841struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100842 /* Regular FPU environment */
843 abi_ulong cw;
844 abi_ulong sw;
845 abi_ulong tag;
846 abi_ulong ipoff;
847 abi_ulong cssel;
848 abi_ulong dataoff;
849 abi_ulong datasel;
850 struct target_fpreg _st[8];
851 uint16_t status;
852 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000853
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100854 /* FXSR FPU environment */
855 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
856 abi_ulong mxcsr;
857 abi_ulong reserved;
858 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
859 struct target_xmmreg _xmm[8];
860 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000861};
862
863#define X86_FXSR_MAGIC 0x0000
864
865struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100866 uint16_t gs, __gsh;
867 uint16_t fs, __fsh;
868 uint16_t es, __esh;
869 uint16_t ds, __dsh;
870 abi_ulong edi;
871 abi_ulong esi;
872 abi_ulong ebp;
873 abi_ulong esp;
874 abi_ulong ebx;
875 abi_ulong edx;
876 abi_ulong ecx;
877 abi_ulong eax;
878 abi_ulong trapno;
879 abi_ulong err;
880 abi_ulong eip;
881 uint16_t cs, __csh;
882 abi_ulong eflags;
883 abi_ulong esp_at_signal;
884 uint16_t ss, __ssh;
885 abi_ulong fpstate; /* pointer */
886 abi_ulong oldmask;
887 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000888};
889
bellard66fb9762003-03-23 01:06:05 +0000890struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100891 abi_ulong tuc_flags;
892 abi_ulong tuc_link;
893 target_stack_t tuc_stack;
894 struct target_sigcontext tuc_mcontext;
895 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000896};
897
898struct sigframe
899{
blueswir1992f48a2007-10-14 16:27:31 +0000900 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000901 int sig;
902 struct target_sigcontext sc;
903 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000904 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000905 char retcode[8];
906};
907
908struct rt_sigframe
909{
blueswir1992f48a2007-10-14 16:27:31 +0000910 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000911 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000912 abi_ulong pinfo;
913 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000914 struct target_siginfo info;
915 struct target_ucontext uc;
916 struct target_fpstate fpstate;
917 char retcode[8];
918};
919
920/*
921 * Set up a signal frame.
922 */
923
bellard66fb9762003-03-23 01:06:05 +0000924/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300925static void setup_sigcontext(struct target_sigcontext *sc,
926 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
927 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000928{
Andreas Färber27103422013-08-26 08:31:06 +0200929 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200930 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000931
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100932 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300933 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
934 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
935 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
936 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
937 __put_user(env->regs[R_EDI], &sc->edi);
938 __put_user(env->regs[R_ESI], &sc->esi);
939 __put_user(env->regs[R_EBP], &sc->ebp);
940 __put_user(env->regs[R_ESP], &sc->esp);
941 __put_user(env->regs[R_EBX], &sc->ebx);
942 __put_user(env->regs[R_EDX], &sc->edx);
943 __put_user(env->regs[R_ECX], &sc->ecx);
944 __put_user(env->regs[R_EAX], &sc->eax);
945 __put_user(cs->exception_index, &sc->trapno);
946 __put_user(env->error_code, &sc->err);
947 __put_user(env->eip, &sc->eip);
948 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
949 __put_user(env->eflags, &sc->eflags);
950 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
951 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000952
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100953 cpu_x86_fsave(env, fpstate_addr, 1);
954 fpstate->status = fpstate->sw;
955 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300956 __put_user(magic, &fpstate->magic);
957 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000958
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100959 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300960 __put_user(mask, &sc->oldmask);
961 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000962}
963
964/*
965 * Determine which stack to use..
966 */
967
bellard579a97f2007-11-11 14:26:47 +0000968static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000969get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000970{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100971 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000972
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100973 /* Default to using normal stack */
974 esp = env->regs[R_ESP];
975 /* This is the X/Open sanctioned signal stack switching. */
976 if (ka->sa_flags & TARGET_SA_ONSTACK) {
977 if (sas_ss_flags(esp) == 0) {
978 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000979 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100980 } else {
bellard66fb9762003-03-23 01:06:05 +0000981
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100982 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000983 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100984 !(ka->sa_flags & TARGET_SA_RESTORER) &&
985 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000986 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100987 }
988 }
989 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000990}
991
bellard579a97f2007-11-11 14:26:47 +0000992/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000993static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100994 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000995{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100996 abi_ulong frame_addr;
997 struct sigframe *frame;
998 int i;
bellard66fb9762003-03-23 01:06:05 +0000999
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001000 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1001 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001002
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001003 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1004 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001005
Peter Maydellb6e2c932015-01-08 12:19:43 +00001006 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001007
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001008 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1009 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001010
Riku Voipio7df2fa32014-04-23 10:34:53 +03001011 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1012 __put_user(set->sig[i], &frame->extramask[i - 1]);
1013 }
bellard66fb9762003-03-23 01:06:05 +00001014
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001015 /* Set up to return from userspace. If provided, use a stub
1016 already in userspace. */
1017 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001018 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001019 } else {
1020 uint16_t val16;
1021 abi_ulong retcode_addr;
1022 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001023 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001024 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1025 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001026 __put_user(val16, (uint16_t *)(frame->retcode+0));
1027 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001028 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001029 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001030 }
bellard66fb9762003-03-23 01:06:05 +00001031
bellard66fb9762003-03-23 01:06:05 +00001032
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001033 /* Set up registers for signal handler */
1034 env->regs[R_ESP] = frame_addr;
1035 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001036
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001037 cpu_x86_load_seg(env, R_DS, __USER_DS);
1038 cpu_x86_load_seg(env, R_ES, __USER_DS);
1039 cpu_x86_load_seg(env, R_SS, __USER_DS);
1040 cpu_x86_load_seg(env, R_CS, __USER_CS);
1041 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001042
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001043 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001044
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001045 return;
bellard66fb9762003-03-23 01:06:05 +00001046
1047give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001048 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001049}
1050
bellard579a97f2007-11-11 14:26:47 +00001051/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001052static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001053 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001054 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001055{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001056 abi_ulong frame_addr, addr;
1057 struct rt_sigframe *frame;
1058 int i;
bellard66fb9762003-03-23 01:06:05 +00001059
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001060 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1061 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001062
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001063 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1064 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001065
Peter Maydellb6e2c932015-01-08 12:19:43 +00001066 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001067 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001068 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001069 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001070 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +00001071 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +00001072
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001073 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001074 __put_user(0, &frame->uc.tuc_flags);
1075 __put_user(0, &frame->uc.tuc_link);
1076 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1077 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1078 &frame->uc.tuc_stack.ss_flags);
1079 __put_user(target_sigaltstack_used.ss_size,
1080 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001081 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1082 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1083
Riku Voipio0188fad2014-04-23 13:34:15 +03001084 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1085 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1086 }
bellard66fb9762003-03-23 01:06:05 +00001087
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001088 /* Set up to return from userspace. If provided, use a stub
1089 already in userspace. */
1090 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001091 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001092 } else {
1093 uint16_t val16;
1094 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001095 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001096 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001097 __put_user(0xb8, (char *)(frame->retcode+0));
1098 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001099 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001100 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 }
bellard66fb9762003-03-23 01:06:05 +00001102
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001103 /* Set up registers for signal handler */
1104 env->regs[R_ESP] = frame_addr;
1105 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001106
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001107 cpu_x86_load_seg(env, R_DS, __USER_DS);
1108 cpu_x86_load_seg(env, R_ES, __USER_DS);
1109 cpu_x86_load_seg(env, R_SS, __USER_DS);
1110 cpu_x86_load_seg(env, R_CS, __USER_CS);
1111 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001112
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001113 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001114
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001115 return;
bellard66fb9762003-03-23 01:06:05 +00001116
1117give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001118 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001119}
1120
1121static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001122restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001123{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 unsigned int err = 0;
1125 abi_ulong fpstate_addr;
1126 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001127
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001128 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1129 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1130 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1131 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001132
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001133 env->regs[R_EDI] = tswapl(sc->edi);
1134 env->regs[R_ESI] = tswapl(sc->esi);
1135 env->regs[R_EBP] = tswapl(sc->ebp);
1136 env->regs[R_ESP] = tswapl(sc->esp);
1137 env->regs[R_EBX] = tswapl(sc->ebx);
1138 env->regs[R_EDX] = tswapl(sc->edx);
1139 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001140 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001141 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001142
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001143 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1144 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001145
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001146 tmpflags = tswapl(sc->eflags);
1147 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1148 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001149
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001150 fpstate_addr = tswapl(sc->fpstate);
1151 if (fpstate_addr != 0) {
1152 if (!access_ok(VERIFY_READ, fpstate_addr,
1153 sizeof(struct target_fpstate)))
1154 goto badframe;
1155 cpu_x86_frstor(env, fpstate_addr, 1);
1156 }
bellard66fb9762003-03-23 01:06:05 +00001157
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001158 return err;
bellard66fb9762003-03-23 01:06:05 +00001159badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001160 return 1;
bellard66fb9762003-03-23 01:06:05 +00001161}
1162
1163long do_sigreturn(CPUX86State *env)
1164{
bellard579a97f2007-11-11 14:26:47 +00001165 struct sigframe *frame;
1166 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001167 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001168 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001169 int i;
bellard66fb9762003-03-23 01:06:05 +00001170
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001171 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001172 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1173 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001174 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001175 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001176 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001177 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001178 }
bellard66fb9762003-03-23 01:06:05 +00001179
bellard92319442004-06-19 16:58:13 +00001180 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001181 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001182
bellard66fb9762003-03-23 01:06:05 +00001183 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001184 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001185 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001186 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001187 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001188
1189badframe:
bellard579a97f2007-11-11 14:26:47 +00001190 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001191 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001192 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001193}
1194
1195long do_rt_sigreturn(CPUX86State *env)
1196{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001197 abi_ulong frame_addr;
1198 struct rt_sigframe *frame;
1199 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001200
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001201 frame_addr = env->regs[R_ESP] - 4;
1202 trace_user_do_rt_sigreturn(env, frame_addr);
1203 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1204 goto badframe;
1205 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001206 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001207
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001208 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001209 goto badframe;
1210 }
bellard66fb9762003-03-23 01:06:05 +00001211
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001212 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1213 get_sp_from_cpustate(env)) == -EFAULT) {
1214 goto badframe;
1215 }
thsa04e1342007-09-27 13:57:58 +00001216
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001217 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001218 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001219
1220badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001221 unlock_user_struct(frame, frame_addr, 0);
1222 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001223 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001224}
1225
Andreas Schwab1744aea2013-09-03 20:12:16 +01001226#elif defined(TARGET_AARCH64)
1227
1228struct target_sigcontext {
1229 uint64_t fault_address;
1230 /* AArch64 registers */
1231 uint64_t regs[31];
1232 uint64_t sp;
1233 uint64_t pc;
1234 uint64_t pstate;
1235 /* 4K reserved for FP/SIMD state and future expansion */
1236 char __reserved[4096] __attribute__((__aligned__(16)));
1237};
1238
1239struct target_ucontext {
1240 abi_ulong tuc_flags;
1241 abi_ulong tuc_link;
1242 target_stack_t tuc_stack;
1243 target_sigset_t tuc_sigmask;
1244 /* glibc uses a 1024-bit sigset_t */
1245 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1246 /* last for future expansion */
1247 struct target_sigcontext tuc_mcontext;
1248};
1249
1250/*
1251 * Header to be used at the beginning of structures extending the user
1252 * context. Such structures must be placed after the rt_sigframe on the stack
1253 * and be 16-byte aligned. The last structure must be a dummy one with the
1254 * magic and size set to 0.
1255 */
1256struct target_aarch64_ctx {
1257 uint32_t magic;
1258 uint32_t size;
1259};
1260
1261#define TARGET_FPSIMD_MAGIC 0x46508001
1262
1263struct target_fpsimd_context {
1264 struct target_aarch64_ctx head;
1265 uint32_t fpsr;
1266 uint32_t fpcr;
1267 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1268};
1269
1270/*
1271 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1272 * user space as it will change with the addition of new context. User space
1273 * should check the magic/size information.
1274 */
1275struct target_aux_context {
1276 struct target_fpsimd_context fpsimd;
1277 /* additional context to be added before "end" */
1278 struct target_aarch64_ctx end;
1279};
1280
1281struct target_rt_sigframe {
1282 struct target_siginfo info;
1283 struct target_ucontext uc;
1284 uint64_t fp;
1285 uint64_t lr;
1286 uint32_t tramp[2];
1287};
1288
1289static int target_setup_sigframe(struct target_rt_sigframe *sf,
1290 CPUARMState *env, target_sigset_t *set)
1291{
1292 int i;
1293 struct target_aux_context *aux =
1294 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1295
1296 /* set up the stack frame for unwinding */
1297 __put_user(env->xregs[29], &sf->fp);
1298 __put_user(env->xregs[30], &sf->lr);
1299
1300 for (i = 0; i < 31; i++) {
1301 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1302 }
1303 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1304 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001305 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001306
Peter Maydell7af03922014-05-01 18:36:17 +01001307 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001308
1309 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1310 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1311 }
1312
1313 for (i = 0; i < 32; i++) {
1314#ifdef TARGET_WORDS_BIGENDIAN
1315 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1316 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1317#else
1318 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1319 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1320#endif
1321 }
Will Newtone0ee1382014-01-04 22:15:48 +00001322 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1323 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001324 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1325 __put_user(sizeof(struct target_fpsimd_context),
1326 &aux->fpsimd.head.size);
1327
1328 /* set the "end" magic */
1329 __put_user(0, &aux->end.magic);
1330 __put_user(0, &aux->end.size);
1331
1332 return 0;
1333}
1334
1335static int target_restore_sigframe(CPUARMState *env,
1336 struct target_rt_sigframe *sf)
1337{
1338 sigset_t set;
1339 int i;
1340 struct target_aux_context *aux =
1341 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001342 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001343 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001344
1345 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001346 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001347
1348 for (i = 0; i < 31; i++) {
1349 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1350 }
1351
1352 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1353 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001354 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1355 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001356
1357 __get_user(magic, &aux->fpsimd.head.magic);
1358 __get_user(size, &aux->fpsimd.head.size);
1359
1360 if (magic != TARGET_FPSIMD_MAGIC
1361 || size != sizeof(struct target_fpsimd_context)) {
1362 return 1;
1363 }
1364
Peter Maydell4cf23482014-03-02 19:36:38 +00001365 for (i = 0; i < 32; i++) {
1366#ifdef TARGET_WORDS_BIGENDIAN
1367 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1368 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1369#else
1370 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1371 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1372#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001373 }
Will Newtone0ee1382014-01-04 22:15:48 +00001374 __get_user(fpsr, &aux->fpsimd.fpsr);
1375 vfp_set_fpsr(env, fpsr);
1376 __get_user(fpcr, &aux->fpsimd.fpcr);
1377 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001378
1379 return 0;
1380}
1381
1382static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1383{
1384 abi_ulong sp;
1385
1386 sp = env->xregs[31];
1387
1388 /*
1389 * This is the X/Open sanctioned signal stack switching.
1390 */
Riku Voipiob545f632014-07-15 17:01:55 +03001391 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001392 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1393 }
1394
1395 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1396
1397 return sp;
1398}
1399
1400static void target_setup_frame(int usig, struct target_sigaction *ka,
1401 target_siginfo_t *info, target_sigset_t *set,
1402 CPUARMState *env)
1403{
1404 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001405 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001406
1407 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001408 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001409 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1410 goto give_sigsegv;
1411 }
1412
1413 __put_user(0, &frame->uc.tuc_flags);
1414 __put_user(0, &frame->uc.tuc_link);
1415
1416 __put_user(target_sigaltstack_used.ss_sp,
1417 &frame->uc.tuc_stack.ss_sp);
1418 __put_user(sas_ss_flags(env->xregs[31]),
1419 &frame->uc.tuc_stack.ss_flags);
1420 __put_user(target_sigaltstack_used.ss_size,
1421 &frame->uc.tuc_stack.ss_size);
1422 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001423 if (ka->sa_flags & TARGET_SA_RESTORER) {
1424 return_addr = ka->sa_restorer;
1425 } else {
1426 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1427 __put_user(0xd2801168, &frame->tramp[0]);
1428 __put_user(0xd4000001, &frame->tramp[1]);
1429 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1430 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001431 env->xregs[0] = usig;
1432 env->xregs[31] = frame_addr;
1433 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1434 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001435 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001436 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001437 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001438 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1439 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1440 }
1441
1442 unlock_user_struct(frame, frame_addr, 1);
1443 return;
1444
1445 give_sigsegv:
1446 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001447 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001448}
1449
1450static void setup_rt_frame(int sig, struct target_sigaction *ka,
1451 target_siginfo_t *info, target_sigset_t *set,
1452 CPUARMState *env)
1453{
1454 target_setup_frame(sig, ka, info, set, env);
1455}
1456
1457static void setup_frame(int sig, struct target_sigaction *ka,
1458 target_sigset_t *set, CPUARMState *env)
1459{
1460 target_setup_frame(sig, ka, 0, set, env);
1461}
1462
1463long do_rt_sigreturn(CPUARMState *env)
1464{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001465 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001466 abi_ulong frame_addr = env->xregs[31];
1467
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001468 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001469 if (frame_addr & 15) {
1470 goto badframe;
1471 }
1472
1473 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1474 goto badframe;
1475 }
1476
1477 if (target_restore_sigframe(env, frame)) {
1478 goto badframe;
1479 }
1480
1481 if (do_sigaltstack(frame_addr +
1482 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1483 0, get_sp_from_cpustate(env)) == -EFAULT) {
1484 goto badframe;
1485 }
1486
1487 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001488 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001489
1490 badframe:
1491 unlock_user_struct(frame, frame_addr, 0);
1492 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001493 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001494}
1495
1496long do_sigreturn(CPUARMState *env)
1497{
1498 return do_rt_sigreturn(env);
1499}
1500
bellard43fff232003-07-09 19:31:39 +00001501#elif defined(TARGET_ARM)
1502
1503struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001504 abi_ulong trap_no;
1505 abi_ulong error_code;
1506 abi_ulong oldmask;
1507 abi_ulong arm_r0;
1508 abi_ulong arm_r1;
1509 abi_ulong arm_r2;
1510 abi_ulong arm_r3;
1511 abi_ulong arm_r4;
1512 abi_ulong arm_r5;
1513 abi_ulong arm_r6;
1514 abi_ulong arm_r7;
1515 abi_ulong arm_r8;
1516 abi_ulong arm_r9;
1517 abi_ulong arm_r10;
1518 abi_ulong arm_fp;
1519 abi_ulong arm_ip;
1520 abi_ulong arm_sp;
1521 abi_ulong arm_lr;
1522 abi_ulong arm_pc;
1523 abi_ulong arm_cpsr;
1524 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001525};
1526
pbrooka745ec62008-05-06 15:36:17 +00001527struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001528 abi_ulong tuc_flags;
1529 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001530 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001531 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001532 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001533};
1534
pbrooka745ec62008-05-06 15:36:17 +00001535struct target_ucontext_v2 {
1536 abi_ulong tuc_flags;
1537 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001538 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001539 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001540 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001541 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001542 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1543};
1544
Peter Maydell0d871bd2010-11-24 15:20:05 +00001545struct target_user_vfp {
1546 uint64_t fpregs[32];
1547 abi_ulong fpscr;
1548};
1549
1550struct target_user_vfp_exc {
1551 abi_ulong fpexc;
1552 abi_ulong fpinst;
1553 abi_ulong fpinst2;
1554};
1555
1556struct target_vfp_sigframe {
1557 abi_ulong magic;
1558 abi_ulong size;
1559 struct target_user_vfp ufp;
1560 struct target_user_vfp_exc ufp_exc;
1561} __attribute__((__aligned__(8)));
1562
Peter Maydell08e11252010-11-24 15:20:07 +00001563struct target_iwmmxt_sigframe {
1564 abi_ulong magic;
1565 abi_ulong size;
1566 uint64_t regs[16];
1567 /* Note that not all the coprocessor control registers are stored here */
1568 uint32_t wcssf;
1569 uint32_t wcasf;
1570 uint32_t wcgr0;
1571 uint32_t wcgr1;
1572 uint32_t wcgr2;
1573 uint32_t wcgr3;
1574} __attribute__((__aligned__(8)));
1575
Peter Maydell0d871bd2010-11-24 15:20:05 +00001576#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001577#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001578
pbrooka8c33202008-05-07 23:22:46 +00001579struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001580{
1581 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001582 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1583 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001584};
1585
pbrooka8c33202008-05-07 23:22:46 +00001586struct sigframe_v2
1587{
1588 struct target_ucontext_v2 uc;
1589 abi_ulong retcode;
1590};
1591
pbrooka745ec62008-05-06 15:36:17 +00001592struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001593{
bellardf8b0aa22007-11-11 23:03:42 +00001594 abi_ulong pinfo;
1595 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001596 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001597 struct target_ucontext_v1 uc;
1598 abi_ulong retcode;
1599};
1600
1601struct rt_sigframe_v2
1602{
1603 struct target_siginfo info;
1604 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001605 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001606};
1607
1608#define TARGET_CONFIG_CPU_32 1
1609
1610/*
1611 * For ARM syscalls, we encode the syscall number into the instruction.
1612 */
1613#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1614#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1615
1616/*
1617 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1618 * need two 16-bit instructions.
1619 */
1620#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1621#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1622
blueswir1992f48a2007-10-14 16:27:31 +00001623static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001624 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1625 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1626};
1627
1628
Andreas Färber05390242012-02-25 03:37:53 +01001629static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001630{
1631 return 1;
1632}
1633
pbrooka8c33202008-05-07 23:22:46 +00001634static void
bellard43fff232003-07-09 19:31:39 +00001635setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001636 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001637{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001638 __put_user(env->regs[0], &sc->arm_r0);
1639 __put_user(env->regs[1], &sc->arm_r1);
1640 __put_user(env->regs[2], &sc->arm_r2);
1641 __put_user(env->regs[3], &sc->arm_r3);
1642 __put_user(env->regs[4], &sc->arm_r4);
1643 __put_user(env->regs[5], &sc->arm_r5);
1644 __put_user(env->regs[6], &sc->arm_r6);
1645 __put_user(env->regs[7], &sc->arm_r7);
1646 __put_user(env->regs[8], &sc->arm_r8);
1647 __put_user(env->regs[9], &sc->arm_r9);
1648 __put_user(env->regs[10], &sc->arm_r10);
1649 __put_user(env->regs[11], &sc->arm_fp);
1650 __put_user(env->regs[12], &sc->arm_ip);
1651 __put_user(env->regs[13], &sc->arm_sp);
1652 __put_user(env->regs[14], &sc->arm_lr);
1653 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001654#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001655 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001656#endif
1657
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001658 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1659 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1660 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1661 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001662}
1663
bellard579a97f2007-11-11 14:26:47 +00001664static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001665get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001666{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001667 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001668
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001669 /*
1670 * This is the X/Open sanctioned signal stack switching.
1671 */
1672 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1673 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1674 }
1675 /*
1676 * ATPCS B01 mandates 8-byte alignment
1677 */
1678 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001679}
1680
Riku Voipio0188fad2014-04-23 13:34:15 +03001681static void
Andreas Färber05390242012-02-25 03:37:53 +01001682setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001683 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001684{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001685 abi_ulong handler = ka->_sa_handler;
1686 abi_ulong retcode;
1687 int thumb = handler & 1;
1688 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001689
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001690 cpsr &= ~CPSR_IT;
1691 if (thumb) {
1692 cpsr |= CPSR_T;
1693 } else {
1694 cpsr &= ~CPSR_T;
1695 }
bellard43fff232003-07-09 19:31:39 +00001696
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001697 if (ka->sa_flags & TARGET_SA_RESTORER) {
1698 retcode = ka->sa_restorer;
1699 } else {
1700 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001701
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001702 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1703 idx += 2;
1704 }
bellard43fff232003-07-09 19:31:39 +00001705
Riku Voipio0188fad2014-04-23 13:34:15 +03001706 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001707
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001708 retcode = rc_addr + thumb;
1709 }
bellard43fff232003-07-09 19:31:39 +00001710
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001711 env->regs[0] = usig;
1712 env->regs[13] = frame_addr;
1713 env->regs[14] = retcode;
1714 env->regs[15] = handler & (thumb ? ~1 : ~3);
1715 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001716}
1717
Andreas Färber05390242012-02-25 03:37:53 +01001718static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001719{
1720 int i;
1721 struct target_vfp_sigframe *vfpframe;
1722 vfpframe = (struct target_vfp_sigframe *)regspace;
1723 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1724 __put_user(sizeof(*vfpframe), &vfpframe->size);
1725 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001726 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001727 }
1728 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1729 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1730 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1731 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1732 return (abi_ulong*)(vfpframe+1);
1733}
1734
Andreas Färber05390242012-02-25 03:37:53 +01001735static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1736 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001737{
1738 int i;
1739 struct target_iwmmxt_sigframe *iwmmxtframe;
1740 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1741 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1742 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1743 for (i = 0; i < 16; i++) {
1744 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1745 }
1746 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1747 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1748 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1749 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1750 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1751 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1752 return (abi_ulong*)(iwmmxtframe+1);
1753}
1754
pbrooka8c33202008-05-07 23:22:46 +00001755static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001756 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001757{
pbrooka8c33202008-05-07 23:22:46 +00001758 struct target_sigaltstack stack;
1759 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001760 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001761
1762 /* Clear all the bits of the ucontext we don't use. */
1763 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1764
1765 memset(&stack, 0, sizeof(stack));
1766 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1767 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1768 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1769 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1770
1771 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001772 /* Save coprocessor signal frame. */
1773 regspace = uc->tuc_regspace;
1774 if (arm_feature(env, ARM_FEATURE_VFP)) {
1775 regspace = setup_sigframe_v2_vfp(regspace, env);
1776 }
Peter Maydell08e11252010-11-24 15:20:07 +00001777 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1778 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1779 }
1780
Peter Maydell0d871bd2010-11-24 15:20:05 +00001781 /* Write terminating magic word */
1782 __put_user(0, regspace);
1783
pbrooka8c33202008-05-07 23:22:46 +00001784 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1785 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1786 }
1787}
1788
1789/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001790static void setup_frame_v1(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{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001793 struct sigframe_v1 *frame;
1794 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1795 int i;
bellard43fff232003-07-09 19:31:39 +00001796
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001797 trace_user_setup_frame(regs, frame_addr);
1798 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01001799 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001800 }
bellard579a97f2007-11-11 14:26:47 +00001801
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001802 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001803
Riku Voipio0188fad2014-04-23 13:34:15 +03001804 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1805 __put_user(set->sig[i], &frame->extramask[i - 1]);
1806 }
bellard43fff232003-07-09 19:31:39 +00001807
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001808 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1809 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001810
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001811 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01001812 return;
1813sigsegv:
1814 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00001815}
1816
pbrook624f7972008-05-31 16:11:38 +00001817static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001818 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001819{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001820 struct sigframe_v2 *frame;
1821 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001822
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001823 trace_user_setup_frame(regs, frame_addr);
1824 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01001825 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001826 }
pbrooka8c33202008-05-07 23:22:46 +00001827
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001828 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001829
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001830 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1831 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001832
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001833 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01001834 return;
1835sigsegv:
1836 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00001837}
1838
pbrook624f7972008-05-31 16:11:38 +00001839static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001840 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001841{
1842 if (get_osversion() >= 0x020612) {
1843 setup_frame_v2(usig, ka, set, regs);
1844 } else {
1845 setup_frame_v1(usig, ka, set, regs);
1846 }
bellard43fff232003-07-09 19:31:39 +00001847}
1848
bellard579a97f2007-11-11 14:26:47 +00001849/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001850static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001851 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001852 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001853{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001854 struct rt_sigframe_v1 *frame;
1855 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1856 struct target_sigaltstack stack;
1857 int i;
1858 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001859
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001860 trace_user_setup_rt_frame(env, frame_addr);
1861 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01001862 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001863 }
bellardedf779f2004-02-22 13:40:13 +00001864
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001865 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1866 __put_user(info_addr, &frame->pinfo);
1867 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1868 __put_user(uc_addr, &frame->puc);
1869 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001870
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001871 /* Clear all the bits of the ucontext we don't use. */
1872 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001873
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001874 memset(&stack, 0, sizeof(stack));
1875 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1876 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1877 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1878 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001879
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001880 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1881 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1882 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1883 }
bellard43fff232003-07-09 19:31:39 +00001884
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001885 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1886 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001887
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001888 env->regs[1] = info_addr;
1889 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001890
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001891 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01001892 return;
1893sigsegv:
1894 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00001895}
1896
pbrook624f7972008-05-31 16:11:38 +00001897static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001898 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001899 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001900{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001901 struct rt_sigframe_v2 *frame;
1902 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1903 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001904
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001905 trace_user_setup_rt_frame(env, frame_addr);
1906 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01001907 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001908 }
pbrooka745ec62008-05-06 15:36:17 +00001909
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001910 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1911 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1912 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001913
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001914 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001915
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001916 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1917 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001918
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001919 env->regs[1] = info_addr;
1920 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001921
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001922 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01001923 return;
1924sigsegv:
1925 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00001926}
1927
pbrook624f7972008-05-31 16:11:38 +00001928static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001929 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001930 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001931{
1932 if (get_osversion() >= 0x020612) {
1933 setup_rt_frame_v2(usig, ka, info, set, env);
1934 } else {
1935 setup_rt_frame_v1(usig, ka, info, set, env);
1936 }
1937}
1938
bellard43fff232003-07-09 19:31:39 +00001939static int
Andreas Färber05390242012-02-25 03:37:53 +01001940restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001941{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001942 int err = 0;
1943 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001944
Riku Voipio1d8b5122014-04-23 10:26:05 +03001945 __get_user(env->regs[0], &sc->arm_r0);
1946 __get_user(env->regs[1], &sc->arm_r1);
1947 __get_user(env->regs[2], &sc->arm_r2);
1948 __get_user(env->regs[3], &sc->arm_r3);
1949 __get_user(env->regs[4], &sc->arm_r4);
1950 __get_user(env->regs[5], &sc->arm_r5);
1951 __get_user(env->regs[6], &sc->arm_r6);
1952 __get_user(env->regs[7], &sc->arm_r7);
1953 __get_user(env->regs[8], &sc->arm_r8);
1954 __get_user(env->regs[9], &sc->arm_r9);
1955 __get_user(env->regs[10], &sc->arm_r10);
1956 __get_user(env->regs[11], &sc->arm_fp);
1957 __get_user(env->regs[12], &sc->arm_ip);
1958 __get_user(env->regs[13], &sc->arm_sp);
1959 __get_user(env->regs[14], &sc->arm_lr);
1960 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001961#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001962 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001963 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001964#endif
1965
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001966 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001967
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001968 return err;
bellard43fff232003-07-09 19:31:39 +00001969}
1970
Andreas Färber05390242012-02-25 03:37:53 +01001971static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001972{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001973 abi_ulong frame_addr;
1974 struct sigframe_v1 *frame = NULL;
1975 target_sigset_t set;
1976 sigset_t host_set;
1977 int i;
bellard43fff232003-07-09 19:31:39 +00001978
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001979 /*
1980 * Since we stacked the signal on a 64-bit boundary,
1981 * then 'sp' should be word aligned here. If it's
1982 * not, then the user is trying to mess with us.
1983 */
1984 frame_addr = env->regs[13];
1985 trace_user_do_sigreturn(env, frame_addr);
1986 if (frame_addr & 7) {
1987 goto badframe;
1988 }
Peter Maydell978fae92013-07-29 12:00:32 +01001989
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001990 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1991 goto badframe;
1992 }
bellard43fff232003-07-09 19:31:39 +00001993
Riku Voipiof5f601a2014-04-23 13:00:17 +03001994 __get_user(set.sig[0], &frame->sc.oldmask);
1995 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1996 __get_user(set.sig[i], &frame->extramask[i - 1]);
1997 }
bellard43fff232003-07-09 19:31:39 +00001998
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001999 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002000 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002001
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002002 if (restore_sigcontext(env, &frame->sc)) {
2003 goto badframe;
2004 }
bellard43fff232003-07-09 19:31:39 +00002005
2006#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002007 /* Send SIGTRAP if we're single-stepping */
2008 if (ptrace_cancel_bpt(current))
2009 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002010#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002011 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002012 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002013
2014badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002015 force_sig(TARGET_SIGSEGV);
2016 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002017}
2018
Andreas Färber05390242012-02-25 03:37:53 +01002019static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002020{
2021 int i;
2022 abi_ulong magic, sz;
2023 uint32_t fpscr, fpexc;
2024 struct target_vfp_sigframe *vfpframe;
2025 vfpframe = (struct target_vfp_sigframe *)regspace;
2026
2027 __get_user(magic, &vfpframe->magic);
2028 __get_user(sz, &vfpframe->size);
2029 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2030 return 0;
2031 }
2032 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00002033 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002034 }
2035 __get_user(fpscr, &vfpframe->ufp.fpscr);
2036 vfp_set_fpscr(env, fpscr);
2037 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2038 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2039 * and the exception flag is cleared
2040 */
2041 fpexc |= (1 << 30);
2042 fpexc &= ~((1 << 31) | (1 << 28));
2043 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2044 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2045 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2046 return (abi_ulong*)(vfpframe + 1);
2047}
2048
Andreas Färber05390242012-02-25 03:37:53 +01002049static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2050 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002051{
2052 int i;
2053 abi_ulong magic, sz;
2054 struct target_iwmmxt_sigframe *iwmmxtframe;
2055 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2056
2057 __get_user(magic, &iwmmxtframe->magic);
2058 __get_user(sz, &iwmmxtframe->size);
2059 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2060 return 0;
2061 }
2062 for (i = 0; i < 16; i++) {
2063 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2064 }
2065 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2066 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2067 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2068 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2069 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2070 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2071 return (abi_ulong*)(iwmmxtframe + 1);
2072}
2073
Andreas Färber05390242012-02-25 03:37:53 +01002074static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00002075 struct target_ucontext_v2 *uc)
2076{
2077 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002078 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002079
2080 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002081 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002082
2083 if (restore_sigcontext(env, &uc->tuc_mcontext))
2084 return 1;
2085
Peter Maydell5f9099d2010-11-24 15:20:06 +00002086 /* Restore coprocessor signal frame */
2087 regspace = uc->tuc_regspace;
2088 if (arm_feature(env, ARM_FEATURE_VFP)) {
2089 regspace = restore_sigframe_v2_vfp(env, regspace);
2090 if (!regspace) {
2091 return 1;
2092 }
2093 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002094 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2095 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2096 if (!regspace) {
2097 return 1;
2098 }
2099 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002100
pbrooka8c33202008-05-07 23:22:46 +00002101 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2102 return 1;
2103
2104#if 0
2105 /* Send SIGTRAP if we're single-stepping */
2106 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002107 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002108#endif
2109
2110 return 0;
2111}
2112
Andreas Färber05390242012-02-25 03:37:53 +01002113static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002114{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002115 abi_ulong frame_addr;
2116 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002117
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002118 /*
2119 * Since we stacked the signal on a 64-bit boundary,
2120 * then 'sp' should be word aligned here. If it's
2121 * not, then the user is trying to mess with us.
2122 */
2123 frame_addr = env->regs[13];
2124 trace_user_do_sigreturn(env, frame_addr);
2125 if (frame_addr & 7) {
2126 goto badframe;
2127 }
Peter Maydell978fae92013-07-29 12:00:32 +01002128
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002129 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2130 goto badframe;
2131 }
pbrooka8c33202008-05-07 23:22:46 +00002132
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002133 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2134 goto badframe;
2135 }
pbrooka8c33202008-05-07 23:22:46 +00002136
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002137 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002138 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002139
2140badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002141 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002142 force_sig(TARGET_SIGSEGV);
2143 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002144}
2145
Andreas Färber05390242012-02-25 03:37:53 +01002146long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002147{
2148 if (get_osversion() >= 0x020612) {
2149 return do_sigreturn_v2(env);
2150 } else {
2151 return do_sigreturn_v1(env);
2152 }
2153}
2154
Andreas Färber05390242012-02-25 03:37:53 +01002155static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002156{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002157 abi_ulong frame_addr;
2158 struct rt_sigframe_v1 *frame = NULL;
2159 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002160
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002161 /*
2162 * Since we stacked the signal on a 64-bit boundary,
2163 * then 'sp' should be word aligned here. If it's
2164 * not, then the user is trying to mess with us.
2165 */
2166 frame_addr = env->regs[13];
2167 trace_user_do_rt_sigreturn(env, frame_addr);
2168 if (frame_addr & 7) {
2169 goto badframe;
2170 }
Peter Maydell978fae92013-07-29 12:00:32 +01002171
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002172 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2173 goto badframe;
2174 }
bellard43fff232003-07-09 19:31:39 +00002175
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002176 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002177 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002178
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002179 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2180 goto badframe;
2181 }
bellard43fff232003-07-09 19:31:39 +00002182
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002183 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2184 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002185
bellard43fff232003-07-09 19:31:39 +00002186#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002187 /* Send SIGTRAP if we're single-stepping */
2188 if (ptrace_cancel_bpt(current))
2189 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002190#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002191 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002192 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002193
2194badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002195 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002196 force_sig(TARGET_SIGSEGV);
2197 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002198}
2199
Andreas Färber05390242012-02-25 03:37:53 +01002200static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002201{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002202 abi_ulong frame_addr;
2203 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002204
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002205 /*
2206 * Since we stacked the signal on a 64-bit boundary,
2207 * then 'sp' should be word aligned here. If it's
2208 * not, then the user is trying to mess with us.
2209 */
2210 frame_addr = env->regs[13];
2211 trace_user_do_rt_sigreturn(env, frame_addr);
2212 if (frame_addr & 7) {
2213 goto badframe;
2214 }
Peter Maydell978fae92013-07-29 12:00:32 +01002215
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002216 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2217 goto badframe;
2218 }
pbrooka745ec62008-05-06 15:36:17 +00002219
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002220 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2221 goto badframe;
2222 }
pbrooka745ec62008-05-06 15:36:17 +00002223
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002224 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002225 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002226
2227badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002228 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002229 force_sig(TARGET_SIGSEGV);
2230 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002231}
2232
Andreas Färber05390242012-02-25 03:37:53 +01002233long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002234{
2235 if (get_osversion() >= 0x020612) {
2236 return do_rt_sigreturn_v2(env);
2237 } else {
2238 return do_rt_sigreturn_v1(env);
2239 }
2240}
2241
bellard6d5e2162004-09-30 22:04:13 +00002242#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002243
bellard6d5e2162004-09-30 22:04:13 +00002244#define __SUNOS_MAXWIN 31
2245
2246/* This is what SunOS does, so shall I. */
2247struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002248 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002249
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002250 abi_ulong sigc_mask; /* sigmask to restore */
2251 abi_ulong sigc_sp; /* stack pointer */
2252 abi_ulong sigc_pc; /* program counter */
2253 abi_ulong sigc_npc; /* next program counter */
2254 abi_ulong sigc_psr; /* for condition codes etc */
2255 abi_ulong sigc_g1; /* User uses these two registers */
2256 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002257
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002258 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002259 * at the time of the signal.
2260 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002262
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002263 /* stack ptrs for each regwin buf */
2264 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002265
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002266 /* Windows to restore after signal */
2267 struct {
2268 abi_ulong locals[8];
2269 abi_ulong ins[8];
2270 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002271};
2272/* A Sparc stack frame */
2273struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002274 abi_ulong locals[8];
2275 abi_ulong ins[8];
2276 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002277 * since we never need to access them ourselves.
2278 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002279 char *structptr;
2280 abi_ulong xargs[6];
2281 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002282};
2283
2284typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 struct {
2286 abi_ulong psr;
2287 abi_ulong pc;
2288 abi_ulong npc;
2289 abi_ulong y;
2290 abi_ulong u_regs[16]; /* globals and ins */
2291 } si_regs;
2292 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002293} __siginfo_t;
2294
2295typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002296 abi_ulong si_float_regs[32];
2297 unsigned long si_fsr;
2298 unsigned long si_fpqdepth;
2299 struct {
2300 unsigned long *insn_addr;
2301 unsigned long insn;
2302 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002303} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002304
2305
2306struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002307 struct sparc_stackf ss;
2308 __siginfo_t info;
2309 abi_ulong fpu_save;
2310 abi_ulong insns[2] __attribute__ ((aligned (8)));
2311 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2312 abi_ulong extra_size; /* Should be 0 */
2313 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002314};
2315struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002316 struct sparc_stackf ss;
2317 siginfo_t info;
2318 abi_ulong regs[20];
2319 sigset_t mask;
2320 abi_ulong fpu_save;
2321 unsigned int insns[2];
2322 stack_t stack;
2323 unsigned int extra_size; /* Should be 0 */
2324 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002325};
2326
bellarde80cfcf2004-12-19 23:18:01 +00002327#define UREG_O0 16
2328#define UREG_O6 22
2329#define UREG_I0 0
2330#define UREG_I1 1
2331#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002332#define UREG_I3 3
2333#define UREG_I4 4
2334#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002335#define UREG_I6 6
2336#define UREG_I7 7
2337#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002338#define UREG_FP UREG_I6
2339#define UREG_SP UREG_O6
2340
pbrook624f7972008-05-31 16:11:38 +00002341static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002342 CPUSPARCState *env,
2343 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002344{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002345 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002346
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002348
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002349 /* This is the X/Open sanctioned signal stack switching. */
2350 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2351 if (!on_sig_stack(sp)
2352 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2353 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2354 }
2355 }
2356 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002357}
2358
2359static int
Andreas Färber05390242012-02-25 03:37:53 +01002360setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002361{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002362 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002363
Riku Voipio1d8b5122014-04-23 10:26:05 +03002364 __put_user(env->psr, &si->si_regs.psr);
2365 __put_user(env->pc, &si->si_regs.pc);
2366 __put_user(env->npc, &si->si_regs.npc);
2367 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002368 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002369 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002370 }
2371 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002372 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002373 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002374 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002375 return err;
bellard6d5e2162004-09-30 22:04:13 +00002376}
bellarde80cfcf2004-12-19 23:18:01 +00002377
bellard80a9d032005-01-03 23:31:27 +00002378#if 0
bellard6d5e2162004-09-30 22:04:13 +00002379static int
2380setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002381 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002382{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002383 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002384
Riku Voipio1d8b5122014-04-23 10:26:05 +03002385 __put_user(mask, &sc->sigc_mask);
2386 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2387 __put_user(env->pc, &sc->sigc_pc);
2388 __put_user(env->npc, &sc->sigc_npc);
2389 __put_user(env->psr, &sc->sigc_psr);
2390 __put_user(env->gregs[1], &sc->sigc_g1);
2391 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002392
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002393 return err;
bellard6d5e2162004-09-30 22:04:13 +00002394}
bellard80a9d032005-01-03 23:31:27 +00002395#endif
bellard6d5e2162004-09-30 22:04:13 +00002396#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2397
pbrook624f7972008-05-31 16:11:38 +00002398static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002399 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002400{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002401 abi_ulong sf_addr;
2402 struct target_signal_frame *sf;
2403 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002404
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002405 /* 1. Make sure everything is clean */
2406 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002407
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002408 sigframe_size = NF_ALIGNEDSZ;
2409 sf_addr = get_sigframe(ka, env, sigframe_size);
2410 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002411
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002412 sf = lock_user(VERIFY_WRITE, sf_addr,
2413 sizeof(struct target_signal_frame), 0);
2414 if (!sf) {
2415 goto sigsegv;
2416 }
bellard6d5e2162004-09-30 22:04:13 +00002417#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002418 if (invalid_frame_pointer(sf, sigframe_size))
2419 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002420#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002421 /* 2. Save the current process state */
2422 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002423 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002424
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002425 //save_fpu_state(regs, &sf->fpu_state);
2426 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002427
Riku Voipio1d8b5122014-04-23 10:26:05 +03002428 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002429 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002430 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002431 }
bellard6d5e2162004-09-30 22:04:13 +00002432
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002433 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002434 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002435 }
2436 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002437 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002438 }
2439 if (err)
2440 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002441
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002442 /* 3. signal handler back-trampoline and parameters */
2443 env->regwptr[UREG_FP] = sf_addr;
2444 env->regwptr[UREG_I0] = sig;
2445 env->regwptr[UREG_I1] = sf_addr +
2446 offsetof(struct target_signal_frame, info);
2447 env->regwptr[UREG_I2] = sf_addr +
2448 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002449
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002450 /* 4. signal handler */
2451 env->pc = ka->_sa_handler;
2452 env->npc = (env->pc + 4);
2453 /* 5. return to kernel instructions */
2454 if (ka->sa_restorer) {
2455 env->regwptr[UREG_I7] = ka->sa_restorer;
2456 } else {
2457 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002458
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002459 env->regwptr[UREG_I7] = sf_addr +
2460 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002461
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002462 /* mov __NR_sigreturn, %g1 */
2463 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002464 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002465
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002466 /* t 0x10 */
2467 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002468 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002469 if (err)
2470 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002471
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002472 /* Flush instruction space. */
2473 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2474 // tb_flush(env);
2475 }
2476 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2477 return;
bellard459a4012007-11-11 19:45:10 +00002478#if 0
2479sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002480 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002481#endif
bellard6d5e2162004-09-30 22:04:13 +00002482sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002483 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002484 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002485}
bellard6d5e2162004-09-30 22:04:13 +00002486
pbrook624f7972008-05-31 16:11:38 +00002487static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002488 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002489 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002490{
2491 fprintf(stderr, "setup_rt_frame: not implemented\n");
2492}
2493
Andreas Färber05390242012-02-25 03:37:53 +01002494long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002495{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002496 abi_ulong sf_addr;
2497 struct target_signal_frame *sf;
2498 uint32_t up_psr, pc, npc;
2499 target_sigset_t set;
2500 sigset_t host_set;
2501 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002502
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002503 sf_addr = env->regwptr[UREG_FP];
2504 trace_user_do_sigreturn(env, sf_addr);
2505 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2506 goto segv_and_exit;
2507 }
bellard6d5e2162004-09-30 22:04:13 +00002508
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002509 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002510
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002511 if (sf_addr & 3)
2512 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002513
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002514 __get_user(pc, &sf->info.si_regs.pc);
2515 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002516
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002517 if ((pc | npc) & 3) {
2518 goto segv_and_exit;
2519 }
bellard6d5e2162004-09-30 22:04:13 +00002520
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002521 /* 2. Restore the state */
2522 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002523
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002524 /* User can only change condition codes and FPU enabling in %psr. */
2525 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2526 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002527
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002528 env->pc = pc;
2529 env->npc = npc;
2530 __get_user(env->y, &sf->info.si_regs.y);
2531 for (i=0; i < 8; i++) {
2532 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2533 }
2534 for (i=0; i < 8; i++) {
2535 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2536 }
bellard6d5e2162004-09-30 22:04:13 +00002537
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002538 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002539 * __get_user(fpu_save, &sf->fpu_save);
2540 * if (fpu_save)
2541 * err |= restore_fpu_state(env, fpu_save);
2542 */
bellard6d5e2162004-09-30 22:04:13 +00002543
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002544 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002545 * the races which exist anyways.
2546 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002547 __get_user(set.sig[0], &sf->info.si_mask);
2548 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2549 __get_user(set.sig[i], &sf->extramask[i - 1]);
2550 }
bellarde80cfcf2004-12-19 23:18:01 +00002551
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002552 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002553 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002554
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002555 if (err) {
2556 goto segv_and_exit;
2557 }
2558 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002559 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002560
2561segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002562 unlock_user_struct(sf, sf_addr, 0);
2563 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002564 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002565}
2566
Andreas Färber05390242012-02-25 03:37:53 +01002567long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002568{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002569 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002570 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002571 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002572}
2573
bellard459a4012007-11-11 19:45:10 +00002574#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002575#define MC_TSTATE 0
2576#define MC_PC 1
2577#define MC_NPC 2
2578#define MC_Y 3
2579#define MC_G1 4
2580#define MC_G2 5
2581#define MC_G3 6
2582#define MC_G4 7
2583#define MC_G5 8
2584#define MC_G6 9
2585#define MC_G7 10
2586#define MC_O0 11
2587#define MC_O1 12
2588#define MC_O2 13
2589#define MC_O3 14
2590#define MC_O4 15
2591#define MC_O5 16
2592#define MC_O6 17
2593#define MC_O7 18
2594#define MC_NGREG 19
2595
Anthony Liguoric227f092009-10-01 16:12:16 -05002596typedef abi_ulong target_mc_greg_t;
2597typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002598
2599struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002600 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002601 uint32_t mcfq_insn;
2602};
2603
2604struct target_mc_fpu {
2605 union {
2606 uint32_t sregs[32];
2607 uint64_t dregs[32];
2608 //uint128_t qregs[16];
2609 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002610 abi_ulong mcfpu_fsr;
2611 abi_ulong mcfpu_fprs;
2612 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002613 struct target_mc_fq *mcfpu_fq;
2614 unsigned char mcfpu_qcnt;
2615 unsigned char mcfpu_qentsz;
2616 unsigned char mcfpu_enab;
2617};
Anthony Liguoric227f092009-10-01 16:12:16 -05002618typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002619
2620typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002621 target_mc_gregset_t mc_gregs;
2622 target_mc_greg_t mc_fp;
2623 target_mc_greg_t mc_i7;
2624 target_mc_fpu_t mc_fpregs;
2625} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002626
2627struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002628 struct target_ucontext *tuc_link;
2629 abi_ulong tuc_flags;
2630 target_sigset_t tuc_sigmask;
2631 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002632};
2633
2634/* A V9 register window */
2635struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002636 abi_ulong locals[8];
2637 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002638};
2639
2640#define TARGET_STACK_BIAS 2047
2641
2642/* {set, get}context() needed for 64-bit SparcLinux userland. */
2643void sparc64_set_context(CPUSPARCState *env)
2644{
bellard459a4012007-11-11 19:45:10 +00002645 abi_ulong ucp_addr;
2646 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002647 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002648 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002649 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002650 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002651
bellard459a4012007-11-11 19:45:10 +00002652 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002653 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002654 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002655 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002656 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002657 __get_user(pc, &((*grp)[MC_PC]));
2658 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002659 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002660 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002661 }
blueswir15bfb56b2007-10-05 17:01:51 +00002662 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002663 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002664 sigset_t set;
2665
2666 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002667 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002668 } else {
bellard459a4012007-11-11 19:45:10 +00002669 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002670 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002671 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002672 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002673 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002674 }
blueswir15bfb56b2007-10-05 17:01:51 +00002675 }
2676 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002677 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002678 }
2679 env->pc = pc;
2680 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002681 __get_user(env->y, &((*grp)[MC_Y]));
2682 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002683 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002684 cpu_put_ccr(env, tstate >> 32);
2685 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002686 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2687 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2688 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2689 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2690 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2691 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2692 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2693 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2694 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2695 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2696 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2697 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2698 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2699 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2700 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002701
Riku Voipio1d8b5122014-04-23 10:26:05 +03002702 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2703 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002704
bellard459a4012007-11-11 19:45:10 +00002705 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002706 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2707 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002708 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002709 }
2710 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2711 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002712 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002713 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002714 /* FIXME this does not match how the kernel handles the FPU in
2715 * its sparc64_set_context implementation. In particular the FPU
2716 * is only restored if fenab is non-zero in:
2717 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2718 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002719 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002720 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002721 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2722 for (i = 0; i < 64; i++, src++) {
2723 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002724 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002725 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002726 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002727 }
2728 }
bellard459a4012007-11-11 19:45:10 +00002729 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002730 __get_user(env->fsr,
2731 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2732 __get_user(env->gsr,
2733 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002734 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002735 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002736do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002737 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002738 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002739}
2740
2741void sparc64_get_context(CPUSPARCState *env)
2742{
bellard459a4012007-11-11 19:45:10 +00002743 abi_ulong ucp_addr;
2744 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002745 target_mc_gregset_t *grp;
2746 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002747 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002748 int err;
2749 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002750 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002751 sigset_t set;
2752
bellard459a4012007-11-11 19:45:10 +00002753 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002754 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002755 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002756 }
bellard459a4012007-11-11 19:45:10 +00002757
Aurelien Jarno60e99242010-03-29 02:12:51 +02002758 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002759 grp = &mcp->mc_gregs;
2760
2761 /* Skip over the trap instruction, first. */
2762 env->pc = env->npc;
2763 env->npc += 4;
2764
Peter Maydell3d3efba2016-05-27 15:51:49 +01002765 /* If we're only reading the signal mask then do_sigprocmask()
2766 * is guaranteed not to fail, which is important because we don't
2767 * have any way to signal a failure or restart this operation since
2768 * this is not a normal syscall.
2769 */
2770 err = do_sigprocmask(0, NULL, &set);
2771 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002772 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002773 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002774 __put_user(target_set.sig[0],
2775 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002776 } else {
2777 abi_ulong *src, *dst;
2778 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002779 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002780 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002781 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002782 }
blueswir15bfb56b2007-10-05 17:01:51 +00002783 if (err)
2784 goto do_sigsegv;
2785 }
2786
bellard459a4012007-11-11 19:45:10 +00002787 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002788 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2789 __put_user(env->pc, &((*grp)[MC_PC]));
2790 __put_user(env->npc, &((*grp)[MC_NPC]));
2791 __put_user(env->y, &((*grp)[MC_Y]));
2792 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2793 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2794 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2795 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2796 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2797 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2798 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2799 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2800 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2801 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2802 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2803 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2804 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2805 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2806 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002807
bellard459a4012007-11-11 19:45:10 +00002808 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2809 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002810 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2811 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002812 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002813 }
2814 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2815 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002816 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002817 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002818 __put_user(fp, &(mcp->mc_fp));
2819 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002820
bellard459a4012007-11-11 19:45:10 +00002821 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002822 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2823 for (i = 0; i < 64; i++, dst++) {
2824 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002825 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002826 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002827 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002828 }
2829 }
bellard459a4012007-11-11 19:45:10 +00002830 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002831 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2832 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2833 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002834
2835 if (err)
2836 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002837 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002838 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002839do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002840 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002841 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002842}
2843#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002844#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002845
Richard Hendersonff970902013-02-10 10:30:42 -08002846# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002847struct target_sigcontext {
2848 uint32_t sc_regmask; /* Unused */
2849 uint32_t sc_status;
2850 uint64_t sc_pc;
2851 uint64_t sc_regs[32];
2852 uint64_t sc_fpregs[32];
2853 uint32_t sc_ownedfp; /* Unused */
2854 uint32_t sc_fpc_csr;
2855 uint32_t sc_fpc_eir; /* Unused */
2856 uint32_t sc_used_math;
2857 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002858 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002859 uint64_t sc_mdhi;
2860 uint64_t sc_mdlo;
2861 target_ulong sc_hi1; /* Was sc_cause */
2862 target_ulong sc_lo1; /* Was sc_badvaddr */
2863 target_ulong sc_hi2; /* Was sc_sigset[4] */
2864 target_ulong sc_lo2;
2865 target_ulong sc_hi3;
2866 target_ulong sc_lo3;
2867};
Richard Hendersonff970902013-02-10 10:30:42 -08002868# else /* N32 || N64 */
2869struct target_sigcontext {
2870 uint64_t sc_regs[32];
2871 uint64_t sc_fpregs[32];
2872 uint64_t sc_mdhi;
2873 uint64_t sc_hi1;
2874 uint64_t sc_hi2;
2875 uint64_t sc_hi3;
2876 uint64_t sc_mdlo;
2877 uint64_t sc_lo1;
2878 uint64_t sc_lo2;
2879 uint64_t sc_lo3;
2880 uint64_t sc_pc;
2881 uint32_t sc_fpc_csr;
2882 uint32_t sc_used_math;
2883 uint32_t sc_dsp;
2884 uint32_t sc_reserved;
2885};
2886# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002887
2888struct sigframe {
2889 uint32_t sf_ass[4]; /* argument save space for o32 */
2890 uint32_t sf_code[2]; /* signal trampoline */
2891 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002892 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002893};
2894
pbrook0b1bcb02009-04-21 01:41:10 +00002895struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002896 target_ulong tuc_flags;
2897 target_ulong tuc_link;
2898 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002899 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002900 struct target_sigcontext tuc_mcontext;
2901 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002902};
2903
2904struct target_rt_sigframe {
2905 uint32_t rs_ass[4]; /* argument save space for o32 */
2906 uint32_t rs_code[2]; /* signal trampoline */
2907 struct target_siginfo rs_info;
2908 struct target_ucontext rs_uc;
2909};
2910
bellard106ec872006-06-27 21:08:10 +00002911/* Install trampoline to jump back from signal handler */
2912static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2913{
Richard Henderson084d0492013-02-10 10:30:44 -08002914 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002915
2916 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002917 * Set up the return code ...
2918 *
2919 * li v0, __NR__foo_sigreturn
2920 * syscall
2921 */
bellard106ec872006-06-27 21:08:10 +00002922
Riku Voipio1d8b5122014-04-23 10:26:05 +03002923 __put_user(0x24020000 + syscall, tramp + 0);
2924 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002925 return err;
2926}
2927
Riku Voipio41ecc722014-04-23 11:01:00 +03002928static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002929 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002930{
Richard Henderson084d0492013-02-10 10:30:44 -08002931 int i;
bellard106ec872006-06-27 21:08:10 +00002932
Riku Voipio1d8b5122014-04-23 10:26:05 +03002933 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002934 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002935
Richard Henderson084d0492013-02-10 10:30:44 -08002936 __put_user(0, &sc->sc_regs[0]);
2937 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002938 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002939 }
bellard106ec872006-06-27 21:08:10 +00002940
Riku Voipio1d8b5122014-04-23 10:26:05 +03002941 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2942 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002943
Richard Henderson084d0492013-02-10 10:30:44 -08002944 /* Rather than checking for dsp existence, always copy. The storage
2945 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002946 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2947 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2948 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2949 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2950 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2951 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002952 {
2953 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002954 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002955 }
Richard Henderson084d0492013-02-10 10:30:44 -08002956
Riku Voipio1d8b5122014-04-23 10:26:05 +03002957 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002958
2959 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002960 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002961 }
bellard106ec872006-06-27 21:08:10 +00002962}
2963
Riku Voipio016d2e12014-04-23 11:19:48 +03002964static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002965restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002966{
Richard Henderson084d0492013-02-10 10:30:44 -08002967 int i;
bellard106ec872006-06-27 21:08:10 +00002968
Riku Voipio1d8b5122014-04-23 10:26:05 +03002969 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002970
Riku Voipio1d8b5122014-04-23 10:26:05 +03002971 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2972 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002973
Richard Henderson084d0492013-02-10 10:30:44 -08002974 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002975 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002976 }
2977
Riku Voipio1d8b5122014-04-23 10:26:05 +03002978 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2979 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2980 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2981 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2982 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2983 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002984 {
2985 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002986 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002987 cpu_wrdsp(dsp, 0x3ff, regs);
2988 }
2989
2990 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002991 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002992 }
bellard106ec872006-06-27 21:08:10 +00002993}
Richard Hendersonff970902013-02-10 10:30:42 -08002994
bellard106ec872006-06-27 21:08:10 +00002995/*
2996 * Determine which stack to use..
2997 */
bellard579a97f2007-11-11 14:26:47 +00002998static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002999get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003000{
3001 unsigned long sp;
3002
3003 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003004 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003005
3006 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003007 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003008 * above the user stack, 16-bytes before the next lowest
3009 * 16 byte boundary. Try to avoid trashing it.
3010 */
3011 sp -= 32;
3012
bellard106ec872006-06-27 21:08:10 +00003013 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003014 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003015 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3016 }
bellard106ec872006-06-27 21:08:10 +00003017
bellard579a97f2007-11-11 14:26:47 +00003018 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003019}
3020
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003021static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3022{
3023 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3024 env->hflags &= ~MIPS_HFLAG_M16;
3025 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3026 env->active_tc.PC &= ~(target_ulong) 1;
3027 }
3028}
3029
Richard Hendersonff970902013-02-10 10:30:42 -08003030# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003031/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003032static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003033 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003034{
3035 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003036 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003037 int i;
3038
bellard579a97f2007-11-11 14:26:47 +00003039 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003040 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003041 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3042 goto give_sigsegv;
3043 }
bellard106ec872006-06-27 21:08:10 +00003044
3045 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3046
Riku Voipio41ecc722014-04-23 11:01:00 +03003047 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003048
3049 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003050 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003051 }
3052
3053 /*
3054 * Arguments to signal handler:
3055 *
3056 * a0 = signal number
3057 * a1 = 0 (should be cause)
3058 * a2 = pointer to struct sigcontext
3059 *
3060 * $25 and PC point to the signal handler, $29 points to the
3061 * struct sigframe.
3062 */
thsb5dc7732008-06-27 10:02:35 +00003063 regs->active_tc.gpr[ 4] = sig;
3064 regs->active_tc.gpr[ 5] = 0;
3065 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3066 regs->active_tc.gpr[29] = frame_addr;
3067 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003068 /* The original kernel code sets CP0_EPC to the handler
3069 * since it returns to userland using eret
3070 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003071 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003072 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003073 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003074 return;
3075
3076give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003077 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003078}
3079
Andreas Färber05390242012-02-25 03:37:53 +01003080long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003081{
ths388bb212007-05-13 13:58:00 +00003082 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003083 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003084 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003085 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003086 int i;
bellard106ec872006-06-27 21:08:10 +00003087
thsb5dc7732008-06-27 10:02:35 +00003088 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003089 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003090 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003091 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003092
ths388bb212007-05-13 13:58:00 +00003093 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003094 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003095 }
bellard106ec872006-06-27 21:08:10 +00003096
ths388bb212007-05-13 13:58:00 +00003097 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003098 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003099
Riku Voipio016d2e12014-04-23 11:19:48 +03003100 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003101
3102#if 0
ths388bb212007-05-13 13:58:00 +00003103 /*
3104 * Don't let your children do this ...
3105 */
3106 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003107 "move\t$29, %0\n\t"
3108 "j\tsyscall_exit"
3109 :/* no outputs */
3110 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003111 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003112#endif
ths3b46e622007-09-17 08:09:54 +00003113
thsb5dc7732008-06-27 10:02:35 +00003114 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003115 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003116 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003117 * maybe a problem with nested signals ? */
3118 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003119 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003120
3121badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003122 force_sig(TARGET_SIGSEGV);
3123 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003124}
Richard Hendersonff970902013-02-10 10:30:42 -08003125# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003126
pbrook624f7972008-05-31 16:11:38 +00003127static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003128 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003129 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003130{
pbrook0b1bcb02009-04-21 01:41:10 +00003131 struct target_rt_sigframe *frame;
3132 abi_ulong frame_addr;
3133 int i;
3134
3135 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003136 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003137 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3138 goto give_sigsegv;
3139 }
pbrook0b1bcb02009-04-21 01:41:10 +00003140
3141 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3142
Peter Maydellf6c7a052015-01-08 12:19:48 +00003143 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003144
Aurelien Jarno60e99242010-03-29 02:12:51 +02003145 __put_user(0, &frame->rs_uc.tuc_flags);
3146 __put_user(0, &frame->rs_uc.tuc_link);
3147 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3148 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003149 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003150 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003151
Aurelien Jarno60e99242010-03-29 02:12:51 +02003152 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003153
3154 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003155 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003156 }
3157
3158 /*
3159 * Arguments to signal handler:
3160 *
3161 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003162 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003163 * a2 = pointer to struct ucontext
3164 *
3165 * $25 and PC point to the signal handler, $29 points to the
3166 * struct sigframe.
3167 */
3168 env->active_tc.gpr[ 4] = sig;
3169 env->active_tc.gpr[ 5] = frame_addr
3170 + offsetof(struct target_rt_sigframe, rs_info);
3171 env->active_tc.gpr[ 6] = frame_addr
3172 + offsetof(struct target_rt_sigframe, rs_uc);
3173 env->active_tc.gpr[29] = frame_addr;
3174 env->active_tc.gpr[31] = frame_addr
3175 + offsetof(struct target_rt_sigframe, rs_code);
3176 /* The original kernel code sets CP0_EPC to the handler
3177 * since it returns to userland using eret
3178 * we cannot do this here, and we must set PC directly */
3179 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003180 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003181 unlock_user_struct(frame, frame_addr, 1);
3182 return;
3183
3184give_sigsegv:
3185 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003186 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003187}
3188
Andreas Färber05390242012-02-25 03:37:53 +01003189long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003190{
pbrook0b1bcb02009-04-21 01:41:10 +00003191 struct target_rt_sigframe *frame;
3192 abi_ulong frame_addr;
3193 sigset_t blocked;
3194
pbrook0b1bcb02009-04-21 01:41:10 +00003195 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003196 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003197 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3198 goto badframe;
3199 }
pbrook0b1bcb02009-04-21 01:41:10 +00003200
Aurelien Jarno60e99242010-03-29 02:12:51 +02003201 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003202 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003203
Riku Voipio016d2e12014-04-23 11:19:48 +03003204 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003205
3206 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003207 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3208 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003209 goto badframe;
3210
3211 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003212 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003213 /* I am not sure this is right, but it seems to work
3214 * maybe a problem with nested signals ? */
3215 env->CP0_EPC = 0;
3216 return -TARGET_QEMU_ESIGRETURN;
3217
3218badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003219 force_sig(TARGET_SIGSEGV);
3220 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003221}
bellard6d5e2162004-09-30 22:04:13 +00003222
thsc3b5bc82007-12-02 06:31:25 +00003223#elif defined(TARGET_SH4)
3224
3225/*
3226 * code and data structures from linux kernel:
3227 * include/asm-sh/sigcontext.h
3228 * arch/sh/kernel/signal.c
3229 */
3230
3231struct target_sigcontext {
3232 target_ulong oldmask;
3233
3234 /* CPU registers */
3235 target_ulong sc_gregs[16];
3236 target_ulong sc_pc;
3237 target_ulong sc_pr;
3238 target_ulong sc_sr;
3239 target_ulong sc_gbr;
3240 target_ulong sc_mach;
3241 target_ulong sc_macl;
3242
3243 /* FPU registers */
3244 target_ulong sc_fpregs[16];
3245 target_ulong sc_xfpregs[16];
3246 unsigned int sc_fpscr;
3247 unsigned int sc_fpul;
3248 unsigned int sc_ownedfp;
3249};
3250
3251struct target_sigframe
3252{
3253 struct target_sigcontext sc;
3254 target_ulong extramask[TARGET_NSIG_WORDS-1];
3255 uint16_t retcode[3];
3256};
3257
3258
3259struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003260 target_ulong tuc_flags;
3261 struct target_ucontext *tuc_link;
3262 target_stack_t tuc_stack;
3263 struct target_sigcontext tuc_mcontext;
3264 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003265};
3266
3267struct target_rt_sigframe
3268{
3269 struct target_siginfo info;
3270 struct target_ucontext uc;
3271 uint16_t retcode[3];
3272};
3273
3274
3275#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3276#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3277
pbrook624f7972008-05-31 16:11:38 +00003278static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003279 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003280{
pbrook624f7972008-05-31 16:11:38 +00003281 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003282 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3283 }
3284
3285 return (sp - frame_size) & -8ul;
3286}
3287
Riku Voipio41ecc722014-04-23 11:01:00 +03003288static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003289 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003290{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003291 int i;
thsc3b5bc82007-12-02 06:31:25 +00003292
Riku Voipio1d8b5122014-04-23 10:26:05 +03003293#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003294 COPY(gregs[0]); COPY(gregs[1]);
3295 COPY(gregs[2]); COPY(gregs[3]);
3296 COPY(gregs[4]); COPY(gregs[5]);
3297 COPY(gregs[6]); COPY(gregs[7]);
3298 COPY(gregs[8]); COPY(gregs[9]);
3299 COPY(gregs[10]); COPY(gregs[11]);
3300 COPY(gregs[12]); COPY(gregs[13]);
3301 COPY(gregs[14]); COPY(gregs[15]);
3302 COPY(gbr); COPY(mach);
3303 COPY(macl); COPY(pr);
3304 COPY(sr); COPY(pc);
3305#undef COPY
3306
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003307 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003308 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003309 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003310 __put_user(regs->fpscr, &sc->sc_fpscr);
3311 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003312
3313 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003314 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003315}
3316
Timothy E Baldwinba412492016-05-12 18:47:35 +01003317static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003318{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003319 int i;
thsc3b5bc82007-12-02 06:31:25 +00003320
Riku Voipio1d8b5122014-04-23 10:26:05 +03003321#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003322 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003323 COPY(gregs[2]); COPY(gregs[3]);
3324 COPY(gregs[4]); COPY(gregs[5]);
3325 COPY(gregs[6]); COPY(gregs[7]);
3326 COPY(gregs[8]); COPY(gregs[9]);
3327 COPY(gregs[10]); COPY(gregs[11]);
3328 COPY(gregs[12]); COPY(gregs[13]);
3329 COPY(gregs[14]); COPY(gregs[15]);
3330 COPY(gbr); COPY(mach);
3331 COPY(macl); COPY(pr);
3332 COPY(sr); COPY(pc);
3333#undef COPY
3334
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003335 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003336 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003337 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003338 __get_user(regs->fpscr, &sc->sc_fpscr);
3339 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003340
3341 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003342}
3343
pbrook624f7972008-05-31 16:11:38 +00003344static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003345 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003346{
3347 struct target_sigframe *frame;
3348 abi_ulong frame_addr;
3349 int i;
thsc3b5bc82007-12-02 06:31:25 +00003350
3351 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003352 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003353 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3354 goto give_sigsegv;
3355 }
thsc3b5bc82007-12-02 06:31:25 +00003356
Riku Voipio41ecc722014-04-23 11:01:00 +03003357 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003358
3359 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003360 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003361 }
3362
3363 /* Set up to return from userspace. If provided, use a stub
3364 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003365 if (ka->sa_flags & TARGET_SA_RESTORER) {
3366 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003367 } else {
3368 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003369 abi_ulong retcode_addr = frame_addr +
3370 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003371 __put_user(MOVW(2), &frame->retcode[0]);
3372 __put_user(TRAP_NOARG, &frame->retcode[1]);
3373 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003374 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003375 }
3376
thsc3b5bc82007-12-02 06:31:25 +00003377 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003378 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003379 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003380 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003381 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003382 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003383
3384 unlock_user_struct(frame, frame_addr, 1);
3385 return;
3386
3387give_sigsegv:
3388 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003389 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003390}
3391
pbrook624f7972008-05-31 16:11:38 +00003392static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003393 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003394 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003395{
3396 struct target_rt_sigframe *frame;
3397 abi_ulong frame_addr;
3398 int i;
thsc3b5bc82007-12-02 06:31:25 +00003399
3400 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003401 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003402 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3403 goto give_sigsegv;
3404 }
thsc3b5bc82007-12-02 06:31:25 +00003405
Peter Maydellf6c7a052015-01-08 12:19:48 +00003406 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003407
3408 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003409 __put_user(0, &frame->uc.tuc_flags);
3410 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3411 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3412 &frame->uc.tuc_stack.ss_sp);
3413 __put_user(sas_ss_flags(regs->gregs[15]),
3414 &frame->uc.tuc_stack.ss_flags);
3415 __put_user(target_sigaltstack_used.ss_size,
3416 &frame->uc.tuc_stack.ss_size);
3417 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003418 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003419 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003420 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003421 }
3422
3423 /* Set up to return from userspace. If provided, use a stub
3424 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003425 if (ka->sa_flags & TARGET_SA_RESTORER) {
3426 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003427 } else {
3428 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003429 abi_ulong retcode_addr = frame_addr +
3430 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003431 __put_user(MOVW(2), &frame->retcode[0]);
3432 __put_user(TRAP_NOARG, &frame->retcode[1]);
3433 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003434 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003435 }
3436
thsc3b5bc82007-12-02 06:31:25 +00003437 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003438 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003439 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003440 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3441 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003442 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003443
3444 unlock_user_struct(frame, frame_addr, 1);
3445 return;
3446
3447give_sigsegv:
3448 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003449 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003450}
3451
Andreas Färber05390242012-02-25 03:37:53 +01003452long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003453{
3454 struct target_sigframe *frame;
3455 abi_ulong frame_addr;
3456 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003457 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003458 int i;
3459 int err = 0;
3460
thsc3b5bc82007-12-02 06:31:25 +00003461 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003462 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003463 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3464 goto badframe;
3465 }
thsc3b5bc82007-12-02 06:31:25 +00003466
Riku Voipio1d8b5122014-04-23 10:26:05 +03003467 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003468 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003469 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003470 }
3471
3472 if (err)
3473 goto badframe;
3474
3475 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003476 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003477
Timothy E Baldwinba412492016-05-12 18:47:35 +01003478 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003479
3480 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003481 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003482
3483badframe:
3484 unlock_user_struct(frame, frame_addr, 0);
3485 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003486 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003487}
3488
Andreas Färber05390242012-02-25 03:37:53 +01003489long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003490{
3491 struct target_rt_sigframe *frame;
3492 abi_ulong frame_addr;
3493 sigset_t blocked;
3494
thsc3b5bc82007-12-02 06:31:25 +00003495 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003496 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003497 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3498 goto badframe;
3499 }
thsc3b5bc82007-12-02 06:31:25 +00003500
Aurelien Jarno60e99242010-03-29 02:12:51 +02003501 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003502 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003503
Timothy E Baldwinba412492016-05-12 18:47:35 +01003504 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003505
3506 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003507 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3508 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003509 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003510 }
thsc3b5bc82007-12-02 06:31:25 +00003511
3512 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003513 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003514
3515badframe:
3516 unlock_user_struct(frame, frame_addr, 0);
3517 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003518 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003519}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003520#elif defined(TARGET_MICROBLAZE)
3521
3522struct target_sigcontext {
3523 struct target_pt_regs regs; /* needs to be first */
3524 uint32_t oldmask;
3525};
3526
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003527struct target_stack_t {
3528 abi_ulong ss_sp;
3529 int ss_flags;
3530 unsigned int ss_size;
3531};
3532
3533struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003534 abi_ulong tuc_flags;
3535 abi_ulong tuc_link;
3536 struct target_stack_t tuc_stack;
3537 struct target_sigcontext tuc_mcontext;
3538 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003539};
3540
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003541/* Signal frames. */
3542struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003543 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003544 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3545 uint32_t tramp[2];
3546};
3547
3548struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003549 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003550 struct ucontext uc;
3551 uint32_t tramp[2];
3552};
3553
Andreas Färber05390242012-02-25 03:37:53 +01003554static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003555{
3556 __put_user(env->regs[0], &sc->regs.r0);
3557 __put_user(env->regs[1], &sc->regs.r1);
3558 __put_user(env->regs[2], &sc->regs.r2);
3559 __put_user(env->regs[3], &sc->regs.r3);
3560 __put_user(env->regs[4], &sc->regs.r4);
3561 __put_user(env->regs[5], &sc->regs.r5);
3562 __put_user(env->regs[6], &sc->regs.r6);
3563 __put_user(env->regs[7], &sc->regs.r7);
3564 __put_user(env->regs[8], &sc->regs.r8);
3565 __put_user(env->regs[9], &sc->regs.r9);
3566 __put_user(env->regs[10], &sc->regs.r10);
3567 __put_user(env->regs[11], &sc->regs.r11);
3568 __put_user(env->regs[12], &sc->regs.r12);
3569 __put_user(env->regs[13], &sc->regs.r13);
3570 __put_user(env->regs[14], &sc->regs.r14);
3571 __put_user(env->regs[15], &sc->regs.r15);
3572 __put_user(env->regs[16], &sc->regs.r16);
3573 __put_user(env->regs[17], &sc->regs.r17);
3574 __put_user(env->regs[18], &sc->regs.r18);
3575 __put_user(env->regs[19], &sc->regs.r19);
3576 __put_user(env->regs[20], &sc->regs.r20);
3577 __put_user(env->regs[21], &sc->regs.r21);
3578 __put_user(env->regs[22], &sc->regs.r22);
3579 __put_user(env->regs[23], &sc->regs.r23);
3580 __put_user(env->regs[24], &sc->regs.r24);
3581 __put_user(env->regs[25], &sc->regs.r25);
3582 __put_user(env->regs[26], &sc->regs.r26);
3583 __put_user(env->regs[27], &sc->regs.r27);
3584 __put_user(env->regs[28], &sc->regs.r28);
3585 __put_user(env->regs[29], &sc->regs.r29);
3586 __put_user(env->regs[30], &sc->regs.r30);
3587 __put_user(env->regs[31], &sc->regs.r31);
3588 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3589}
3590
Andreas Färber05390242012-02-25 03:37:53 +01003591static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003592{
3593 __get_user(env->regs[0], &sc->regs.r0);
3594 __get_user(env->regs[1], &sc->regs.r1);
3595 __get_user(env->regs[2], &sc->regs.r2);
3596 __get_user(env->regs[3], &sc->regs.r3);
3597 __get_user(env->regs[4], &sc->regs.r4);
3598 __get_user(env->regs[5], &sc->regs.r5);
3599 __get_user(env->regs[6], &sc->regs.r6);
3600 __get_user(env->regs[7], &sc->regs.r7);
3601 __get_user(env->regs[8], &sc->regs.r8);
3602 __get_user(env->regs[9], &sc->regs.r9);
3603 __get_user(env->regs[10], &sc->regs.r10);
3604 __get_user(env->regs[11], &sc->regs.r11);
3605 __get_user(env->regs[12], &sc->regs.r12);
3606 __get_user(env->regs[13], &sc->regs.r13);
3607 __get_user(env->regs[14], &sc->regs.r14);
3608 __get_user(env->regs[15], &sc->regs.r15);
3609 __get_user(env->regs[16], &sc->regs.r16);
3610 __get_user(env->regs[17], &sc->regs.r17);
3611 __get_user(env->regs[18], &sc->regs.r18);
3612 __get_user(env->regs[19], &sc->regs.r19);
3613 __get_user(env->regs[20], &sc->regs.r20);
3614 __get_user(env->regs[21], &sc->regs.r21);
3615 __get_user(env->regs[22], &sc->regs.r22);
3616 __get_user(env->regs[23], &sc->regs.r23);
3617 __get_user(env->regs[24], &sc->regs.r24);
3618 __get_user(env->regs[25], &sc->regs.r25);
3619 __get_user(env->regs[26], &sc->regs.r26);
3620 __get_user(env->regs[27], &sc->regs.r27);
3621 __get_user(env->regs[28], &sc->regs.r28);
3622 __get_user(env->regs[29], &sc->regs.r29);
3623 __get_user(env->regs[30], &sc->regs.r30);
3624 __get_user(env->regs[31], &sc->regs.r31);
3625 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3626}
3627
3628static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003629 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003630{
3631 abi_ulong sp = env->regs[1];
3632
Riku Voipiob545f632014-07-15 17:01:55 +03003633 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003634 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003635 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003636
3637 return ((sp - frame_size) & -8UL);
3638}
3639
3640static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003641 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003642{
3643 struct target_signal_frame *frame;
3644 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003645 int i;
3646
3647 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003648 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003649 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3650 goto badframe;
3651
3652 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003653 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003654
3655 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003656 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003657 }
3658
Richard Hendersonf711df62010-11-22 14:57:52 -08003659 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003660
3661 /* Set up to return from userspace. If provided, use a stub
3662 already in userspace. */
3663 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3664 if (ka->sa_flags & TARGET_SA_RESTORER) {
3665 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3666 } else {
3667 uint32_t t;
3668 /* Note, these encodings are _big endian_! */
3669 /* addi r12, r0, __NR_sigreturn */
3670 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003671 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003672 /* brki r14, 0x8 */
3673 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003674 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003675
3676 /* Return from sighandler will jump to the tramp.
3677 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003678 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3679 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003680 }
3681
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003682 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003683 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003684 /* Signal handler args: */
3685 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003686 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003687 /* arg 1: sigcontext */
3688 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003689
3690 /* Offset of 4 to handle microblaze rtid r14, 0 */
3691 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3692
3693 unlock_user_struct(frame, frame_addr, 1);
3694 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003695badframe:
Peter Maydell09391662016-07-28 16:44:47 +01003696 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003697}
3698
3699static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003700 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003701 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003702{
3703 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3704}
3705
Andreas Färber05390242012-02-25 03:37:53 +01003706long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003707{
3708 struct target_signal_frame *frame;
3709 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003710 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003711 sigset_t set;
3712 int i;
3713
3714 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003715 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003716 /* Make sure the guest isn't playing games. */
3717 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3718 goto badframe;
3719
3720 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003721 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003722 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003723 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003724 }
3725 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003726 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003727
Richard Hendersonf711df62010-11-22 14:57:52 -08003728 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003729 /* We got here through a sigreturn syscall, our path back is via an
3730 rtb insn so setup r14 for that. */
3731 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003732
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003733 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003734 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003735badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003736 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003737 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003738}
3739
Andreas Färber05390242012-02-25 03:37:53 +01003740long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003741{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003742 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003743 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3744 return -TARGET_ENOSYS;
3745}
3746
edgar_iglb6d3abd2008-02-28 11:29:27 +00003747#elif defined(TARGET_CRIS)
3748
3749struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003750 struct target_pt_regs regs; /* needs to be first */
3751 uint32_t oldmask;
3752 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003753};
3754
3755/* Signal frames. */
3756struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003757 struct target_sigcontext sc;
3758 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3759 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003760};
3761
3762struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003763 siginfo_t *pinfo;
3764 void *puc;
3765 siginfo_t info;
3766 struct ucontext uc;
3767 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003768};
3769
Andreas Färber05390242012-02-25 03:37:53 +01003770static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003771{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003772 __put_user(env->regs[0], &sc->regs.r0);
3773 __put_user(env->regs[1], &sc->regs.r1);
3774 __put_user(env->regs[2], &sc->regs.r2);
3775 __put_user(env->regs[3], &sc->regs.r3);
3776 __put_user(env->regs[4], &sc->regs.r4);
3777 __put_user(env->regs[5], &sc->regs.r5);
3778 __put_user(env->regs[6], &sc->regs.r6);
3779 __put_user(env->regs[7], &sc->regs.r7);
3780 __put_user(env->regs[8], &sc->regs.r8);
3781 __put_user(env->regs[9], &sc->regs.r9);
3782 __put_user(env->regs[10], &sc->regs.r10);
3783 __put_user(env->regs[11], &sc->regs.r11);
3784 __put_user(env->regs[12], &sc->regs.r12);
3785 __put_user(env->regs[13], &sc->regs.r13);
3786 __put_user(env->regs[14], &sc->usp);
3787 __put_user(env->regs[15], &sc->regs.acr);
3788 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3789 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3790 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003791}
edgar_igl9664d922008-03-03 22:23:53 +00003792
Andreas Färber05390242012-02-25 03:37:53 +01003793static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003794{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003795 __get_user(env->regs[0], &sc->regs.r0);
3796 __get_user(env->regs[1], &sc->regs.r1);
3797 __get_user(env->regs[2], &sc->regs.r2);
3798 __get_user(env->regs[3], &sc->regs.r3);
3799 __get_user(env->regs[4], &sc->regs.r4);
3800 __get_user(env->regs[5], &sc->regs.r5);
3801 __get_user(env->regs[6], &sc->regs.r6);
3802 __get_user(env->regs[7], &sc->regs.r7);
3803 __get_user(env->regs[8], &sc->regs.r8);
3804 __get_user(env->regs[9], &sc->regs.r9);
3805 __get_user(env->regs[10], &sc->regs.r10);
3806 __get_user(env->regs[11], &sc->regs.r11);
3807 __get_user(env->regs[12], &sc->regs.r12);
3808 __get_user(env->regs[13], &sc->regs.r13);
3809 __get_user(env->regs[14], &sc->usp);
3810 __get_user(env->regs[15], &sc->regs.acr);
3811 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3812 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3813 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003814}
3815
Andreas Färber05390242012-02-25 03:37:53 +01003816static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003817{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003818 abi_ulong sp;
3819 /* Align the stack downwards to 4. */
3820 sp = (env->regs[R_SP] & ~3);
3821 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003822}
3823
pbrook624f7972008-05-31 16:11:38 +00003824static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003825 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003826{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003827 struct target_signal_frame *frame;
3828 abi_ulong frame_addr;
3829 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003830
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003831 frame_addr = get_sigframe(env, sizeof *frame);
3832 trace_user_setup_frame(env, frame_addr);
3833 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3834 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003835
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003836 /*
3837 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3838 * use this trampoline anymore but it sets it up for GDB.
3839 * In QEMU, using the trampoline simplifies things a bit so we use it.
3840 *
3841 * This is movu.w __NR_sigreturn, r9; break 13;
3842 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003843 __put_user(0x9c5f, frame->retcode+0);
3844 __put_user(TARGET_NR_sigreturn,
3845 frame->retcode + 1);
3846 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003847
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003848 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003849 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003850
Riku Voipio0188fad2014-04-23 13:34:15 +03003851 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3852 __put_user(set->sig[i], &frame->extramask[i - 1]);
3853 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003854
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003855 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003856
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003857 /* Move the stack and setup the arguments for the handler. */
3858 env->regs[R_SP] = frame_addr;
3859 env->regs[10] = sig;
3860 env->pc = (unsigned long) ka->_sa_handler;
3861 /* Link SRP so the guest returns through the trampoline. */
3862 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003863
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003864 unlock_user_struct(frame, frame_addr, 1);
3865 return;
3866badframe:
Peter Maydell09391662016-07-28 16:44:47 +01003867 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003868}
3869
pbrook624f7972008-05-31 16:11:38 +00003870static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003871 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003872 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003873{
3874 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3875}
3876
Andreas Färber05390242012-02-25 03:37:53 +01003877long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003878{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003879 struct target_signal_frame *frame;
3880 abi_ulong frame_addr;
3881 target_sigset_t target_set;
3882 sigset_t set;
3883 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003884
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003885 frame_addr = env->regs[R_SP];
3886 trace_user_do_sigreturn(env, frame_addr);
3887 /* Make sure the guest isn't playing games. */
3888 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3889 goto badframe;
3890 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003891
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003892 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003893 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003894 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003895 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003896 }
3897 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003898 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003899
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003900 restore_sigcontext(&frame->sc, env);
3901 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003902 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003903badframe:
3904 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003905 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003906}
3907
Andreas Färber05390242012-02-25 03:37:53 +01003908long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003909{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003910 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003911 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3912 return -TARGET_ENOSYS;
3913}
thsc3b5bc82007-12-02 06:31:25 +00003914
Jia Liud9627832012-07-20 15:50:52 +08003915#elif defined(TARGET_OPENRISC)
3916
3917struct target_sigcontext {
3918 struct target_pt_regs regs;
3919 abi_ulong oldmask;
3920 abi_ulong usp;
3921};
3922
3923struct target_ucontext {
3924 abi_ulong tuc_flags;
3925 abi_ulong tuc_link;
3926 target_stack_t tuc_stack;
3927 struct target_sigcontext tuc_mcontext;
3928 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3929};
3930
3931struct target_rt_sigframe {
3932 abi_ulong pinfo;
3933 uint64_t puc;
3934 struct target_siginfo info;
3935 struct target_sigcontext sc;
3936 struct target_ucontext uc;
3937 unsigned char retcode[16]; /* trampoline code */
3938};
3939
3940/* This is the asm-generic/ucontext.h version */
3941#if 0
3942static int restore_sigcontext(CPUOpenRISCState *regs,
3943 struct target_sigcontext *sc)
3944{
3945 unsigned int err = 0;
3946 unsigned long old_usp;
3947
3948 /* Alwys make any pending restarted system call return -EINTR */
3949 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3950
3951 /* restore the regs from &sc->regs (same as sc, since regs is first)
3952 * (sc is already checked for VERIFY_READ since the sigframe was
3953 * checked in sys_sigreturn previously)
3954 */
3955
3956 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3957 goto badframe;
3958 }
3959
3960 /* make sure the U-flag is set so user-mode cannot fool us */
3961
3962 regs->sr &= ~SR_SM;
3963
3964 /* restore the old USP as it was before we stacked the sc etc.
3965 * (we cannot just pop the sigcontext since we aligned the sp and
3966 * stuff after pushing it)
3967 */
3968
Riku Voipio1d8b5122014-04-23 10:26:05 +03003969 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003970 phx_signal("old_usp 0x%lx", old_usp);
3971
3972 __PHX__ REALLY /* ??? */
3973 wrusp(old_usp);
3974 regs->gpr[1] = old_usp;
3975
3976 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3977 * after this completes, but we don't use that mechanism. maybe we can
3978 * use it now ?
3979 */
3980
3981 return err;
3982
3983badframe:
3984 return 1;
3985}
3986#endif
3987
3988/* Set up a signal frame. */
3989
Riku Voipio41ecc722014-04-23 11:01:00 +03003990static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003991 CPUOpenRISCState *regs,
3992 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003993{
Jia Liud9627832012-07-20 15:50:52 +08003994 unsigned long usp = regs->gpr[1];
3995
3996 /* copy the regs. they are first in sc so we can use sc directly */
3997
Riku Voipio1d8b5122014-04-23 10:26:05 +03003998 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003999
4000 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4001 the signal handler. The frametype will be restored to its previous
4002 value in restore_sigcontext. */
4003 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4004
4005 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004006 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004007 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004008}
4009
4010static inline unsigned long align_sigframe(unsigned long sp)
4011{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004012 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004013}
4014
4015static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4016 CPUOpenRISCState *regs,
4017 size_t frame_size)
4018{
4019 unsigned long sp = regs->gpr[1];
4020 int onsigstack = on_sig_stack(sp);
4021
4022 /* redzone */
4023 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004024 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004025 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4026 }
4027
4028 sp = align_sigframe(sp - frame_size);
4029
4030 /*
4031 * If we are on the alternate signal stack and would overflow it, don't.
4032 * Return an always-bogus address instead so we will die with SIGSEGV.
4033 */
4034
4035 if (onsigstack && !likely(on_sig_stack(sp))) {
4036 return -1L;
4037 }
4038
4039 return sp;
4040}
4041
Jia Liud9627832012-07-20 15:50:52 +08004042static void setup_rt_frame(int sig, struct target_sigaction *ka,
4043 target_siginfo_t *info,
4044 target_sigset_t *set, CPUOpenRISCState *env)
4045{
4046 int err = 0;
4047 abi_ulong frame_addr;
4048 unsigned long return_ip;
4049 struct target_rt_sigframe *frame;
4050 abi_ulong info_addr, uc_addr;
4051
Jia Liud9627832012-07-20 15:50:52 +08004052 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004053 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004054 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4055 goto give_sigsegv;
4056 }
4057
4058 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004059 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004060 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004061 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004062
4063 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004064 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004065 }
4066
4067 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004068 __put_user(0, &frame->uc.tuc_flags);
4069 __put_user(0, &frame->uc.tuc_link);
4070 __put_user(target_sigaltstack_used.ss_sp,
4071 &frame->uc.tuc_stack.ss_sp);
4072 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
4073 __put_user(target_sigaltstack_used.ss_size,
4074 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004075 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004076
4077 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4078
Jia Liud9627832012-07-20 15:50:52 +08004079 /* trampoline - the desired return ip is the retcode itself */
4080 return_ip = (unsigned long)&frame->retcode;
4081 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004082 __put_user(0xa960, (short *)(frame->retcode + 0));
4083 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4084 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4085 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004086
4087 if (err) {
4088 goto give_sigsegv;
4089 }
4090
4091 /* TODO what is the current->exec_domain stuff and invmap ? */
4092
4093 /* Set up registers for signal handler */
4094 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
4095 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
4096 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
4097 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
4098 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
4099
4100 /* actually move the usp to reflect the stacked frame */
4101 env->gpr[1] = (unsigned long)frame;
4102
4103 return;
4104
4105give_sigsegv:
4106 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004107 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004108}
4109
4110long do_sigreturn(CPUOpenRISCState *env)
4111{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004112 trace_user_do_sigreturn(env, 0);
4113 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004114 return -TARGET_ENOSYS;
4115}
4116
4117long do_rt_sigreturn(CPUOpenRISCState *env)
4118{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004119 trace_user_do_rt_sigreturn(env, 0);
4120 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004121 return -TARGET_ENOSYS;
4122}
4123/* TARGET_OPENRISC */
4124
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004125#elif defined(TARGET_S390X)
4126
4127#define __NUM_GPRS 16
4128#define __NUM_FPRS 16
4129#define __NUM_ACRS 16
4130
4131#define S390_SYSCALL_SIZE 2
4132#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4133
4134#define _SIGCONTEXT_NSIG 64
4135#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4136#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4137#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4138#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4139#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4140
4141typedef struct {
4142 target_psw_t psw;
4143 target_ulong gprs[__NUM_GPRS];
4144 unsigned int acrs[__NUM_ACRS];
4145} target_s390_regs_common;
4146
4147typedef struct {
4148 unsigned int fpc;
4149 double fprs[__NUM_FPRS];
4150} target_s390_fp_regs;
4151
4152typedef struct {
4153 target_s390_regs_common regs;
4154 target_s390_fp_regs fpregs;
4155} target_sigregs;
4156
4157struct target_sigcontext {
4158 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4159 target_sigregs *sregs;
4160};
4161
4162typedef struct {
4163 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4164 struct target_sigcontext sc;
4165 target_sigregs sregs;
4166 int signo;
4167 uint8_t retcode[S390_SYSCALL_SIZE];
4168} sigframe;
4169
4170struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004171 target_ulong tuc_flags;
4172 struct target_ucontext *tuc_link;
4173 target_stack_t tuc_stack;
4174 target_sigregs tuc_mcontext;
4175 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004176};
4177
4178typedef struct {
4179 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4180 uint8_t retcode[S390_SYSCALL_SIZE];
4181 struct target_siginfo info;
4182 struct target_ucontext uc;
4183} rt_sigframe;
4184
4185static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004186get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004187{
4188 abi_ulong sp;
4189
4190 /* Default to using normal stack */
4191 sp = env->regs[15];
4192
4193 /* This is the X/Open sanctioned signal stack switching. */
4194 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4195 if (!sas_ss_flags(sp)) {
4196 sp = target_sigaltstack_used.ss_sp +
4197 target_sigaltstack_used.ss_size;
4198 }
4199 }
4200
4201 /* This is the legacy signal stack switching. */
4202 else if (/* FIXME !user_mode(regs) */ 0 &&
4203 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4204 ka->sa_restorer) {
4205 sp = (abi_ulong) ka->sa_restorer;
4206 }
4207
4208 return (sp - frame_size) & -8ul;
4209}
4210
Andreas Färber05390242012-02-25 03:37:53 +01004211static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004212{
4213 int i;
4214 //save_access_regs(current->thread.acrs); FIXME
4215
4216 /* Copy a 'clean' PSW mask to the user to avoid leaking
4217 information about whether PER is currently on. */
4218 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4219 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4220 for (i = 0; i < 16; i++) {
4221 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4222 }
4223 for (i = 0; i < 16; i++) {
4224 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4225 }
4226 /*
4227 * We have to store the fp registers to current->thread.fp_regs
4228 * to merge them with the emulated registers.
4229 */
4230 //save_fp_regs(&current->thread.fp_regs); FIXME
4231 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004232 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004233 }
4234}
4235
4236static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004237 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004238{
4239 sigframe *frame;
4240 abi_ulong frame_addr;
4241
4242 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004243 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004244 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004245 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004246 }
4247
Riku Voipio0188fad2014-04-23 13:34:15 +03004248 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004249
4250 save_sigregs(env, &frame->sregs);
4251
4252 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4253 (abi_ulong *)&frame->sc.sregs);
4254
4255 /* Set up to return from userspace. If provided, use a stub
4256 already in userspace. */
4257 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004258 env->regs[14] = (unsigned long)
4259 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004260 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004261 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4262 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004263 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4264 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004265 }
4266
4267 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004268 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004269
4270 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004271 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004272 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4273
4274 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004275 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004276
4277 /* We forgot to include these in the sigcontext.
4278 To avoid breaking binary compatibility, they are passed as args. */
4279 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4280 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4281
4282 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02004283 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004284 unlock_user_struct(frame, frame_addr, 1);
4285 return;
4286
4287give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004288 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004289}
4290
4291static void setup_rt_frame(int sig, struct target_sigaction *ka,
4292 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004293 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004294{
4295 int i;
4296 rt_sigframe *frame;
4297 abi_ulong frame_addr;
4298
4299 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004300 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004301 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4302 goto give_sigsegv;
4303 }
4304
Peter Maydellf6c7a052015-01-08 12:19:48 +00004305 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004306
4307 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004308 __put_user(0, &frame->uc.tuc_flags);
4309 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4310 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004311 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004312 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004313 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4314 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004315 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4316 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004317 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004318 }
4319
4320 /* Set up to return from userspace. If provided, use a stub
4321 already in userspace. */
4322 if (ka->sa_flags & TARGET_SA_RESTORER) {
4323 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4324 } else {
4325 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004326 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4327 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004328 }
4329
4330 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004331 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004332
4333 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004334 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004335 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4336
4337 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004338 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4339 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004340 return;
4341
4342give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004343 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004344}
4345
4346static int
Andreas Färber05390242012-02-25 03:37:53 +01004347restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004348{
4349 int err = 0;
4350 int i;
4351
4352 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004353 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004354 }
4355
Riku Voipio1d8b5122014-04-23 10:26:05 +03004356 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004357 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4358 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004359 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004360 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4361
4362 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004363 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004364 }
4365 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004366 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004367 }
4368
4369 return err;
4370}
4371
Andreas Färber05390242012-02-25 03:37:53 +01004372long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004373{
4374 sigframe *frame;
4375 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004376 target_sigset_t target_set;
4377 sigset_t set;
4378
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004379 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004380 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4381 goto badframe;
4382 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004383 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004384
4385 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004386 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004387
4388 if (restore_sigregs(env, &frame->sregs)) {
4389 goto badframe;
4390 }
4391
4392 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004393 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004394
4395badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004396 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004397 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004398}
4399
Andreas Färber05390242012-02-25 03:37:53 +01004400long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004401{
4402 rt_sigframe *frame;
4403 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004404 sigset_t set;
4405
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004406 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004407 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4408 goto badframe;
4409 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004410 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004411
Peter Maydell9eede5b2016-05-27 15:51:46 +01004412 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004413
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004414 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004415 goto badframe;
4416 }
4417
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004418 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004419 get_sp_from_cpustate(env)) == -EFAULT) {
4420 goto badframe;
4421 }
4422 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004423 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004424
4425badframe:
4426 unlock_user_struct(frame, frame_addr, 0);
4427 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004428 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004429}
4430
Tom Musta61e75fe2014-06-30 08:13:38 -05004431#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004432
4433/* Size of dummy stack frame allocated when calling signal handler.
4434 See arch/powerpc/include/asm/ptrace.h. */
4435#if defined(TARGET_PPC64)
4436#define SIGNAL_FRAMESIZE 128
4437#else
4438#define SIGNAL_FRAMESIZE 64
4439#endif
4440
Tom Musta61e75fe2014-06-30 08:13:38 -05004441/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4442 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4443struct target_mcontext {
4444 target_ulong mc_gregs[48];
4445 /* Includes fpscr. */
4446 uint64_t mc_fregs[33];
4447 target_ulong mc_pad[2];
4448 /* We need to handle Altivec and SPE at the same time, which no
4449 kernel needs to do. Fortunately, the kernel defines this bit to
4450 be Altivec-register-large all the time, rather than trying to
4451 twiddle it based on the specific platform. */
4452 union {
4453 /* SPE vector registers. One extra for SPEFSCR. */
4454 uint32_t spe[33];
4455 /* Altivec vector registers. The packing of VSCR and VRSAVE
4456 varies depending on whether we're PPC64 or not: PPC64 splits
4457 them apart; PPC32 stuffs them together. */
4458#if defined(TARGET_PPC64)
4459#define QEMU_NVRREG 34
4460#else
4461#define QEMU_NVRREG 33
4462#endif
4463 ppc_avr_t altivec[QEMU_NVRREG];
4464#undef QEMU_NVRREG
4465 } mc_vregs __attribute__((__aligned__(16)));
4466};
4467
Nathan Froydbcd49332009-05-12 19:13:18 -07004468/* See arch/powerpc/include/asm/sigcontext.h. */
4469struct target_sigcontext {
4470 target_ulong _unused[4];
4471 int32_t signal;
4472#if defined(TARGET_PPC64)
4473 int32_t pad0;
4474#endif
4475 target_ulong handler;
4476 target_ulong oldmask;
4477 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004478#if defined(TARGET_PPC64)
4479 struct target_mcontext mcontext;
4480#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004481};
4482
4483/* Indices for target_mcontext.mc_gregs, below.
4484 See arch/powerpc/include/asm/ptrace.h for details. */
4485enum {
4486 TARGET_PT_R0 = 0,
4487 TARGET_PT_R1 = 1,
4488 TARGET_PT_R2 = 2,
4489 TARGET_PT_R3 = 3,
4490 TARGET_PT_R4 = 4,
4491 TARGET_PT_R5 = 5,
4492 TARGET_PT_R6 = 6,
4493 TARGET_PT_R7 = 7,
4494 TARGET_PT_R8 = 8,
4495 TARGET_PT_R9 = 9,
4496 TARGET_PT_R10 = 10,
4497 TARGET_PT_R11 = 11,
4498 TARGET_PT_R12 = 12,
4499 TARGET_PT_R13 = 13,
4500 TARGET_PT_R14 = 14,
4501 TARGET_PT_R15 = 15,
4502 TARGET_PT_R16 = 16,
4503 TARGET_PT_R17 = 17,
4504 TARGET_PT_R18 = 18,
4505 TARGET_PT_R19 = 19,
4506 TARGET_PT_R20 = 20,
4507 TARGET_PT_R21 = 21,
4508 TARGET_PT_R22 = 22,
4509 TARGET_PT_R23 = 23,
4510 TARGET_PT_R24 = 24,
4511 TARGET_PT_R25 = 25,
4512 TARGET_PT_R26 = 26,
4513 TARGET_PT_R27 = 27,
4514 TARGET_PT_R28 = 28,
4515 TARGET_PT_R29 = 29,
4516 TARGET_PT_R30 = 30,
4517 TARGET_PT_R31 = 31,
4518 TARGET_PT_NIP = 32,
4519 TARGET_PT_MSR = 33,
4520 TARGET_PT_ORIG_R3 = 34,
4521 TARGET_PT_CTR = 35,
4522 TARGET_PT_LNK = 36,
4523 TARGET_PT_XER = 37,
4524 TARGET_PT_CCR = 38,
4525 /* Yes, there are two registers with #39. One is 64-bit only. */
4526 TARGET_PT_MQ = 39,
4527 TARGET_PT_SOFTE = 39,
4528 TARGET_PT_TRAP = 40,
4529 TARGET_PT_DAR = 41,
4530 TARGET_PT_DSISR = 42,
4531 TARGET_PT_RESULT = 43,
4532 TARGET_PT_REGS_COUNT = 44
4533};
4534
Nathan Froydbcd49332009-05-12 19:13:18 -07004535
4536struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004537 target_ulong tuc_flags;
4538 target_ulong tuc_link; /* struct ucontext __user * */
4539 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004540#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004541 int32_t tuc_pad[7];
4542 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004543 points to uc_mcontext field */
4544#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004545 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004546#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004547 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004548 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004549#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004550 int32_t tuc_maskext[30];
4551 int32_t tuc_pad2[3];
4552 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004553#endif
4554};
4555
4556/* See arch/powerpc/kernel/signal_32.c. */
4557struct target_sigframe {
4558 struct target_sigcontext sctx;
4559 struct target_mcontext mctx;
4560 int32_t abigap[56];
4561};
4562
Tom Musta61e75fe2014-06-30 08:13:38 -05004563#if defined(TARGET_PPC64)
4564
4565#define TARGET_TRAMP_SIZE 6
4566
4567struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004568 /* sys_rt_sigreturn requires the ucontext be the first field */
4569 struct target_ucontext uc;
4570 target_ulong _unused[2];
4571 uint32_t trampoline[TARGET_TRAMP_SIZE];
4572 target_ulong pinfo; /* struct siginfo __user * */
4573 target_ulong puc; /* void __user * */
4574 struct target_siginfo info;
4575 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4576 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004577} __attribute__((aligned(16)));
4578
4579#else
4580
Nathan Froydbcd49332009-05-12 19:13:18 -07004581struct target_rt_sigframe {
4582 struct target_siginfo info;
4583 struct target_ucontext uc;
4584 int32_t abigap[56];
4585};
4586
Tom Musta61e75fe2014-06-30 08:13:38 -05004587#endif
4588
Tom Musta8d6ab332014-06-30 08:13:39 -05004589#if defined(TARGET_PPC64)
4590
4591struct target_func_ptr {
4592 target_ulong entry;
4593 target_ulong toc;
4594};
4595
4596#endif
4597
Nathan Froydbcd49332009-05-12 19:13:18 -07004598/* We use the mc_pad field for the signal return trampoline. */
4599#define tramp mc_pad
4600
4601/* See arch/powerpc/kernel/signal.c. */
4602static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004603 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004604 int frame_size)
4605{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004606 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07004607
4608 oldsp = env->gpr[1];
4609
4610 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004611 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004612 oldsp = (target_sigaltstack_used.ss_sp
4613 + target_sigaltstack_used.ss_size);
4614 }
4615
Eduardo Habkost9be38592016-06-13 18:57:58 -03004616 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07004617}
4618
Tom Musta76781082014-06-30 08:13:37 -05004619static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004620{
4621 target_ulong msr = env->msr;
4622 int i;
4623 target_ulong ccr = 0;
4624
4625 /* In general, the kernel attempts to be intelligent about what it
4626 needs to save for Altivec/FP/SPE registers. We don't care that
4627 much, so we just go ahead and save everything. */
4628
4629 /* Save general registers. */
4630 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004631 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004632 }
Riku Voipioc650c002014-04-23 13:53:45 +03004633 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4634 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4635 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4636 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004637
4638 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4639 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4640 }
Riku Voipioc650c002014-04-23 13:53:45 +03004641 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004642
4643 /* Save Altivec registers if necessary. */
4644 if (env->insns_flags & PPC_ALTIVEC) {
4645 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004646 ppc_avr_t *avr = &env->avr[i];
4647 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004648
Riku Voipioc650c002014-04-23 13:53:45 +03004649 __put_user(avr->u64[0], &vreg->u64[0]);
4650 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004651 }
4652 /* Set MSR_VR in the saved MSR value to indicate that
4653 frame->mc_vregs contains valid data. */
4654 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004655 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4656 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004657 }
4658
4659 /* Save floating point registers. */
4660 if (env->insns_flags & PPC_FLOAT) {
4661 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004662 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004663 }
Riku Voipioc650c002014-04-23 13:53:45 +03004664 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004665 }
4666
4667 /* Save SPE registers. The kernel only saves the high half. */
4668 if (env->insns_flags & PPC_SPE) {
4669#if defined(TARGET_PPC64)
4670 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004671 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004672 }
4673#else
4674 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004675 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004676 }
4677#endif
4678 /* Set MSR_SPE in the saved MSR value to indicate that
4679 frame->mc_vregs contains valid data. */
4680 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004681 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004682 }
4683
4684 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004685 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004686}
Nathan Froydbcd49332009-05-12 19:13:18 -07004687
Tom Musta76781082014-06-30 08:13:37 -05004688static void encode_trampoline(int sigret, uint32_t *tramp)
4689{
Nathan Froydbcd49332009-05-12 19:13:18 -07004690 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4691 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004692 __put_user(0x38000000 | sigret, &tramp[0]);
4693 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004694 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004695}
4696
Riku Voipioc650c002014-04-23 13:53:45 +03004697static void restore_user_regs(CPUPPCState *env,
4698 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004699{
4700 target_ulong save_r2 = 0;
4701 target_ulong msr;
4702 target_ulong ccr;
4703
4704 int i;
4705
4706 if (!sig) {
4707 save_r2 = env->gpr[2];
4708 }
4709
4710 /* Restore general registers. */
4711 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004712 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004713 }
Riku Voipioc650c002014-04-23 13:53:45 +03004714 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4715 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4716 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4717 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4718 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004719
4720 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4721 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4722 }
4723
4724 if (!sig) {
4725 env->gpr[2] = save_r2;
4726 }
4727 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004728 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004729
4730 /* If doing signal return, restore the previous little-endian mode. */
4731 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004732 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07004733
4734 /* Restore Altivec registers if necessary. */
4735 if (env->insns_flags & PPC_ALTIVEC) {
4736 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004737 ppc_avr_t *avr = &env->avr[i];
4738 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004739
Riku Voipioc650c002014-04-23 13:53:45 +03004740 __get_user(avr->u64[0], &vreg->u64[0]);
4741 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004742 }
4743 /* Set MSR_VEC in the saved MSR value to indicate that
4744 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004745 __get_user(env->spr[SPR_VRSAVE],
4746 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004747 }
4748
4749 /* Restore floating point registers. */
4750 if (env->insns_flags & PPC_FLOAT) {
4751 uint64_t fpscr;
4752 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004753 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004754 }
Riku Voipioc650c002014-04-23 13:53:45 +03004755 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004756 env->fpscr = (uint32_t) fpscr;
4757 }
4758
4759 /* Save SPE registers. The kernel only saves the high half. */
4760 if (env->insns_flags & PPC_SPE) {
4761#if defined(TARGET_PPC64)
4762 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4763 uint32_t hi;
4764
Riku Voipioc650c002014-04-23 13:53:45 +03004765 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004766 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4767 }
4768#else
4769 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004770 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004771 }
4772#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004773 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004774 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004775}
4776
4777static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004778 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004779{
4780 struct target_sigframe *frame;
4781 struct target_sigcontext *sc;
4782 target_ulong frame_addr, newsp;
4783 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004784#if defined(TARGET_PPC64)
4785 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4786#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004787
4788 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004789 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004790 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4791 goto sigsegv;
4792 sc = &frame->sctx;
4793
Riku Voipio1d8b5122014-04-23 10:26:05 +03004794 __put_user(ka->_sa_handler, &sc->handler);
4795 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004796#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004797 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004798#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004799 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004800#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004801 __put_user(h2g(&frame->mctx), &sc->regs);
4802 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004803
4804 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004805 save_user_regs(env, &frame->mctx);
4806
4807 /* Construct the trampoline code on the stack. */
4808 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004809
4810 /* The kernel checks for the presence of a VDSO here. We don't
4811 emulate a vdso, so use a sigreturn system call. */
4812 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4813
4814 /* Turn off all fp exceptions. */
4815 env->fpscr = 0;
4816
4817 /* Create a stack frame for the caller of the handler. */
4818 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004819 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004820
4821 if (err)
4822 goto sigsegv;
4823
4824 /* Set up registers for signal handler. */
4825 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004826 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004827 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004828
4829#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004830 if (get_ppc64_abi(image) < 2) {
4831 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4832 struct target_func_ptr *handler =
4833 (struct target_func_ptr *)g2h(ka->_sa_handler);
4834 env->nip = tswapl(handler->entry);
4835 env->gpr[2] = tswapl(handler->toc);
4836 } else {
4837 /* ELFv2 PPC64 function pointers are entry points, but R12
4838 * must also be set */
4839 env->nip = tswapl((target_ulong) ka->_sa_handler);
4840 env->gpr[12] = env->nip;
4841 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004842#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004843 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004844#endif
4845
Nathan Froydbcd49332009-05-12 19:13:18 -07004846 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004847 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004848
4849 unlock_user_struct(frame, frame_addr, 1);
4850 return;
4851
4852sigsegv:
4853 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004854 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004855}
4856
4857static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004858 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004859 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004860{
4861 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004862 uint32_t *trampptr = 0;
4863 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004864 target_ulong rt_sf_addr, newsp = 0;
4865 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004866#if defined(TARGET_PPC64)
4867 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4868#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004869
4870 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4871 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4872 goto sigsegv;
4873
Peter Maydellf6c7a052015-01-08 12:19:48 +00004874 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004875
Riku Voipio1d8b5122014-04-23 10:26:05 +03004876 __put_user(0, &rt_sf->uc.tuc_flags);
4877 __put_user(0, &rt_sf->uc.tuc_link);
4878 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4879 &rt_sf->uc.tuc_stack.ss_sp);
4880 __put_user(sas_ss_flags(env->gpr[1]),
4881 &rt_sf->uc.tuc_stack.ss_flags);
4882 __put_user(target_sigaltstack_used.ss_size,
4883 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004884#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004885 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4886 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004887#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004888 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004889 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004890 }
4891
Tom Musta61e75fe2014-06-30 08:13:38 -05004892#if defined(TARGET_PPC64)
4893 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4894 trampptr = &rt_sf->trampoline[0];
4895#else
4896 mctx = &rt_sf->uc.tuc_mcontext;
4897 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4898#endif
4899
4900 save_user_regs(env, mctx);
4901 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004902
4903 /* The kernel checks for the presence of a VDSO here. We don't
4904 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004905 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004906
4907 /* Turn off all fp exceptions. */
4908 env->fpscr = 0;
4909
4910 /* Create a stack frame for the caller of the handler. */
4911 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004912 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004913
4914 if (err)
4915 goto sigsegv;
4916
4917 /* Set up registers for signal handler. */
4918 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004919 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004920 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4921 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4922 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004923
4924#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004925 if (get_ppc64_abi(image) < 2) {
4926 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4927 struct target_func_ptr *handler =
4928 (struct target_func_ptr *)g2h(ka->_sa_handler);
4929 env->nip = tswapl(handler->entry);
4930 env->gpr[2] = tswapl(handler->toc);
4931 } else {
4932 /* ELFv2 PPC64 function pointers are entry points, but R12
4933 * must also be set */
4934 env->nip = tswapl((target_ulong) ka->_sa_handler);
4935 env->gpr[12] = env->nip;
4936 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004937#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004938 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004939#endif
4940
Nathan Froydbcd49332009-05-12 19:13:18 -07004941 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004942 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004943
4944 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4945 return;
4946
4947sigsegv:
4948 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004949 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004950
4951}
4952
Andreas Färber05390242012-02-25 03:37:53 +01004953long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004954{
4955 struct target_sigcontext *sc = NULL;
4956 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004957 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004958 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004959 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004960
4961 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4962 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4963 goto sigsegv;
4964
4965#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004966 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004967#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004968 __get_user(set.sig[0], &sc->oldmask);
4969 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004970#endif
4971 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004972 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07004973
Riku Voipiof5f601a2014-04-23 13:00:17 +03004974 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004975 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4976 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004977 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004978
4979 unlock_user_struct(sr, sr_addr, 1);
4980 unlock_user_struct(sc, sc_addr, 1);
4981 return -TARGET_QEMU_ESIGRETURN;
4982
4983sigsegv:
4984 unlock_user_struct(sr, sr_addr, 1);
4985 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004986 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004987 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07004988}
4989
4990/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004991static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004992{
4993 struct target_mcontext *mcp;
4994 target_ulong mcp_addr;
4995 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004996 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004997
Aurelien Jarno60e99242010-03-29 02:12:51 +02004998 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004999 sizeof (set)))
5000 return 1;
5001
Tom Musta19774ec2014-06-30 08:13:40 -05005002#if defined(TARGET_PPC64)
5003 mcp_addr = h2g(ucp) +
5004 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5005#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005006 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005007#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005008
5009 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5010 return 1;
5011
5012 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005013 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005014 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005015
5016 unlock_user_struct(mcp, mcp_addr, 1);
5017 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005018}
5019
Andreas Färber05390242012-02-25 03:37:53 +01005020long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005021{
5022 struct target_rt_sigframe *rt_sf = NULL;
5023 target_ulong rt_sf_addr;
5024
5025 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5026 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5027 goto sigsegv;
5028
5029 if (do_setcontext(&rt_sf->uc, env, 1))
5030 goto sigsegv;
5031
5032 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005033 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005034 0, env->gpr[1]);
5035
5036 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5037 return -TARGET_QEMU_ESIGRETURN;
5038
5039sigsegv:
5040 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005041 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005042 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005043}
5044
Laurent Vivier492a8742009-08-03 16:12:17 +02005045#elif defined(TARGET_M68K)
5046
5047struct target_sigcontext {
5048 abi_ulong sc_mask;
5049 abi_ulong sc_usp;
5050 abi_ulong sc_d0;
5051 abi_ulong sc_d1;
5052 abi_ulong sc_a0;
5053 abi_ulong sc_a1;
5054 unsigned short sc_sr;
5055 abi_ulong sc_pc;
5056};
5057
5058struct target_sigframe
5059{
5060 abi_ulong pretcode;
5061 int sig;
5062 int code;
5063 abi_ulong psc;
5064 char retcode[8];
5065 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5066 struct target_sigcontext sc;
5067};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005068
Anthony Liguoric227f092009-10-01 16:12:16 -05005069typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005070#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005071typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005072
5073typedef struct target_fpregset {
5074 int f_fpcntl[3];
5075 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005076} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005077
5078struct target_mcontext {
5079 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005080 target_gregset_t gregs;
5081 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005082};
5083
5084#define TARGET_MCONTEXT_VERSION 2
5085
5086struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005087 abi_ulong tuc_flags;
5088 abi_ulong tuc_link;
5089 target_stack_t tuc_stack;
5090 struct target_mcontext tuc_mcontext;
5091 abi_long tuc_filler[80];
5092 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005093};
5094
5095struct target_rt_sigframe
5096{
5097 abi_ulong pretcode;
5098 int sig;
5099 abi_ulong pinfo;
5100 abi_ulong puc;
5101 char retcode[8];
5102 struct target_siginfo info;
5103 struct target_ucontext uc;
5104};
Laurent Vivier492a8742009-08-03 16:12:17 +02005105
Riku Voipio41ecc722014-04-23 11:01:00 +03005106static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005107 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005108{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005109 __put_user(mask, &sc->sc_mask);
5110 __put_user(env->aregs[7], &sc->sc_usp);
5111 __put_user(env->dregs[0], &sc->sc_d0);
5112 __put_user(env->dregs[1], &sc->sc_d1);
5113 __put_user(env->aregs[0], &sc->sc_a0);
5114 __put_user(env->aregs[1], &sc->sc_a1);
5115 __put_user(env->sr, &sc->sc_sr);
5116 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005117}
5118
Riku Voipio016d2e12014-04-23 11:19:48 +03005119static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005120restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005121{
Laurent Vivier492a8742009-08-03 16:12:17 +02005122 int temp;
5123
Riku Voipio1d8b5122014-04-23 10:26:05 +03005124 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005125 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005126 __get_user(env->dregs[1], &sc->sc_d1);
5127 __get_user(env->aregs[0], &sc->sc_a0);
5128 __get_user(env->aregs[1], &sc->sc_a1);
5129 __get_user(env->pc, &sc->sc_pc);
5130 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005131 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005132}
5133
5134/*
5135 * Determine which stack to use..
5136 */
5137static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005138get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5139 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005140{
5141 unsigned long sp;
5142
5143 sp = regs->aregs[7];
5144
5145 /* This is the X/Open sanctioned signal stack switching. */
5146 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5147 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5148 }
5149
5150 return ((sp - frame_size) & -8UL);
5151}
5152
5153static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005154 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005155{
5156 struct target_sigframe *frame;
5157 abi_ulong frame_addr;
5158 abi_ulong retcode_addr;
5159 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005160 int i;
5161
5162 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005163 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005164 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5165 goto give_sigsegv;
5166 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005167
Riku Voipio1d8b5122014-04-23 10:26:05 +03005168 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005169
5170 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005171 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005172
Riku Voipio41ecc722014-04-23 11:01:00 +03005173 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005174
5175 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005176 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005177 }
5178
5179 /* Set up to return from userspace. */
5180
5181 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005182 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005183
5184 /* moveq #,d0; trap #0 */
5185
Riku Voipio1d8b5122014-04-23 10:26:05 +03005186 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005187 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005188
Laurent Vivier492a8742009-08-03 16:12:17 +02005189 /* Set up to return from userspace */
5190
5191 env->aregs[7] = frame_addr;
5192 env->pc = ka->_sa_handler;
5193
5194 unlock_user_struct(frame, frame_addr, 1);
5195 return;
5196
5197give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005198 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005199}
5200
Laurent Vivier71811552009-08-03 16:12:18 +02005201static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005202 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005203{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005204 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005205
Riku Voipio1d8b5122014-04-23 10:26:05 +03005206 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5207 __put_user(env->dregs[0], &gregs[0]);
5208 __put_user(env->dregs[1], &gregs[1]);
5209 __put_user(env->dregs[2], &gregs[2]);
5210 __put_user(env->dregs[3], &gregs[3]);
5211 __put_user(env->dregs[4], &gregs[4]);
5212 __put_user(env->dregs[5], &gregs[5]);
5213 __put_user(env->dregs[6], &gregs[6]);
5214 __put_user(env->dregs[7], &gregs[7]);
5215 __put_user(env->aregs[0], &gregs[8]);
5216 __put_user(env->aregs[1], &gregs[9]);
5217 __put_user(env->aregs[2], &gregs[10]);
5218 __put_user(env->aregs[3], &gregs[11]);
5219 __put_user(env->aregs[4], &gregs[12]);
5220 __put_user(env->aregs[5], &gregs[13]);
5221 __put_user(env->aregs[6], &gregs[14]);
5222 __put_user(env->aregs[7], &gregs[15]);
5223 __put_user(env->pc, &gregs[16]);
5224 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005225
Riku Voipio1d8b5122014-04-23 10:26:05 +03005226 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005227}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005228
Andreas Färber05390242012-02-25 03:37:53 +01005229static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005230 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005231{
5232 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005233 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005234
Riku Voipio1d8b5122014-04-23 10:26:05 +03005235 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005236 if (temp != TARGET_MCONTEXT_VERSION)
5237 goto badframe;
5238
5239 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005240 __get_user(env->dregs[0], &gregs[0]);
5241 __get_user(env->dregs[1], &gregs[1]);
5242 __get_user(env->dregs[2], &gregs[2]);
5243 __get_user(env->dregs[3], &gregs[3]);
5244 __get_user(env->dregs[4], &gregs[4]);
5245 __get_user(env->dregs[5], &gregs[5]);
5246 __get_user(env->dregs[6], &gregs[6]);
5247 __get_user(env->dregs[7], &gregs[7]);
5248 __get_user(env->aregs[0], &gregs[8]);
5249 __get_user(env->aregs[1], &gregs[9]);
5250 __get_user(env->aregs[2], &gregs[10]);
5251 __get_user(env->aregs[3], &gregs[11]);
5252 __get_user(env->aregs[4], &gregs[12]);
5253 __get_user(env->aregs[5], &gregs[13]);
5254 __get_user(env->aregs[6], &gregs[14]);
5255 __get_user(env->aregs[7], &gregs[15]);
5256 __get_user(env->pc, &gregs[16]);
5257 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005258 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5259
Riku Voipio1d8b5122014-04-23 10:26:05 +03005260 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005261
5262badframe:
5263 return 1;
5264}
5265
Laurent Vivier492a8742009-08-03 16:12:17 +02005266static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005267 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005268 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005269{
Laurent Vivier71811552009-08-03 16:12:18 +02005270 struct target_rt_sigframe *frame;
5271 abi_ulong frame_addr;
5272 abi_ulong retcode_addr;
5273 abi_ulong info_addr;
5274 abi_ulong uc_addr;
5275 int err = 0;
5276 int i;
5277
5278 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005279 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005280 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5281 goto give_sigsegv;
5282 }
Laurent Vivier71811552009-08-03 16:12:18 +02005283
Riku Voipio1d8b5122014-04-23 10:26:05 +03005284 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005285
5286 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005287 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005288
5289 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005290 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005291
Peter Maydellf6c7a052015-01-08 12:19:48 +00005292 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005293
5294 /* Create the ucontext */
5295
Riku Voipio1d8b5122014-04-23 10:26:05 +03005296 __put_user(0, &frame->uc.tuc_flags);
5297 __put_user(0, &frame->uc.tuc_link);
5298 __put_user(target_sigaltstack_used.ss_sp,
5299 &frame->uc.tuc_stack.ss_sp);
5300 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005301 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005302 __put_user(target_sigaltstack_used.ss_size,
5303 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005304 err |= target_rt_setup_ucontext(&frame->uc, env);
5305
5306 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005307 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005308
5309 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005310 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005311 }
5312
5313 /* Set up to return from userspace. */
5314
5315 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005316 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005317
5318 /* moveq #,d0; notb d0; trap #0 */
5319
Riku Voipio1d8b5122014-04-23 10:26:05 +03005320 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005321 (uint32_t *)(frame->retcode + 0));
5322 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005323
5324 if (err)
5325 goto give_sigsegv;
5326
5327 /* Set up to return from userspace */
5328
5329 env->aregs[7] = frame_addr;
5330 env->pc = ka->_sa_handler;
5331
5332 unlock_user_struct(frame, frame_addr, 1);
5333 return;
5334
5335give_sigsegv:
5336 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005337 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005338}
5339
Andreas Färber05390242012-02-25 03:37:53 +01005340long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005341{
5342 struct target_sigframe *frame;
5343 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005344 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005345 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005346 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005347
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005348 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005349 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5350 goto badframe;
5351
5352 /* set blocked signals */
5353
Riku Voipiof5f601a2014-04-23 13:00:17 +03005354 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005355
5356 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005357 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005358 }
5359
5360 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005361 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005362
5363 /* restore registers */
5364
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005365 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005366
5367 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005368 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005369
5370badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005371 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005372 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005373}
5374
Andreas Färber05390242012-02-25 03:37:53 +01005375long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005376{
Laurent Vivier71811552009-08-03 16:12:18 +02005377 struct target_rt_sigframe *frame;
5378 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005379 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005380 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005381
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005382 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005383 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5384 goto badframe;
5385
5386 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005387 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005388
5389 /* restore registers */
5390
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005391 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005392 goto badframe;
5393
5394 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005395 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005396 0, get_sp_from_cpustate(env)) == -EFAULT)
5397 goto badframe;
5398
5399 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005400 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005401
5402badframe:
5403 unlock_user_struct(frame, frame_addr, 0);
5404 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005405 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005406}
5407
Richard Henderson6049f4f2009-12-27 18:30:03 -08005408#elif defined(TARGET_ALPHA)
5409
5410struct target_sigcontext {
5411 abi_long sc_onstack;
5412 abi_long sc_mask;
5413 abi_long sc_pc;
5414 abi_long sc_ps;
5415 abi_long sc_regs[32];
5416 abi_long sc_ownedfp;
5417 abi_long sc_fpregs[32];
5418 abi_ulong sc_fpcr;
5419 abi_ulong sc_fp_control;
5420 abi_ulong sc_reserved1;
5421 abi_ulong sc_reserved2;
5422 abi_ulong sc_ssize;
5423 abi_ulong sc_sbase;
5424 abi_ulong sc_traparg_a0;
5425 abi_ulong sc_traparg_a1;
5426 abi_ulong sc_traparg_a2;
5427 abi_ulong sc_fp_trap_pc;
5428 abi_ulong sc_fp_trigger_sum;
5429 abi_ulong sc_fp_trigger_inst;
5430};
5431
5432struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005433 abi_ulong tuc_flags;
5434 abi_ulong tuc_link;
5435 abi_ulong tuc_osf_sigmask;
5436 target_stack_t tuc_stack;
5437 struct target_sigcontext tuc_mcontext;
5438 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005439};
5440
5441struct target_sigframe {
5442 struct target_sigcontext sc;
5443 unsigned int retcode[3];
5444};
5445
5446struct target_rt_sigframe {
5447 target_siginfo_t info;
5448 struct target_ucontext uc;
5449 unsigned int retcode[3];
5450};
5451
5452#define INSN_MOV_R30_R16 0x47fe0410
5453#define INSN_LDI_R0 0x201f0000
5454#define INSN_CALLSYS 0x00000083
5455
Riku Voipio41ecc722014-04-23 11:01:00 +03005456static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005457 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005458{
Riku Voipio41ecc722014-04-23 11:01:00 +03005459 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005460
Riku Voipio1d8b5122014-04-23 10:26:05 +03005461 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5462 __put_user(set->sig[0], &sc->sc_mask);
5463 __put_user(env->pc, &sc->sc_pc);
5464 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005465
5466 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005467 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005468 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005469 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005470
5471 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005472 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005473 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005474 __put_user(0, &sc->sc_fpregs[31]);
5475 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005476
Riku Voipio1d8b5122014-04-23 10:26:05 +03005477 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5478 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5479 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005480}
5481
Riku Voipio016d2e12014-04-23 11:19:48 +03005482static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005483 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005484{
5485 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005486 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005487
Riku Voipio1d8b5122014-04-23 10:26:05 +03005488 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005489
5490 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005491 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005492 }
5493 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005494 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005495 }
5496
Riku Voipio1d8b5122014-04-23 10:26:05 +03005497 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005498 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005499}
5500
5501static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005502 CPUAlphaState *env,
5503 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005504{
5505 abi_ulong sp = env->ir[IR_SP];
5506
5507 /* This is the X/Open sanctioned signal stack switching. */
5508 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5509 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5510 }
5511 return (sp - framesize) & -32;
5512}
5513
5514static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005515 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005516{
5517 abi_ulong frame_addr, r26;
5518 struct target_sigframe *frame;
5519 int err = 0;
5520
5521 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005522 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005523 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5524 goto give_sigsegv;
5525 }
5526
Riku Voipio41ecc722014-04-23 11:01:00 +03005527 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005528
5529 if (ka->sa_restorer) {
5530 r26 = ka->sa_restorer;
5531 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005532 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5533 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5534 &frame->retcode[1]);
5535 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005536 /* imb() */
5537 r26 = frame_addr;
5538 }
5539
5540 unlock_user_struct(frame, frame_addr, 1);
5541
5542 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005543give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005544 force_sigsegv(sig);
5545 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005546 }
5547
5548 env->ir[IR_RA] = r26;
5549 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5550 env->ir[IR_A0] = sig;
5551 env->ir[IR_A1] = 0;
5552 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5553 env->ir[IR_SP] = frame_addr;
5554}
5555
5556static void setup_rt_frame(int sig, struct target_sigaction *ka,
5557 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005558 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005559{
5560 abi_ulong frame_addr, r26;
5561 struct target_rt_sigframe *frame;
5562 int i, err = 0;
5563
5564 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005565 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005566 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5567 goto give_sigsegv;
5568 }
5569
Peter Maydellf6c7a052015-01-08 12:19:48 +00005570 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005571
Riku Voipio1d8b5122014-04-23 10:26:05 +03005572 __put_user(0, &frame->uc.tuc_flags);
5573 __put_user(0, &frame->uc.tuc_link);
5574 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5575 __put_user(target_sigaltstack_used.ss_sp,
5576 &frame->uc.tuc_stack.ss_sp);
5577 __put_user(sas_ss_flags(env->ir[IR_SP]),
5578 &frame->uc.tuc_stack.ss_flags);
5579 __put_user(target_sigaltstack_used.ss_size,
5580 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005581 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005582 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005583 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005584 }
5585
5586 if (ka->sa_restorer) {
5587 r26 = ka->sa_restorer;
5588 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005589 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5590 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5591 &frame->retcode[1]);
5592 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005593 /* imb(); */
5594 r26 = frame_addr;
5595 }
5596
5597 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005598give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005599 force_sigsegv(sig);
5600 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005601 }
5602
5603 env->ir[IR_RA] = r26;
5604 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5605 env->ir[IR_A0] = sig;
5606 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5607 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5608 env->ir[IR_SP] = frame_addr;
5609}
5610
Andreas Färber05390242012-02-25 03:37:53 +01005611long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005612{
5613 struct target_sigcontext *sc;
5614 abi_ulong sc_addr = env->ir[IR_A0];
5615 target_sigset_t target_set;
5616 sigset_t set;
5617
5618 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5619 goto badframe;
5620 }
5621
5622 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005623 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005624
5625 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005626 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005627
Riku Voipio016d2e12014-04-23 11:19:48 +03005628 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005629 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005630 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005631
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005632badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005633 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005634 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005635}
5636
Andreas Färber05390242012-02-25 03:37:53 +01005637long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005638{
5639 abi_ulong frame_addr = env->ir[IR_A0];
5640 struct target_rt_sigframe *frame;
5641 sigset_t set;
5642
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005643 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005644 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5645 goto badframe;
5646 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005647 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005648 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005649
Riku Voipio016d2e12014-04-23 11:19:48 +03005650 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005651 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005652 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005653 0, env->ir[IR_SP]) == -EFAULT) {
5654 goto badframe;
5655 }
5656
5657 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005658 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005659
5660
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005661badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005662 unlock_user_struct(frame, frame_addr, 0);
5663 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005664 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005665}
5666
Chen Gangbf0f60a2015-09-27 08:10:18 +08005667#elif defined(TARGET_TILEGX)
5668
5669struct target_sigcontext {
5670 union {
5671 /* General-purpose registers. */
5672 abi_ulong gregs[56];
5673 struct {
5674 abi_ulong __gregs[53];
5675 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5676 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5677 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5678 };
5679 };
5680 abi_ulong pc; /* Program counter. */
5681 abi_ulong ics; /* In Interrupt Critical Section? */
5682 abi_ulong faultnum; /* Fault number. */
5683 abi_ulong pad[5];
5684};
5685
5686struct target_ucontext {
5687 abi_ulong tuc_flags;
5688 abi_ulong tuc_link;
5689 target_stack_t tuc_stack;
5690 struct target_sigcontext tuc_mcontext;
5691 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5692};
5693
5694struct target_rt_sigframe {
5695 unsigned char save_area[16]; /* caller save area */
5696 struct target_siginfo info;
5697 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08005698 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08005699};
5700
Chen Gangf1d9d102016-03-29 21:53:49 +08005701#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5702#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5703
5704
Chen Gangbf0f60a2015-09-27 08:10:18 +08005705static void setup_sigcontext(struct target_sigcontext *sc,
5706 CPUArchState *env, int signo)
5707{
5708 int i;
5709
5710 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5711 __put_user(env->regs[i], &sc->gregs[i]);
5712 }
5713
5714 __put_user(env->pc, &sc->pc);
5715 __put_user(0, &sc->ics);
5716 __put_user(signo, &sc->faultnum);
5717}
5718
5719static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5720{
5721 int i;
5722
5723 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5724 __get_user(env->regs[i], &sc->gregs[i]);
5725 }
5726
5727 __get_user(env->pc, &sc->pc);
5728}
5729
5730static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5731 size_t frame_size)
5732{
5733 unsigned long sp = env->regs[TILEGX_R_SP];
5734
5735 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5736 return -1UL;
5737 }
5738
5739 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5740 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5741 }
5742
5743 sp -= frame_size;
5744 sp &= -16UL;
5745 return sp;
5746}
5747
5748static void setup_rt_frame(int sig, struct target_sigaction *ka,
5749 target_siginfo_t *info,
5750 target_sigset_t *set, CPUArchState *env)
5751{
5752 abi_ulong frame_addr;
5753 struct target_rt_sigframe *frame;
5754 unsigned long restorer;
5755
5756 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005757 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005758 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5759 goto give_sigsegv;
5760 }
5761
5762 /* Always write at least the signal number for the stack backtracer. */
5763 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5764 /* At sigreturn time, restore the callee-save registers too. */
5765 tswap_siginfo(&frame->info, info);
5766 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5767 } else {
5768 __put_user(info->si_signo, &frame->info.si_signo);
5769 }
5770
5771 /* Create the ucontext. */
5772 __put_user(0, &frame->uc.tuc_flags);
5773 __put_user(0, &frame->uc.tuc_link);
5774 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5775 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5776 &frame->uc.tuc_stack.ss_flags);
5777 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5778 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5779
Chen Gangbf0f60a2015-09-27 08:10:18 +08005780 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08005781 restorer = (unsigned long) ka->sa_restorer;
5782 } else {
5783 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5784 __put_user(INSN_SWINT1, &frame->retcode[1]);
5785 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005786 }
5787 env->pc = (unsigned long) ka->_sa_handler;
5788 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5789 env->regs[TILEGX_R_LR] = restorer;
5790 env->regs[0] = (unsigned long) sig;
5791 env->regs[1] = (unsigned long) &frame->info;
5792 env->regs[2] = (unsigned long) &frame->uc;
5793 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5794
5795 unlock_user_struct(frame, frame_addr, 1);
5796 return;
5797
5798give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005799 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005800}
5801
5802long do_rt_sigreturn(CPUTLGState *env)
5803{
5804 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5805 struct target_rt_sigframe *frame;
5806 sigset_t set;
5807
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005808 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005809 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5810 goto badframe;
5811 }
5812 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005813 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005814
5815 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5816 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5817 uc.tuc_stack),
5818 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5819 goto badframe;
5820 }
5821
5822 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005823 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005824
5825
5826 badframe:
5827 unlock_user_struct(frame, frame_addr, 0);
5828 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005829 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005830}
5831
bellardb346ff42003-06-15 20:05:50 +00005832#else
5833
pbrook624f7972008-05-31 16:11:38 +00005834static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005835 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005836{
5837 fprintf(stderr, "setup_frame: not implemented\n");
5838}
5839
pbrook624f7972008-05-31 16:11:38 +00005840static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005841 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005842 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005843{
5844 fprintf(stderr, "setup_rt_frame: not implemented\n");
5845}
5846
Andreas Färber9349b4f2012-03-14 01:38:32 +01005847long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005848{
5849 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005850 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005851}
5852
Andreas Färber9349b4f2012-03-14 01:38:32 +01005853long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005854{
5855 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005856 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005857}
5858
bellard66fb9762003-03-23 01:06:05 +00005859#endif
5860
Peter Maydell31efaef2016-07-06 15:09:29 +01005861static void handle_pending_signal(CPUArchState *cpu_env, int sig,
5862 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01005863{
5864 CPUState *cpu = ENV_GET_CPU(cpu_env);
5865 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005866 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01005867 target_sigset_t target_old_set;
5868 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01005869 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01005870
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005871 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005872 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005873 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005874
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005875 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005876 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005877 sa = NULL;
5878 handler = TARGET_SIG_IGN;
5879 } else {
5880 sa = &sigact_table[sig - 1];
5881 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005882 }
bellard66fb9762003-03-23 01:06:05 +00005883
Peter Maydell0cb581d2016-07-18 18:12:24 +01005884 if (do_strace) {
5885 print_taken_signal(sig, &k->info);
5886 }
5887
bellard66fb9762003-03-23 01:06:05 +00005888 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005889 /* default handler : ignore some signal. The other are job control or fatal */
5890 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5891 kill(getpid(),SIGSTOP);
5892 } else if (sig != TARGET_SIGCHLD &&
5893 sig != TARGET_SIGURG &&
5894 sig != TARGET_SIGWINCH &&
5895 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01005896 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00005897 }
5898 } else if (handler == TARGET_SIG_IGN) {
5899 /* ignore sig */
5900 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01005901 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00005902 } else {
bellard9de5e442003-03-23 16:49:39 +00005903 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005904 sigset_t *blocked_set;
5905
pbrook624f7972008-05-31 16:11:38 +00005906 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005907 /* SA_NODEFER indicates that the current signal should not be
5908 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005909 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005910 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005911
bellard9de5e442003-03-23 16:49:39 +00005912 /* save the previous blocked signal state to restore it at the
5913 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005914 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
5915
5916 /* block signals in the handler */
5917 blocked_set = ts->in_sigsuspend ?
5918 &ts->sigsuspend_mask : &ts->signal_mask;
5919 sigorset(&ts->signal_mask, blocked_set, &set);
5920 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00005921
bellardbc8a22c2003-03-30 21:02:40 +00005922 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005923#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005924 {
5925 CPUX86State *env = cpu_env;
5926 if (env->eflags & VM_MASK)
5927 save_v86_state(env);
5928 }
5929#endif
bellard9de5e442003-03-23 16:49:39 +00005930 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005931#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005932 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005933 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005934 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005935#else
pbrook624f7972008-05-31 16:11:38 +00005936 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01005937 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005938 else
pbrook624f7972008-05-31 16:11:38 +00005939 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005940#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01005941 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00005942 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01005943 }
bellard31e31b82003-02-18 22:55:36 +00005944 }
bellard31e31b82003-02-18 22:55:36 +00005945}
Peter Maydelle902d582016-05-27 15:51:44 +01005946
5947void process_pending_signals(CPUArchState *cpu_env)
5948{
5949 CPUState *cpu = ENV_GET_CPU(cpu_env);
5950 int sig;
5951 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005952 sigset_t set;
5953 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01005954
Peter Maydell3d3efba2016-05-27 15:51:49 +01005955 while (atomic_read(&ts->signal_pending)) {
5956 /* FIXME: This is not threadsafe. */
5957 sigfillset(&set);
5958 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01005959
Peter Maydell8bd37732016-07-28 16:44:45 +01005960 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01005961 sig = ts->sync_signal.pending;
5962 if (sig) {
5963 /* Synchronous signals are forced,
5964 * see force_sig_info() and callers in Linux
5965 * Note that not all of our queue_signal() calls in QEMU correspond
5966 * to force_sig_info() calls in Linux (some are send_sig_info()).
5967 * However it seems like a kernel bug to me to allow the process
5968 * to block a synchronous signal since it could then just end up
5969 * looping round and round indefinitely.
5970 */
5971 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
5972 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
5973 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
5974 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
5975 }
5976
Peter Maydell31efaef2016-07-06 15:09:29 +01005977 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01005978 }
5979
Peter Maydell3d3efba2016-05-27 15:51:49 +01005980 for (sig = 1; sig <= TARGET_NSIG; sig++) {
5981 blocked_set = ts->in_sigsuspend ?
5982 &ts->sigsuspend_mask : &ts->signal_mask;
5983
5984 if (ts->sigtab[sig - 1].pending &&
5985 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01005986 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01005987 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01005988 /* Restart scan from the beginning, as handle_pending_signal
5989 * might have resulted in a new synchronous signal (eg SIGSEGV).
5990 */
5991 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005992 }
Peter Maydelle902d582016-05-27 15:51:44 +01005993 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01005994
5995 /* if no signal is pending, unblock signals and recheck (the act
5996 * of unblocking might cause us to take another host signal which
5997 * will set signal_pending again).
5998 */
5999 atomic_set(&ts->signal_pending, 0);
6000 ts->in_sigsuspend = 0;
6001 set = ts->signal_mask;
6002 sigdelset(&set, SIGSEGV);
6003 sigdelset(&set, SIGBUS);
6004 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01006005 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01006006 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01006007}