blob: 0f956740ef9438f7f3c09d64f900885e81e47b46 [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"
Laurent Vivierbefb7442018-04-24 21:26:16 +020028#include "signal-common.h"
bellard66fb9762003-03-23 01:06:05 +000029
Laurent Vivierbefb7442018-04-24 21:26:16 +020030struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000031 .ss_sp = 0,
32 .ss_size = 0,
33 .ss_flags = TARGET_SS_DISABLE,
34};
35
pbrook624f7972008-05-31 16:11:38 +000036static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000037
ths5fafdf22007-09-16 21:08:06 +000038static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000039 void *puc);
40
Arnaud Patard3ca05582009-03-30 01:18:20 +020041static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000042 [SIGHUP] = TARGET_SIGHUP,
43 [SIGINT] = TARGET_SIGINT,
44 [SIGQUIT] = TARGET_SIGQUIT,
45 [SIGILL] = TARGET_SIGILL,
46 [SIGTRAP] = TARGET_SIGTRAP,
47 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000048/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000049 [SIGBUS] = TARGET_SIGBUS,
50 [SIGFPE] = TARGET_SIGFPE,
51 [SIGKILL] = TARGET_SIGKILL,
52 [SIGUSR1] = TARGET_SIGUSR1,
53 [SIGSEGV] = TARGET_SIGSEGV,
54 [SIGUSR2] = TARGET_SIGUSR2,
55 [SIGPIPE] = TARGET_SIGPIPE,
56 [SIGALRM] = TARGET_SIGALRM,
57 [SIGTERM] = TARGET_SIGTERM,
58#ifdef SIGSTKFLT
59 [SIGSTKFLT] = TARGET_SIGSTKFLT,
60#endif
61 [SIGCHLD] = TARGET_SIGCHLD,
62 [SIGCONT] = TARGET_SIGCONT,
63 [SIGSTOP] = TARGET_SIGSTOP,
64 [SIGTSTP] = TARGET_SIGTSTP,
65 [SIGTTIN] = TARGET_SIGTTIN,
66 [SIGTTOU] = TARGET_SIGTTOU,
67 [SIGURG] = TARGET_SIGURG,
68 [SIGXCPU] = TARGET_SIGXCPU,
69 [SIGXFSZ] = TARGET_SIGXFSZ,
70 [SIGVTALRM] = TARGET_SIGVTALRM,
71 [SIGPROF] = TARGET_SIGPROF,
72 [SIGWINCH] = TARGET_SIGWINCH,
73 [SIGIO] = TARGET_SIGIO,
74 [SIGPWR] = TARGET_SIGPWR,
75 [SIGSYS] = TARGET_SIGSYS,
76 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000077 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080078 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000079 To fix this properly we need to do manual signal delivery multiplexed
80 over a single host signal. */
81 [__SIGRTMIN] = __SIGRTMAX,
82 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000083};
Arnaud Patard3ca05582009-03-30 01:18:20 +020084static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000085
pbrook1d9d8b52009-04-16 15:17:02 +000086int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000087{
Andreas Schwab167c50d2013-07-02 14:04:12 +010088 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000089 return sig;
bellard9e5f5282003-07-13 17:33:54 +000090 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +000091}
92
pbrook4cb05962008-05-30 18:05:19 +000093int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000094{
Andreas Schwab167c50d2013-07-02 14:04:12 +010095 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000096 return sig;
bellard9e5f5282003-07-13 17:33:54 +000097 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +000098}
99
Anthony Liguoric227f092009-10-01 16:12:16 -0500100static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000101{
102 signum--;
103 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
104 set->sig[signum / TARGET_NSIG_BPW] |= mask;
105}
106
Anthony Liguoric227f092009-10-01 16:12:16 -0500107static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000108{
109 signum--;
110 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
111 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
112}
113
Laurent Vivierbefb7442018-04-24 21:26:16 +0200114void host_to_target_sigset_internal(target_sigset_t *d,
115 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000116{
117 int i;
pbrookf5545b52008-05-30 22:37:07 +0000118 target_sigemptyset(d);
119 for (i = 1; i <= TARGET_NSIG; i++) {
120 if (sigismember(s, i)) {
121 target_sigaddset(d, host_to_target_signal(i));
122 }
bellard9e5f5282003-07-13 17:33:54 +0000123 }
bellard66fb9762003-03-23 01:06:05 +0000124}
125
Anthony Liguoric227f092009-10-01 16:12:16 -0500126void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000127{
Anthony Liguoric227f092009-10-01 16:12:16 -0500128 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000129 int i;
130
131 host_to_target_sigset_internal(&d1, s);
132 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200133 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000134}
135
Laurent Vivierbefb7442018-04-24 21:26:16 +0200136void target_to_host_sigset_internal(sigset_t *d,
137 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000138{
139 int i;
pbrookf5545b52008-05-30 22:37:07 +0000140 sigemptyset(d);
141 for (i = 1; i <= TARGET_NSIG; i++) {
142 if (target_sigismember(s, i)) {
143 sigaddset(d, target_to_host_signal(i));
144 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100145 }
bellard66fb9762003-03-23 01:06:05 +0000146}
147
Anthony Liguoric227f092009-10-01 16:12:16 -0500148void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000149{
Anthony Liguoric227f092009-10-01 16:12:16 -0500150 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000151 int i;
152
153 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200154 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000155 target_to_host_sigset_internal(d, &s1);
156}
ths3b46e622007-09-17 08:09:54 +0000157
blueswir1992f48a2007-10-14 16:27:31 +0000158void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000159 const sigset_t *sigset)
160{
Anthony Liguoric227f092009-10-01 16:12:16 -0500161 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000162 host_to_target_sigset(&d, sigset);
163 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000164}
165
ths5fafdf22007-09-16 21:08:06 +0000166void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000167 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000168{
Anthony Liguoric227f092009-10-01 16:12:16 -0500169 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000170 int i;
171
172 d.sig[0] = *old_sigset;
173 for(i = 1;i < TARGET_NSIG_WORDS; i++)
174 d.sig[i] = 0;
175 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000176}
177
Peter Maydell3d3efba2016-05-27 15:51:49 +0100178int block_signals(void)
179{
180 TaskState *ts = (TaskState *)thread_cpu->opaque;
181 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100182
183 /* It's OK to block everything including SIGSEGV, because we won't
184 * run any further guest code before unblocking signals in
185 * process_pending_signals().
186 */
187 sigfillset(&set);
188 sigprocmask(SIG_SETMASK, &set, 0);
189
Eduardo Habkost9be38592016-06-13 18:57:58 -0300190 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100191}
192
Alex Barcelo1c275922014-03-14 14:36:55 +0000193/* Wrapper for sigprocmask function
194 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100195 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
196 * a signal was already pending and the syscall must be restarted, or
197 * 0 on success.
198 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000199 */
200int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
201{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100202 TaskState *ts = (TaskState *)thread_cpu->opaque;
203
204 if (oldset) {
205 *oldset = ts->signal_mask;
206 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000207
208 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100209 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000210
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 if (block_signals()) {
212 return -TARGET_ERESTARTSYS;
213 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000214
215 switch (how) {
216 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100217 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000218 break;
219 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100220 for (i = 1; i <= NSIG; ++i) {
221 if (sigismember(set, i)) {
222 sigdelset(&ts->signal_mask, i);
223 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000224 }
225 break;
226 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000228 break;
229 default:
230 g_assert_not_reached();
231 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100232
233 /* Silently ignore attempts to change blocking status of KILL or STOP */
234 sigdelset(&ts->signal_mask, SIGKILL);
235 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000236 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100237 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000238}
239
Peter Maydelldaa43742018-03-08 14:47:32 +0000240#if !defined(TARGET_OPENRISC) && !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100241/* Just set the guest's signal mask to the specified value; the
242 * caller is assumed to have called block_signals() already.
243 */
Laurent Vivierbefb7442018-04-24 21:26:16 +0200244void set_sigmask(const sigset_t *set)
Peter Maydell9eede5b2016-05-27 15:51:46 +0100245{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100246 TaskState *ts = (TaskState *)thread_cpu->opaque;
247
248 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100249}
250#endif
251
bellard9de5e442003-03-23 16:49:39 +0000252/* siginfo conversion */
253
Anthony Liguoric227f092009-10-01 16:12:16 -0500254static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000255 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000256{
Richard Hendersona05c6402012-09-15 11:34:20 -0700257 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100258 int si_code = info->si_code;
259 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000260 tinfo->si_signo = sig;
261 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000262 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700263
Peter Maydell55d72a72016-06-13 11:22:05 +0100264 /* This memset serves two purposes:
265 * (1) ensure we don't leak random junk to the guest later
266 * (2) placate false positives from gcc about fields
267 * being used uninitialized if it chooses to inline both this
268 * function and tswap_siginfo() into host_to_target_siginfo().
269 */
270 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
271
Peter Maydella70dadc2016-05-27 15:51:59 +0100272 /* This is awkward, because we have to use a combination of
273 * the si_code and si_signo to figure out which of the union's
274 * members are valid. (Within the host kernel it is always possible
275 * to tell, but the kernel carefully avoids giving userspace the
276 * high 16 bits of si_code, so we don't have the information to
277 * do this the easy way...) We therefore make our best guess,
278 * bearing in mind that a guest can spoof most of the si_codes
279 * via rt_sigqueueinfo() if it likes.
280 *
281 * Once we have made our guess, we record it in the top 16 bits of
282 * the si_code, so that tswap_siginfo() later can use it.
283 * tswap_siginfo() will strip these top bits out before writing
284 * si_code to the guest (sign-extending the lower bits).
285 */
286
287 switch (si_code) {
288 case SI_USER:
289 case SI_TKILL:
290 case SI_KERNEL:
291 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
292 * These are the only unspoofable si_code values.
293 */
294 tinfo->_sifields._kill._pid = info->si_pid;
295 tinfo->_sifields._kill._uid = info->si_uid;
296 si_type = QEMU_SI_KILL;
297 break;
298 default:
299 /* Everything else is spoofable. Make best guess based on signal */
300 switch (sig) {
301 case TARGET_SIGCHLD:
302 tinfo->_sifields._sigchld._pid = info->si_pid;
303 tinfo->_sifields._sigchld._uid = info->si_uid;
304 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100305 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100306 tinfo->_sifields._sigchld._utime = info->si_utime;
307 tinfo->_sifields._sigchld._stime = info->si_stime;
308 si_type = QEMU_SI_CHLD;
309 break;
310 case TARGET_SIGIO:
311 tinfo->_sifields._sigpoll._band = info->si_band;
312 tinfo->_sifields._sigpoll._fd = info->si_fd;
313 si_type = QEMU_SI_POLL;
314 break;
315 default:
316 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
317 tinfo->_sifields._rt._pid = info->si_pid;
318 tinfo->_sifields._rt._uid = info->si_uid;
319 /* XXX: potential problem if 64 bit */
320 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100321 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100322 si_type = QEMU_SI_RT;
323 break;
324 }
325 break;
bellard9de5e442003-03-23 16:49:39 +0000326 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100327
328 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000329}
330
Laurent Vivierbefb7442018-04-24 21:26:16 +0200331void tswap_siginfo(target_siginfo_t *tinfo,
332 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000333{
Peter Maydella70dadc2016-05-27 15:51:59 +0100334 int si_type = extract32(info->si_code, 16, 16);
335 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700336
Peter Maydella70dadc2016-05-27 15:51:59 +0100337 __put_user(info->si_signo, &tinfo->si_signo);
338 __put_user(info->si_errno, &tinfo->si_errno);
339 __put_user(si_code, &tinfo->si_code);
340
341 /* We can use our internal marker of which fields in the structure
342 * are valid, rather than duplicating the guesswork of
343 * host_to_target_siginfo_noswap() here.
344 */
345 switch (si_type) {
346 case QEMU_SI_KILL:
347 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
348 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
349 break;
350 case QEMU_SI_TIMER:
351 __put_user(info->_sifields._timer._timer1,
352 &tinfo->_sifields._timer._timer1);
353 __put_user(info->_sifields._timer._timer2,
354 &tinfo->_sifields._timer._timer2);
355 break;
356 case QEMU_SI_POLL:
357 __put_user(info->_sifields._sigpoll._band,
358 &tinfo->_sifields._sigpoll._band);
359 __put_user(info->_sifields._sigpoll._fd,
360 &tinfo->_sifields._sigpoll._fd);
361 break;
362 case QEMU_SI_FAULT:
363 __put_user(info->_sifields._sigfault._addr,
364 &tinfo->_sifields._sigfault._addr);
365 break;
366 case QEMU_SI_CHLD:
367 __put_user(info->_sifields._sigchld._pid,
368 &tinfo->_sifields._sigchld._pid);
369 __put_user(info->_sifields._sigchld._uid,
370 &tinfo->_sifields._sigchld._uid);
371 __put_user(info->_sifields._sigchld._status,
372 &tinfo->_sifields._sigchld._status);
373 __put_user(info->_sifields._sigchld._utime,
374 &tinfo->_sifields._sigchld._utime);
375 __put_user(info->_sifields._sigchld._stime,
376 &tinfo->_sifields._sigchld._stime);
377 break;
378 case QEMU_SI_RT:
379 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
380 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
381 __put_user(info->_sifields._rt._sigval.sival_ptr,
382 &tinfo->_sifields._rt._sigval.sival_ptr);
383 break;
384 default:
385 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000386 }
387}
388
Anthony Liguoric227f092009-10-01 16:12:16 -0500389void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000390{
Peter Maydell55d72a72016-06-13 11:22:05 +0100391 target_siginfo_t tgt_tmp;
392 host_to_target_siginfo_noswap(&tgt_tmp, info);
393 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000394}
395
396/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000397/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500398void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000399{
Peter Maydell90c0f082016-05-27 15:52:01 +0100400 /* This conversion is used only for the rt_sigqueueinfo syscall,
401 * and so we know that the _rt fields are the valid ones.
402 */
403 abi_ulong sival_ptr;
404
405 __get_user(info->si_signo, &tinfo->si_signo);
406 __get_user(info->si_errno, &tinfo->si_errno);
407 __get_user(info->si_code, &tinfo->si_code);
408 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
409 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
410 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
411 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000412}
413
aurel32ca587a82008-12-18 22:44:13 +0000414static int fatal_signal (int sig)
415{
416 switch (sig) {
417 case TARGET_SIGCHLD:
418 case TARGET_SIGURG:
419 case TARGET_SIGWINCH:
420 /* Ignored by default. */
421 return 0;
422 case TARGET_SIGCONT:
423 case TARGET_SIGSTOP:
424 case TARGET_SIGTSTP:
425 case TARGET_SIGTTIN:
426 case TARGET_SIGTTOU:
427 /* Job control signals. */
428 return 0;
429 default:
430 return 1;
431 }
432}
433
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300434/* returns 1 if given signal should dump core if not handled */
435static int core_dump_signal(int sig)
436{
437 switch (sig) {
438 case TARGET_SIGABRT:
439 case TARGET_SIGFPE:
440 case TARGET_SIGILL:
441 case TARGET_SIGQUIT:
442 case TARGET_SIGSEGV:
443 case TARGET_SIGTRAP:
444 case TARGET_SIGBUS:
445 return (1);
446 default:
447 return (0);
448 }
449}
450
bellard31e31b82003-02-18 22:55:36 +0000451void signal_init(void)
452{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100453 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000454 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000455 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000456 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000457 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000458
bellard9e5f5282003-07-13 17:33:54 +0000459 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200460 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000461 if (host_to_target_signal_table[i] == 0)
462 host_to_target_signal_table[i] = i;
463 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200464 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000465 j = host_to_target_signal_table[i];
466 target_to_host_signal_table[j] = i;
467 }
ths3b46e622007-09-17 08:09:54 +0000468
Peter Maydell3d3efba2016-05-27 15:51:49 +0100469 /* Set the signal mask from the host mask. */
470 sigprocmask(0, 0, &ts->signal_mask);
471
bellard9de5e442003-03-23 16:49:39 +0000472 /* set all host signal handlers. ALL signals are blocked during
473 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000474 memset(sigact_table, 0, sizeof(sigact_table));
475
bellard9de5e442003-03-23 16:49:39 +0000476 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000477 act.sa_flags = SA_SIGINFO;
478 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000479 for(i = 1; i <= TARGET_NSIG; i++) {
480 host_sig = target_to_host_signal(i);
481 sigaction(host_sig, NULL, &oact);
482 if (oact.sa_sigaction == (void *)SIG_IGN) {
483 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
484 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
485 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
486 }
487 /* If there's already a handler installed then something has
488 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000489 /* Install some handlers for our own use. We need at least
490 SIGSEGV and SIGBUS, to detect exceptions. We can not just
491 trap all signals because it affects syscall interrupt
492 behavior. But do trap all default-fatal signals. */
493 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000494 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000495 }
bellard31e31b82003-02-18 22:55:36 +0000496}
497
Peter Maydellc599d4d2016-07-28 16:44:49 +0100498/* Force a synchronously taken signal. The kernel force_sig() function
499 * also forces the signal to "not blocked, not ignored", but for QEMU
500 * that work is done in process_pending_signals().
501 */
Laurent Vivierbefb7442018-04-24 21:26:16 +0200502void force_sig(int sig)
Peter Maydellc599d4d2016-07-28 16:44:49 +0100503{
504 CPUState *cpu = thread_cpu;
505 CPUArchState *env = cpu->env_ptr;
506 target_siginfo_t info;
507
508 info.si_signo = sig;
509 info.si_errno = 0;
510 info.si_code = TARGET_SI_KERNEL;
511 info._sifields._kill._pid = 0;
512 info._sifields._kill._uid = 0;
513 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
514}
Peter Maydell09391662016-07-28 16:44:47 +0100515
516/* Force a SIGSEGV if we couldn't write to memory trying to set
517 * up the signal frame. oldsig is the signal we were trying to handle
518 * at the point of failure.
519 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300520#if !defined(TARGET_RISCV)
Laurent Vivierbefb7442018-04-24 21:26:16 +0200521void force_sigsegv(int oldsig)
Peter Maydell09391662016-07-28 16:44:47 +0100522{
Peter Maydell09391662016-07-28 16:44:47 +0100523 if (oldsig == SIGSEGV) {
524 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100525 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100526 */
527 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
528 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100529 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100530}
bellard66fb9762003-03-23 01:06:05 +0000531
Michael Clark47ae93c2018-03-03 01:31:11 +1300532#endif
533
bellard9de5e442003-03-23 16:49:39 +0000534/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100535static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000536{
Andreas Färber0429a972013-08-26 18:14:44 +0200537 CPUState *cpu = thread_cpu;
538 CPUArchState *env = cpu->env_ptr;
539 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300540 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000541 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100542
Riku Voipio66393fb2009-12-04 15:16:32 +0200543 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100544 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200545 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000546
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300547 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200548 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300549 stop_all_tasks();
550 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200551 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300552 }
553 if (core_dumped) {
554 /* we already dumped the core of target process, we don't want
555 * a coredump of qemu itself */
556 struct rlimit nodump;
557 getrlimit(RLIMIT_CORE, &nodump);
558 nodump.rlim_cur=0;
559 setrlimit(RLIMIT_CORE, &nodump);
560 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200561 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300562 }
563
Stefan Weil0c587512011-04-28 17:20:32 +0200564 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000565 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
566 * a negative value. To get the proper exit code we need to
567 * actually die from an uncaught signal. Here the default signal
568 * handler is installed, we send ourself a signal and we wait for
569 * it to arrive. */
570 sigfillset(&act.sa_mask);
571 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000572 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000573 sigaction(host_sig, &act, NULL);
574
575 /* For some reason raise(host_sig) doesn't send the signal when
576 * statically linked on x86-64. */
577 kill(getpid(), host_sig);
578
579 /* Make sure the signal isn't masked (just reuse the mask inside
580 of act) */
581 sigdelset(&act.sa_mask, host_sig);
582 sigsuspend(&act.sa_mask);
583
584 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000585 abort();
bellard66fb9762003-03-23 01:06:05 +0000586}
587
bellard9de5e442003-03-23 16:49:39 +0000588/* queue a signal so that it will be send to the virtual CPU as soon
589 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100590int queue_signal(CPUArchState *env, int sig, int si_type,
591 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000592{
Andreas Färber0429a972013-08-26 18:14:44 +0200593 CPUState *cpu = ENV_GET_CPU(env);
594 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000595
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100596 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000597
Peter Maydell9d2803f2016-07-28 16:44:46 +0100598 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100599
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100600 ts->sync_signal.info = *info;
601 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100602 /* signal that a new signal is pending */
603 atomic_set(&ts->signal_pending, 1);
604 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000605}
606
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100607#ifndef HAVE_SAFE_SYSCALL
608static inline void rewind_if_in_safe_syscall(void *puc)
609{
610 /* Default version: never rewind */
611}
612#endif
613
ths5fafdf22007-09-16 21:08:06 +0000614static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000615 void *puc)
616{
Andreas Färbera2247f82013-06-09 19:47:04 +0200617 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100618 CPUState *cpu = ENV_GET_CPU(env);
619 TaskState *ts = cpu->opaque;
620
bellard9de5e442003-03-23 16:49:39 +0000621 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500622 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100623 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100624 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000625
626 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000627 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000628 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000629 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000630 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000631 return;
632 }
633
634 /* get target signal number */
635 sig = host_to_target_signal(host_signum);
636 if (sig < 1 || sig > TARGET_NSIG)
637 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100638 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100639
640 rewind_if_in_safe_syscall(puc);
641
bellard9de5e442003-03-23 16:49:39 +0000642 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100643 k = &ts->sigtab[sig - 1];
644 k->info = tinfo;
645 k->pending = sig;
646 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100647
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100648 /* Block host signals until target signal handler entered. We
649 * can't block SIGSEGV or SIGBUS while we're executing guest
650 * code in case the guest code provokes one in the window between
651 * now and it getting out to the main loop. Signals will be
652 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100653 *
654 * WARNING: we cannot use sigfillset() here because the uc_sigmask
655 * field is a kernel sigset_t, which is much smaller than the
656 * libc sigset_t which sigfillset() operates on. Using sigfillset()
657 * would write 0xff bytes off the end of the structure and trash
658 * data on the struct.
659 * We can't use sizeof(uc->uc_sigmask) either, because the libc
660 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100661 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100662 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100663 sigdelset(&uc->uc_sigmask, SIGSEGV);
664 sigdelset(&uc->uc_sigmask, SIGBUS);
665
666 /* interrupt the virtual CPU as soon as possible */
667 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000668}
669
ths0da46a62007-10-20 20:23:07 +0000670/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000671/* compare linux/kernel/signal.c:do_sigaltstack() */
672abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000673{
674 int ret;
675 struct target_sigaltstack oss;
676
677 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000678 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000679 {
680 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
681 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
682 __put_user(sas_ss_flags(sp), &oss.ss_flags);
683 }
684
bellard579a97f2007-11-11 14:26:47 +0000685 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000686 {
bellard579a97f2007-11-11 14:26:47 +0000687 struct target_sigaltstack *uss;
688 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500689 size_t minstacksize = TARGET_MINSIGSTKSZ;
690
691#if defined(TARGET_PPC64)
692 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
693 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
694 if (get_ppc64_abi(image) > 1) {
695 minstacksize = 4096;
696 }
697#endif
thsa04e1342007-09-27 13:57:58 +0000698
ths0da46a62007-10-20 20:23:07 +0000699 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300700 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000701 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300702 }
703 __get_user(ss.ss_sp, &uss->ss_sp);
704 __get_user(ss.ss_size, &uss->ss_size);
705 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000706 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000707
ths0da46a62007-10-20 20:23:07 +0000708 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000709 if (on_sig_stack(sp))
710 goto out;
711
ths0da46a62007-10-20 20:23:07 +0000712 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000713 if (ss.ss_flags != TARGET_SS_DISABLE
714 && ss.ss_flags != TARGET_SS_ONSTACK
715 && ss.ss_flags != 0)
716 goto out;
717
718 if (ss.ss_flags == TARGET_SS_DISABLE) {
719 ss.ss_size = 0;
720 ss.ss_sp = 0;
721 } else {
ths0da46a62007-10-20 20:23:07 +0000722 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500723 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000724 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500725 }
thsa04e1342007-09-27 13:57:58 +0000726 }
727
728 target_sigaltstack_used.ss_sp = ss.ss_sp;
729 target_sigaltstack_used.ss_size = ss.ss_size;
730 }
731
bellard579a97f2007-11-11 14:26:47 +0000732 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000733 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000734 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000735 goto out;
thsa04e1342007-09-27 13:57:58 +0000736 }
737
738 ret = 0;
739out:
740 return ret;
741}
742
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100743/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000744int do_sigaction(int sig, const struct target_sigaction *act,
745 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000746{
pbrook624f7972008-05-31 16:11:38 +0000747 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000748 struct sigaction act1;
749 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000750 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000751
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100752 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
753 return -TARGET_EINVAL;
754 }
755
756 if (block_signals()) {
757 return -TARGET_ERESTARTSYS;
758 }
759
bellard66fb9762003-03-23 01:06:05 +0000760 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000761 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800762 __put_user(k->_sa_handler, &oact->_sa_handler);
763 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100764#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800765 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000766#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800767 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000768 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000769 }
770 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000771 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800772 __get_user(k->_sa_handler, &act->_sa_handler);
773 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100774#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800775 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000776#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800777 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000778 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000779
780 /* we update the host linux signal state */
781 host_sig = target_to_host_signal(sig);
782 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
783 sigfillset(&act1.sa_mask);
784 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000785 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000786 act1.sa_flags |= SA_RESTART;
787 /* NOTE: it is important to update the host kernel signal
788 ignore state to avoid getting unexpected interrupted
789 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000790 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000791 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000792 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000793 if (fatal_signal (sig))
794 act1.sa_sigaction = host_signal_handler;
795 else
796 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000797 } else {
798 act1.sa_sigaction = host_signal_handler;
799 }
ths0da46a62007-10-20 20:23:07 +0000800 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000801 }
bellard66fb9762003-03-23 01:06:05 +0000802 }
ths0da46a62007-10-20 20:23:07 +0000803 return ret;
bellard66fb9762003-03-23 01:06:05 +0000804}
bellard31e31b82003-02-18 22:55:36 +0000805
Pranith Kumar1c1df012017-02-26 11:53:44 -0500806#if defined(TARGET_I386)
807/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000808
809struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100810 uint16_t significand[4];
811 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000812};
813
814struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100815 uint16_t significand[4];
816 uint16_t exponent;
817 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000818};
819
820struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500821 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000822};
823
Pranith Kumar1c1df012017-02-26 11:53:44 -0500824struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100825 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500826 uint32_t cw;
827 uint32_t sw;
828 uint32_t tag;
829 uint32_t ipoff;
830 uint32_t cssel;
831 uint32_t dataoff;
832 uint32_t datasel;
833 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100834 uint16_t status;
835 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000836
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100837 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500838 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
839 uint32_t mxcsr;
840 uint32_t reserved;
841 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
842 struct target_xmmreg xmm[8];
843 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000844};
845
Pranith Kumar1c1df012017-02-26 11:53:44 -0500846struct target_fpstate_64 {
847 /* FXSAVE format */
848 uint16_t cw;
849 uint16_t sw;
850 uint16_t twd;
851 uint16_t fop;
852 uint64_t rip;
853 uint64_t rdp;
854 uint32_t mxcsr;
855 uint32_t mxcsr_mask;
856 uint32_t st_space[32];
857 uint32_t xmm_space[64];
858 uint32_t reserved[24];
859};
bellard66fb9762003-03-23 01:06:05 +0000860
Pranith Kumar1c1df012017-02-26 11:53:44 -0500861#ifndef TARGET_X86_64
862# define target_fpstate target_fpstate_32
863#else
864# define target_fpstate target_fpstate_64
865#endif
866
867struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100868 uint16_t gs, __gsh;
869 uint16_t fs, __fsh;
870 uint16_t es, __esh;
871 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500872 uint32_t edi;
873 uint32_t esi;
874 uint32_t ebp;
875 uint32_t esp;
876 uint32_t ebx;
877 uint32_t edx;
878 uint32_t ecx;
879 uint32_t eax;
880 uint32_t trapno;
881 uint32_t err;
882 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100883 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500884 uint32_t eflags;
885 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100886 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500887 uint32_t fpstate; /* pointer */
888 uint32_t oldmask;
889 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000890};
891
Pranith Kumar1c1df012017-02-26 11:53:44 -0500892struct target_sigcontext_64 {
893 uint64_t r8;
894 uint64_t r9;
895 uint64_t r10;
896 uint64_t r11;
897 uint64_t r12;
898 uint64_t r13;
899 uint64_t r14;
900 uint64_t r15;
901
902 uint64_t rdi;
903 uint64_t rsi;
904 uint64_t rbp;
905 uint64_t rbx;
906 uint64_t rdx;
907 uint64_t rax;
908 uint64_t rcx;
909 uint64_t rsp;
910 uint64_t rip;
911
912 uint64_t eflags;
913
914 uint16_t cs;
915 uint16_t gs;
916 uint16_t fs;
917 uint16_t ss;
918
919 uint64_t err;
920 uint64_t trapno;
921 uint64_t oldmask;
922 uint64_t cr2;
923
924 uint64_t fpstate; /* pointer */
925 uint64_t padding[8];
926};
927
928#ifndef TARGET_X86_64
929# define target_sigcontext target_sigcontext_32
930#else
931# define target_sigcontext target_sigcontext_64
932#endif
933
934/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000935struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100936 abi_ulong tuc_flags;
937 abi_ulong tuc_link;
938 target_stack_t tuc_stack;
939 struct target_sigcontext tuc_mcontext;
940 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000941};
942
Pranith Kumar1c1df012017-02-26 11:53:44 -0500943#ifndef TARGET_X86_64
944struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000945 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000946 int sig;
947 struct target_sigcontext sc;
948 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000949 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000950 char retcode[8];
951};
952
Pranith Kumar1c1df012017-02-26 11:53:44 -0500953struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000954 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000955 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000956 abi_ulong pinfo;
957 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000958 struct target_siginfo info;
959 struct target_ucontext uc;
960 struct target_fpstate fpstate;
961 char retcode[8];
962};
963
Pranith Kumar1c1df012017-02-26 11:53:44 -0500964#else
965
966struct rt_sigframe {
967 abi_ulong pretcode;
968 struct target_ucontext uc;
969 struct target_siginfo info;
970 struct target_fpstate fpstate;
971};
972
973#endif
974
bellard66fb9762003-03-23 01:06:05 +0000975/*
976 * Set up a signal frame.
977 */
978
bellard66fb9762003-03-23 01:06:05 +0000979/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300980static void setup_sigcontext(struct target_sigcontext *sc,
981 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
982 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000983{
Andreas Färber27103422013-08-26 08:31:06 +0200984 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -0500985#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +0200986 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000987
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100988 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300989 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
990 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
991 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
992 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
993 __put_user(env->regs[R_EDI], &sc->edi);
994 __put_user(env->regs[R_ESI], &sc->esi);
995 __put_user(env->regs[R_EBP], &sc->ebp);
996 __put_user(env->regs[R_ESP], &sc->esp);
997 __put_user(env->regs[R_EBX], &sc->ebx);
998 __put_user(env->regs[R_EDX], &sc->edx);
999 __put_user(env->regs[R_ECX], &sc->ecx);
1000 __put_user(env->regs[R_EAX], &sc->eax);
1001 __put_user(cs->exception_index, &sc->trapno);
1002 __put_user(env->error_code, &sc->err);
1003 __put_user(env->eip, &sc->eip);
1004 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1005 __put_user(env->eflags, &sc->eflags);
1006 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1007 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001008
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001009 cpu_x86_fsave(env, fpstate_addr, 1);
1010 fpstate->status = fpstate->sw;
1011 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001012 __put_user(magic, &fpstate->magic);
1013 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001014
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001015 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001016 __put_user(mask, &sc->oldmask);
1017 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001018#else
1019 __put_user(env->regs[R_EDI], &sc->rdi);
1020 __put_user(env->regs[R_ESI], &sc->rsi);
1021 __put_user(env->regs[R_EBP], &sc->rbp);
1022 __put_user(env->regs[R_ESP], &sc->rsp);
1023 __put_user(env->regs[R_EBX], &sc->rbx);
1024 __put_user(env->regs[R_EDX], &sc->rdx);
1025 __put_user(env->regs[R_ECX], &sc->rcx);
1026 __put_user(env->regs[R_EAX], &sc->rax);
1027
1028 __put_user(env->regs[8], &sc->r8);
1029 __put_user(env->regs[9], &sc->r9);
1030 __put_user(env->regs[10], &sc->r10);
1031 __put_user(env->regs[11], &sc->r11);
1032 __put_user(env->regs[12], &sc->r12);
1033 __put_user(env->regs[13], &sc->r13);
1034 __put_user(env->regs[14], &sc->r14);
1035 __put_user(env->regs[15], &sc->r15);
1036
1037 __put_user(cs->exception_index, &sc->trapno);
1038 __put_user(env->error_code, &sc->err);
1039 __put_user(env->eip, &sc->rip);
1040
1041 __put_user(env->eflags, &sc->eflags);
1042 __put_user(env->segs[R_CS].selector, &sc->cs);
1043 __put_user((uint16_t)0, &sc->gs);
1044 __put_user((uint16_t)0, &sc->fs);
1045 __put_user(env->segs[R_SS].selector, &sc->ss);
1046
1047 __put_user(mask, &sc->oldmask);
1048 __put_user(env->cr[2], &sc->cr2);
1049
1050 /* fpstate_addr must be 16 byte aligned for fxsave */
1051 assert(!(fpstate_addr & 0xf));
1052
1053 cpu_x86_fxsave(env, fpstate_addr);
1054 __put_user(fpstate_addr, &sc->fpstate);
1055#endif
bellard66fb9762003-03-23 01:06:05 +00001056}
1057
1058/*
1059 * Determine which stack to use..
1060 */
1061
bellard579a97f2007-11-11 14:26:47 +00001062static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001063get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001064{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001065 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001066
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001067 /* Default to using normal stack */
1068 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001069#ifdef TARGET_X86_64
1070 esp -= 128; /* this is the redzone */
1071#endif
1072
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001073 /* This is the X/Open sanctioned signal stack switching. */
1074 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1075 if (sas_ss_flags(esp) == 0) {
1076 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001077 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001078 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001079#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001080 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001081 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001082 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1083 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001084 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001085 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001086#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001087 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001088
1089#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001090 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001091#else
1092 return ((esp - frame_size) & (~15ul)) - 8;
1093#endif
bellard66fb9762003-03-23 01:06:05 +00001094}
1095
Pranith Kumar1c1df012017-02-26 11:53:44 -05001096#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001097/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001098static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001099 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001100{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 abi_ulong frame_addr;
1102 struct sigframe *frame;
1103 int i;
bellard66fb9762003-03-23 01:06:05 +00001104
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001105 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1106 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001107
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001108 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1109 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001110
Peter Maydellb6e2c932015-01-08 12:19:43 +00001111 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001112
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001113 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1114 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001115
Riku Voipio7df2fa32014-04-23 10:34:53 +03001116 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1117 __put_user(set->sig[i], &frame->extramask[i - 1]);
1118 }
bellard66fb9762003-03-23 01:06:05 +00001119
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001120 /* Set up to return from userspace. If provided, use a stub
1121 already in userspace. */
1122 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001123 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 } else {
1125 uint16_t val16;
1126 abi_ulong retcode_addr;
1127 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001128 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001129 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1130 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001131 __put_user(val16, (uint16_t *)(frame->retcode+0));
1132 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001133 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001134 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001135 }
bellard66fb9762003-03-23 01:06:05 +00001136
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001137 /* Set up registers for signal handler */
1138 env->regs[R_ESP] = frame_addr;
1139 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001140
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001141 cpu_x86_load_seg(env, R_DS, __USER_DS);
1142 cpu_x86_load_seg(env, R_ES, __USER_DS);
1143 cpu_x86_load_seg(env, R_SS, __USER_DS);
1144 cpu_x86_load_seg(env, R_CS, __USER_CS);
1145 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001146
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001147 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001148
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001149 return;
bellard66fb9762003-03-23 01:06:05 +00001150
1151give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001152 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001153}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001154#endif
bellard66fb9762003-03-23 01:06:05 +00001155
Pranith Kumar1c1df012017-02-26 11:53:44 -05001156/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001157static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001158 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001159 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001160{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001161 abi_ulong frame_addr;
1162#ifndef TARGET_X86_64
1163 abi_ulong addr;
1164#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001165 struct rt_sigframe *frame;
1166 int i;
bellard66fb9762003-03-23 01:06:05 +00001167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001168 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1169 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001170
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001171 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1172 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001173
Pranith Kumar1c1df012017-02-26 11:53:44 -05001174 /* These fields are only in rt_sigframe on 32 bit */
1175#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001176 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001177 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001178 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001179 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001180 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001181#endif
1182 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1183 tswap_siginfo(&frame->info, info);
1184 }
bellard66fb9762003-03-23 01:06:05 +00001185
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001186 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001187 __put_user(0, &frame->uc.tuc_flags);
1188 __put_user(0, &frame->uc.tuc_link);
1189 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1190 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1191 &frame->uc.tuc_stack.ss_flags);
1192 __put_user(target_sigaltstack_used.ss_size,
1193 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001194 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1195 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1196
Riku Voipio0188fad2014-04-23 13:34:15 +03001197 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1198 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1199 }
bellard66fb9762003-03-23 01:06:05 +00001200
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001201 /* Set up to return from userspace. If provided, use a stub
1202 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001203#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001204 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001205 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001206 } else {
1207 uint16_t val16;
1208 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001209 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001210 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001211 __put_user(0xb8, (char *)(frame->retcode+0));
1212 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001213 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001214 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001215 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001216#else
1217 /* XXX: Would be slightly better to return -EFAULT here if test fails
1218 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1219 __put_user(ka->sa_restorer, &frame->pretcode);
1220#endif
bellard66fb9762003-03-23 01:06:05 +00001221
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001222 /* Set up registers for signal handler */
1223 env->regs[R_ESP] = frame_addr;
1224 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001225
Pranith Kumar1c1df012017-02-26 11:53:44 -05001226#ifndef TARGET_X86_64
1227 env->regs[R_EAX] = sig;
1228 env->regs[R_EDX] = (unsigned long)&frame->info;
1229 env->regs[R_ECX] = (unsigned long)&frame->uc;
1230#else
1231 env->regs[R_EAX] = 0;
1232 env->regs[R_EDI] = sig;
1233 env->regs[R_ESI] = (unsigned long)&frame->info;
1234 env->regs[R_EDX] = (unsigned long)&frame->uc;
1235#endif
1236
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001237 cpu_x86_load_seg(env, R_DS, __USER_DS);
1238 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001239 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001240 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001241 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001242
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001243 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001244
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001245 return;
bellard66fb9762003-03-23 01:06:05 +00001246
1247give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001248 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001249}
1250
1251static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001252restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001253{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001254 unsigned int err = 0;
1255 abi_ulong fpstate_addr;
1256 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001257
Pranith Kumar1c1df012017-02-26 11:53:44 -05001258#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001259 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1260 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1261 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1262 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001263
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001264 env->regs[R_EDI] = tswapl(sc->edi);
1265 env->regs[R_ESI] = tswapl(sc->esi);
1266 env->regs[R_EBP] = tswapl(sc->ebp);
1267 env->regs[R_ESP] = tswapl(sc->esp);
1268 env->regs[R_EBX] = tswapl(sc->ebx);
1269 env->regs[R_EDX] = tswapl(sc->edx);
1270 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001271 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001272
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001273 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001274#else
1275 env->regs[8] = tswapl(sc->r8);
1276 env->regs[9] = tswapl(sc->r9);
1277 env->regs[10] = tswapl(sc->r10);
1278 env->regs[11] = tswapl(sc->r11);
1279 env->regs[12] = tswapl(sc->r12);
1280 env->regs[13] = tswapl(sc->r13);
1281 env->regs[14] = tswapl(sc->r14);
1282 env->regs[15] = tswapl(sc->r15);
1283
1284 env->regs[R_EDI] = tswapl(sc->rdi);
1285 env->regs[R_ESI] = tswapl(sc->rsi);
1286 env->regs[R_EBP] = tswapl(sc->rbp);
1287 env->regs[R_EBX] = tswapl(sc->rbx);
1288 env->regs[R_EDX] = tswapl(sc->rdx);
1289 env->regs[R_EAX] = tswapl(sc->rax);
1290 env->regs[R_ECX] = tswapl(sc->rcx);
1291 env->regs[R_ESP] = tswapl(sc->rsp);
1292
1293 env->eip = tswapl(sc->rip);
1294#endif
bellard66fb9762003-03-23 01:06:05 +00001295
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001296 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1297 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001298
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001299 tmpflags = tswapl(sc->eflags);
1300 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1301 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001302
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001303 fpstate_addr = tswapl(sc->fpstate);
1304 if (fpstate_addr != 0) {
1305 if (!access_ok(VERIFY_READ, fpstate_addr,
1306 sizeof(struct target_fpstate)))
1307 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001308#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001309 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001310#else
1311 cpu_x86_fxrstor(env, fpstate_addr);
1312#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001313 }
bellard66fb9762003-03-23 01:06:05 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 return err;
bellard66fb9762003-03-23 01:06:05 +00001316badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001317 return 1;
bellard66fb9762003-03-23 01:06:05 +00001318}
1319
Pranith Kumar1c1df012017-02-26 11:53:44 -05001320/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1321#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001322long do_sigreturn(CPUX86State *env)
1323{
bellard579a97f2007-11-11 14:26:47 +00001324 struct sigframe *frame;
1325 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001326 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001327 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001328 int i;
bellard66fb9762003-03-23 01:06:05 +00001329
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001330 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001331 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1332 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001333 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001334 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001335 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001336 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001337 }
bellard66fb9762003-03-23 01:06:05 +00001338
bellard92319442004-06-19 16:58:13 +00001339 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001340 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001341
bellard66fb9762003-03-23 01:06:05 +00001342 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001343 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001344 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001345 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001346 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001347
1348badframe:
bellard579a97f2007-11-11 14:26:47 +00001349 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001350 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001351 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001352}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001353#endif
bellard66fb9762003-03-23 01:06:05 +00001354
1355long do_rt_sigreturn(CPUX86State *env)
1356{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001357 abi_ulong frame_addr;
1358 struct rt_sigframe *frame;
1359 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001360
Pranith Kumar1c1df012017-02-26 11:53:44 -05001361 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001362 trace_user_do_rt_sigreturn(env, frame_addr);
1363 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1364 goto badframe;
1365 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001366 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001367
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001368 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001369 goto badframe;
1370 }
bellard66fb9762003-03-23 01:06:05 +00001371
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001372 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1373 get_sp_from_cpustate(env)) == -EFAULT) {
1374 goto badframe;
1375 }
thsa04e1342007-09-27 13:57:58 +00001376
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001377 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001378 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001379
1380badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001381 unlock_user_struct(frame, frame_addr, 0);
1382 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001383 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001384}
1385
Andreas Schwab1744aea2013-09-03 20:12:16 +01001386#elif defined(TARGET_AARCH64)
1387
1388struct target_sigcontext {
1389 uint64_t fault_address;
1390 /* AArch64 registers */
1391 uint64_t regs[31];
1392 uint64_t sp;
1393 uint64_t pc;
1394 uint64_t pstate;
1395 /* 4K reserved for FP/SIMD state and future expansion */
1396 char __reserved[4096] __attribute__((__aligned__(16)));
1397};
1398
1399struct target_ucontext {
1400 abi_ulong tuc_flags;
1401 abi_ulong tuc_link;
1402 target_stack_t tuc_stack;
1403 target_sigset_t tuc_sigmask;
1404 /* glibc uses a 1024-bit sigset_t */
1405 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1406 /* last for future expansion */
1407 struct target_sigcontext tuc_mcontext;
1408};
1409
1410/*
1411 * Header to be used at the beginning of structures extending the user
1412 * context. Such structures must be placed after the rt_sigframe on the stack
1413 * and be 16-byte aligned. The last structure must be a dummy one with the
1414 * magic and size set to 0.
1415 */
1416struct target_aarch64_ctx {
1417 uint32_t magic;
1418 uint32_t size;
1419};
1420
1421#define TARGET_FPSIMD_MAGIC 0x46508001
1422
1423struct target_fpsimd_context {
1424 struct target_aarch64_ctx head;
1425 uint32_t fpsr;
1426 uint32_t fpcr;
1427 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1428};
1429
Richard Henderson7a53fb92018-03-09 17:09:43 +00001430#define TARGET_EXTRA_MAGIC 0x45585401
1431
1432struct target_extra_context {
1433 struct target_aarch64_ctx head;
1434 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
1435 uint32_t size; /* size in bytes of the extra space */
1436 uint32_t reserved[3];
1437};
1438
Richard Henderson8c5931d2018-03-09 17:09:44 +00001439#define TARGET_SVE_MAGIC 0x53564501
1440
1441struct target_sve_context {
1442 struct target_aarch64_ctx head;
1443 uint16_t vl;
1444 uint16_t reserved[3];
1445 /* The actual SVE data immediately follows. It is layed out
1446 * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
1447 * the original struct pointer.
1448 */
1449};
1450
1451#define TARGET_SVE_VQ_BYTES 16
1452
1453#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
1454#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
1455
1456#define TARGET_SVE_SIG_REGS_OFFSET \
1457 QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
1458#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
1459 (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
1460#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
1461 (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
1462#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
1463 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
1464#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
1465 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
1466
Andreas Schwab1744aea2013-09-03 20:12:16 +01001467struct target_rt_sigframe {
1468 struct target_siginfo info;
1469 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001470};
1471
1472struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001473 uint64_t fp;
1474 uint64_t lr;
1475 uint32_t tramp[2];
1476};
1477
Richard Henderson3b505bb2018-03-09 17:09:43 +00001478static void target_setup_general_frame(struct target_rt_sigframe *sf,
1479 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001480{
1481 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001482
Richard Henderson3b505bb2018-03-09 17:09:43 +00001483 __put_user(0, &sf->uc.tuc_flags);
1484 __put_user(0, &sf->uc.tuc_link);
1485
1486 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1487 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1488 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001489
1490 for (i = 0; i < 31; i++) {
1491 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1492 }
1493 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1494 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001495 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001496
Peter Maydell7af03922014-05-01 18:36:17 +01001497 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001498
1499 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1500 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1501 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001502}
1503
1504static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1505 CPUARMState *env)
1506{
1507 int i;
1508
1509 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1510 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1511 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1512 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001513
1514 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001515 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001516#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001517 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1518 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001519#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001520 __put_user(q[0], &fpsimd->vregs[i * 2]);
1521 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001522#endif
1523 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001524}
1525
Richard Henderson7a53fb92018-03-09 17:09:43 +00001526static void target_setup_extra_record(struct target_extra_context *extra,
1527 uint64_t datap, uint32_t extra_size)
1528{
1529 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
1530 __put_user(sizeof(struct target_extra_context), &extra->head.size);
1531 __put_user(datap, &extra->datap);
1532 __put_user(extra_size, &extra->size);
1533}
1534
Richard Henderson3b505bb2018-03-09 17:09:43 +00001535static void target_setup_end_record(struct target_aarch64_ctx *end)
1536{
1537 __put_user(0, &end->magic);
1538 __put_user(0, &end->size);
1539}
1540
Richard Henderson8c5931d2018-03-09 17:09:44 +00001541static void target_setup_sve_record(struct target_sve_context *sve,
1542 CPUARMState *env, int vq, int size)
1543{
1544 int i, j;
1545
1546 __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
1547 __put_user(size, &sve->head.size);
1548 __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
1549
1550 /* Note that SVE regs are stored as a byte stream, with each byte element
1551 * at a subsequent address. This corresponds to a little-endian store
1552 * of our 64-bit hunks.
1553 */
1554 for (i = 0; i < 32; ++i) {
1555 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1556 for (j = 0; j < vq * 2; ++j) {
1557 __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
1558 }
1559 }
1560 for (i = 0; i <= 16; ++i) {
1561 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1562 for (j = 0; j < vq; ++j) {
1563 uint64_t r = env->vfp.pregs[i].p[j >> 2];
1564 __put_user_e(r >> ((j & 3) * 16), p + j, le);
1565 }
1566 }
1567}
1568
Richard Henderson3b505bb2018-03-09 17:09:43 +00001569static void target_restore_general_frame(CPUARMState *env,
1570 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001571{
1572 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001573 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001574 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001575
1576 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001577 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001578
1579 for (i = 0; i < 31; i++) {
1580 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1581 }
1582
1583 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1584 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001585 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1586 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001587}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001588
Richard Henderson3b505bb2018-03-09 17:09:43 +00001589static void target_restore_fpsimd_record(CPUARMState *env,
1590 struct target_fpsimd_context *fpsimd)
1591{
1592 uint32_t fpsr, fpcr;
1593 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001594
Richard Henderson3b505bb2018-03-09 17:09:43 +00001595 __get_user(fpsr, &fpsimd->fpsr);
1596 vfp_set_fpsr(env, fpsr);
1597 __get_user(fpcr, &fpsimd->fpcr);
1598 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001599
Peter Maydell4cf23482014-03-02 19:36:38 +00001600 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001601 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001602#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001603 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1604 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001605#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001606 __get_user(q[0], &fpsimd->vregs[i * 2]);
1607 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001608#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001609 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001610}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001611
Richard Henderson8c5931d2018-03-09 17:09:44 +00001612static void target_restore_sve_record(CPUARMState *env,
1613 struct target_sve_context *sve, int vq)
1614{
1615 int i, j;
1616
1617 /* Note that SVE regs are stored as a byte stream, with each byte element
1618 * at a subsequent address. This corresponds to a little-endian load
1619 * of our 64-bit hunks.
1620 */
1621 for (i = 0; i < 32; ++i) {
1622 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1623 for (j = 0; j < vq * 2; ++j) {
1624 __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
1625 }
1626 }
1627 for (i = 0; i <= 16; ++i) {
1628 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1629 for (j = 0; j < vq; ++j) {
1630 uint16_t r;
1631 __get_user_e(r, p + j, le);
1632 if (j & 3) {
1633 env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
1634 } else {
1635 env->vfp.pregs[i].p[j >> 2] = r;
1636 }
1637 }
1638 }
1639}
1640
Richard Henderson3b505bb2018-03-09 17:09:43 +00001641static int target_restore_sigframe(CPUARMState *env,
1642 struct target_rt_sigframe *sf)
1643{
Richard Henderson7a53fb92018-03-09 17:09:43 +00001644 struct target_aarch64_ctx *ctx, *extra = NULL;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001645 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001646 struct target_sve_context *sve = NULL;
Richard Henderson7a53fb92018-03-09 17:09:43 +00001647 uint64_t extra_datap = 0;
1648 bool used_extra = false;
1649 bool err = false;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001650 int vq = 0, sve_size = 0;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001651
1652 target_restore_general_frame(env, sf);
1653
Richard Hendersone1eecd12018-03-09 17:09:43 +00001654 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1655 while (ctx) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001656 uint32_t magic, size, extra_size;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001657
1658 __get_user(magic, &ctx->magic);
1659 __get_user(size, &ctx->size);
1660 switch (magic) {
1661 case 0:
1662 if (size != 0) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001663 err = true;
1664 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001665 }
Richard Henderson7a53fb92018-03-09 17:09:43 +00001666 if (used_extra) {
1667 ctx = NULL;
1668 } else {
1669 ctx = extra;
1670 used_extra = true;
1671 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001672 continue;
1673
1674 case TARGET_FPSIMD_MAGIC:
1675 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001676 err = true;
1677 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001678 }
1679 fpsimd = (struct target_fpsimd_context *)ctx;
1680 break;
1681
Richard Henderson8c5931d2018-03-09 17:09:44 +00001682 case TARGET_SVE_MAGIC:
1683 if (arm_feature(env, ARM_FEATURE_SVE)) {
1684 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1685 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1686 if (!sve && size == sve_size) {
1687 sve = (struct target_sve_context *)ctx;
1688 break;
1689 }
1690 }
1691 err = true;
1692 goto exit;
1693
Richard Henderson7a53fb92018-03-09 17:09:43 +00001694 case TARGET_EXTRA_MAGIC:
1695 if (extra || size != sizeof(struct target_extra_context)) {
1696 err = true;
1697 goto exit;
1698 }
1699 __get_user(extra_datap,
1700 &((struct target_extra_context *)ctx)->datap);
1701 __get_user(extra_size,
1702 &((struct target_extra_context *)ctx)->size);
1703 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
1704 break;
1705
Richard Hendersone1eecd12018-03-09 17:09:43 +00001706 default:
1707 /* Unknown record -- we certainly didn't generate it.
1708 * Did we in fact get out of sync?
1709 */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001710 err = true;
1711 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001712 }
1713 ctx = (void *)ctx + size;
1714 }
1715
1716 /* Require FPSIMD always. */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001717 if (fpsimd) {
1718 target_restore_fpsimd_record(env, fpsimd);
1719 } else {
1720 err = true;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001721 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001722
Richard Henderson8c5931d2018-03-09 17:09:44 +00001723 /* SVE data, if present, overwrites FPSIMD data. */
1724 if (sve) {
1725 target_restore_sve_record(env, sve, vq);
1726 }
1727
Richard Henderson7a53fb92018-03-09 17:09:43 +00001728 exit:
1729 unlock_user(extra, extra_datap, 0);
1730 return err;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001731}
1732
Richard Henderson8c5931d2018-03-09 17:09:44 +00001733static abi_ulong get_sigframe(struct target_sigaction *ka,
1734 CPUARMState *env, int size)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001735{
1736 abi_ulong sp;
1737
1738 sp = env->xregs[31];
1739
1740 /*
1741 * This is the X/Open sanctioned signal stack switching.
1742 */
Riku Voipiob545f632014-07-15 17:01:55 +03001743 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001744 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1745 }
1746
Richard Henderson8c5931d2018-03-09 17:09:44 +00001747 sp = (sp - size) & ~15;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001748
1749 return sp;
1750}
1751
Richard Henderson8c5931d2018-03-09 17:09:44 +00001752typedef struct {
1753 int total_size;
1754 int extra_base;
1755 int extra_size;
1756 int std_end_ofs;
1757 int extra_ofs;
1758 int extra_end_ofs;
1759} target_sigframe_layout;
1760
1761static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
1762{
1763 /* Make sure there will always be space for the end marker. */
1764 const int std_size = sizeof(struct target_rt_sigframe)
1765 - sizeof(struct target_aarch64_ctx);
1766 int this_loc = l->total_size;
1767
1768 if (l->extra_base) {
1769 /* Once we have begun an extra space, all allocations go there. */
1770 l->extra_size += this_size;
1771 } else if (this_size + this_loc > std_size) {
1772 /* This allocation does not fit in the standard space. */
1773 /* Allocate the extra record. */
1774 l->extra_ofs = this_loc;
1775 l->total_size += sizeof(struct target_extra_context);
1776
1777 /* Allocate the standard end record. */
1778 l->std_end_ofs = l->total_size;
1779 l->total_size += sizeof(struct target_aarch64_ctx);
1780
1781 /* Allocate the requested record. */
1782 l->extra_base = this_loc = l->total_size;
1783 l->extra_size = this_size;
1784 }
1785 l->total_size += this_size;
1786
1787 return this_loc;
1788}
1789
Andreas Schwab1744aea2013-09-03 20:12:16 +01001790static void target_setup_frame(int usig, struct target_sigaction *ka,
1791 target_siginfo_t *info, target_sigset_t *set,
1792 CPUARMState *env)
1793{
Richard Henderson8c5931d2018-03-09 17:09:44 +00001794 target_sigframe_layout layout = {
1795 /* Begin with the size pointing to the reserved space. */
1796 .total_size = offsetof(struct target_rt_sigframe,
1797 uc.tuc_mcontext.__reserved),
1798 };
1799 int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001800 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001801 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001802 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001803
Richard Henderson8c5931d2018-03-09 17:09:44 +00001804 /* FPSIMD record is always in the standard space. */
1805 fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
1806 &layout);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001807
Richard Henderson8c5931d2018-03-09 17:09:44 +00001808 /* SVE state needs saving only if it exists. */
1809 if (arm_feature(env, ARM_FEATURE_SVE)) {
1810 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1811 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1812 sve_ofs = alloc_sigframe_space(sve_size, &layout);
1813 }
1814
1815 if (layout.extra_ofs) {
1816 /* Reserve space for the extra end marker. The standard end marker
1817 * will have been allocated when we allocated the extra record.
1818 */
1819 layout.extra_end_ofs
1820 = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
1821 } else {
1822 /* Reserve space for the standard end marker.
1823 * Do not use alloc_sigframe_space because we cheat
1824 * std_size therein to reserve space for this.
1825 */
1826 layout.std_end_ofs = layout.total_size;
1827 layout.total_size += sizeof(struct target_aarch64_ctx);
1828 }
1829
Peter Maydellaac8f552018-04-12 15:02:22 +01001830 /* We must always provide at least the standard 4K reserved space,
1831 * even if we don't use all of it (this is part of the ABI)
1832 */
1833 layout.total_size = MAX(layout.total_size,
1834 sizeof(struct target_rt_sigframe));
1835
Richard Henderson8c5931d2018-03-09 17:09:44 +00001836 /* Reserve space for the return code. On a real system this would
1837 * be within the VDSO. So, despite the name this is not a "real"
1838 * record within the frame.
1839 */
1840 fr_ofs = layout.total_size;
1841 layout.total_size += sizeof(struct target_rt_frame_record);
1842
1843 frame_addr = get_sigframe(ka, env, layout.total_size);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001844 trace_user_setup_frame(env, frame_addr);
Peter Maydellbb3ba352018-04-16 16:19:23 +01001845 frame = lock_user(VERIFY_WRITE, frame_addr, layout.total_size, 0);
1846 if (!frame) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001847 goto give_sigsegv;
1848 }
1849
Richard Henderson3b505bb2018-03-09 17:09:43 +00001850 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001851 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson8c5931d2018-03-09 17:09:44 +00001852 target_setup_end_record((void *)frame + layout.std_end_ofs);
1853 if (layout.extra_ofs) {
1854 target_setup_extra_record((void *)frame + layout.extra_ofs,
1855 frame_addr + layout.extra_base,
1856 layout.extra_size);
1857 target_setup_end_record((void *)frame + layout.extra_end_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001858 }
Richard Henderson8c5931d2018-03-09 17:09:44 +00001859 if (sve_ofs) {
1860 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001861 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001862
1863 /* Set up the stack frame for unwinding. */
1864 fr = (void *)frame + fr_ofs;
1865 __put_user(env->xregs[29], &fr->fp);
1866 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001867
Michael Matz8a3ae912014-03-02 19:36:39 +00001868 if (ka->sa_flags & TARGET_SA_RESTORER) {
1869 return_addr = ka->sa_restorer;
1870 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001871 /*
1872 * mov x8,#__NR_rt_sigreturn; svc #0
1873 * Since these are instructions they need to be put as little-endian
1874 * regardless of target default or current CPU endianness.
1875 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001876 __put_user_e(0xd2801168, &fr->tramp[0], le);
1877 __put_user_e(0xd4000001, &fr->tramp[1], le);
1878 return_addr = frame_addr + fr_ofs
1879 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001880 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001881 env->xregs[0] = usig;
1882 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001883 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001884 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001885 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001886 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001887 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001888 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1889 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1890 }
1891
Peter Maydellbb3ba352018-04-16 16:19:23 +01001892 unlock_user(frame, frame_addr, layout.total_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001893 return;
1894
1895 give_sigsegv:
Peter Maydellbb3ba352018-04-16 16:19:23 +01001896 unlock_user(frame, frame_addr, layout.total_size);
Peter Maydell09391662016-07-28 16:44:47 +01001897 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001898}
1899
1900static void setup_rt_frame(int sig, struct target_sigaction *ka,
1901 target_siginfo_t *info, target_sigset_t *set,
1902 CPUARMState *env)
1903{
1904 target_setup_frame(sig, ka, info, set, env);
1905}
1906
1907static void setup_frame(int sig, struct target_sigaction *ka,
1908 target_sigset_t *set, CPUARMState *env)
1909{
1910 target_setup_frame(sig, ka, 0, set, env);
1911}
1912
1913long do_rt_sigreturn(CPUARMState *env)
1914{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001915 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001916 abi_ulong frame_addr = env->xregs[31];
1917
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001918 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001919 if (frame_addr & 15) {
1920 goto badframe;
1921 }
1922
1923 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1924 goto badframe;
1925 }
1926
1927 if (target_restore_sigframe(env, frame)) {
1928 goto badframe;
1929 }
1930
1931 if (do_sigaltstack(frame_addr +
1932 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1933 0, get_sp_from_cpustate(env)) == -EFAULT) {
1934 goto badframe;
1935 }
1936
1937 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001938 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001939
1940 badframe:
1941 unlock_user_struct(frame, frame_addr, 0);
1942 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001943 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001944}
1945
1946long do_sigreturn(CPUARMState *env)
1947{
1948 return do_rt_sigreturn(env);
1949}
1950
bellard43fff232003-07-09 19:31:39 +00001951#elif defined(TARGET_ARM)
1952
1953struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001954 abi_ulong trap_no;
1955 abi_ulong error_code;
1956 abi_ulong oldmask;
1957 abi_ulong arm_r0;
1958 abi_ulong arm_r1;
1959 abi_ulong arm_r2;
1960 abi_ulong arm_r3;
1961 abi_ulong arm_r4;
1962 abi_ulong arm_r5;
1963 abi_ulong arm_r6;
1964 abi_ulong arm_r7;
1965 abi_ulong arm_r8;
1966 abi_ulong arm_r9;
1967 abi_ulong arm_r10;
1968 abi_ulong arm_fp;
1969 abi_ulong arm_ip;
1970 abi_ulong arm_sp;
1971 abi_ulong arm_lr;
1972 abi_ulong arm_pc;
1973 abi_ulong arm_cpsr;
1974 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001975};
1976
pbrooka745ec62008-05-06 15:36:17 +00001977struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001978 abi_ulong tuc_flags;
1979 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001980 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001981 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001982 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001983};
1984
pbrooka745ec62008-05-06 15:36:17 +00001985struct target_ucontext_v2 {
1986 abi_ulong tuc_flags;
1987 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001988 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001989 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001990 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001991 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001992 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1993};
1994
Peter Maydell0d871bd2010-11-24 15:20:05 +00001995struct target_user_vfp {
1996 uint64_t fpregs[32];
1997 abi_ulong fpscr;
1998};
1999
2000struct target_user_vfp_exc {
2001 abi_ulong fpexc;
2002 abi_ulong fpinst;
2003 abi_ulong fpinst2;
2004};
2005
2006struct target_vfp_sigframe {
2007 abi_ulong magic;
2008 abi_ulong size;
2009 struct target_user_vfp ufp;
2010 struct target_user_vfp_exc ufp_exc;
2011} __attribute__((__aligned__(8)));
2012
Peter Maydell08e11252010-11-24 15:20:07 +00002013struct target_iwmmxt_sigframe {
2014 abi_ulong magic;
2015 abi_ulong size;
2016 uint64_t regs[16];
2017 /* Note that not all the coprocessor control registers are stored here */
2018 uint32_t wcssf;
2019 uint32_t wcasf;
2020 uint32_t wcgr0;
2021 uint32_t wcgr1;
2022 uint32_t wcgr2;
2023 uint32_t wcgr3;
2024} __attribute__((__aligned__(8)));
2025
Peter Maydell0d871bd2010-11-24 15:20:05 +00002026#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00002027#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00002028
pbrooka8c33202008-05-07 23:22:46 +00002029struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002030{
2031 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00002032 abi_ulong extramask[TARGET_NSIG_WORDS-1];
2033 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002034};
2035
pbrooka8c33202008-05-07 23:22:46 +00002036struct sigframe_v2
2037{
2038 struct target_ucontext_v2 uc;
2039 abi_ulong retcode;
2040};
2041
pbrooka745ec62008-05-06 15:36:17 +00002042struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002043{
bellardf8b0aa22007-11-11 23:03:42 +00002044 abi_ulong pinfo;
2045 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00002046 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00002047 struct target_ucontext_v1 uc;
2048 abi_ulong retcode;
2049};
2050
2051struct rt_sigframe_v2
2052{
2053 struct target_siginfo info;
2054 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00002055 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002056};
2057
2058#define TARGET_CONFIG_CPU_32 1
2059
2060/*
2061 * For ARM syscalls, we encode the syscall number into the instruction.
2062 */
2063#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
2064#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
2065
2066/*
2067 * For Thumb syscalls, we pass the syscall number via r7. We therefore
2068 * need two 16-bit instructions.
2069 */
2070#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
2071#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
2072
blueswir1992f48a2007-10-14 16:27:31 +00002073static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00002074 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
2075 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
2076};
2077
2078
Andreas Färber05390242012-02-25 03:37:53 +01002079static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00002080{
2081 return 1;
2082}
2083
pbrooka8c33202008-05-07 23:22:46 +00002084static void
bellard43fff232003-07-09 19:31:39 +00002085setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002086 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00002087{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002088 __put_user(env->regs[0], &sc->arm_r0);
2089 __put_user(env->regs[1], &sc->arm_r1);
2090 __put_user(env->regs[2], &sc->arm_r2);
2091 __put_user(env->regs[3], &sc->arm_r3);
2092 __put_user(env->regs[4], &sc->arm_r4);
2093 __put_user(env->regs[5], &sc->arm_r5);
2094 __put_user(env->regs[6], &sc->arm_r6);
2095 __put_user(env->regs[7], &sc->arm_r7);
2096 __put_user(env->regs[8], &sc->arm_r8);
2097 __put_user(env->regs[9], &sc->arm_r9);
2098 __put_user(env->regs[10], &sc->arm_r10);
2099 __put_user(env->regs[11], &sc->arm_fp);
2100 __put_user(env->regs[12], &sc->arm_ip);
2101 __put_user(env->regs[13], &sc->arm_sp);
2102 __put_user(env->regs[14], &sc->arm_lr);
2103 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002104#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002105 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00002106#endif
2107
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002108 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
2109 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
2110 __put_user(/* current->thread.address */ 0, &sc->fault_address);
2111 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00002112}
2113
bellard579a97f2007-11-11 14:26:47 +00002114static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002115get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00002116{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002117 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00002118
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002119 /*
2120 * This is the X/Open sanctioned signal stack switching.
2121 */
2122 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
2123 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2124 }
2125 /*
2126 * ATPCS B01 mandates 8-byte alignment
2127 */
2128 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00002129}
2130
Riku Voipio0188fad2014-04-23 13:34:15 +03002131static void
Andreas Färber05390242012-02-25 03:37:53 +01002132setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002133 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00002134{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002135 abi_ulong handler = ka->_sa_handler;
2136 abi_ulong retcode;
2137 int thumb = handler & 1;
2138 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01002139
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002140 cpsr &= ~CPSR_IT;
2141 if (thumb) {
2142 cpsr |= CPSR_T;
2143 } else {
2144 cpsr &= ~CPSR_T;
2145 }
bellard43fff232003-07-09 19:31:39 +00002146
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002147 if (ka->sa_flags & TARGET_SA_RESTORER) {
2148 retcode = ka->sa_restorer;
2149 } else {
2150 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00002151
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002152 if (ka->sa_flags & TARGET_SA_SIGINFO) {
2153 idx += 2;
2154 }
bellard43fff232003-07-09 19:31:39 +00002155
Riku Voipio0188fad2014-04-23 13:34:15 +03002156 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02002157
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002158 retcode = rc_addr + thumb;
2159 }
bellard43fff232003-07-09 19:31:39 +00002160
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002161 env->regs[0] = usig;
2162 env->regs[13] = frame_addr;
2163 env->regs[14] = retcode;
2164 env->regs[15] = handler & (thumb ? ~1 : ~3);
2165 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002166}
2167
Andreas Färber05390242012-02-25 03:37:53 +01002168static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002169{
2170 int i;
2171 struct target_vfp_sigframe *vfpframe;
2172 vfpframe = (struct target_vfp_sigframe *)regspace;
2173 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2174 __put_user(sizeof(*vfpframe), &vfpframe->size);
2175 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002176 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002177 }
2178 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2179 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2180 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2181 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2182 return (abi_ulong*)(vfpframe+1);
2183}
2184
Andreas Färber05390242012-02-25 03:37:53 +01002185static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2186 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002187{
2188 int i;
2189 struct target_iwmmxt_sigframe *iwmmxtframe;
2190 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2191 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2192 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2193 for (i = 0; i < 16; i++) {
2194 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2195 }
2196 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2197 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2198 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2199 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2200 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2201 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2202 return (abi_ulong*)(iwmmxtframe+1);
2203}
2204
pbrooka8c33202008-05-07 23:22:46 +00002205static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002206 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002207{
pbrooka8c33202008-05-07 23:22:46 +00002208 struct target_sigaltstack stack;
2209 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002210 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002211
2212 /* Clear all the bits of the ucontext we don't use. */
2213 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2214
2215 memset(&stack, 0, sizeof(stack));
2216 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2217 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2218 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2219 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2220
2221 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002222 /* Save coprocessor signal frame. */
2223 regspace = uc->tuc_regspace;
2224 if (arm_feature(env, ARM_FEATURE_VFP)) {
2225 regspace = setup_sigframe_v2_vfp(regspace, env);
2226 }
Peter Maydell08e11252010-11-24 15:20:07 +00002227 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2228 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2229 }
2230
Peter Maydell0d871bd2010-11-24 15:20:05 +00002231 /* Write terminating magic word */
2232 __put_user(0, regspace);
2233
pbrooka8c33202008-05-07 23:22:46 +00002234 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2235 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2236 }
2237}
2238
2239/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002240static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002241 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002242{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002243 struct sigframe_v1 *frame;
2244 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2245 int i;
bellard43fff232003-07-09 19:31:39 +00002246
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002247 trace_user_setup_frame(regs, frame_addr);
2248 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002249 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002250 }
bellard579a97f2007-11-11 14:26:47 +00002251
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002252 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002253
Riku Voipio0188fad2014-04-23 13:34:15 +03002254 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2255 __put_user(set->sig[i], &frame->extramask[i - 1]);
2256 }
bellard43fff232003-07-09 19:31:39 +00002257
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002258 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2259 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002260
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002262 return;
2263sigsegv:
2264 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002265}
2266
pbrook624f7972008-05-31 16:11:38 +00002267static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002268 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002269{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002270 struct sigframe_v2 *frame;
2271 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002272
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002273 trace_user_setup_frame(regs, frame_addr);
2274 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002275 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002276 }
pbrooka8c33202008-05-07 23:22:46 +00002277
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002278 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002279
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002280 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2281 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002282
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002283 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002284 return;
2285sigsegv:
2286 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002287}
2288
pbrook624f7972008-05-31 16:11:38 +00002289static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002290 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002291{
2292 if (get_osversion() >= 0x020612) {
2293 setup_frame_v2(usig, ka, set, regs);
2294 } else {
2295 setup_frame_v1(usig, ka, set, regs);
2296 }
bellard43fff232003-07-09 19:31:39 +00002297}
2298
bellard579a97f2007-11-11 14:26:47 +00002299/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002300static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002301 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002302 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002303{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002304 struct rt_sigframe_v1 *frame;
2305 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2306 struct target_sigaltstack stack;
2307 int i;
2308 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002309
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002310 trace_user_setup_rt_frame(env, frame_addr);
2311 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002312 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002313 }
bellardedf779f2004-02-22 13:40:13 +00002314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002315 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2316 __put_user(info_addr, &frame->pinfo);
2317 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2318 __put_user(uc_addr, &frame->puc);
2319 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002320
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002321 /* Clear all the bits of the ucontext we don't use. */
2322 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002323
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002324 memset(&stack, 0, sizeof(stack));
2325 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2326 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2327 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2328 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002329
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002330 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2331 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2332 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2333 }
bellard43fff232003-07-09 19:31:39 +00002334
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002335 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2336 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002337
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002338 env->regs[1] = info_addr;
2339 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002340
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002341 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002342 return;
2343sigsegv:
2344 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002345}
2346
pbrook624f7972008-05-31 16:11:38 +00002347static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002348 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002349 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002350{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002351 struct rt_sigframe_v2 *frame;
2352 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2353 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002354
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002355 trace_user_setup_rt_frame(env, frame_addr);
2356 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002357 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002358 }
pbrooka745ec62008-05-06 15:36:17 +00002359
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002360 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2361 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2362 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002363
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002364 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002365
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002366 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2367 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002368
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002369 env->regs[1] = info_addr;
2370 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002371
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002372 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002373 return;
2374sigsegv:
2375 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002376}
2377
pbrook624f7972008-05-31 16:11:38 +00002378static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002379 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002380 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002381{
2382 if (get_osversion() >= 0x020612) {
2383 setup_rt_frame_v2(usig, ka, info, set, env);
2384 } else {
2385 setup_rt_frame_v1(usig, ka, info, set, env);
2386 }
2387}
2388
bellard43fff232003-07-09 19:31:39 +00002389static int
Andreas Färber05390242012-02-25 03:37:53 +01002390restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002391{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002392 int err = 0;
2393 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002394
Riku Voipio1d8b5122014-04-23 10:26:05 +03002395 __get_user(env->regs[0], &sc->arm_r0);
2396 __get_user(env->regs[1], &sc->arm_r1);
2397 __get_user(env->regs[2], &sc->arm_r2);
2398 __get_user(env->regs[3], &sc->arm_r3);
2399 __get_user(env->regs[4], &sc->arm_r4);
2400 __get_user(env->regs[5], &sc->arm_r5);
2401 __get_user(env->regs[6], &sc->arm_r6);
2402 __get_user(env->regs[7], &sc->arm_r7);
2403 __get_user(env->regs[8], &sc->arm_r8);
2404 __get_user(env->regs[9], &sc->arm_r9);
2405 __get_user(env->regs[10], &sc->arm_r10);
2406 __get_user(env->regs[11], &sc->arm_fp);
2407 __get_user(env->regs[12], &sc->arm_ip);
2408 __get_user(env->regs[13], &sc->arm_sp);
2409 __get_user(env->regs[14], &sc->arm_lr);
2410 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002411#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002412 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002413 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002414#endif
2415
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002416 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002417
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002418 return err;
bellard43fff232003-07-09 19:31:39 +00002419}
2420
Andreas Färber05390242012-02-25 03:37:53 +01002421static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002422{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002423 abi_ulong frame_addr;
2424 struct sigframe_v1 *frame = NULL;
2425 target_sigset_t set;
2426 sigset_t host_set;
2427 int i;
bellard43fff232003-07-09 19:31:39 +00002428
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002429 /*
2430 * Since we stacked the signal on a 64-bit boundary,
2431 * then 'sp' should be word aligned here. If it's
2432 * not, then the user is trying to mess with us.
2433 */
2434 frame_addr = env->regs[13];
2435 trace_user_do_sigreturn(env, frame_addr);
2436 if (frame_addr & 7) {
2437 goto badframe;
2438 }
Peter Maydell978fae92013-07-29 12:00:32 +01002439
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002440 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2441 goto badframe;
2442 }
bellard43fff232003-07-09 19:31:39 +00002443
Riku Voipiof5f601a2014-04-23 13:00:17 +03002444 __get_user(set.sig[0], &frame->sc.oldmask);
2445 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2446 __get_user(set.sig[i], &frame->extramask[i - 1]);
2447 }
bellard43fff232003-07-09 19:31:39 +00002448
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002449 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002450 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002451
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002452 if (restore_sigcontext(env, &frame->sc)) {
2453 goto badframe;
2454 }
bellard43fff232003-07-09 19:31:39 +00002455
2456#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002457 /* Send SIGTRAP if we're single-stepping */
2458 if (ptrace_cancel_bpt(current))
2459 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002460#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002461 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002462 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002463
2464badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002465 force_sig(TARGET_SIGSEGV);
2466 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002467}
2468
Andreas Färber05390242012-02-25 03:37:53 +01002469static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002470{
2471 int i;
2472 abi_ulong magic, sz;
2473 uint32_t fpscr, fpexc;
2474 struct target_vfp_sigframe *vfpframe;
2475 vfpframe = (struct target_vfp_sigframe *)regspace;
2476
2477 __get_user(magic, &vfpframe->magic);
2478 __get_user(sz, &vfpframe->size);
2479 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2480 return 0;
2481 }
2482 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002483 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002484 }
2485 __get_user(fpscr, &vfpframe->ufp.fpscr);
2486 vfp_set_fpscr(env, fpscr);
2487 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2488 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2489 * and the exception flag is cleared
2490 */
2491 fpexc |= (1 << 30);
2492 fpexc &= ~((1 << 31) | (1 << 28));
2493 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2494 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2495 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2496 return (abi_ulong*)(vfpframe + 1);
2497}
2498
Andreas Färber05390242012-02-25 03:37:53 +01002499static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2500 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002501{
2502 int i;
2503 abi_ulong magic, sz;
2504 struct target_iwmmxt_sigframe *iwmmxtframe;
2505 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2506
2507 __get_user(magic, &iwmmxtframe->magic);
2508 __get_user(sz, &iwmmxtframe->size);
2509 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2510 return 0;
2511 }
2512 for (i = 0; i < 16; i++) {
2513 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2514 }
2515 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2516 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2517 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2518 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2519 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2520 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2521 return (abi_ulong*)(iwmmxtframe + 1);
2522}
2523
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002524static int do_sigframe_return_v2(CPUARMState *env,
2525 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002526 struct target_ucontext_v2 *uc)
2527{
2528 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002529 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002530
2531 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002532 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002533
2534 if (restore_sigcontext(env, &uc->tuc_mcontext))
2535 return 1;
2536
Peter Maydell5f9099d2010-11-24 15:20:06 +00002537 /* Restore coprocessor signal frame */
2538 regspace = uc->tuc_regspace;
2539 if (arm_feature(env, ARM_FEATURE_VFP)) {
2540 regspace = restore_sigframe_v2_vfp(env, regspace);
2541 if (!regspace) {
2542 return 1;
2543 }
2544 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002545 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2546 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2547 if (!regspace) {
2548 return 1;
2549 }
2550 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002551
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002552 if (do_sigaltstack(context_addr
2553 + offsetof(struct target_ucontext_v2, tuc_stack),
2554 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002555 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002556 }
pbrooka8c33202008-05-07 23:22:46 +00002557
2558#if 0
2559 /* Send SIGTRAP if we're single-stepping */
2560 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002561 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002562#endif
2563
2564 return 0;
2565}
2566
Andreas Färber05390242012-02-25 03:37:53 +01002567static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002568{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002569 abi_ulong frame_addr;
2570 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002571
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002572 /*
2573 * Since we stacked the signal on a 64-bit boundary,
2574 * then 'sp' should be word aligned here. If it's
2575 * not, then the user is trying to mess with us.
2576 */
2577 frame_addr = env->regs[13];
2578 trace_user_do_sigreturn(env, frame_addr);
2579 if (frame_addr & 7) {
2580 goto badframe;
2581 }
Peter Maydell978fae92013-07-29 12:00:32 +01002582
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002583 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2584 goto badframe;
2585 }
pbrooka8c33202008-05-07 23:22:46 +00002586
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002587 if (do_sigframe_return_v2(env,
2588 frame_addr
2589 + offsetof(struct sigframe_v2, uc),
2590 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002591 goto badframe;
2592 }
pbrooka8c33202008-05-07 23:22:46 +00002593
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002594 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002595 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002596
2597badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002598 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002599 force_sig(TARGET_SIGSEGV);
2600 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002601}
2602
Andreas Färber05390242012-02-25 03:37:53 +01002603long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002604{
2605 if (get_osversion() >= 0x020612) {
2606 return do_sigreturn_v2(env);
2607 } else {
2608 return do_sigreturn_v1(env);
2609 }
2610}
2611
Andreas Färber05390242012-02-25 03:37:53 +01002612static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002613{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002614 abi_ulong frame_addr;
2615 struct rt_sigframe_v1 *frame = NULL;
2616 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002617
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002618 /*
2619 * Since we stacked the signal on a 64-bit boundary,
2620 * then 'sp' should be word aligned here. If it's
2621 * not, then the user is trying to mess with us.
2622 */
2623 frame_addr = env->regs[13];
2624 trace_user_do_rt_sigreturn(env, frame_addr);
2625 if (frame_addr & 7) {
2626 goto badframe;
2627 }
Peter Maydell978fae92013-07-29 12:00:32 +01002628
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002629 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2630 goto badframe;
2631 }
bellard43fff232003-07-09 19:31:39 +00002632
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002633 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002634 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002635
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002636 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2637 goto badframe;
2638 }
bellard43fff232003-07-09 19:31:39 +00002639
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002640 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2641 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002642
bellard43fff232003-07-09 19:31:39 +00002643#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002644 /* Send SIGTRAP if we're single-stepping */
2645 if (ptrace_cancel_bpt(current))
2646 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002647#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002648 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002649 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002650
2651badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002652 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002653 force_sig(TARGET_SIGSEGV);
2654 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002655}
2656
Andreas Färber05390242012-02-25 03:37:53 +01002657static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002658{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002659 abi_ulong frame_addr;
2660 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002661
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002662 /*
2663 * Since we stacked the signal on a 64-bit boundary,
2664 * then 'sp' should be word aligned here. If it's
2665 * not, then the user is trying to mess with us.
2666 */
2667 frame_addr = env->regs[13];
2668 trace_user_do_rt_sigreturn(env, frame_addr);
2669 if (frame_addr & 7) {
2670 goto badframe;
2671 }
Peter Maydell978fae92013-07-29 12:00:32 +01002672
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002673 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2674 goto badframe;
2675 }
pbrooka745ec62008-05-06 15:36:17 +00002676
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002677 if (do_sigframe_return_v2(env,
2678 frame_addr
2679 + offsetof(struct rt_sigframe_v2, uc),
2680 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002681 goto badframe;
2682 }
pbrooka745ec62008-05-06 15:36:17 +00002683
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002684 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002685 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002686
2687badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002688 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002689 force_sig(TARGET_SIGSEGV);
2690 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002691}
2692
Andreas Färber05390242012-02-25 03:37:53 +01002693long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002694{
2695 if (get_osversion() >= 0x020612) {
2696 return do_rt_sigreturn_v2(env);
2697 } else {
2698 return do_rt_sigreturn_v1(env);
2699 }
2700}
2701
bellard6d5e2162004-09-30 22:04:13 +00002702#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002703
bellard6d5e2162004-09-30 22:04:13 +00002704#define __SUNOS_MAXWIN 31
2705
2706/* This is what SunOS does, so shall I. */
2707struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002708 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002709
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002710 abi_ulong sigc_mask; /* sigmask to restore */
2711 abi_ulong sigc_sp; /* stack pointer */
2712 abi_ulong sigc_pc; /* program counter */
2713 abi_ulong sigc_npc; /* next program counter */
2714 abi_ulong sigc_psr; /* for condition codes etc */
2715 abi_ulong sigc_g1; /* User uses these two registers */
2716 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002717
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002718 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002719 * at the time of the signal.
2720 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002721 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002722
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002723 /* stack ptrs for each regwin buf */
2724 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002725
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002726 /* Windows to restore after signal */
2727 struct {
2728 abi_ulong locals[8];
2729 abi_ulong ins[8];
2730 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002731};
2732/* A Sparc stack frame */
2733struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002734 abi_ulong locals[8];
2735 abi_ulong ins[8];
2736 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002737 * since we never need to access them ourselves.
2738 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002739 char *structptr;
2740 abi_ulong xargs[6];
2741 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002742};
2743
2744typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002745 struct {
2746 abi_ulong psr;
2747 abi_ulong pc;
2748 abi_ulong npc;
2749 abi_ulong y;
2750 abi_ulong u_regs[16]; /* globals and ins */
2751 } si_regs;
2752 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002753} __siginfo_t;
2754
2755typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002756 abi_ulong si_float_regs[32];
2757 unsigned long si_fsr;
2758 unsigned long si_fpqdepth;
2759 struct {
2760 unsigned long *insn_addr;
2761 unsigned long insn;
2762 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002763} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002764
2765
2766struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002767 struct sparc_stackf ss;
2768 __siginfo_t info;
2769 abi_ulong fpu_save;
2770 abi_ulong insns[2] __attribute__ ((aligned (8)));
2771 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2772 abi_ulong extra_size; /* Should be 0 */
2773 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002774};
2775struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002776 struct sparc_stackf ss;
2777 siginfo_t info;
2778 abi_ulong regs[20];
2779 sigset_t mask;
2780 abi_ulong fpu_save;
2781 unsigned int insns[2];
2782 stack_t stack;
2783 unsigned int extra_size; /* Should be 0 */
2784 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002785};
2786
bellarde80cfcf2004-12-19 23:18:01 +00002787#define UREG_O0 16
2788#define UREG_O6 22
2789#define UREG_I0 0
2790#define UREG_I1 1
2791#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002792#define UREG_I3 3
2793#define UREG_I4 4
2794#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002795#define UREG_I6 6
2796#define UREG_I7 7
2797#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002798#define UREG_FP UREG_I6
2799#define UREG_SP UREG_O6
2800
pbrook624f7972008-05-31 16:11:38 +00002801static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002802 CPUSPARCState *env,
2803 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002804{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002805 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002806
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002807 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002808
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002809 /* This is the X/Open sanctioned signal stack switching. */
2810 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2811 if (!on_sig_stack(sp)
2812 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2813 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2814 }
2815 }
2816 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002817}
2818
2819static int
Andreas Färber05390242012-02-25 03:37:53 +01002820setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002821{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002822 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002823
Riku Voipio1d8b5122014-04-23 10:26:05 +03002824 __put_user(env->psr, &si->si_regs.psr);
2825 __put_user(env->pc, &si->si_regs.pc);
2826 __put_user(env->npc, &si->si_regs.npc);
2827 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002828 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002829 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002830 }
2831 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002832 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002833 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002834 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002835 return err;
bellard6d5e2162004-09-30 22:04:13 +00002836}
bellarde80cfcf2004-12-19 23:18:01 +00002837
bellard80a9d032005-01-03 23:31:27 +00002838#if 0
bellard6d5e2162004-09-30 22:04:13 +00002839static int
2840setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002841 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002842{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002843 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002844
Riku Voipio1d8b5122014-04-23 10:26:05 +03002845 __put_user(mask, &sc->sigc_mask);
2846 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2847 __put_user(env->pc, &sc->sigc_pc);
2848 __put_user(env->npc, &sc->sigc_npc);
2849 __put_user(env->psr, &sc->sigc_psr);
2850 __put_user(env->gregs[1], &sc->sigc_g1);
2851 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002852
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002853 return err;
bellard6d5e2162004-09-30 22:04:13 +00002854}
bellard80a9d032005-01-03 23:31:27 +00002855#endif
bellard6d5e2162004-09-30 22:04:13 +00002856#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2857
pbrook624f7972008-05-31 16:11:38 +00002858static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002859 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002860{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002861 abi_ulong sf_addr;
2862 struct target_signal_frame *sf;
2863 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002864
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002865 /* 1. Make sure everything is clean */
2866 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002867
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002868 sigframe_size = NF_ALIGNEDSZ;
2869 sf_addr = get_sigframe(ka, env, sigframe_size);
2870 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002871
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002872 sf = lock_user(VERIFY_WRITE, sf_addr,
2873 sizeof(struct target_signal_frame), 0);
2874 if (!sf) {
2875 goto sigsegv;
2876 }
bellard6d5e2162004-09-30 22:04:13 +00002877#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002878 if (invalid_frame_pointer(sf, sigframe_size))
2879 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002880#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002881 /* 2. Save the current process state */
2882 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002883 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002884
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002885 //save_fpu_state(regs, &sf->fpu_state);
2886 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002887
Riku Voipio1d8b5122014-04-23 10:26:05 +03002888 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002889 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002890 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002891 }
bellard6d5e2162004-09-30 22:04:13 +00002892
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002893 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002894 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002895 }
2896 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002897 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002898 }
2899 if (err)
2900 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002901
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002902 /* 3. signal handler back-trampoline and parameters */
2903 env->regwptr[UREG_FP] = sf_addr;
2904 env->regwptr[UREG_I0] = sig;
2905 env->regwptr[UREG_I1] = sf_addr +
2906 offsetof(struct target_signal_frame, info);
2907 env->regwptr[UREG_I2] = sf_addr +
2908 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002909
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002910 /* 4. signal handler */
2911 env->pc = ka->_sa_handler;
2912 env->npc = (env->pc + 4);
2913 /* 5. return to kernel instructions */
Laurent Vivier5de154e2018-04-02 12:24:52 +02002914 if (ka->ka_restorer) {
2915 env->regwptr[UREG_I7] = ka->ka_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002916 } else {
2917 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002918
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002919 env->regwptr[UREG_I7] = sf_addr +
2920 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002921
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002922 /* mov __NR_sigreturn, %g1 */
2923 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002924 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002925
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002926 /* t 0x10 */
2927 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002928 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002929 if (err)
2930 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002931
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002932 /* Flush instruction space. */
2933 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2934 // tb_flush(env);
2935 }
2936 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2937 return;
bellard459a4012007-11-11 19:45:10 +00002938#if 0
2939sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002940 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002941#endif
bellard6d5e2162004-09-30 22:04:13 +00002942sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002943 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002944 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002945}
bellard6d5e2162004-09-30 22:04:13 +00002946
pbrook624f7972008-05-31 16:11:38 +00002947static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002948 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002949 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002950{
2951 fprintf(stderr, "setup_rt_frame: not implemented\n");
2952}
2953
Andreas Färber05390242012-02-25 03:37:53 +01002954long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002955{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002956 abi_ulong sf_addr;
2957 struct target_signal_frame *sf;
2958 uint32_t up_psr, pc, npc;
2959 target_sigset_t set;
2960 sigset_t host_set;
2961 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002962
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002963 sf_addr = env->regwptr[UREG_FP];
2964 trace_user_do_sigreturn(env, sf_addr);
2965 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2966 goto segv_and_exit;
2967 }
bellard6d5e2162004-09-30 22:04:13 +00002968
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002969 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002970
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002971 if (sf_addr & 3)
2972 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002973
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002974 __get_user(pc, &sf->info.si_regs.pc);
2975 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002976
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002977 if ((pc | npc) & 3) {
2978 goto segv_and_exit;
2979 }
bellard6d5e2162004-09-30 22:04:13 +00002980
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002981 /* 2. Restore the state */
2982 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002983
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002984 /* User can only change condition codes and FPU enabling in %psr. */
2985 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2986 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002987
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002988 env->pc = pc;
2989 env->npc = npc;
2990 __get_user(env->y, &sf->info.si_regs.y);
2991 for (i=0; i < 8; i++) {
2992 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2993 }
2994 for (i=0; i < 8; i++) {
2995 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2996 }
bellard6d5e2162004-09-30 22:04:13 +00002997
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002998 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002999 * __get_user(fpu_save, &sf->fpu_save);
3000 * if (fpu_save)
3001 * err |= restore_fpu_state(env, fpu_save);
3002 */
bellard6d5e2162004-09-30 22:04:13 +00003003
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003004 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00003005 * the races which exist anyways.
3006 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003007 __get_user(set.sig[0], &sf->info.si_mask);
3008 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3009 __get_user(set.sig[i], &sf->extramask[i - 1]);
3010 }
bellarde80cfcf2004-12-19 23:18:01 +00003011
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003012 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003013 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00003014
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003015 if (err) {
3016 goto segv_and_exit;
3017 }
3018 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01003019 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003020
3021segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003022 unlock_user_struct(sf, sf_addr, 0);
3023 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003024 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003025}
3026
Andreas Färber05390242012-02-25 03:37:53 +01003027long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00003028{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003029 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00003030 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00003031 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00003032}
3033
bellard459a4012007-11-11 19:45:10 +00003034#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00003035#define SPARC_MC_TSTATE 0
3036#define SPARC_MC_PC 1
3037#define SPARC_MC_NPC 2
3038#define SPARC_MC_Y 3
3039#define SPARC_MC_G1 4
3040#define SPARC_MC_G2 5
3041#define SPARC_MC_G3 6
3042#define SPARC_MC_G4 7
3043#define SPARC_MC_G5 8
3044#define SPARC_MC_G6 9
3045#define SPARC_MC_G7 10
3046#define SPARC_MC_O0 11
3047#define SPARC_MC_O1 12
3048#define SPARC_MC_O2 13
3049#define SPARC_MC_O3 14
3050#define SPARC_MC_O4 15
3051#define SPARC_MC_O5 16
3052#define SPARC_MC_O6 17
3053#define SPARC_MC_O7 18
3054#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00003055
Anthony Liguoric227f092009-10-01 16:12:16 -05003056typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003057typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00003058
3059struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00003060 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003061 uint32_t mcfq_insn;
3062};
3063
3064struct target_mc_fpu {
3065 union {
3066 uint32_t sregs[32];
3067 uint64_t dregs[32];
3068 //uint128_t qregs[16];
3069 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00003070 abi_ulong mcfpu_fsr;
3071 abi_ulong mcfpu_fprs;
3072 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00003073 struct target_mc_fq *mcfpu_fq;
3074 unsigned char mcfpu_qcnt;
3075 unsigned char mcfpu_qentsz;
3076 unsigned char mcfpu_enab;
3077};
Anthony Liguoric227f092009-10-01 16:12:16 -05003078typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003079
3080typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05003081 target_mc_gregset_t mc_gregs;
3082 target_mc_greg_t mc_fp;
3083 target_mc_greg_t mc_i7;
3084 target_mc_fpu_t mc_fpregs;
3085} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003086
3087struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003088 struct target_ucontext *tuc_link;
3089 abi_ulong tuc_flags;
3090 target_sigset_t tuc_sigmask;
3091 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003092};
3093
3094/* A V9 register window */
3095struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00003096 abi_ulong locals[8];
3097 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00003098};
3099
3100#define TARGET_STACK_BIAS 2047
3101
3102/* {set, get}context() needed for 64-bit SparcLinux userland. */
3103void sparc64_set_context(CPUSPARCState *env)
3104{
bellard459a4012007-11-11 19:45:10 +00003105 abi_ulong ucp_addr;
3106 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003107 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00003108 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00003109 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003110 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00003111
bellard459a4012007-11-11 19:45:10 +00003112 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003113 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00003114 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003115 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02003116 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003117 __get_user(pc, &((*grp)[SPARC_MC_PC]));
3118 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003119 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00003120 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003121 }
blueswir15bfb56b2007-10-05 17:01:51 +00003122 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05003123 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003124 sigset_t set;
3125
3126 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003127 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00003128 } else {
bellard459a4012007-11-11 19:45:10 +00003129 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003130 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00003131 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003132 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003133 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003134 }
blueswir15bfb56b2007-10-05 17:01:51 +00003135 }
3136 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003137 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00003138 }
3139 env->pc = pc;
3140 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003141 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
3142 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00003143 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00003144 cpu_put_ccr(env, tstate >> 32);
3145 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00003146 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
3147 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
3148 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
3149 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
3150 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
3151 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
3152 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
3153 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
3154 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
3155 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
3156 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
3157 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
3158 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
3159 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
3160 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003161
Riku Voipio1d8b5122014-04-23 10:26:05 +03003162 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3163 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003164
bellard459a4012007-11-11 19:45:10 +00003165 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003166 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3167 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003168 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003169 }
3170 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3171 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003172 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003173 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003174 /* FIXME this does not match how the kernel handles the FPU in
3175 * its sparc64_set_context implementation. In particular the FPU
3176 * is only restored if fenab is non-zero in:
3177 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3178 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003179 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003180 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003181 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3182 for (i = 0; i < 64; i++, src++) {
3183 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003184 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003185 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003186 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003187 }
3188 }
bellard459a4012007-11-11 19:45:10 +00003189 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003190 __get_user(env->fsr,
3191 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3192 __get_user(env->gsr,
3193 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003194 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003195 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003196do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003197 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003198 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003199}
3200
3201void sparc64_get_context(CPUSPARCState *env)
3202{
bellard459a4012007-11-11 19:45:10 +00003203 abi_ulong ucp_addr;
3204 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003205 target_mc_gregset_t *grp;
3206 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003207 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003208 int err;
3209 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003210 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003211 sigset_t set;
3212
bellard459a4012007-11-11 19:45:10 +00003213 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003214 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003215 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003216 }
bellard459a4012007-11-11 19:45:10 +00003217
Aurelien Jarno60e99242010-03-29 02:12:51 +02003218 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003219 grp = &mcp->mc_gregs;
3220
3221 /* Skip over the trap instruction, first. */
3222 env->pc = env->npc;
3223 env->npc += 4;
3224
Peter Maydell3d3efba2016-05-27 15:51:49 +01003225 /* If we're only reading the signal mask then do_sigprocmask()
3226 * is guaranteed not to fail, which is important because we don't
3227 * have any way to signal a failure or restart this operation since
3228 * this is not a normal syscall.
3229 */
3230 err = do_sigprocmask(0, NULL, &set);
3231 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003232 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003233 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003234 __put_user(target_set.sig[0],
3235 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003236 } else {
3237 abi_ulong *src, *dst;
3238 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003239 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003240 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003241 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003242 }
blueswir15bfb56b2007-10-05 17:01:51 +00003243 if (err)
3244 goto do_sigsegv;
3245 }
3246
bellard459a4012007-11-11 19:45:10 +00003247 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003248 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3249 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3250 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3251 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3252 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3253 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3254 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3255 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3256 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3257 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3258 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3259 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3260 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3261 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3262 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3263 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3264 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3265 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3266 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003267
bellard459a4012007-11-11 19:45:10 +00003268 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3269 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003270 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3271 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003272 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003273 }
3274 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3275 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003276 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003277 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003278 __put_user(fp, &(mcp->mc_fp));
3279 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003280
bellard459a4012007-11-11 19:45:10 +00003281 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003282 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3283 for (i = 0; i < 64; i++, dst++) {
3284 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003285 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003286 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003287 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003288 }
3289 }
bellard459a4012007-11-11 19:45:10 +00003290 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003291 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3292 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3293 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003294
3295 if (err)
3296 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003297 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003298 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003299do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003300 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003301 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003302}
3303#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003304#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003305
Richard Hendersonff970902013-02-10 10:30:42 -08003306# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003307struct target_sigcontext {
3308 uint32_t sc_regmask; /* Unused */
3309 uint32_t sc_status;
3310 uint64_t sc_pc;
3311 uint64_t sc_regs[32];
3312 uint64_t sc_fpregs[32];
3313 uint32_t sc_ownedfp; /* Unused */
3314 uint32_t sc_fpc_csr;
3315 uint32_t sc_fpc_eir; /* Unused */
3316 uint32_t sc_used_math;
3317 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003318 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003319 uint64_t sc_mdhi;
3320 uint64_t sc_mdlo;
3321 target_ulong sc_hi1; /* Was sc_cause */
3322 target_ulong sc_lo1; /* Was sc_badvaddr */
3323 target_ulong sc_hi2; /* Was sc_sigset[4] */
3324 target_ulong sc_lo2;
3325 target_ulong sc_hi3;
3326 target_ulong sc_lo3;
3327};
Richard Hendersonff970902013-02-10 10:30:42 -08003328# else /* N32 || N64 */
3329struct target_sigcontext {
3330 uint64_t sc_regs[32];
3331 uint64_t sc_fpregs[32];
3332 uint64_t sc_mdhi;
3333 uint64_t sc_hi1;
3334 uint64_t sc_hi2;
3335 uint64_t sc_hi3;
3336 uint64_t sc_mdlo;
3337 uint64_t sc_lo1;
3338 uint64_t sc_lo2;
3339 uint64_t sc_lo3;
3340 uint64_t sc_pc;
3341 uint32_t sc_fpc_csr;
3342 uint32_t sc_used_math;
3343 uint32_t sc_dsp;
3344 uint32_t sc_reserved;
3345};
3346# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003347
3348struct sigframe {
3349 uint32_t sf_ass[4]; /* argument save space for o32 */
3350 uint32_t sf_code[2]; /* signal trampoline */
3351 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003352 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003353};
3354
pbrook0b1bcb02009-04-21 01:41:10 +00003355struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003356 target_ulong tuc_flags;
3357 target_ulong tuc_link;
3358 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003359 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003360 struct target_sigcontext tuc_mcontext;
3361 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003362};
3363
3364struct target_rt_sigframe {
3365 uint32_t rs_ass[4]; /* argument save space for o32 */
3366 uint32_t rs_code[2]; /* signal trampoline */
3367 struct target_siginfo rs_info;
3368 struct target_ucontext rs_uc;
3369};
3370
bellard106ec872006-06-27 21:08:10 +00003371/* Install trampoline to jump back from signal handler */
3372static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3373{
Richard Henderson084d0492013-02-10 10:30:44 -08003374 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003375
3376 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003377 * Set up the return code ...
3378 *
3379 * li v0, __NR__foo_sigreturn
3380 * syscall
3381 */
bellard106ec872006-06-27 21:08:10 +00003382
Riku Voipio1d8b5122014-04-23 10:26:05 +03003383 __put_user(0x24020000 + syscall, tramp + 0);
3384 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003385 return err;
3386}
3387
Riku Voipio41ecc722014-04-23 11:01:00 +03003388static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003389 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003390{
Richard Henderson084d0492013-02-10 10:30:44 -08003391 int i;
bellard106ec872006-06-27 21:08:10 +00003392
Riku Voipio1d8b5122014-04-23 10:26:05 +03003393 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003394 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003395
Richard Henderson084d0492013-02-10 10:30:44 -08003396 __put_user(0, &sc->sc_regs[0]);
3397 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003398 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003399 }
bellard106ec872006-06-27 21:08:10 +00003400
Riku Voipio1d8b5122014-04-23 10:26:05 +03003401 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3402 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003403
Richard Henderson084d0492013-02-10 10:30:44 -08003404 /* Rather than checking for dsp existence, always copy. The storage
3405 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003406 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3407 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3408 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3409 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3410 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3411 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003412 {
3413 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003414 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003415 }
Richard Henderson084d0492013-02-10 10:30:44 -08003416
Riku Voipio1d8b5122014-04-23 10:26:05 +03003417 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003418
3419 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003420 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003421 }
bellard106ec872006-06-27 21:08:10 +00003422}
3423
Riku Voipio016d2e12014-04-23 11:19:48 +03003424static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003425restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003426{
Richard Henderson084d0492013-02-10 10:30:44 -08003427 int i;
bellard106ec872006-06-27 21:08:10 +00003428
Riku Voipio1d8b5122014-04-23 10:26:05 +03003429 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003430
Riku Voipio1d8b5122014-04-23 10:26:05 +03003431 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3432 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003433
Richard Henderson084d0492013-02-10 10:30:44 -08003434 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003435 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003436 }
3437
Riku Voipio1d8b5122014-04-23 10:26:05 +03003438 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3439 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3440 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3441 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3442 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3443 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003444 {
3445 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003446 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003447 cpu_wrdsp(dsp, 0x3ff, regs);
3448 }
3449
3450 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003451 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003452 }
bellard106ec872006-06-27 21:08:10 +00003453}
Richard Hendersonff970902013-02-10 10:30:42 -08003454
bellard106ec872006-06-27 21:08:10 +00003455/*
3456 * Determine which stack to use..
3457 */
bellard579a97f2007-11-11 14:26:47 +00003458static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003459get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003460{
3461 unsigned long sp;
3462
3463 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003464 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003465
3466 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003467 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003468 * above the user stack, 16-bytes before the next lowest
3469 * 16 byte boundary. Try to avoid trashing it.
3470 */
3471 sp -= 32;
3472
bellard106ec872006-06-27 21:08:10 +00003473 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003474 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003475 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3476 }
bellard106ec872006-06-27 21:08:10 +00003477
bellard579a97f2007-11-11 14:26:47 +00003478 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003479}
3480
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003481static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3482{
3483 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3484 env->hflags &= ~MIPS_HFLAG_M16;
3485 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3486 env->active_tc.PC &= ~(target_ulong) 1;
3487 }
3488}
3489
Richard Hendersonff970902013-02-10 10:30:42 -08003490# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003491/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003492static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003493 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003494{
3495 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003496 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003497 int i;
3498
bellard579a97f2007-11-11 14:26:47 +00003499 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003500 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003501 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3502 goto give_sigsegv;
3503 }
bellard106ec872006-06-27 21:08:10 +00003504
3505 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3506
Riku Voipio41ecc722014-04-23 11:01:00 +03003507 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003508
3509 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003510 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003511 }
3512
3513 /*
3514 * Arguments to signal handler:
3515 *
3516 * a0 = signal number
3517 * a1 = 0 (should be cause)
3518 * a2 = pointer to struct sigcontext
3519 *
3520 * $25 and PC point to the signal handler, $29 points to the
3521 * struct sigframe.
3522 */
thsb5dc7732008-06-27 10:02:35 +00003523 regs->active_tc.gpr[ 4] = sig;
3524 regs->active_tc.gpr[ 5] = 0;
3525 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3526 regs->active_tc.gpr[29] = frame_addr;
3527 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003528 /* The original kernel code sets CP0_EPC to the handler
3529 * since it returns to userland using eret
3530 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003531 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003532 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003533 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003534 return;
3535
3536give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003537 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003538}
3539
Andreas Färber05390242012-02-25 03:37:53 +01003540long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003541{
ths388bb212007-05-13 13:58:00 +00003542 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003543 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003544 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003545 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003546 int i;
bellard106ec872006-06-27 21:08:10 +00003547
thsb5dc7732008-06-27 10:02:35 +00003548 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003549 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003550 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003551 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003552
ths388bb212007-05-13 13:58:00 +00003553 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003554 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003555 }
bellard106ec872006-06-27 21:08:10 +00003556
ths388bb212007-05-13 13:58:00 +00003557 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003558 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003559
Riku Voipio016d2e12014-04-23 11:19:48 +03003560 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003561
3562#if 0
ths388bb212007-05-13 13:58:00 +00003563 /*
3564 * Don't let your children do this ...
3565 */
3566 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003567 "move\t$29, %0\n\t"
3568 "j\tsyscall_exit"
3569 :/* no outputs */
3570 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003571 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003572#endif
ths3b46e622007-09-17 08:09:54 +00003573
thsb5dc7732008-06-27 10:02:35 +00003574 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003575 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003576 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003577 * maybe a problem with nested signals ? */
3578 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003579 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003580
3581badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003582 force_sig(TARGET_SIGSEGV);
3583 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003584}
Richard Hendersonff970902013-02-10 10:30:42 -08003585# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003586
pbrook624f7972008-05-31 16:11:38 +00003587static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003588 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003589 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003590{
pbrook0b1bcb02009-04-21 01:41:10 +00003591 struct target_rt_sigframe *frame;
3592 abi_ulong frame_addr;
3593 int i;
3594
3595 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003596 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003597 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3598 goto give_sigsegv;
3599 }
pbrook0b1bcb02009-04-21 01:41:10 +00003600
3601 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3602
Peter Maydellf6c7a052015-01-08 12:19:48 +00003603 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003604
Aurelien Jarno60e99242010-03-29 02:12:51 +02003605 __put_user(0, &frame->rs_uc.tuc_flags);
3606 __put_user(0, &frame->rs_uc.tuc_link);
3607 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3608 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003609 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003610 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003611
Aurelien Jarno60e99242010-03-29 02:12:51 +02003612 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003613
3614 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003615 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003616 }
3617
3618 /*
3619 * Arguments to signal handler:
3620 *
3621 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003622 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003623 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003624 *
3625 * $25 and PC point to the signal handler, $29 points to the
3626 * struct sigframe.
3627 */
3628 env->active_tc.gpr[ 4] = sig;
3629 env->active_tc.gpr[ 5] = frame_addr
3630 + offsetof(struct target_rt_sigframe, rs_info);
3631 env->active_tc.gpr[ 6] = frame_addr
3632 + offsetof(struct target_rt_sigframe, rs_uc);
3633 env->active_tc.gpr[29] = frame_addr;
3634 env->active_tc.gpr[31] = frame_addr
3635 + offsetof(struct target_rt_sigframe, rs_code);
3636 /* The original kernel code sets CP0_EPC to the handler
3637 * since it returns to userland using eret
3638 * we cannot do this here, and we must set PC directly */
3639 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003640 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003641 unlock_user_struct(frame, frame_addr, 1);
3642 return;
3643
3644give_sigsegv:
3645 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003646 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003647}
3648
Andreas Färber05390242012-02-25 03:37:53 +01003649long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003650{
pbrook0b1bcb02009-04-21 01:41:10 +00003651 struct target_rt_sigframe *frame;
3652 abi_ulong frame_addr;
3653 sigset_t blocked;
3654
pbrook0b1bcb02009-04-21 01:41:10 +00003655 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003656 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003657 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3658 goto badframe;
3659 }
pbrook0b1bcb02009-04-21 01:41:10 +00003660
Aurelien Jarno60e99242010-03-29 02:12:51 +02003661 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003662 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003663
Riku Voipio016d2e12014-04-23 11:19:48 +03003664 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003665
3666 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003667 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3668 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003669 goto badframe;
3670
3671 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003672 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003673 /* I am not sure this is right, but it seems to work
3674 * maybe a problem with nested signals ? */
3675 env->CP0_EPC = 0;
3676 return -TARGET_QEMU_ESIGRETURN;
3677
3678badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003679 force_sig(TARGET_SIGSEGV);
3680 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003681}
bellard6d5e2162004-09-30 22:04:13 +00003682
thsc3b5bc82007-12-02 06:31:25 +00003683#elif defined(TARGET_SH4)
3684
3685/*
3686 * code and data structures from linux kernel:
3687 * include/asm-sh/sigcontext.h
3688 * arch/sh/kernel/signal.c
3689 */
3690
3691struct target_sigcontext {
3692 target_ulong oldmask;
3693
3694 /* CPU registers */
3695 target_ulong sc_gregs[16];
3696 target_ulong sc_pc;
3697 target_ulong sc_pr;
3698 target_ulong sc_sr;
3699 target_ulong sc_gbr;
3700 target_ulong sc_mach;
3701 target_ulong sc_macl;
3702
3703 /* FPU registers */
3704 target_ulong sc_fpregs[16];
3705 target_ulong sc_xfpregs[16];
3706 unsigned int sc_fpscr;
3707 unsigned int sc_fpul;
3708 unsigned int sc_ownedfp;
3709};
3710
3711struct target_sigframe
3712{
3713 struct target_sigcontext sc;
3714 target_ulong extramask[TARGET_NSIG_WORDS-1];
3715 uint16_t retcode[3];
3716};
3717
3718
3719struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003720 target_ulong tuc_flags;
3721 struct target_ucontext *tuc_link;
3722 target_stack_t tuc_stack;
3723 struct target_sigcontext tuc_mcontext;
3724 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003725};
3726
3727struct target_rt_sigframe
3728{
3729 struct target_siginfo info;
3730 struct target_ucontext uc;
3731 uint16_t retcode[3];
3732};
3733
3734
3735#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3736#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3737
pbrook624f7972008-05-31 16:11:38 +00003738static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003739 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003740{
pbrook624f7972008-05-31 16:11:38 +00003741 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003742 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3743 }
3744
3745 return (sp - frame_size) & -8ul;
3746}
3747
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003748/* Notice when we're in the middle of a gUSA region and reset.
3749 Note that this will only occur for !parallel_cpus, as we will
3750 translate such sequences differently in a parallel context. */
3751static void unwind_gusa(CPUSH4State *regs)
3752{
3753 /* If the stack pointer is sufficiently negative, and we haven't
3754 completed the sequence, then reset to the entry to the region. */
3755 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3756 However, the page mappings in qemu linux-user aren't as restricted
3757 and we wind up with the normal stack mapped above 0xF0000000.
3758 That said, there is no reason why the kernel should be allowing
3759 a gUSA region that spans 1GB. Use a tighter check here, for what
3760 can actually be enabled by the immediate move. */
3761 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3762 /* Reset the PC to before the gUSA region, as computed from
3763 R0 = region end, SP = -(region size), plus one more for the
3764 insn that actually initializes SP to the region size. */
3765 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3766
3767 /* Reset the SP to the saved version in R1. */
3768 regs->gregs[15] = regs->gregs[1];
3769 }
3770}
3771
Riku Voipio41ecc722014-04-23 11:01:00 +03003772static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003773 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003774{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003775 int i;
thsc3b5bc82007-12-02 06:31:25 +00003776
Riku Voipio1d8b5122014-04-23 10:26:05 +03003777#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003778 COPY(gregs[0]); COPY(gregs[1]);
3779 COPY(gregs[2]); COPY(gregs[3]);
3780 COPY(gregs[4]); COPY(gregs[5]);
3781 COPY(gregs[6]); COPY(gregs[7]);
3782 COPY(gregs[8]); COPY(gregs[9]);
3783 COPY(gregs[10]); COPY(gregs[11]);
3784 COPY(gregs[12]); COPY(gregs[13]);
3785 COPY(gregs[14]); COPY(gregs[15]);
3786 COPY(gbr); COPY(mach);
3787 COPY(macl); COPY(pr);
3788 COPY(sr); COPY(pc);
3789#undef COPY
3790
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003791 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003792 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003793 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003794 __put_user(regs->fpscr, &sc->sc_fpscr);
3795 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003796
3797 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003798 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003799}
3800
Timothy E Baldwinba412492016-05-12 18:47:35 +01003801static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003802{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003803 int i;
thsc3b5bc82007-12-02 06:31:25 +00003804
Riku Voipio1d8b5122014-04-23 10:26:05 +03003805#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003806 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003807 COPY(gregs[2]); COPY(gregs[3]);
3808 COPY(gregs[4]); COPY(gregs[5]);
3809 COPY(gregs[6]); COPY(gregs[7]);
3810 COPY(gregs[8]); COPY(gregs[9]);
3811 COPY(gregs[10]); COPY(gregs[11]);
3812 COPY(gregs[12]); COPY(gregs[13]);
3813 COPY(gregs[14]); COPY(gregs[15]);
3814 COPY(gbr); COPY(mach);
3815 COPY(macl); COPY(pr);
3816 COPY(sr); COPY(pc);
3817#undef COPY
3818
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003819 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003820 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003821 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003822 __get_user(regs->fpscr, &sc->sc_fpscr);
3823 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003824
3825 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003826 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003827}
3828
pbrook624f7972008-05-31 16:11:38 +00003829static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003830 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003831{
3832 struct target_sigframe *frame;
3833 abi_ulong frame_addr;
3834 int i;
thsc3b5bc82007-12-02 06:31:25 +00003835
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003836 unwind_gusa(regs);
3837
thsc3b5bc82007-12-02 06:31:25 +00003838 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003839 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003840 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3841 goto give_sigsegv;
3842 }
thsc3b5bc82007-12-02 06:31:25 +00003843
Riku Voipio41ecc722014-04-23 11:01:00 +03003844 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003845
3846 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003847 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003848 }
3849
3850 /* Set up to return from userspace. If provided, use a stub
3851 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003852 if (ka->sa_flags & TARGET_SA_RESTORER) {
3853 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003854 } else {
3855 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003856 abi_ulong retcode_addr = frame_addr +
3857 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003858 __put_user(MOVW(2), &frame->retcode[0]);
3859 __put_user(TRAP_NOARG, &frame->retcode[1]);
3860 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003861 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003862 }
3863
thsc3b5bc82007-12-02 06:31:25 +00003864 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003865 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003866 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003867 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003868 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003869 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003870 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003871
3872 unlock_user_struct(frame, frame_addr, 1);
3873 return;
3874
3875give_sigsegv:
3876 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003877 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003878}
3879
pbrook624f7972008-05-31 16:11:38 +00003880static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003881 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003882 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003883{
3884 struct target_rt_sigframe *frame;
3885 abi_ulong frame_addr;
3886 int i;
thsc3b5bc82007-12-02 06:31:25 +00003887
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003888 unwind_gusa(regs);
3889
thsc3b5bc82007-12-02 06:31:25 +00003890 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003891 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003892 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3893 goto give_sigsegv;
3894 }
thsc3b5bc82007-12-02 06:31:25 +00003895
Peter Maydellf6c7a052015-01-08 12:19:48 +00003896 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003897
3898 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003899 __put_user(0, &frame->uc.tuc_flags);
3900 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3901 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3902 &frame->uc.tuc_stack.ss_sp);
3903 __put_user(sas_ss_flags(regs->gregs[15]),
3904 &frame->uc.tuc_stack.ss_flags);
3905 __put_user(target_sigaltstack_used.ss_size,
3906 &frame->uc.tuc_stack.ss_size);
3907 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003908 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003909 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003910 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003911 }
3912
3913 /* Set up to return from userspace. If provided, use a stub
3914 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003915 if (ka->sa_flags & TARGET_SA_RESTORER) {
3916 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003917 } else {
3918 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003919 abi_ulong retcode_addr = frame_addr +
3920 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003921 __put_user(MOVW(2), &frame->retcode[0]);
3922 __put_user(TRAP_NOARG, &frame->retcode[1]);
3923 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003924 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003925 }
3926
thsc3b5bc82007-12-02 06:31:25 +00003927 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003928 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003929 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003930 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3931 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003932 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003933 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003934
3935 unlock_user_struct(frame, frame_addr, 1);
3936 return;
3937
3938give_sigsegv:
3939 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003940 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003941}
3942
Andreas Färber05390242012-02-25 03:37:53 +01003943long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003944{
3945 struct target_sigframe *frame;
3946 abi_ulong frame_addr;
3947 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003948 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003949 int i;
3950 int err = 0;
3951
thsc3b5bc82007-12-02 06:31:25 +00003952 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003953 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003954 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3955 goto badframe;
3956 }
thsc3b5bc82007-12-02 06:31:25 +00003957
Riku Voipio1d8b5122014-04-23 10:26:05 +03003958 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003959 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003960 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003961 }
3962
3963 if (err)
3964 goto badframe;
3965
3966 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003967 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003968
Timothy E Baldwinba412492016-05-12 18:47:35 +01003969 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003970
3971 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003972 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003973
3974badframe:
3975 unlock_user_struct(frame, frame_addr, 0);
3976 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003977 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003978}
3979
Andreas Färber05390242012-02-25 03:37:53 +01003980long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003981{
3982 struct target_rt_sigframe *frame;
3983 abi_ulong frame_addr;
3984 sigset_t blocked;
3985
thsc3b5bc82007-12-02 06:31:25 +00003986 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003987 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003988 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3989 goto badframe;
3990 }
thsc3b5bc82007-12-02 06:31:25 +00003991
Aurelien Jarno60e99242010-03-29 02:12:51 +02003992 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003993 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003994
Timothy E Baldwinba412492016-05-12 18:47:35 +01003995 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003996
3997 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003998 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3999 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00004000 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004001 }
thsc3b5bc82007-12-02 06:31:25 +00004002
4003 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01004004 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004005
4006badframe:
4007 unlock_user_struct(frame, frame_addr, 0);
4008 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004009 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004010}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004011#elif defined(TARGET_MICROBLAZE)
4012
4013struct target_sigcontext {
4014 struct target_pt_regs regs; /* needs to be first */
4015 uint32_t oldmask;
4016};
4017
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004018struct target_stack_t {
4019 abi_ulong ss_sp;
4020 int ss_flags;
4021 unsigned int ss_size;
4022};
4023
4024struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08004025 abi_ulong tuc_flags;
4026 abi_ulong tuc_link;
4027 struct target_stack_t tuc_stack;
4028 struct target_sigcontext tuc_mcontext;
4029 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004030};
4031
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004032/* Signal frames. */
4033struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004034 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004035 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4036 uint32_t tramp[2];
4037};
4038
4039struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00004040 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004041 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004042 uint32_t tramp[2];
4043};
4044
Andreas Färber05390242012-02-25 03:37:53 +01004045static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004046{
4047 __put_user(env->regs[0], &sc->regs.r0);
4048 __put_user(env->regs[1], &sc->regs.r1);
4049 __put_user(env->regs[2], &sc->regs.r2);
4050 __put_user(env->regs[3], &sc->regs.r3);
4051 __put_user(env->regs[4], &sc->regs.r4);
4052 __put_user(env->regs[5], &sc->regs.r5);
4053 __put_user(env->regs[6], &sc->regs.r6);
4054 __put_user(env->regs[7], &sc->regs.r7);
4055 __put_user(env->regs[8], &sc->regs.r8);
4056 __put_user(env->regs[9], &sc->regs.r9);
4057 __put_user(env->regs[10], &sc->regs.r10);
4058 __put_user(env->regs[11], &sc->regs.r11);
4059 __put_user(env->regs[12], &sc->regs.r12);
4060 __put_user(env->regs[13], &sc->regs.r13);
4061 __put_user(env->regs[14], &sc->regs.r14);
4062 __put_user(env->regs[15], &sc->regs.r15);
4063 __put_user(env->regs[16], &sc->regs.r16);
4064 __put_user(env->regs[17], &sc->regs.r17);
4065 __put_user(env->regs[18], &sc->regs.r18);
4066 __put_user(env->regs[19], &sc->regs.r19);
4067 __put_user(env->regs[20], &sc->regs.r20);
4068 __put_user(env->regs[21], &sc->regs.r21);
4069 __put_user(env->regs[22], &sc->regs.r22);
4070 __put_user(env->regs[23], &sc->regs.r23);
4071 __put_user(env->regs[24], &sc->regs.r24);
4072 __put_user(env->regs[25], &sc->regs.r25);
4073 __put_user(env->regs[26], &sc->regs.r26);
4074 __put_user(env->regs[27], &sc->regs.r27);
4075 __put_user(env->regs[28], &sc->regs.r28);
4076 __put_user(env->regs[29], &sc->regs.r29);
4077 __put_user(env->regs[30], &sc->regs.r30);
4078 __put_user(env->regs[31], &sc->regs.r31);
4079 __put_user(env->sregs[SR_PC], &sc->regs.pc);
4080}
4081
Andreas Färber05390242012-02-25 03:37:53 +01004082static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004083{
4084 __get_user(env->regs[0], &sc->regs.r0);
4085 __get_user(env->regs[1], &sc->regs.r1);
4086 __get_user(env->regs[2], &sc->regs.r2);
4087 __get_user(env->regs[3], &sc->regs.r3);
4088 __get_user(env->regs[4], &sc->regs.r4);
4089 __get_user(env->regs[5], &sc->regs.r5);
4090 __get_user(env->regs[6], &sc->regs.r6);
4091 __get_user(env->regs[7], &sc->regs.r7);
4092 __get_user(env->regs[8], &sc->regs.r8);
4093 __get_user(env->regs[9], &sc->regs.r9);
4094 __get_user(env->regs[10], &sc->regs.r10);
4095 __get_user(env->regs[11], &sc->regs.r11);
4096 __get_user(env->regs[12], &sc->regs.r12);
4097 __get_user(env->regs[13], &sc->regs.r13);
4098 __get_user(env->regs[14], &sc->regs.r14);
4099 __get_user(env->regs[15], &sc->regs.r15);
4100 __get_user(env->regs[16], &sc->regs.r16);
4101 __get_user(env->regs[17], &sc->regs.r17);
4102 __get_user(env->regs[18], &sc->regs.r18);
4103 __get_user(env->regs[19], &sc->regs.r19);
4104 __get_user(env->regs[20], &sc->regs.r20);
4105 __get_user(env->regs[21], &sc->regs.r21);
4106 __get_user(env->regs[22], &sc->regs.r22);
4107 __get_user(env->regs[23], &sc->regs.r23);
4108 __get_user(env->regs[24], &sc->regs.r24);
4109 __get_user(env->regs[25], &sc->regs.r25);
4110 __get_user(env->regs[26], &sc->regs.r26);
4111 __get_user(env->regs[27], &sc->regs.r27);
4112 __get_user(env->regs[28], &sc->regs.r28);
4113 __get_user(env->regs[29], &sc->regs.r29);
4114 __get_user(env->regs[30], &sc->regs.r30);
4115 __get_user(env->regs[31], &sc->regs.r31);
4116 __get_user(env->sregs[SR_PC], &sc->regs.pc);
4117}
4118
4119static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004120 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004121{
4122 abi_ulong sp = env->regs[1];
4123
Riku Voipiob545f632014-07-15 17:01:55 +03004124 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004125 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03004126 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004127
4128 return ((sp - frame_size) & -8UL);
4129}
4130
4131static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004132 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004133{
4134 struct target_signal_frame *frame;
4135 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004136 int i;
4137
4138 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004139 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004140 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4141 goto badframe;
4142
4143 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004144 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004145
4146 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03004147 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004148 }
4149
Richard Hendersonf711df62010-11-22 14:57:52 -08004150 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004151
4152 /* Set up to return from userspace. If provided, use a stub
4153 already in userspace. */
4154 /* minus 8 is offset to cater for "rtsd r15,8" offset */
4155 if (ka->sa_flags & TARGET_SA_RESTORER) {
4156 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
4157 } else {
4158 uint32_t t;
4159 /* Note, these encodings are _big endian_! */
4160 /* addi r12, r0, __NR_sigreturn */
4161 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004162 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004163 /* brki r14, 0x8 */
4164 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004165 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004166
4167 /* Return from sighandler will jump to the tramp.
4168 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004169 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4170 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004171 }
4172
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004173 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004174 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004175 /* Signal handler args: */
4176 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004177 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004178 /* arg 1: sigcontext */
4179 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004180
4181 /* Offset of 4 to handle microblaze rtid r14, 0 */
4182 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4183
4184 unlock_user_struct(frame, frame_addr, 1);
4185 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004186badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004187 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004188}
4189
4190static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004191 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004192 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004193{
4194 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4195}
4196
Andreas Färber05390242012-02-25 03:37:53 +01004197long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004198{
4199 struct target_signal_frame *frame;
4200 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004201 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004202 sigset_t set;
4203 int i;
4204
4205 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004206 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004207 /* Make sure the guest isn't playing games. */
4208 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4209 goto badframe;
4210
4211 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004212 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004213 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004214 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004215 }
4216 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004217 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004218
Richard Hendersonf711df62010-11-22 14:57:52 -08004219 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004220 /* We got here through a sigreturn syscall, our path back is via an
4221 rtb insn so setup r14 for that. */
4222 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004223
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004224 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004225 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004226badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004227 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004228 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004229}
4230
Andreas Färber05390242012-02-25 03:37:53 +01004231long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004232{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004233 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004234 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4235 return -TARGET_ENOSYS;
4236}
4237
edgar_iglb6d3abd2008-02-28 11:29:27 +00004238#elif defined(TARGET_CRIS)
4239
4240struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004241 struct target_pt_regs regs; /* needs to be first */
4242 uint32_t oldmask;
4243 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004244};
4245
4246/* Signal frames. */
4247struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004248 struct target_sigcontext sc;
4249 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4250 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004251};
4252
4253struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004254 siginfo_t *pinfo;
4255 void *puc;
4256 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004257 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004258 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004259};
4260
Andreas Färber05390242012-02-25 03:37:53 +01004261static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004262{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004263 __put_user(env->regs[0], &sc->regs.r0);
4264 __put_user(env->regs[1], &sc->regs.r1);
4265 __put_user(env->regs[2], &sc->regs.r2);
4266 __put_user(env->regs[3], &sc->regs.r3);
4267 __put_user(env->regs[4], &sc->regs.r4);
4268 __put_user(env->regs[5], &sc->regs.r5);
4269 __put_user(env->regs[6], &sc->regs.r6);
4270 __put_user(env->regs[7], &sc->regs.r7);
4271 __put_user(env->regs[8], &sc->regs.r8);
4272 __put_user(env->regs[9], &sc->regs.r9);
4273 __put_user(env->regs[10], &sc->regs.r10);
4274 __put_user(env->regs[11], &sc->regs.r11);
4275 __put_user(env->regs[12], &sc->regs.r12);
4276 __put_user(env->regs[13], &sc->regs.r13);
4277 __put_user(env->regs[14], &sc->usp);
4278 __put_user(env->regs[15], &sc->regs.acr);
4279 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4280 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4281 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004282}
edgar_igl9664d922008-03-03 22:23:53 +00004283
Andreas Färber05390242012-02-25 03:37:53 +01004284static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004285{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004286 __get_user(env->regs[0], &sc->regs.r0);
4287 __get_user(env->regs[1], &sc->regs.r1);
4288 __get_user(env->regs[2], &sc->regs.r2);
4289 __get_user(env->regs[3], &sc->regs.r3);
4290 __get_user(env->regs[4], &sc->regs.r4);
4291 __get_user(env->regs[5], &sc->regs.r5);
4292 __get_user(env->regs[6], &sc->regs.r6);
4293 __get_user(env->regs[7], &sc->regs.r7);
4294 __get_user(env->regs[8], &sc->regs.r8);
4295 __get_user(env->regs[9], &sc->regs.r9);
4296 __get_user(env->regs[10], &sc->regs.r10);
4297 __get_user(env->regs[11], &sc->regs.r11);
4298 __get_user(env->regs[12], &sc->regs.r12);
4299 __get_user(env->regs[13], &sc->regs.r13);
4300 __get_user(env->regs[14], &sc->usp);
4301 __get_user(env->regs[15], &sc->regs.acr);
4302 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4303 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4304 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004305}
4306
Andreas Färber05390242012-02-25 03:37:53 +01004307static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004308{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004309 abi_ulong sp;
4310 /* Align the stack downwards to 4. */
4311 sp = (env->regs[R_SP] & ~3);
4312 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004313}
4314
pbrook624f7972008-05-31 16:11:38 +00004315static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004316 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004317{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004318 struct target_signal_frame *frame;
4319 abi_ulong frame_addr;
4320 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004322 frame_addr = get_sigframe(env, sizeof *frame);
4323 trace_user_setup_frame(env, frame_addr);
4324 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4325 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004326
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004327 /*
4328 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4329 * use this trampoline anymore but it sets it up for GDB.
4330 * In QEMU, using the trampoline simplifies things a bit so we use it.
4331 *
4332 * This is movu.w __NR_sigreturn, r9; break 13;
4333 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004334 __put_user(0x9c5f, frame->retcode+0);
4335 __put_user(TARGET_NR_sigreturn,
4336 frame->retcode + 1);
4337 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004338
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004339 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004340 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004341
Riku Voipio0188fad2014-04-23 13:34:15 +03004342 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4343 __put_user(set->sig[i], &frame->extramask[i - 1]);
4344 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004345
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004346 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004347
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004348 /* Move the stack and setup the arguments for the handler. */
4349 env->regs[R_SP] = frame_addr;
4350 env->regs[10] = sig;
4351 env->pc = (unsigned long) ka->_sa_handler;
4352 /* Link SRP so the guest returns through the trampoline. */
4353 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004354
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004355 unlock_user_struct(frame, frame_addr, 1);
4356 return;
4357badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004358 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004359}
4360
pbrook624f7972008-05-31 16:11:38 +00004361static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004362 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004363 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004364{
4365 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4366}
4367
Andreas Färber05390242012-02-25 03:37:53 +01004368long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004369{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004370 struct target_signal_frame *frame;
4371 abi_ulong frame_addr;
4372 target_sigset_t target_set;
4373 sigset_t set;
4374 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004375
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004376 frame_addr = env->regs[R_SP];
4377 trace_user_do_sigreturn(env, frame_addr);
4378 /* Make sure the guest isn't playing games. */
4379 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4380 goto badframe;
4381 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004382
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004383 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004384 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004385 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004386 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004387 }
4388 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004389 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004390
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004391 restore_sigcontext(&frame->sc, env);
4392 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004393 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004394badframe:
4395 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004396 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004397}
4398
Andreas Färber05390242012-02-25 03:37:53 +01004399long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004400{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004401 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004402 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4403 return -TARGET_ENOSYS;
4404}
thsc3b5bc82007-12-02 06:31:25 +00004405
Marek Vasuta0a839b2017-01-18 23:01:42 +01004406#elif defined(TARGET_NIOS2)
4407
4408#define MCONTEXT_VERSION 2
4409
4410struct target_sigcontext {
4411 int version;
4412 unsigned long gregs[32];
4413};
4414
4415struct target_ucontext {
4416 abi_ulong tuc_flags;
4417 abi_ulong tuc_link;
4418 target_stack_t tuc_stack;
4419 struct target_sigcontext tuc_mcontext;
4420 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4421};
4422
4423struct target_rt_sigframe {
4424 struct target_siginfo info;
4425 struct target_ucontext uc;
4426};
4427
4428static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4429{
4430 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4431#ifdef CONFIG_STACK_GROWSUP
4432 return target_sigaltstack_used.ss_sp;
4433#else
4434 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4435#endif
4436 }
4437 return sp;
4438}
4439
4440static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4441{
4442 unsigned long *gregs = uc->tuc_mcontext.gregs;
4443
4444 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4445 __put_user(env->regs[1], &gregs[0]);
4446 __put_user(env->regs[2], &gregs[1]);
4447 __put_user(env->regs[3], &gregs[2]);
4448 __put_user(env->regs[4], &gregs[3]);
4449 __put_user(env->regs[5], &gregs[4]);
4450 __put_user(env->regs[6], &gregs[5]);
4451 __put_user(env->regs[7], &gregs[6]);
4452 __put_user(env->regs[8], &gregs[7]);
4453 __put_user(env->regs[9], &gregs[8]);
4454 __put_user(env->regs[10], &gregs[9]);
4455 __put_user(env->regs[11], &gregs[10]);
4456 __put_user(env->regs[12], &gregs[11]);
4457 __put_user(env->regs[13], &gregs[12]);
4458 __put_user(env->regs[14], &gregs[13]);
4459 __put_user(env->regs[15], &gregs[14]);
4460 __put_user(env->regs[16], &gregs[15]);
4461 __put_user(env->regs[17], &gregs[16]);
4462 __put_user(env->regs[18], &gregs[17]);
4463 __put_user(env->regs[19], &gregs[18]);
4464 __put_user(env->regs[20], &gregs[19]);
4465 __put_user(env->regs[21], &gregs[20]);
4466 __put_user(env->regs[22], &gregs[21]);
4467 __put_user(env->regs[23], &gregs[22]);
4468 __put_user(env->regs[R_RA], &gregs[23]);
4469 __put_user(env->regs[R_FP], &gregs[24]);
4470 __put_user(env->regs[R_GP], &gregs[25]);
4471 __put_user(env->regs[R_EA], &gregs[27]);
4472 __put_user(env->regs[R_SP], &gregs[28]);
4473
4474 return 0;
4475}
4476
4477static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4478 int *pr2)
4479{
4480 int temp;
4481 abi_ulong off, frame_addr = env->regs[R_SP];
4482 unsigned long *gregs = uc->tuc_mcontext.gregs;
4483 int err;
4484
4485 /* Always make any pending restarted system calls return -EINTR */
4486 /* current->restart_block.fn = do_no_restart_syscall; */
4487
4488 __get_user(temp, &uc->tuc_mcontext.version);
4489 if (temp != MCONTEXT_VERSION) {
4490 return 1;
4491 }
4492
4493 /* restore passed registers */
4494 __get_user(env->regs[1], &gregs[0]);
4495 __get_user(env->regs[2], &gregs[1]);
4496 __get_user(env->regs[3], &gregs[2]);
4497 __get_user(env->regs[4], &gregs[3]);
4498 __get_user(env->regs[5], &gregs[4]);
4499 __get_user(env->regs[6], &gregs[5]);
4500 __get_user(env->regs[7], &gregs[6]);
4501 __get_user(env->regs[8], &gregs[7]);
4502 __get_user(env->regs[9], &gregs[8]);
4503 __get_user(env->regs[10], &gregs[9]);
4504 __get_user(env->regs[11], &gregs[10]);
4505 __get_user(env->regs[12], &gregs[11]);
4506 __get_user(env->regs[13], &gregs[12]);
4507 __get_user(env->regs[14], &gregs[13]);
4508 __get_user(env->regs[15], &gregs[14]);
4509 __get_user(env->regs[16], &gregs[15]);
4510 __get_user(env->regs[17], &gregs[16]);
4511 __get_user(env->regs[18], &gregs[17]);
4512 __get_user(env->regs[19], &gregs[18]);
4513 __get_user(env->regs[20], &gregs[19]);
4514 __get_user(env->regs[21], &gregs[20]);
4515 __get_user(env->regs[22], &gregs[21]);
4516 __get_user(env->regs[23], &gregs[22]);
4517 /* gregs[23] is handled below */
4518 /* Verify, should this be settable */
4519 __get_user(env->regs[R_FP], &gregs[24]);
4520 /* Verify, should this be settable */
4521 __get_user(env->regs[R_GP], &gregs[25]);
4522 /* Not really necessary no user settable bits */
4523 __get_user(temp, &gregs[26]);
4524 __get_user(env->regs[R_EA], &gregs[27]);
4525
4526 __get_user(env->regs[R_RA], &gregs[23]);
4527 __get_user(env->regs[R_SP], &gregs[28]);
4528
4529 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4530 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4531 if (err == -EFAULT) {
4532 return 1;
4533 }
4534
4535 *pr2 = env->regs[2];
4536 return 0;
4537}
4538
4539static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4540 size_t frame_size)
4541{
4542 unsigned long usp;
4543
4544 /* Default to using normal stack. */
4545 usp = env->regs[R_SP];
4546
4547 /* This is the X/Open sanctioned signal stack switching. */
4548 usp = sigsp(usp, ka);
4549
4550 /* Verify, is it 32 or 64 bit aligned */
4551 return (void *)((usp - frame_size) & -8UL);
4552}
4553
4554static void setup_rt_frame(int sig, struct target_sigaction *ka,
4555 target_siginfo_t *info,
4556 target_sigset_t *set,
4557 CPUNios2State *env)
4558{
4559 struct target_rt_sigframe *frame;
4560 int i, err = 0;
4561
4562 frame = get_sigframe(ka, env, sizeof(*frame));
4563
4564 if (ka->sa_flags & SA_SIGINFO) {
4565 tswap_siginfo(&frame->info, info);
4566 }
4567
4568 /* Create the ucontext. */
4569 __put_user(0, &frame->uc.tuc_flags);
4570 __put_user(0, &frame->uc.tuc_link);
4571 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4572 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4573 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4574 err |= rt_setup_ucontext(&frame->uc, env);
4575 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4576 __put_user((abi_ulong)set->sig[i],
4577 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4578 }
4579
4580 if (err) {
4581 goto give_sigsegv;
4582 }
4583
4584 /* Set up to return from userspace; jump to fixed address sigreturn
4585 trampoline on kuser page. */
4586 env->regs[R_RA] = (unsigned long) (0x1044);
4587
4588 /* Set up registers for signal handler */
4589 env->regs[R_SP] = (unsigned long) frame;
4590 env->regs[4] = (unsigned long) sig;
4591 env->regs[5] = (unsigned long) &frame->info;
4592 env->regs[6] = (unsigned long) &frame->uc;
4593 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4594 return;
4595
4596give_sigsegv:
4597 if (sig == TARGET_SIGSEGV) {
4598 ka->_sa_handler = TARGET_SIG_DFL;
4599 }
4600 force_sigsegv(sig);
4601 return;
4602}
4603
4604long do_sigreturn(CPUNios2State *env)
4605{
4606 trace_user_do_sigreturn(env, 0);
4607 fprintf(stderr, "do_sigreturn: not implemented\n");
4608 return -TARGET_ENOSYS;
4609}
4610
4611long do_rt_sigreturn(CPUNios2State *env)
4612{
4613 /* Verify, can we follow the stack back */
4614 abi_ulong frame_addr = env->regs[R_SP];
4615 struct target_rt_sigframe *frame;
4616 sigset_t set;
4617 int rval;
4618
4619 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4620 goto badframe;
4621 }
4622
4623 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4624 do_sigprocmask(SIG_SETMASK, &set, NULL);
4625
4626 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4627 goto badframe;
4628 }
4629
4630 unlock_user_struct(frame, frame_addr, 0);
4631 return rval;
4632
4633badframe:
4634 unlock_user_struct(frame, frame_addr, 0);
4635 force_sig(TARGET_SIGSEGV);
4636 return 0;
4637}
4638/* TARGET_NIOS2 */
4639
Jia Liud9627832012-07-20 15:50:52 +08004640#elif defined(TARGET_OPENRISC)
4641
4642struct target_sigcontext {
4643 struct target_pt_regs regs;
4644 abi_ulong oldmask;
4645 abi_ulong usp;
4646};
4647
4648struct target_ucontext {
4649 abi_ulong tuc_flags;
4650 abi_ulong tuc_link;
4651 target_stack_t tuc_stack;
4652 struct target_sigcontext tuc_mcontext;
4653 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4654};
4655
4656struct target_rt_sigframe {
4657 abi_ulong pinfo;
4658 uint64_t puc;
4659 struct target_siginfo info;
4660 struct target_sigcontext sc;
4661 struct target_ucontext uc;
4662 unsigned char retcode[16]; /* trampoline code */
4663};
4664
4665/* This is the asm-generic/ucontext.h version */
4666#if 0
4667static int restore_sigcontext(CPUOpenRISCState *regs,
4668 struct target_sigcontext *sc)
4669{
4670 unsigned int err = 0;
4671 unsigned long old_usp;
4672
4673 /* Alwys make any pending restarted system call return -EINTR */
4674 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4675
4676 /* restore the regs from &sc->regs (same as sc, since regs is first)
4677 * (sc is already checked for VERIFY_READ since the sigframe was
4678 * checked in sys_sigreturn previously)
4679 */
4680
4681 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4682 goto badframe;
4683 }
4684
4685 /* make sure the U-flag is set so user-mode cannot fool us */
4686
4687 regs->sr &= ~SR_SM;
4688
4689 /* restore the old USP as it was before we stacked the sc etc.
4690 * (we cannot just pop the sigcontext since we aligned the sp and
4691 * stuff after pushing it)
4692 */
4693
Riku Voipio1d8b5122014-04-23 10:26:05 +03004694 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004695 phx_signal("old_usp 0x%lx", old_usp);
4696
4697 __PHX__ REALLY /* ??? */
4698 wrusp(old_usp);
4699 regs->gpr[1] = old_usp;
4700
4701 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4702 * after this completes, but we don't use that mechanism. maybe we can
4703 * use it now ?
4704 */
4705
4706 return err;
4707
4708badframe:
4709 return 1;
4710}
4711#endif
4712
4713/* Set up a signal frame. */
4714
Riku Voipio41ecc722014-04-23 11:01:00 +03004715static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004716 CPUOpenRISCState *regs,
4717 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004718{
Stafford Horned89e71e2017-04-06 06:44:56 +09004719 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004720
4721 /* copy the regs. they are first in sc so we can use sc directly */
4722
Riku Voipio1d8b5122014-04-23 10:26:05 +03004723 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004724
4725 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4726 the signal handler. The frametype will be restored to its previous
4727 value in restore_sigcontext. */
4728 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4729
4730 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004731 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004732 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004733}
4734
4735static inline unsigned long align_sigframe(unsigned long sp)
4736{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004737 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004738}
4739
4740static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4741 CPUOpenRISCState *regs,
4742 size_t frame_size)
4743{
Stafford Horned89e71e2017-04-06 06:44:56 +09004744 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004745 int onsigstack = on_sig_stack(sp);
4746
4747 /* redzone */
4748 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004749 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004750 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4751 }
4752
4753 sp = align_sigframe(sp - frame_size);
4754
4755 /*
4756 * If we are on the alternate signal stack and would overflow it, don't.
4757 * Return an always-bogus address instead so we will die with SIGSEGV.
4758 */
4759
4760 if (onsigstack && !likely(on_sig_stack(sp))) {
4761 return -1L;
4762 }
4763
4764 return sp;
4765}
4766
Jia Liud9627832012-07-20 15:50:52 +08004767static void setup_rt_frame(int sig, struct target_sigaction *ka,
4768 target_siginfo_t *info,
4769 target_sigset_t *set, CPUOpenRISCState *env)
4770{
4771 int err = 0;
4772 abi_ulong frame_addr;
4773 unsigned long return_ip;
4774 struct target_rt_sigframe *frame;
4775 abi_ulong info_addr, uc_addr;
4776
Jia Liud9627832012-07-20 15:50:52 +08004777 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004778 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004779 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4780 goto give_sigsegv;
4781 }
4782
4783 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004784 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004785 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004786 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004787
4788 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004789 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004790 }
4791
Khem Raj04b33e22017-06-28 13:44:52 -07004792 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004793 __put_user(0, &frame->uc.tuc_flags);
4794 __put_user(0, &frame->uc.tuc_link);
4795 __put_user(target_sigaltstack_used.ss_sp,
4796 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004797 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4798 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004799 __put_user(target_sigaltstack_used.ss_size,
4800 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004801 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004802
4803 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4804
Jia Liud9627832012-07-20 15:50:52 +08004805 /* trampoline - the desired return ip is the retcode itself */
4806 return_ip = (unsigned long)&frame->retcode;
4807 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004808 __put_user(0xa960, (short *)(frame->retcode + 0));
4809 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4810 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4811 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004812
4813 if (err) {
4814 goto give_sigsegv;
4815 }
4816
4817 /* TODO what is the current->exec_domain stuff and invmap ? */
4818
4819 /* Set up registers for signal handler */
4820 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004821 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4822 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4823 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4824 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004825
4826 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004827 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004828
4829 return;
4830
4831give_sigsegv:
4832 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004833 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004834}
4835
4836long do_sigreturn(CPUOpenRISCState *env)
4837{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004838 trace_user_do_sigreturn(env, 0);
4839 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004840 return -TARGET_ENOSYS;
4841}
4842
4843long do_rt_sigreturn(CPUOpenRISCState *env)
4844{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004845 trace_user_do_rt_sigreturn(env, 0);
4846 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004847 return -TARGET_ENOSYS;
4848}
4849/* TARGET_OPENRISC */
4850
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004851#elif defined(TARGET_S390X)
4852
4853#define __NUM_GPRS 16
4854#define __NUM_FPRS 16
4855#define __NUM_ACRS 16
4856
4857#define S390_SYSCALL_SIZE 2
4858#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4859
4860#define _SIGCONTEXT_NSIG 64
4861#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4862#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4863#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4864#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4865#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4866
4867typedef struct {
4868 target_psw_t psw;
4869 target_ulong gprs[__NUM_GPRS];
4870 unsigned int acrs[__NUM_ACRS];
4871} target_s390_regs_common;
4872
4873typedef struct {
4874 unsigned int fpc;
4875 double fprs[__NUM_FPRS];
4876} target_s390_fp_regs;
4877
4878typedef struct {
4879 target_s390_regs_common regs;
4880 target_s390_fp_regs fpregs;
4881} target_sigregs;
4882
4883struct target_sigcontext {
4884 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4885 target_sigregs *sregs;
4886};
4887
4888typedef struct {
4889 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4890 struct target_sigcontext sc;
4891 target_sigregs sregs;
4892 int signo;
4893 uint8_t retcode[S390_SYSCALL_SIZE];
4894} sigframe;
4895
4896struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004897 target_ulong tuc_flags;
4898 struct target_ucontext *tuc_link;
4899 target_stack_t tuc_stack;
4900 target_sigregs tuc_mcontext;
4901 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004902};
4903
4904typedef struct {
4905 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4906 uint8_t retcode[S390_SYSCALL_SIZE];
4907 struct target_siginfo info;
4908 struct target_ucontext uc;
4909} rt_sigframe;
4910
4911static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004912get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004913{
4914 abi_ulong sp;
4915
4916 /* Default to using normal stack */
4917 sp = env->regs[15];
4918
4919 /* This is the X/Open sanctioned signal stack switching. */
4920 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4921 if (!sas_ss_flags(sp)) {
4922 sp = target_sigaltstack_used.ss_sp +
4923 target_sigaltstack_used.ss_size;
4924 }
4925 }
4926
4927 /* This is the legacy signal stack switching. */
4928 else if (/* FIXME !user_mode(regs) */ 0 &&
4929 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4930 ka->sa_restorer) {
4931 sp = (abi_ulong) ka->sa_restorer;
4932 }
4933
4934 return (sp - frame_size) & -8ul;
4935}
4936
Andreas Färber05390242012-02-25 03:37:53 +01004937static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004938{
4939 int i;
4940 //save_access_regs(current->thread.acrs); FIXME
4941
4942 /* Copy a 'clean' PSW mask to the user to avoid leaking
4943 information about whether PER is currently on. */
4944 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4945 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4946 for (i = 0; i < 16; i++) {
4947 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4948 }
4949 for (i = 0; i < 16; i++) {
4950 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4951 }
4952 /*
4953 * We have to store the fp registers to current->thread.fp_regs
4954 * to merge them with the emulated registers.
4955 */
4956 //save_fp_regs(&current->thread.fp_regs); FIXME
4957 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004958 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004959 }
4960}
4961
4962static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004963 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004964{
4965 sigframe *frame;
4966 abi_ulong frame_addr;
4967
4968 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004969 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004970 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004971 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004972 }
4973
Riku Voipio0188fad2014-04-23 13:34:15 +03004974 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004975
4976 save_sigregs(env, &frame->sregs);
4977
4978 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4979 (abi_ulong *)&frame->sc.sregs);
4980
4981 /* Set up to return from userspace. If provided, use a stub
4982 already in userspace. */
4983 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004984 env->regs[14] = (unsigned long)
4985 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004986 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004987 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4988 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004989 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4990 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004991 }
4992
4993 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004994 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004995
4996 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004997 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004998 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4999
5000 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005001 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005002
5003 /* We forgot to include these in the sigcontext.
5004 To avoid breaking binary compatibility, they are passed as args. */
5005 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
5006 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
5007
5008 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02005009 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005010 unlock_user_struct(frame, frame_addr, 1);
5011 return;
5012
5013give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005014 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005015}
5016
5017static void setup_rt_frame(int sig, struct target_sigaction *ka,
5018 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005019 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005020{
5021 int i;
5022 rt_sigframe *frame;
5023 abi_ulong frame_addr;
5024
5025 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005026 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005027 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5028 goto give_sigsegv;
5029 }
5030
Peter Maydellf6c7a052015-01-08 12:19:48 +00005031 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005032
5033 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005034 __put_user(0, &frame->uc.tuc_flags);
5035 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
5036 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005037 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005038 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005039 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5040 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005041 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
5042 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005043 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005044 }
5045
5046 /* Set up to return from userspace. If provided, use a stub
5047 already in userspace. */
5048 if (ka->sa_flags & TARGET_SA_RESTORER) {
5049 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
5050 } else {
5051 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03005052 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
5053 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005054 }
5055
5056 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005057 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005058
5059 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005060 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005061 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5062
5063 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005064 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
5065 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005066 return;
5067
5068give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005069 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005070}
5071
5072static int
Andreas Färber05390242012-02-25 03:37:53 +01005073restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005074{
5075 int err = 0;
5076 int i;
5077
5078 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005079 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005080 }
5081
Riku Voipio1d8b5122014-04-23 10:26:05 +03005082 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005083 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
5084 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005085 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005086 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
5087
5088 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005089 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005090 }
5091 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04005092 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005093 }
5094
5095 return err;
5096}
5097
Andreas Färber05390242012-02-25 03:37:53 +01005098long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005099{
5100 sigframe *frame;
5101 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005102 target_sigset_t target_set;
5103 sigset_t set;
5104
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005105 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005106 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5107 goto badframe;
5108 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03005109 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005110
5111 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005112 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005113
5114 if (restore_sigregs(env, &frame->sregs)) {
5115 goto badframe;
5116 }
5117
5118 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005119 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005120
5121badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005122 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005123 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005124}
5125
Andreas Färber05390242012-02-25 03:37:53 +01005126long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005127{
5128 rt_sigframe *frame;
5129 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005130 sigset_t set;
5131
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005132 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005133 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5134 goto badframe;
5135 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005136 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005137
Peter Maydell9eede5b2016-05-27 15:51:46 +01005138 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005139
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005140 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005141 goto badframe;
5142 }
5143
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005144 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005145 get_sp_from_cpustate(env)) == -EFAULT) {
5146 goto badframe;
5147 }
5148 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005149 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005150
5151badframe:
5152 unlock_user_struct(frame, frame_addr, 0);
5153 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005154 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005155}
5156
Tom Musta61e75fe2014-06-30 08:13:38 -05005157#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07005158
5159/* Size of dummy stack frame allocated when calling signal handler.
5160 See arch/powerpc/include/asm/ptrace.h. */
5161#if defined(TARGET_PPC64)
5162#define SIGNAL_FRAMESIZE 128
5163#else
5164#define SIGNAL_FRAMESIZE 64
5165#endif
5166
Tom Musta61e75fe2014-06-30 08:13:38 -05005167/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5168 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5169struct target_mcontext {
5170 target_ulong mc_gregs[48];
5171 /* Includes fpscr. */
5172 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005173#if defined(TARGET_PPC64)
5174 /* Pointer to the vector regs */
5175 target_ulong v_regs;
5176#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005177 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005178#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005179 /* We need to handle Altivec and SPE at the same time, which no
5180 kernel needs to do. Fortunately, the kernel defines this bit to
5181 be Altivec-register-large all the time, rather than trying to
5182 twiddle it based on the specific platform. */
5183 union {
5184 /* SPE vector registers. One extra for SPEFSCR. */
5185 uint32_t spe[33];
5186 /* Altivec vector registers. The packing of VSCR and VRSAVE
5187 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005188 them apart; PPC32 stuffs them together.
5189 We also need to account for the VSX registers on PPC64
5190 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005191#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005192#define QEMU_NVRREG (34 + 16)
5193 /* On ppc64, this mcontext structure is naturally *unaligned*,
5194 * or rather it is aligned on a 8 bytes boundary but not on
5195 * a 16 bytes one. This pad fixes it up. This is also why the
5196 * vector regs are referenced by the v_regs pointer above so
5197 * any amount of padding can be added here
5198 */
5199 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005200#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005201 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005202#define QEMU_NVRREG 33
5203#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005204 /* We cannot use ppc_avr_t here as we do *not* want the implied
5205 * 16-bytes alignment that would result from it. This would have
5206 * the effect of making the whole struct target_mcontext aligned
5207 * which breaks the layout of struct target_ucontext on ppc64.
5208 */
5209 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005210#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005211 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005212};
5213
Nathan Froydbcd49332009-05-12 19:13:18 -07005214/* See arch/powerpc/include/asm/sigcontext.h. */
5215struct target_sigcontext {
5216 target_ulong _unused[4];
5217 int32_t signal;
5218#if defined(TARGET_PPC64)
5219 int32_t pad0;
5220#endif
5221 target_ulong handler;
5222 target_ulong oldmask;
5223 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005224#if defined(TARGET_PPC64)
5225 struct target_mcontext mcontext;
5226#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005227};
5228
5229/* Indices for target_mcontext.mc_gregs, below.
5230 See arch/powerpc/include/asm/ptrace.h for details. */
5231enum {
5232 TARGET_PT_R0 = 0,
5233 TARGET_PT_R1 = 1,
5234 TARGET_PT_R2 = 2,
5235 TARGET_PT_R3 = 3,
5236 TARGET_PT_R4 = 4,
5237 TARGET_PT_R5 = 5,
5238 TARGET_PT_R6 = 6,
5239 TARGET_PT_R7 = 7,
5240 TARGET_PT_R8 = 8,
5241 TARGET_PT_R9 = 9,
5242 TARGET_PT_R10 = 10,
5243 TARGET_PT_R11 = 11,
5244 TARGET_PT_R12 = 12,
5245 TARGET_PT_R13 = 13,
5246 TARGET_PT_R14 = 14,
5247 TARGET_PT_R15 = 15,
5248 TARGET_PT_R16 = 16,
5249 TARGET_PT_R17 = 17,
5250 TARGET_PT_R18 = 18,
5251 TARGET_PT_R19 = 19,
5252 TARGET_PT_R20 = 20,
5253 TARGET_PT_R21 = 21,
5254 TARGET_PT_R22 = 22,
5255 TARGET_PT_R23 = 23,
5256 TARGET_PT_R24 = 24,
5257 TARGET_PT_R25 = 25,
5258 TARGET_PT_R26 = 26,
5259 TARGET_PT_R27 = 27,
5260 TARGET_PT_R28 = 28,
5261 TARGET_PT_R29 = 29,
5262 TARGET_PT_R30 = 30,
5263 TARGET_PT_R31 = 31,
5264 TARGET_PT_NIP = 32,
5265 TARGET_PT_MSR = 33,
5266 TARGET_PT_ORIG_R3 = 34,
5267 TARGET_PT_CTR = 35,
5268 TARGET_PT_LNK = 36,
5269 TARGET_PT_XER = 37,
5270 TARGET_PT_CCR = 38,
5271 /* Yes, there are two registers with #39. One is 64-bit only. */
5272 TARGET_PT_MQ = 39,
5273 TARGET_PT_SOFTE = 39,
5274 TARGET_PT_TRAP = 40,
5275 TARGET_PT_DAR = 41,
5276 TARGET_PT_DSISR = 42,
5277 TARGET_PT_RESULT = 43,
5278 TARGET_PT_REGS_COUNT = 44
5279};
5280
Nathan Froydbcd49332009-05-12 19:13:18 -07005281
5282struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005283 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005284 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005285 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005286#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005287 int32_t tuc_pad[7];
5288 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005289 points to uc_mcontext field */
5290#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005291 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005292#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005293 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005294 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005295#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005296 int32_t tuc_maskext[30];
5297 int32_t tuc_pad2[3];
5298 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005299#endif
5300};
5301
5302/* See arch/powerpc/kernel/signal_32.c. */
5303struct target_sigframe {
5304 struct target_sigcontext sctx;
5305 struct target_mcontext mctx;
5306 int32_t abigap[56];
5307};
5308
Tom Musta61e75fe2014-06-30 08:13:38 -05005309#if defined(TARGET_PPC64)
5310
5311#define TARGET_TRAMP_SIZE 6
5312
5313struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005314 /* sys_rt_sigreturn requires the ucontext be the first field */
5315 struct target_ucontext uc;
5316 target_ulong _unused[2];
5317 uint32_t trampoline[TARGET_TRAMP_SIZE];
5318 target_ulong pinfo; /* struct siginfo __user * */
5319 target_ulong puc; /* void __user * */
5320 struct target_siginfo info;
5321 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5322 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005323} __attribute__((aligned(16)));
5324
5325#else
5326
Nathan Froydbcd49332009-05-12 19:13:18 -07005327struct target_rt_sigframe {
5328 struct target_siginfo info;
5329 struct target_ucontext uc;
5330 int32_t abigap[56];
5331};
5332
Tom Musta61e75fe2014-06-30 08:13:38 -05005333#endif
5334
Tom Musta8d6ab332014-06-30 08:13:39 -05005335#if defined(TARGET_PPC64)
5336
5337struct target_func_ptr {
5338 target_ulong entry;
5339 target_ulong toc;
5340};
5341
5342#endif
5343
Nathan Froydbcd49332009-05-12 19:13:18 -07005344/* We use the mc_pad field for the signal return trampoline. */
5345#define tramp mc_pad
5346
5347/* See arch/powerpc/kernel/signal.c. */
5348static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005349 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005350 int frame_size)
5351{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005352 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005353
5354 oldsp = env->gpr[1];
5355
5356 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005357 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005358 oldsp = (target_sigaltstack_used.ss_sp
5359 + target_sigaltstack_used.ss_size);
5360 }
5361
Eduardo Habkost9be38592016-06-13 18:57:58 -03005362 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005363}
5364
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005365#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5366 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5367#define PPC_VEC_HI 0
5368#define PPC_VEC_LO 1
5369#else
5370#define PPC_VEC_HI 1
5371#define PPC_VEC_LO 0
5372#endif
5373
5374
Tom Musta76781082014-06-30 08:13:37 -05005375static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005376{
5377 target_ulong msr = env->msr;
5378 int i;
5379 target_ulong ccr = 0;
5380
5381 /* In general, the kernel attempts to be intelligent about what it
5382 needs to save for Altivec/FP/SPE registers. We don't care that
5383 much, so we just go ahead and save everything. */
5384
5385 /* Save general registers. */
5386 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005387 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005388 }
Riku Voipioc650c002014-04-23 13:53:45 +03005389 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5390 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5391 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5392 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005393
5394 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5395 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5396 }
Riku Voipioc650c002014-04-23 13:53:45 +03005397 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005398
5399 /* Save Altivec registers if necessary. */
5400 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005401 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005402 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005403 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005404 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005405
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005406 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5407 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005408 }
5409 /* Set MSR_VR in the saved MSR value to indicate that
5410 frame->mc_vregs contains valid data. */
5411 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005412#if defined(TARGET_PPC64)
5413 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5414 /* 64-bit needs to put a pointer to the vectors in the frame */
5415 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5416#else
5417 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5418#endif
5419 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5420 }
5421
5422 /* Save VSX second halves */
5423 if (env->insns_flags2 & PPC2_VSX) {
5424 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5425 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5426 __put_user(env->vsr[i], &vsregs[i]);
5427 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005428 }
5429
5430 /* Save floating point registers. */
5431 if (env->insns_flags & PPC_FLOAT) {
5432 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005433 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005434 }
Riku Voipioc650c002014-04-23 13:53:45 +03005435 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005436 }
5437
5438 /* Save SPE registers. The kernel only saves the high half. */
5439 if (env->insns_flags & PPC_SPE) {
5440#if defined(TARGET_PPC64)
5441 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005442 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005443 }
5444#else
5445 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005446 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005447 }
5448#endif
5449 /* Set MSR_SPE in the saved MSR value to indicate that
5450 frame->mc_vregs contains valid data. */
5451 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005452 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005453 }
5454
5455 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005456 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005457}
Nathan Froydbcd49332009-05-12 19:13:18 -07005458
Tom Musta76781082014-06-30 08:13:37 -05005459static void encode_trampoline(int sigret, uint32_t *tramp)
5460{
Nathan Froydbcd49332009-05-12 19:13:18 -07005461 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5462 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005463 __put_user(0x38000000 | sigret, &tramp[0]);
5464 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005465 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005466}
5467
Riku Voipioc650c002014-04-23 13:53:45 +03005468static void restore_user_regs(CPUPPCState *env,
5469 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005470{
5471 target_ulong save_r2 = 0;
5472 target_ulong msr;
5473 target_ulong ccr;
5474
5475 int i;
5476
5477 if (!sig) {
5478 save_r2 = env->gpr[2];
5479 }
5480
5481 /* Restore general registers. */
5482 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005483 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005484 }
Riku Voipioc650c002014-04-23 13:53:45 +03005485 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5486 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5487 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5488 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5489 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005490
5491 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5492 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5493 }
5494
5495 if (!sig) {
5496 env->gpr[2] = save_r2;
5497 }
5498 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005499 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005500
5501 /* If doing signal return, restore the previous little-endian mode. */
5502 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005503 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005504
5505 /* Restore Altivec registers if necessary. */
5506 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005507 ppc_avr_t *v_regs;
5508 uint32_t *vrsave;
5509#if defined(TARGET_PPC64)
5510 uint64_t v_addr;
5511 /* 64-bit needs to recover the pointer to the vectors from the frame */
5512 __get_user(v_addr, &frame->v_regs);
5513 v_regs = g2h(v_addr);
5514#else
5515 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5516#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005517 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005518 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005519 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005520
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005521 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5522 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005523 }
5524 /* Set MSR_VEC in the saved MSR value to indicate that
5525 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005526#if defined(TARGET_PPC64)
5527 vrsave = (uint32_t *)&v_regs[33];
5528#else
5529 vrsave = (uint32_t *)&v_regs[32];
5530#endif
5531 __get_user(env->spr[SPR_VRSAVE], vrsave);
5532 }
5533
5534 /* Restore VSX second halves */
5535 if (env->insns_flags2 & PPC2_VSX) {
5536 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5537 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5538 __get_user(env->vsr[i], &vsregs[i]);
5539 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005540 }
5541
5542 /* Restore floating point registers. */
5543 if (env->insns_flags & PPC_FLOAT) {
5544 uint64_t fpscr;
5545 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005546 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005547 }
Riku Voipioc650c002014-04-23 13:53:45 +03005548 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005549 env->fpscr = (uint32_t) fpscr;
5550 }
5551
5552 /* Save SPE registers. The kernel only saves the high half. */
5553 if (env->insns_flags & PPC_SPE) {
5554#if defined(TARGET_PPC64)
5555 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5556 uint32_t hi;
5557
Riku Voipioc650c002014-04-23 13:53:45 +03005558 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005559 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5560 }
5561#else
5562 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005563 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005564 }
5565#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005566 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005567 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005568}
5569
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005570#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005571static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005572 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005573{
5574 struct target_sigframe *frame;
5575 struct target_sigcontext *sc;
5576 target_ulong frame_addr, newsp;
5577 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005578
5579 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005580 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005581 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5582 goto sigsegv;
5583 sc = &frame->sctx;
5584
Riku Voipio1d8b5122014-04-23 10:26:05 +03005585 __put_user(ka->_sa_handler, &sc->handler);
5586 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005587 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005588 __put_user(h2g(&frame->mctx), &sc->regs);
5589 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005590
5591 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005592 save_user_regs(env, &frame->mctx);
5593
5594 /* Construct the trampoline code on the stack. */
5595 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005596
5597 /* The kernel checks for the presence of a VDSO here. We don't
5598 emulate a vdso, so use a sigreturn system call. */
5599 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5600
5601 /* Turn off all fp exceptions. */
5602 env->fpscr = 0;
5603
5604 /* Create a stack frame for the caller of the handler. */
5605 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005606 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005607
5608 if (err)
5609 goto sigsegv;
5610
5611 /* Set up registers for signal handler. */
5612 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005613 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005614 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005615
Nathan Froydbcd49332009-05-12 19:13:18 -07005616 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005617
Nathan Froydbcd49332009-05-12 19:13:18 -07005618 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005619 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005620
5621 unlock_user_struct(frame, frame_addr, 1);
5622 return;
5623
5624sigsegv:
5625 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005626 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005627}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005628#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005629
5630static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005631 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005632 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005633{
5634 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005635 uint32_t *trampptr = 0;
5636 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005637 target_ulong rt_sf_addr, newsp = 0;
5638 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005639#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005640 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005641 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5642#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005643
5644 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5645 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5646 goto sigsegv;
5647
Peter Maydellf6c7a052015-01-08 12:19:48 +00005648 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005649
Riku Voipio1d8b5122014-04-23 10:26:05 +03005650 __put_user(0, &rt_sf->uc.tuc_flags);
5651 __put_user(0, &rt_sf->uc.tuc_link);
5652 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5653 &rt_sf->uc.tuc_stack.ss_sp);
5654 __put_user(sas_ss_flags(env->gpr[1]),
5655 &rt_sf->uc.tuc_stack.ss_flags);
5656 __put_user(target_sigaltstack_used.ss_size,
5657 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005658#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005659 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5660 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005661#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005662 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005663 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005664 }
5665
Tom Musta61e75fe2014-06-30 08:13:38 -05005666#if defined(TARGET_PPC64)
5667 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5668 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005669
5670 sc = &rt_sf->uc.tuc_sigcontext;
5671 __put_user(h2g(mctx), &sc->regs);
5672 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005673#else
5674 mctx = &rt_sf->uc.tuc_mcontext;
5675 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5676#endif
5677
5678 save_user_regs(env, mctx);
5679 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005680
5681 /* The kernel checks for the presence of a VDSO here. We don't
5682 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005683 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005684
5685 /* Turn off all fp exceptions. */
5686 env->fpscr = 0;
5687
5688 /* Create a stack frame for the caller of the handler. */
5689 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005690 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005691
5692 if (err)
5693 goto sigsegv;
5694
5695 /* Set up registers for signal handler. */
5696 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005697 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005698 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5699 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5700 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005701
5702#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005703 if (get_ppc64_abi(image) < 2) {
5704 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5705 struct target_func_ptr *handler =
5706 (struct target_func_ptr *)g2h(ka->_sa_handler);
5707 env->nip = tswapl(handler->entry);
5708 env->gpr[2] = tswapl(handler->toc);
5709 } else {
5710 /* ELFv2 PPC64 function pointers are entry points, but R12
5711 * must also be set */
5712 env->nip = tswapl((target_ulong) ka->_sa_handler);
5713 env->gpr[12] = env->nip;
5714 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005715#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005716 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005717#endif
5718
Nathan Froydbcd49332009-05-12 19:13:18 -07005719 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005720 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005721
5722 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5723 return;
5724
5725sigsegv:
5726 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005727 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005728
5729}
5730
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005731#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005732long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005733{
5734 struct target_sigcontext *sc = NULL;
5735 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005736 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005737 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005738 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005739
5740 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5741 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5742 goto sigsegv;
5743
5744#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005745 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005746#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005747 __get_user(set.sig[0], &sc->oldmask);
5748 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005749#endif
5750 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005751 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005752
Riku Voipiof5f601a2014-04-23 13:00:17 +03005753 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005754 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5755 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005756 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005757
5758 unlock_user_struct(sr, sr_addr, 1);
5759 unlock_user_struct(sc, sc_addr, 1);
5760 return -TARGET_QEMU_ESIGRETURN;
5761
5762sigsegv:
5763 unlock_user_struct(sr, sr_addr, 1);
5764 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005765 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005766 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005767}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005768#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005769
5770/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005771static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005772{
5773 struct target_mcontext *mcp;
5774 target_ulong mcp_addr;
5775 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005776 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005777
Aurelien Jarno60e99242010-03-29 02:12:51 +02005778 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005779 sizeof (set)))
5780 return 1;
5781
Tom Musta19774ec2014-06-30 08:13:40 -05005782#if defined(TARGET_PPC64)
5783 mcp_addr = h2g(ucp) +
5784 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5785#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005786 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005787#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005788
5789 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5790 return 1;
5791
5792 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005793 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005794 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005795
5796 unlock_user_struct(mcp, mcp_addr, 1);
5797 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005798}
5799
Andreas Färber05390242012-02-25 03:37:53 +01005800long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005801{
5802 struct target_rt_sigframe *rt_sf = NULL;
5803 target_ulong rt_sf_addr;
5804
5805 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5806 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5807 goto sigsegv;
5808
5809 if (do_setcontext(&rt_sf->uc, env, 1))
5810 goto sigsegv;
5811
5812 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005813 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005814 0, env->gpr[1]);
5815
5816 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5817 return -TARGET_QEMU_ESIGRETURN;
5818
5819sigsegv:
5820 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005821 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005822 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005823}
5824
Laurent Vivier492a8742009-08-03 16:12:17 +02005825#elif defined(TARGET_M68K)
5826
5827struct target_sigcontext {
5828 abi_ulong sc_mask;
5829 abi_ulong sc_usp;
5830 abi_ulong sc_d0;
5831 abi_ulong sc_d1;
5832 abi_ulong sc_a0;
5833 abi_ulong sc_a1;
5834 unsigned short sc_sr;
5835 abi_ulong sc_pc;
5836};
5837
5838struct target_sigframe
5839{
5840 abi_ulong pretcode;
5841 int sig;
5842 int code;
5843 abi_ulong psc;
5844 char retcode[8];
5845 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5846 struct target_sigcontext sc;
5847};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005848
Anthony Liguoric227f092009-10-01 16:12:16 -05005849typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005850#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005851typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005852
5853typedef struct target_fpregset {
5854 int f_fpcntl[3];
5855 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005856} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005857
5858struct target_mcontext {
5859 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005860 target_gregset_t gregs;
5861 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005862};
5863
5864#define TARGET_MCONTEXT_VERSION 2
5865
5866struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005867 abi_ulong tuc_flags;
5868 abi_ulong tuc_link;
5869 target_stack_t tuc_stack;
5870 struct target_mcontext tuc_mcontext;
5871 abi_long tuc_filler[80];
5872 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005873};
5874
5875struct target_rt_sigframe
5876{
5877 abi_ulong pretcode;
5878 int sig;
5879 abi_ulong pinfo;
5880 abi_ulong puc;
5881 char retcode[8];
5882 struct target_siginfo info;
5883 struct target_ucontext uc;
5884};
Laurent Vivier492a8742009-08-03 16:12:17 +02005885
Riku Voipio41ecc722014-04-23 11:01:00 +03005886static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005887 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005888{
Laurent Vivieref597602018-01-04 02:28:59 +01005889 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005890 __put_user(mask, &sc->sc_mask);
5891 __put_user(env->aregs[7], &sc->sc_usp);
5892 __put_user(env->dregs[0], &sc->sc_d0);
5893 __put_user(env->dregs[1], &sc->sc_d1);
5894 __put_user(env->aregs[0], &sc->sc_a0);
5895 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005896 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005897 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005898}
5899
Riku Voipio016d2e12014-04-23 11:19:48 +03005900static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005901restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005902{
Laurent Vivier492a8742009-08-03 16:12:17 +02005903 int temp;
5904
Riku Voipio1d8b5122014-04-23 10:26:05 +03005905 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005906 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005907 __get_user(env->dregs[1], &sc->sc_d1);
5908 __get_user(env->aregs[0], &sc->sc_a0);
5909 __get_user(env->aregs[1], &sc->sc_a1);
5910 __get_user(env->pc, &sc->sc_pc);
5911 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005912 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005913}
5914
5915/*
5916 * Determine which stack to use..
5917 */
5918static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005919get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5920 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005921{
5922 unsigned long sp;
5923
5924 sp = regs->aregs[7];
5925
5926 /* This is the X/Open sanctioned signal stack switching. */
5927 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5928 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5929 }
5930
5931 return ((sp - frame_size) & -8UL);
5932}
5933
5934static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005935 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005936{
5937 struct target_sigframe *frame;
5938 abi_ulong frame_addr;
5939 abi_ulong retcode_addr;
5940 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005941 int i;
5942
5943 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005944 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005945 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5946 goto give_sigsegv;
5947 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005948
Riku Voipio1d8b5122014-04-23 10:26:05 +03005949 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005950
5951 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005952 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005953
Riku Voipio41ecc722014-04-23 11:01:00 +03005954 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005955
5956 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005957 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005958 }
5959
5960 /* Set up to return from userspace. */
5961
5962 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005963 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005964
5965 /* moveq #,d0; trap #0 */
5966
Riku Voipio1d8b5122014-04-23 10:26:05 +03005967 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005968 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005969
Laurent Vivier492a8742009-08-03 16:12:17 +02005970 /* Set up to return from userspace */
5971
5972 env->aregs[7] = frame_addr;
5973 env->pc = ka->_sa_handler;
5974
5975 unlock_user_struct(frame, frame_addr, 1);
5976 return;
5977
5978give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005979 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005980}
5981
Laurent Vivieree46a462017-09-14 18:35:05 +02005982static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5983 CPUM68KState *env)
5984{
5985 int i;
5986 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5987
5988 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
5989 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
5990 /* fpiar is not emulated */
5991
5992 for (i = 0; i < 8; i++) {
5993 uint32_t high = env->fregs[i].d.high << 16;
5994 __put_user(high, &fpregs->f_fpregs[i * 3]);
5995 __put_user(env->fregs[i].d.low,
5996 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5997 }
5998}
5999
Laurent Vivier71811552009-08-03 16:12:18 +02006000static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01006001 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02006002{
Aurelien Jarno60e99242010-03-29 02:12:51 +02006003 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01006004 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02006005
Riku Voipio1d8b5122014-04-23 10:26:05 +03006006 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
6007 __put_user(env->dregs[0], &gregs[0]);
6008 __put_user(env->dregs[1], &gregs[1]);
6009 __put_user(env->dregs[2], &gregs[2]);
6010 __put_user(env->dregs[3], &gregs[3]);
6011 __put_user(env->dregs[4], &gregs[4]);
6012 __put_user(env->dregs[5], &gregs[5]);
6013 __put_user(env->dregs[6], &gregs[6]);
6014 __put_user(env->dregs[7], &gregs[7]);
6015 __put_user(env->aregs[0], &gregs[8]);
6016 __put_user(env->aregs[1], &gregs[9]);
6017 __put_user(env->aregs[2], &gregs[10]);
6018 __put_user(env->aregs[3], &gregs[11]);
6019 __put_user(env->aregs[4], &gregs[12]);
6020 __put_user(env->aregs[5], &gregs[13]);
6021 __put_user(env->aregs[6], &gregs[14]);
6022 __put_user(env->aregs[7], &gregs[15]);
6023 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006024 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02006025
Laurent Vivieree46a462017-09-14 18:35:05 +02006026 target_rt_save_fpu_state(uc, env);
6027
Riku Voipio1d8b5122014-04-23 10:26:05 +03006028 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006029}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006030
Laurent Vivieree46a462017-09-14 18:35:05 +02006031static inline void target_rt_restore_fpu_state(CPUM68KState *env,
6032 struct target_ucontext *uc)
6033{
6034 int i;
6035 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6036 uint32_t fpcr;
6037
6038 __get_user(fpcr, &fpregs->f_fpcntl[0]);
6039 cpu_m68k_set_fpcr(env, fpcr);
6040 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
6041 /* fpiar is not emulated */
6042
6043 for (i = 0; i < 8; i++) {
6044 uint32_t high;
6045 __get_user(high, &fpregs->f_fpregs[i * 3]);
6046 env->fregs[i].d.high = high >> 16;
6047 __get_user(env->fregs[i].d.low,
6048 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6049 }
6050}
6051
Andreas Färber05390242012-02-25 03:37:53 +01006052static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006053 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02006054{
6055 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02006056 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02006057
Riku Voipio1d8b5122014-04-23 10:26:05 +03006058 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02006059 if (temp != TARGET_MCONTEXT_VERSION)
6060 goto badframe;
6061
6062 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03006063 __get_user(env->dregs[0], &gregs[0]);
6064 __get_user(env->dregs[1], &gregs[1]);
6065 __get_user(env->dregs[2], &gregs[2]);
6066 __get_user(env->dregs[3], &gregs[3]);
6067 __get_user(env->dregs[4], &gregs[4]);
6068 __get_user(env->dregs[5], &gregs[5]);
6069 __get_user(env->dregs[6], &gregs[6]);
6070 __get_user(env->dregs[7], &gregs[7]);
6071 __get_user(env->aregs[0], &gregs[8]);
6072 __get_user(env->aregs[1], &gregs[9]);
6073 __get_user(env->aregs[2], &gregs[10]);
6074 __get_user(env->aregs[3], &gregs[11]);
6075 __get_user(env->aregs[4], &gregs[12]);
6076 __get_user(env->aregs[5], &gregs[13]);
6077 __get_user(env->aregs[6], &gregs[14]);
6078 __get_user(env->aregs[7], &gregs[15]);
6079 __get_user(env->pc, &gregs[16]);
6080 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006081 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02006082
Laurent Vivieree46a462017-09-14 18:35:05 +02006083 target_rt_restore_fpu_state(env, uc);
6084
Riku Voipio1d8b5122014-04-23 10:26:05 +03006085 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006086
6087badframe:
6088 return 1;
6089}
6090
Laurent Vivier492a8742009-08-03 16:12:17 +02006091static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006092 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006093 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006094{
Laurent Vivier71811552009-08-03 16:12:18 +02006095 struct target_rt_sigframe *frame;
6096 abi_ulong frame_addr;
6097 abi_ulong retcode_addr;
6098 abi_ulong info_addr;
6099 abi_ulong uc_addr;
6100 int err = 0;
6101 int i;
6102
6103 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006104 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006105 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6106 goto give_sigsegv;
6107 }
Laurent Vivier71811552009-08-03 16:12:18 +02006108
Riku Voipio1d8b5122014-04-23 10:26:05 +03006109 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02006110
6111 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006112 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02006113
6114 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006115 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02006116
Peter Maydellf6c7a052015-01-08 12:19:48 +00006117 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02006118
6119 /* Create the ucontext */
6120
Riku Voipio1d8b5122014-04-23 10:26:05 +03006121 __put_user(0, &frame->uc.tuc_flags);
6122 __put_user(0, &frame->uc.tuc_link);
6123 __put_user(target_sigaltstack_used.ss_sp,
6124 &frame->uc.tuc_stack.ss_sp);
6125 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006126 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006127 __put_user(target_sigaltstack_used.ss_size,
6128 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02006129 err |= target_rt_setup_ucontext(&frame->uc, env);
6130
6131 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006132 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02006133
6134 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03006135 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02006136 }
6137
6138 /* Set up to return from userspace. */
6139
6140 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006141 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02006142
6143 /* moveq #,d0; notb d0; trap #0 */
6144
Riku Voipio1d8b5122014-04-23 10:26:05 +03006145 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00006146 (uint32_t *)(frame->retcode + 0));
6147 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02006148
6149 if (err)
6150 goto give_sigsegv;
6151
6152 /* Set up to return from userspace */
6153
6154 env->aregs[7] = frame_addr;
6155 env->pc = ka->_sa_handler;
6156
6157 unlock_user_struct(frame, frame_addr, 1);
6158 return;
6159
6160give_sigsegv:
6161 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006162 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006163}
6164
Andreas Färber05390242012-02-25 03:37:53 +01006165long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006166{
6167 struct target_sigframe *frame;
6168 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006169 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006170 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006171 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006172
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006173 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006174 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6175 goto badframe;
6176
6177 /* set blocked signals */
6178
Riku Voipiof5f601a2014-04-23 13:00:17 +03006179 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006180
6181 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006182 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006183 }
6184
6185 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006186 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006187
6188 /* restore registers */
6189
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006190 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006191
6192 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006193 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006194
6195badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006196 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006197 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006198}
6199
Andreas Färber05390242012-02-25 03:37:53 +01006200long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006201{
Laurent Vivier71811552009-08-03 16:12:18 +02006202 struct target_rt_sigframe *frame;
6203 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006204 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006205
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006206 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006207 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6208 goto badframe;
6209
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006210 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006211 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006212
6213 /* restore registers */
6214
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006215 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006216 goto badframe;
6217
6218 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006219 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006220 0, get_sp_from_cpustate(env)) == -EFAULT)
6221 goto badframe;
6222
6223 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006224 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006225
6226badframe:
6227 unlock_user_struct(frame, frame_addr, 0);
6228 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006229 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006230}
6231
Richard Henderson6049f4f2009-12-27 18:30:03 -08006232#elif defined(TARGET_ALPHA)
6233
6234struct target_sigcontext {
6235 abi_long sc_onstack;
6236 abi_long sc_mask;
6237 abi_long sc_pc;
6238 abi_long sc_ps;
6239 abi_long sc_regs[32];
6240 abi_long sc_ownedfp;
6241 abi_long sc_fpregs[32];
6242 abi_ulong sc_fpcr;
6243 abi_ulong sc_fp_control;
6244 abi_ulong sc_reserved1;
6245 abi_ulong sc_reserved2;
6246 abi_ulong sc_ssize;
6247 abi_ulong sc_sbase;
6248 abi_ulong sc_traparg_a0;
6249 abi_ulong sc_traparg_a1;
6250 abi_ulong sc_traparg_a2;
6251 abi_ulong sc_fp_trap_pc;
6252 abi_ulong sc_fp_trigger_sum;
6253 abi_ulong sc_fp_trigger_inst;
6254};
6255
6256struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006257 abi_ulong tuc_flags;
6258 abi_ulong tuc_link;
6259 abi_ulong tuc_osf_sigmask;
6260 target_stack_t tuc_stack;
6261 struct target_sigcontext tuc_mcontext;
6262 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006263};
6264
6265struct target_sigframe {
6266 struct target_sigcontext sc;
6267 unsigned int retcode[3];
6268};
6269
6270struct target_rt_sigframe {
6271 target_siginfo_t info;
6272 struct target_ucontext uc;
6273 unsigned int retcode[3];
6274};
6275
6276#define INSN_MOV_R30_R16 0x47fe0410
6277#define INSN_LDI_R0 0x201f0000
6278#define INSN_CALLSYS 0x00000083
6279
Riku Voipio41ecc722014-04-23 11:01:00 +03006280static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006281 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006282{
Riku Voipio41ecc722014-04-23 11:01:00 +03006283 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006284
Riku Voipio1d8b5122014-04-23 10:26:05 +03006285 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6286 __put_user(set->sig[0], &sc->sc_mask);
6287 __put_user(env->pc, &sc->sc_pc);
6288 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006289
6290 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006291 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006292 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006293 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006294
6295 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006296 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006297 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006298 __put_user(0, &sc->sc_fpregs[31]);
6299 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006300
Riku Voipio1d8b5122014-04-23 10:26:05 +03006301 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6302 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6303 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006304}
6305
Riku Voipio016d2e12014-04-23 11:19:48 +03006306static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006307 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006308{
6309 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006310 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006311
Riku Voipio1d8b5122014-04-23 10:26:05 +03006312 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006313
6314 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006315 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006316 }
6317 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006318 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006319 }
6320
Riku Voipio1d8b5122014-04-23 10:26:05 +03006321 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006322 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006323}
6324
6325static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006326 CPUAlphaState *env,
6327 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006328{
6329 abi_ulong sp = env->ir[IR_SP];
6330
6331 /* This is the X/Open sanctioned signal stack switching. */
6332 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6333 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6334 }
6335 return (sp - framesize) & -32;
6336}
6337
6338static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006339 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006340{
6341 abi_ulong frame_addr, r26;
6342 struct target_sigframe *frame;
6343 int err = 0;
6344
6345 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006346 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006347 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6348 goto give_sigsegv;
6349 }
6350
Riku Voipio41ecc722014-04-23 11:01:00 +03006351 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006352
6353 if (ka->sa_restorer) {
6354 r26 = ka->sa_restorer;
6355 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006356 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6357 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6358 &frame->retcode[1]);
6359 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006360 /* imb() */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006361 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006362 }
6363
6364 unlock_user_struct(frame, frame_addr, 1);
6365
6366 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006367give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006368 force_sigsegv(sig);
6369 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006370 }
6371
6372 env->ir[IR_RA] = r26;
6373 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6374 env->ir[IR_A0] = sig;
6375 env->ir[IR_A1] = 0;
6376 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6377 env->ir[IR_SP] = frame_addr;
6378}
6379
6380static void setup_rt_frame(int sig, struct target_sigaction *ka,
6381 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006382 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006383{
6384 abi_ulong frame_addr, r26;
6385 struct target_rt_sigframe *frame;
6386 int i, err = 0;
6387
6388 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006389 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006390 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6391 goto give_sigsegv;
6392 }
6393
Peter Maydellf6c7a052015-01-08 12:19:48 +00006394 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006395
Riku Voipio1d8b5122014-04-23 10:26:05 +03006396 __put_user(0, &frame->uc.tuc_flags);
6397 __put_user(0, &frame->uc.tuc_link);
6398 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6399 __put_user(target_sigaltstack_used.ss_sp,
6400 &frame->uc.tuc_stack.ss_sp);
6401 __put_user(sas_ss_flags(env->ir[IR_SP]),
6402 &frame->uc.tuc_stack.ss_flags);
6403 __put_user(target_sigaltstack_used.ss_size,
6404 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006405 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006406 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006407 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006408 }
6409
6410 if (ka->sa_restorer) {
6411 r26 = ka->sa_restorer;
6412 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006413 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6414 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6415 &frame->retcode[1]);
6416 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006417 /* imb(); */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006418 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006419 }
6420
6421 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006422give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006423 force_sigsegv(sig);
6424 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006425 }
6426
6427 env->ir[IR_RA] = r26;
6428 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6429 env->ir[IR_A0] = sig;
6430 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6431 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6432 env->ir[IR_SP] = frame_addr;
6433}
6434
Andreas Färber05390242012-02-25 03:37:53 +01006435long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006436{
6437 struct target_sigcontext *sc;
6438 abi_ulong sc_addr = env->ir[IR_A0];
6439 target_sigset_t target_set;
6440 sigset_t set;
6441
6442 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6443 goto badframe;
6444 }
6445
6446 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006447 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006448
6449 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006450 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006451
Riku Voipio016d2e12014-04-23 11:19:48 +03006452 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006453 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006454 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006455
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006456badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006457 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006458 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006459}
6460
Andreas Färber05390242012-02-25 03:37:53 +01006461long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006462{
6463 abi_ulong frame_addr = env->ir[IR_A0];
6464 struct target_rt_sigframe *frame;
6465 sigset_t set;
6466
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006467 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006468 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6469 goto badframe;
6470 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006471 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006472 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006473
Riku Voipio016d2e12014-04-23 11:19:48 +03006474 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006475 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006476 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006477 0, env->ir[IR_SP]) == -EFAULT) {
6478 goto badframe;
6479 }
6480
6481 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006482 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006483
6484
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006485badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006486 unlock_user_struct(frame, frame_addr, 0);
6487 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006488 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006489}
6490
Chen Gangbf0f60a2015-09-27 08:10:18 +08006491#elif defined(TARGET_TILEGX)
6492
6493struct target_sigcontext {
6494 union {
6495 /* General-purpose registers. */
6496 abi_ulong gregs[56];
6497 struct {
6498 abi_ulong __gregs[53];
6499 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6500 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6501 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6502 };
6503 };
6504 abi_ulong pc; /* Program counter. */
6505 abi_ulong ics; /* In Interrupt Critical Section? */
6506 abi_ulong faultnum; /* Fault number. */
6507 abi_ulong pad[5];
6508};
6509
6510struct target_ucontext {
6511 abi_ulong tuc_flags;
6512 abi_ulong tuc_link;
6513 target_stack_t tuc_stack;
6514 struct target_sigcontext tuc_mcontext;
6515 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6516};
6517
6518struct target_rt_sigframe {
6519 unsigned char save_area[16]; /* caller save area */
6520 struct target_siginfo info;
6521 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006522 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006523};
6524
Chen Gangf1d9d102016-03-29 21:53:49 +08006525#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6526#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6527
6528
Chen Gangbf0f60a2015-09-27 08:10:18 +08006529static void setup_sigcontext(struct target_sigcontext *sc,
6530 CPUArchState *env, int signo)
6531{
6532 int i;
6533
6534 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6535 __put_user(env->regs[i], &sc->gregs[i]);
6536 }
6537
6538 __put_user(env->pc, &sc->pc);
6539 __put_user(0, &sc->ics);
6540 __put_user(signo, &sc->faultnum);
6541}
6542
6543static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6544{
6545 int i;
6546
6547 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6548 __get_user(env->regs[i], &sc->gregs[i]);
6549 }
6550
6551 __get_user(env->pc, &sc->pc);
6552}
6553
6554static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6555 size_t frame_size)
6556{
6557 unsigned long sp = env->regs[TILEGX_R_SP];
6558
6559 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6560 return -1UL;
6561 }
6562
6563 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6564 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6565 }
6566
6567 sp -= frame_size;
6568 sp &= -16UL;
6569 return sp;
6570}
6571
6572static void setup_rt_frame(int sig, struct target_sigaction *ka,
6573 target_siginfo_t *info,
6574 target_sigset_t *set, CPUArchState *env)
6575{
6576 abi_ulong frame_addr;
6577 struct target_rt_sigframe *frame;
6578 unsigned long restorer;
6579
6580 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006581 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006582 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6583 goto give_sigsegv;
6584 }
6585
6586 /* Always write at least the signal number for the stack backtracer. */
6587 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6588 /* At sigreturn time, restore the callee-save registers too. */
6589 tswap_siginfo(&frame->info, info);
6590 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6591 } else {
6592 __put_user(info->si_signo, &frame->info.si_signo);
6593 }
6594
6595 /* Create the ucontext. */
6596 __put_user(0, &frame->uc.tuc_flags);
6597 __put_user(0, &frame->uc.tuc_link);
6598 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6599 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6600 &frame->uc.tuc_stack.ss_flags);
6601 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6602 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6603
Chen Gangbf0f60a2015-09-27 08:10:18 +08006604 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006605 restorer = (unsigned long) ka->sa_restorer;
6606 } else {
6607 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6608 __put_user(INSN_SWINT1, &frame->retcode[1]);
6609 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006610 }
6611 env->pc = (unsigned long) ka->_sa_handler;
6612 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6613 env->regs[TILEGX_R_LR] = restorer;
6614 env->regs[0] = (unsigned long) sig;
6615 env->regs[1] = (unsigned long) &frame->info;
6616 env->regs[2] = (unsigned long) &frame->uc;
6617 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6618
6619 unlock_user_struct(frame, frame_addr, 1);
6620 return;
6621
6622give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006623 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006624}
6625
6626long do_rt_sigreturn(CPUTLGState *env)
6627{
6628 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6629 struct target_rt_sigframe *frame;
6630 sigset_t set;
6631
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006632 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006633 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6634 goto badframe;
6635 }
6636 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006637 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006638
6639 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6640 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6641 uc.tuc_stack),
6642 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6643 goto badframe;
6644 }
6645
6646 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006647 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006648
6649
6650 badframe:
6651 unlock_user_struct(frame, frame_addr, 0);
6652 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006653 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006654}
6655
Michael Clark47ae93c2018-03-03 01:31:11 +13006656#elif defined(TARGET_RISCV)
6657
6658/* Signal handler invocation must be transparent for the code being
6659 interrupted. Complete CPU (hart) state is saved on entry and restored
6660 before returning from the handler. Process sigmask is also saved to block
6661 signals while the handler is running. The handler gets its own stack,
6662 which also doubles as storage for the CPU state and sigmask.
6663
6664 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6665
6666struct target_sigcontext {
6667 abi_long pc;
6668 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6669 uint64_t fpr[32];
6670 uint32_t fcsr;
6671}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6672
6673struct target_ucontext {
6674 unsigned long uc_flags;
6675 struct target_ucontext *uc_link;
6676 target_stack_t uc_stack;
6677 struct target_sigcontext uc_mcontext;
6678 target_sigset_t uc_sigmask;
6679};
6680
6681struct target_rt_sigframe {
6682 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6683 struct target_siginfo info;
6684 struct target_ucontext uc;
6685};
6686
6687static abi_ulong get_sigframe(struct target_sigaction *ka,
6688 CPURISCVState *regs, size_t framesize)
6689{
6690 abi_ulong sp = regs->gpr[xSP];
6691 int onsigstack = on_sig_stack(sp);
6692
6693 /* redzone */
6694 /* This is the X/Open sanctioned signal stack switching. */
6695 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6696 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6697 }
6698
6699 sp -= framesize;
6700 sp &= ~3UL; /* align sp on 4-byte boundary */
6701
6702 /* If we are on the alternate signal stack and would overflow it, don't.
6703 Return an always-bogus address instead so we will die with SIGSEGV. */
6704 if (onsigstack && !likely(on_sig_stack(sp))) {
6705 return -1L;
6706 }
6707
6708 return sp;
6709}
6710
6711static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6712{
6713 int i;
6714
6715 __put_user(env->pc, &sc->pc);
6716
6717 for (i = 1; i < 32; i++) {
6718 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6719 }
6720 for (i = 0; i < 32; i++) {
6721 __put_user(env->fpr[i], &sc->fpr[i]);
6722 }
6723
6724 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6725 __put_user(fcsr, &sc->fcsr);
6726}
6727
6728static void setup_ucontext(struct target_ucontext *uc,
6729 CPURISCVState *env, target_sigset_t *set)
6730{
6731 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6732 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6733 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6734
6735 __put_user(0, &(uc->uc_flags));
6736 __put_user(0, &(uc->uc_link));
6737
6738 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6739 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6740 __put_user(ss_size, &(uc->uc_stack.ss_size));
6741
6742 int i;
6743 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6744 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6745 }
6746
6747 setup_sigcontext(&uc->uc_mcontext, env);
6748}
6749
6750static inline void install_sigtramp(uint32_t *tramp)
6751{
6752 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6753 __put_user(0x00000073, tramp + 1); /* ecall */
6754}
6755
6756static void setup_rt_frame(int sig, struct target_sigaction *ka,
6757 target_siginfo_t *info,
6758 target_sigset_t *set, CPURISCVState *env)
6759{
6760 abi_ulong frame_addr;
6761 struct target_rt_sigframe *frame;
6762
6763 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6764 trace_user_setup_rt_frame(env, frame_addr);
6765
6766 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6767 goto badframe;
6768 }
6769
6770 setup_ucontext(&frame->uc, env, set);
6771 tswap_siginfo(&frame->info, info);
6772 install_sigtramp(frame->tramp);
6773
6774 env->pc = ka->_sa_handler;
6775 env->gpr[xSP] = frame_addr;
6776 env->gpr[xA0] = sig;
6777 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6778 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6779 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6780
6781 return;
6782
6783badframe:
6784 unlock_user_struct(frame, frame_addr, 1);
6785 if (sig == TARGET_SIGSEGV) {
6786 ka->_sa_handler = TARGET_SIG_DFL;
6787 }
6788 force_sig(TARGET_SIGSEGV);
6789}
6790
6791static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6792{
6793 int i;
6794
6795 __get_user(env->pc, &sc->pc);
6796
6797 for (i = 1; i < 32; ++i) {
6798 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6799 }
6800 for (i = 0; i < 32; ++i) {
6801 __get_user(env->fpr[i], &sc->fpr[i]);
6802 }
6803
6804 uint32_t fcsr;
6805 __get_user(fcsr, &sc->fcsr);
6806 csr_write_helper(env, fcsr, CSR_FCSR);
6807}
6808
6809static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6810{
6811 sigset_t blocked;
6812 target_sigset_t target_set;
6813 int i;
6814
6815 target_sigemptyset(&target_set);
6816 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6817 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6818 }
6819
6820 target_to_host_sigset_internal(&blocked, &target_set);
6821 set_sigmask(&blocked);
6822
6823 restore_sigcontext(env, &uc->uc_mcontext);
6824}
6825
6826long do_rt_sigreturn(CPURISCVState *env)
6827{
6828 struct target_rt_sigframe *frame;
6829 abi_ulong frame_addr;
6830
6831 frame_addr = env->gpr[xSP];
6832 trace_user_do_sigreturn(env, frame_addr);
6833 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6834 goto badframe;
6835 }
6836
6837 restore_ucontext(env, &frame->uc);
6838
6839 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6840 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6841 goto badframe;
6842 }
6843
6844 unlock_user_struct(frame, frame_addr, 0);
6845 return -TARGET_QEMU_ESIGRETURN;
6846
6847badframe:
6848 unlock_user_struct(frame, frame_addr, 0);
6849 force_sig(TARGET_SIGSEGV);
6850 return 0;
6851}
6852
Richard Henderson1659e382016-12-15 09:59:01 -08006853#elif defined(TARGET_HPPA)
6854
6855struct target_sigcontext {
6856 abi_ulong sc_flags;
6857 abi_ulong sc_gr[32];
6858 uint64_t sc_fr[32];
6859 abi_ulong sc_iasq[2];
6860 abi_ulong sc_iaoq[2];
6861 abi_ulong sc_sar;
6862};
6863
6864struct target_ucontext {
6865 abi_uint tuc_flags;
6866 abi_ulong tuc_link;
6867 target_stack_t tuc_stack;
6868 abi_uint pad[1];
6869 struct target_sigcontext tuc_mcontext;
6870 target_sigset_t tuc_sigmask;
6871};
6872
6873struct target_rt_sigframe {
6874 abi_uint tramp[9];
6875 target_siginfo_t info;
6876 struct target_ucontext uc;
6877 /* hidden location of upper halves of pa2.0 64-bit gregs */
6878};
6879
6880static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6881{
6882 int flags = 0;
6883 int i;
6884
6885 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6886
6887 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6888 /* In the gateway page, executing a syscall. */
6889 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6890 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6891 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6892 } else {
6893 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6894 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6895 }
6896 __put_user(0, &sc->sc_iasq[0]);
6897 __put_user(0, &sc->sc_iasq[1]);
6898 __put_user(flags, &sc->sc_flags);
6899
6900 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6901 for (i = 1; i < 32; ++i) {
6902 __put_user(env->gr[i], &sc->sc_gr[i]);
6903 }
6904
6905 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6906 for (i = 1; i < 32; ++i) {
6907 __put_user(env->fr[i], &sc->sc_fr[i]);
6908 }
6909
Richard Henderson35136a72017-10-10 21:19:34 -07006910 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006911}
6912
6913static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6914{
6915 target_ulong psw;
6916 int i;
6917
6918 __get_user(psw, &sc->sc_gr[0]);
6919 cpu_hppa_put_psw(env, psw);
6920
6921 for (i = 1; i < 32; ++i) {
6922 __get_user(env->gr[i], &sc->sc_gr[i]);
6923 }
6924 for (i = 0; i < 32; ++i) {
6925 __get_user(env->fr[i], &sc->sc_fr[i]);
6926 }
6927 cpu_hppa_loaded_fr0(env);
6928
6929 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6930 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006931 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006932}
6933
6934/* No, this doesn't look right, but it's copied straight from the kernel. */
6935#define PARISC_RT_SIGFRAME_SIZE32 \
6936 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6937
6938static void setup_rt_frame(int sig, struct target_sigaction *ka,
6939 target_siginfo_t *info,
6940 target_sigset_t *set, CPUArchState *env)
6941{
6942 abi_ulong frame_addr, sp, haddr;
6943 struct target_rt_sigframe *frame;
6944 int i;
6945
6946 sp = env->gr[30];
6947 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6948 if (sas_ss_flags(sp) == 0) {
6949 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6950 }
6951 }
6952 frame_addr = QEMU_ALIGN_UP(sp, 64);
6953 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6954
6955 trace_user_setup_rt_frame(env, frame_addr);
6956
6957 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6958 goto give_sigsegv;
6959 }
6960
6961 tswap_siginfo(&frame->info, info);
6962 frame->uc.tuc_flags = 0;
6963 frame->uc.tuc_link = 0;
6964
6965 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6966 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6967 &frame->uc.tuc_stack.ss_flags);
6968 __put_user(target_sigaltstack_used.ss_size,
6969 &frame->uc.tuc_stack.ss_size);
6970
6971 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6972 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6973 }
6974
6975 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6976
6977 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6978 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6979 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6980 __put_user(0x08000240, frame->tramp + 3); /* nop */
6981
6982 unlock_user_struct(frame, frame_addr, 1);
6983
6984 env->gr[2] = h2g(frame->tramp);
6985 env->gr[30] = sp;
6986 env->gr[26] = sig;
6987 env->gr[25] = h2g(&frame->info);
6988 env->gr[24] = h2g(&frame->uc);
6989
6990 haddr = ka->_sa_handler;
6991 if (haddr & 2) {
6992 /* Function descriptor. */
6993 target_ulong *fdesc, dest;
6994
6995 haddr &= -4;
6996 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
6997 goto give_sigsegv;
6998 }
6999 __get_user(dest, fdesc);
7000 __get_user(env->gr[19], fdesc + 1);
7001 unlock_user_struct(fdesc, haddr, 1);
7002 haddr = dest;
7003 }
7004 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02007005 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08007006 return;
7007
7008 give_sigsegv:
7009 force_sigsegv(sig);
7010}
7011
7012long do_rt_sigreturn(CPUArchState *env)
7013{
7014 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
7015 struct target_rt_sigframe *frame;
7016 sigset_t set;
7017
7018 trace_user_do_rt_sigreturn(env, frame_addr);
7019 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7020 goto badframe;
7021 }
7022 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7023 set_sigmask(&set);
7024
7025 restore_sigcontext(env, &frame->uc.tuc_mcontext);
7026 unlock_user_struct(frame, frame_addr, 0);
7027
7028 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
7029 uc.tuc_stack),
7030 0, env->gr[30]) == -EFAULT) {
7031 goto badframe;
7032 }
7033
7034 unlock_user_struct(frame, frame_addr, 0);
7035 return -TARGET_QEMU_ESIGRETURN;
7036
7037 badframe:
7038 force_sig(TARGET_SIGSEGV);
7039 return -TARGET_QEMU_ESIGRETURN;
7040}
7041
Max Filippovba7651f2017-01-25 10:54:11 -08007042#elif defined(TARGET_XTENSA)
7043
7044struct target_sigcontext {
7045 abi_ulong sc_pc;
7046 abi_ulong sc_ps;
7047 abi_ulong sc_lbeg;
7048 abi_ulong sc_lend;
7049 abi_ulong sc_lcount;
7050 abi_ulong sc_sar;
7051 abi_ulong sc_acclo;
7052 abi_ulong sc_acchi;
7053 abi_ulong sc_a[16];
7054 abi_ulong sc_xtregs;
7055};
7056
7057struct target_ucontext {
7058 abi_ulong tuc_flags;
7059 abi_ulong tuc_link;
7060 target_stack_t tuc_stack;
7061 struct target_sigcontext tuc_mcontext;
7062 target_sigset_t tuc_sigmask;
7063};
7064
7065struct target_rt_sigframe {
7066 target_siginfo_t info;
7067 struct target_ucontext uc;
7068 /* TODO: xtregs */
7069 uint8_t retcode[6];
7070 abi_ulong window[4];
7071};
7072
7073static abi_ulong get_sigframe(struct target_sigaction *sa,
7074 CPUXtensaState *env,
7075 unsigned long framesize)
7076{
7077 abi_ulong sp = env->regs[1];
7078
7079 /* This is the X/Open sanctioned signal stack switching. */
7080 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
7081 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
7082 }
7083 return (sp - framesize) & -16;
7084}
7085
7086static int flush_window_regs(CPUXtensaState *env)
7087{
Max Filippovba7651f2017-01-25 10:54:11 -08007088 uint32_t wb = env->sregs[WINDOW_BASE];
Max Filippov20ef6672018-03-28 00:25:22 -07007089 uint32_t ws = xtensa_replicate_windowstart(env) >> (wb + 1);
7090 unsigned d = ctz32(ws) + 1;
7091 unsigned i;
7092 int ret = 0;
Max Filippovba7651f2017-01-25 10:54:11 -08007093
Max Filippov20ef6672018-03-28 00:25:22 -07007094 for (i = d; i < env->config->nareg / 4; i += d) {
7095 uint32_t ssp, osp;
7096 unsigned j;
Max Filippovba7651f2017-01-25 10:54:11 -08007097
Max Filippov20ef6672018-03-28 00:25:22 -07007098 ws >>= d;
7099 xtensa_rotate_window(env, d);
Max Filippovba7651f2017-01-25 10:54:11 -08007100
7101 if (ws & 0x1) {
Max Filippov20ef6672018-03-28 00:25:22 -07007102 ssp = env->regs[5];
Max Filippovba7651f2017-01-25 10:54:11 -08007103 d = 1;
7104 } else if (ws & 0x2) {
Max Filippov20ef6672018-03-28 00:25:22 -07007105 ssp = env->regs[9];
7106 ret |= get_user_ual(osp, env->regs[1] - 12);
7107 osp -= 32;
Max Filippovba7651f2017-01-25 10:54:11 -08007108 d = 2;
Max Filippovba7651f2017-01-25 10:54:11 -08007109 } else if (ws & 0x4) {
Max Filippov20ef6672018-03-28 00:25:22 -07007110 ssp = env->regs[13];
7111 ret |= get_user_ual(osp, env->regs[1] - 12);
7112 osp -= 48;
Max Filippovba7651f2017-01-25 10:54:11 -08007113 d = 3;
Max Filippovba7651f2017-01-25 10:54:11 -08007114 } else {
7115 g_assert_not_reached();
7116 }
Max Filippov20ef6672018-03-28 00:25:22 -07007117
7118 for (j = 0; j < 4; ++j) {
7119 ret |= put_user_ual(env->regs[j], ssp - 16 + j * 4);
Max Filippovba7651f2017-01-25 10:54:11 -08007120 }
Max Filippov20ef6672018-03-28 00:25:22 -07007121 for (j = 4; j < d * 4; ++j) {
7122 ret |= put_user_ual(env->regs[j], osp - 16 + j * 4);
7123 }
Max Filippovba7651f2017-01-25 10:54:11 -08007124 }
Max Filippov20ef6672018-03-28 00:25:22 -07007125 xtensa_rotate_window(env, d);
7126 g_assert(env->sregs[WINDOW_BASE] == wb);
Max Filippovba7651f2017-01-25 10:54:11 -08007127 return ret == 0;
7128}
7129
7130static int setup_sigcontext(struct target_rt_sigframe *frame,
7131 CPUXtensaState *env)
7132{
7133 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7134 int i;
7135
7136 __put_user(env->pc, &sc->sc_pc);
7137 __put_user(env->sregs[PS], &sc->sc_ps);
7138 __put_user(env->sregs[LBEG], &sc->sc_lbeg);
7139 __put_user(env->sregs[LEND], &sc->sc_lend);
7140 __put_user(env->sregs[LCOUNT], &sc->sc_lcount);
7141 if (!flush_window_regs(env)) {
7142 return 0;
7143 }
7144 for (i = 0; i < 16; ++i) {
7145 __put_user(env->regs[i], sc->sc_a + i);
7146 }
7147 __put_user(0, &sc->sc_xtregs);
7148 /* TODO: xtregs */
7149 return 1;
7150}
7151
7152static void setup_rt_frame(int sig, struct target_sigaction *ka,
7153 target_siginfo_t *info,
7154 target_sigset_t *set, CPUXtensaState *env)
7155{
7156 abi_ulong frame_addr;
7157 struct target_rt_sigframe *frame;
7158 uint32_t ra;
7159 int i;
7160
7161 frame_addr = get_sigframe(ka, env, sizeof(*frame));
7162 trace_user_setup_rt_frame(env, frame_addr);
7163
7164 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
7165 goto give_sigsegv;
7166 }
7167
7168 if (ka->sa_flags & SA_SIGINFO) {
7169 tswap_siginfo(&frame->info, info);
7170 }
7171
7172 __put_user(0, &frame->uc.tuc_flags);
7173 __put_user(0, &frame->uc.tuc_link);
7174 __put_user(target_sigaltstack_used.ss_sp,
7175 &frame->uc.tuc_stack.ss_sp);
7176 __put_user(sas_ss_flags(env->regs[1]),
7177 &frame->uc.tuc_stack.ss_flags);
7178 __put_user(target_sigaltstack_used.ss_size,
7179 &frame->uc.tuc_stack.ss_size);
7180 if (!setup_sigcontext(frame, env)) {
7181 unlock_user_struct(frame, frame_addr, 0);
7182 goto give_sigsegv;
7183 }
7184 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
7185 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7186 }
7187
7188 if (ka->sa_flags & TARGET_SA_RESTORER) {
7189 ra = ka->sa_restorer;
7190 } else {
7191 ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
7192#ifdef TARGET_WORDS_BIGENDIAN
7193 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7194 __put_user(0x22, &frame->retcode[0]);
7195 __put_user(0x0a, &frame->retcode[1]);
7196 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7197 /* Generate instruction: SYSCALL */
7198 __put_user(0x00, &frame->retcode[3]);
7199 __put_user(0x05, &frame->retcode[4]);
7200 __put_user(0x00, &frame->retcode[5]);
7201#else
7202 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7203 __put_user(0x22, &frame->retcode[0]);
7204 __put_user(0xa0, &frame->retcode[1]);
7205 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7206 /* Generate instruction: SYSCALL */
7207 __put_user(0x00, &frame->retcode[3]);
7208 __put_user(0x50, &frame->retcode[4]);
7209 __put_user(0x00, &frame->retcode[5]);
7210#endif
7211 }
7212 env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
7213 if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
7214 env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
7215 }
7216 memset(env->regs, 0, sizeof(env->regs));
7217 env->pc = ka->_sa_handler;
7218 env->regs[1] = frame_addr;
7219 env->sregs[WINDOW_BASE] = 0;
7220 env->sregs[WINDOW_START] = 1;
7221
7222 env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
7223 env->regs[6] = sig;
7224 env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
7225 env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
7226 unlock_user_struct(frame, frame_addr, 1);
7227 return;
7228
7229give_sigsegv:
7230 force_sigsegv(sig);
7231 return;
7232}
7233
7234static void restore_sigcontext(CPUXtensaState *env,
7235 struct target_rt_sigframe *frame)
7236{
7237 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7238 uint32_t ps;
7239 int i;
7240
7241 __get_user(env->pc, &sc->sc_pc);
7242 __get_user(ps, &sc->sc_ps);
7243 __get_user(env->sregs[LBEG], &sc->sc_lbeg);
7244 __get_user(env->sregs[LEND], &sc->sc_lend);
7245 __get_user(env->sregs[LCOUNT], &sc->sc_lcount);
7246
7247 env->sregs[WINDOW_BASE] = 0;
7248 env->sregs[WINDOW_START] = 1;
7249 env->sregs[PS] = deposit32(env->sregs[PS],
7250 PS_CALLINC_SHIFT,
7251 PS_CALLINC_LEN,
7252 extract32(ps, PS_CALLINC_SHIFT,
7253 PS_CALLINC_LEN));
7254 for (i = 0; i < 16; ++i) {
7255 __get_user(env->regs[i], sc->sc_a + i);
7256 }
7257 /* TODO: xtregs */
7258}
7259
7260long do_rt_sigreturn(CPUXtensaState *env)
7261{
7262 abi_ulong frame_addr = env->regs[1];
7263 struct target_rt_sigframe *frame;
7264 sigset_t set;
7265
7266 trace_user_do_rt_sigreturn(env, frame_addr);
7267 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7268 goto badframe;
7269 }
7270 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7271 set_sigmask(&set);
7272
7273 restore_sigcontext(env, frame);
7274
7275 if (do_sigaltstack(frame_addr +
7276 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7277 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) {
7278 goto badframe;
7279 }
7280 unlock_user_struct(frame, frame_addr, 0);
7281 return -TARGET_QEMU_ESIGRETURN;
7282
7283badframe:
7284 unlock_user_struct(frame, frame_addr, 0);
7285 force_sig(TARGET_SIGSEGV);
7286 return -TARGET_QEMU_ESIGRETURN;
7287}
bellard66fb9762003-03-23 01:06:05 +00007288#endif
7289
Peter Maydell31efaef2016-07-06 15:09:29 +01007290static void handle_pending_signal(CPUArchState *cpu_env, int sig,
7291 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01007292{
7293 CPUState *cpu = ENV_GET_CPU(cpu_env);
7294 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007295 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01007296 target_sigset_t target_old_set;
7297 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01007298 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01007299
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01007300 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00007301 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007302 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00007303
Andreas Färberdb6b81d2013-06-27 19:49:31 +02007304 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00007305 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00007306 sa = NULL;
7307 handler = TARGET_SIG_IGN;
7308 } else {
7309 sa = &sigact_table[sig - 1];
7310 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00007311 }
bellard66fb9762003-03-23 01:06:05 +00007312
Peter Maydell0cb581d2016-07-18 18:12:24 +01007313 if (do_strace) {
7314 print_taken_signal(sig, &k->info);
7315 }
7316
bellard66fb9762003-03-23 01:06:05 +00007317 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00007318 /* default handler : ignore some signal. The other are job control or fatal */
7319 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
7320 kill(getpid(),SIGSTOP);
7321 } else if (sig != TARGET_SIGCHLD &&
7322 sig != TARGET_SIGURG &&
7323 sig != TARGET_SIGWINCH &&
7324 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007325 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007326 }
7327 } else if (handler == TARGET_SIG_IGN) {
7328 /* ignore sig */
7329 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007330 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007331 } else {
bellard9de5e442003-03-23 16:49:39 +00007332 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007333 sigset_t *blocked_set;
7334
pbrook624f7972008-05-31 16:11:38 +00007335 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00007336 /* SA_NODEFER indicates that the current signal should not be
7337 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00007338 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00007339 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00007340
bellard9de5e442003-03-23 16:49:39 +00007341 /* save the previous blocked signal state to restore it at the
7342 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007343 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
7344
7345 /* block signals in the handler */
7346 blocked_set = ts->in_sigsuspend ?
7347 &ts->sigsuspend_mask : &ts->signal_mask;
7348 sigorset(&ts->signal_mask, blocked_set, &set);
7349 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00007350
bellardbc8a22c2003-03-30 21:02:40 +00007351 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00007352#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00007353 {
7354 CPUX86State *env = cpu_env;
7355 if (env->eflags & VM_MASK)
7356 save_v86_state(env);
7357 }
7358#endif
bellard9de5e442003-03-23 16:49:39 +00007359 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08007360#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10007361 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01007362 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13007363 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
Max Filippovba7651f2017-01-25 10:54:11 -08007364 || defined(TARGET_RISCV) || defined(TARGET_XTENSA)
Richard Hendersonff970902013-02-10 10:30:42 -08007365 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007366 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007367#else
pbrook624f7972008-05-31 16:11:38 +00007368 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007369 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00007370 else
pbrook624f7972008-05-31 16:11:38 +00007371 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007372#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01007373 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00007374 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01007375 }
bellard31e31b82003-02-18 22:55:36 +00007376 }
bellard31e31b82003-02-18 22:55:36 +00007377}
Peter Maydelle902d582016-05-27 15:51:44 +01007378
7379void process_pending_signals(CPUArchState *cpu_env)
7380{
7381 CPUState *cpu = ENV_GET_CPU(cpu_env);
7382 int sig;
7383 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007384 sigset_t set;
7385 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007386
Peter Maydell3d3efba2016-05-27 15:51:49 +01007387 while (atomic_read(&ts->signal_pending)) {
7388 /* FIXME: This is not threadsafe. */
7389 sigfillset(&set);
7390 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007391
Peter Maydell8bd37732016-07-28 16:44:45 +01007392 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007393 sig = ts->sync_signal.pending;
7394 if (sig) {
7395 /* Synchronous signals are forced,
7396 * see force_sig_info() and callers in Linux
7397 * Note that not all of our queue_signal() calls in QEMU correspond
7398 * to force_sig_info() calls in Linux (some are send_sig_info()).
7399 * However it seems like a kernel bug to me to allow the process
7400 * to block a synchronous signal since it could then just end up
7401 * looping round and round indefinitely.
7402 */
7403 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7404 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7405 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7406 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7407 }
7408
Peter Maydell31efaef2016-07-06 15:09:29 +01007409 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007410 }
7411
Peter Maydell3d3efba2016-05-27 15:51:49 +01007412 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7413 blocked_set = ts->in_sigsuspend ?
7414 &ts->sigsuspend_mask : &ts->signal_mask;
7415
7416 if (ts->sigtab[sig - 1].pending &&
7417 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007418 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007419 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007420 /* Restart scan from the beginning, as handle_pending_signal
7421 * might have resulted in a new synchronous signal (eg SIGSEGV).
7422 */
7423 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007424 }
Peter Maydelle902d582016-05-27 15:51:44 +01007425 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007426
7427 /* if no signal is pending, unblock signals and recheck (the act
7428 * of unblocking might cause us to take another host signal which
7429 * will set signal_pending again).
7430 */
7431 atomic_set(&ts->signal_pending, 0);
7432 ts->in_sigsuspend = 0;
7433 set = ts->signal_mask;
7434 sigdelset(&set, SIGSEGV);
7435 sigdelset(&set, SIGBUS);
7436 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007437 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007438 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007439}