blob: 8d9e6e84105305e214ea3fe8d57a0d42b7f6aae9 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydelldaa43742018-03-08 14:47:32 +0000256#if !defined(TARGET_OPENRISC) && !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100257/* Just set the guest's signal mask to the specified value; the
258 * caller is assumed to have called block_signals() already.
259 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100260static void set_sigmask(const sigset_t *set)
261{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100262 TaskState *ts = (TaskState *)thread_cpu->opaque;
263
264 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100265}
266#endif
267
bellard9de5e442003-03-23 16:49:39 +0000268/* siginfo conversion */
269
Anthony Liguoric227f092009-10-01 16:12:16 -0500270static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000271 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000272{
Richard Hendersona05c6402012-09-15 11:34:20 -0700273 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100274 int si_code = info->si_code;
275 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000276 tinfo->si_signo = sig;
277 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000278 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700279
Peter Maydell55d72a72016-06-13 11:22:05 +0100280 /* This memset serves two purposes:
281 * (1) ensure we don't leak random junk to the guest later
282 * (2) placate false positives from gcc about fields
283 * being used uninitialized if it chooses to inline both this
284 * function and tswap_siginfo() into host_to_target_siginfo().
285 */
286 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
287
Peter Maydella70dadc2016-05-27 15:51:59 +0100288 /* This is awkward, because we have to use a combination of
289 * the si_code and si_signo to figure out which of the union's
290 * members are valid. (Within the host kernel it is always possible
291 * to tell, but the kernel carefully avoids giving userspace the
292 * high 16 bits of si_code, so we don't have the information to
293 * do this the easy way...) We therefore make our best guess,
294 * bearing in mind that a guest can spoof most of the si_codes
295 * via rt_sigqueueinfo() if it likes.
296 *
297 * Once we have made our guess, we record it in the top 16 bits of
298 * the si_code, so that tswap_siginfo() later can use it.
299 * tswap_siginfo() will strip these top bits out before writing
300 * si_code to the guest (sign-extending the lower bits).
301 */
302
303 switch (si_code) {
304 case SI_USER:
305 case SI_TKILL:
306 case SI_KERNEL:
307 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
308 * These are the only unspoofable si_code values.
309 */
310 tinfo->_sifields._kill._pid = info->si_pid;
311 tinfo->_sifields._kill._uid = info->si_uid;
312 si_type = QEMU_SI_KILL;
313 break;
314 default:
315 /* Everything else is spoofable. Make best guess based on signal */
316 switch (sig) {
317 case TARGET_SIGCHLD:
318 tinfo->_sifields._sigchld._pid = info->si_pid;
319 tinfo->_sifields._sigchld._uid = info->si_uid;
320 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100321 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100322 tinfo->_sifields._sigchld._utime = info->si_utime;
323 tinfo->_sifields._sigchld._stime = info->si_stime;
324 si_type = QEMU_SI_CHLD;
325 break;
326 case TARGET_SIGIO:
327 tinfo->_sifields._sigpoll._band = info->si_band;
328 tinfo->_sifields._sigpoll._fd = info->si_fd;
329 si_type = QEMU_SI_POLL;
330 break;
331 default:
332 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
333 tinfo->_sifields._rt._pid = info->si_pid;
334 tinfo->_sifields._rt._uid = info->si_uid;
335 /* XXX: potential problem if 64 bit */
336 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100337 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100338 si_type = QEMU_SI_RT;
339 break;
340 }
341 break;
bellard9de5e442003-03-23 16:49:39 +0000342 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100343
344 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000345}
346
Anthony Liguoric227f092009-10-01 16:12:16 -0500347static void tswap_siginfo(target_siginfo_t *tinfo,
348 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000349{
Peter Maydella70dadc2016-05-27 15:51:59 +0100350 int si_type = extract32(info->si_code, 16, 16);
351 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700352
Peter Maydella70dadc2016-05-27 15:51:59 +0100353 __put_user(info->si_signo, &tinfo->si_signo);
354 __put_user(info->si_errno, &tinfo->si_errno);
355 __put_user(si_code, &tinfo->si_code);
356
357 /* We can use our internal marker of which fields in the structure
358 * are valid, rather than duplicating the guesswork of
359 * host_to_target_siginfo_noswap() here.
360 */
361 switch (si_type) {
362 case QEMU_SI_KILL:
363 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
364 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
365 break;
366 case QEMU_SI_TIMER:
367 __put_user(info->_sifields._timer._timer1,
368 &tinfo->_sifields._timer._timer1);
369 __put_user(info->_sifields._timer._timer2,
370 &tinfo->_sifields._timer._timer2);
371 break;
372 case QEMU_SI_POLL:
373 __put_user(info->_sifields._sigpoll._band,
374 &tinfo->_sifields._sigpoll._band);
375 __put_user(info->_sifields._sigpoll._fd,
376 &tinfo->_sifields._sigpoll._fd);
377 break;
378 case QEMU_SI_FAULT:
379 __put_user(info->_sifields._sigfault._addr,
380 &tinfo->_sifields._sigfault._addr);
381 break;
382 case QEMU_SI_CHLD:
383 __put_user(info->_sifields._sigchld._pid,
384 &tinfo->_sifields._sigchld._pid);
385 __put_user(info->_sifields._sigchld._uid,
386 &tinfo->_sifields._sigchld._uid);
387 __put_user(info->_sifields._sigchld._status,
388 &tinfo->_sifields._sigchld._status);
389 __put_user(info->_sifields._sigchld._utime,
390 &tinfo->_sifields._sigchld._utime);
391 __put_user(info->_sifields._sigchld._stime,
392 &tinfo->_sifields._sigchld._stime);
393 break;
394 case QEMU_SI_RT:
395 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
396 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
397 __put_user(info->_sifields._rt._sigval.sival_ptr,
398 &tinfo->_sifields._rt._sigval.sival_ptr);
399 break;
400 default:
401 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000402 }
403}
404
Anthony Liguoric227f092009-10-01 16:12:16 -0500405void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000406{
Peter Maydell55d72a72016-06-13 11:22:05 +0100407 target_siginfo_t tgt_tmp;
408 host_to_target_siginfo_noswap(&tgt_tmp, info);
409 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000410}
411
412/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000413/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500414void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000415{
Peter Maydell90c0f082016-05-27 15:52:01 +0100416 /* This conversion is used only for the rt_sigqueueinfo syscall,
417 * and so we know that the _rt fields are the valid ones.
418 */
419 abi_ulong sival_ptr;
420
421 __get_user(info->si_signo, &tinfo->si_signo);
422 __get_user(info->si_errno, &tinfo->si_errno);
423 __get_user(info->si_code, &tinfo->si_code);
424 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
425 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
426 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
427 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000428}
429
aurel32ca587a82008-12-18 22:44:13 +0000430static int fatal_signal (int sig)
431{
432 switch (sig) {
433 case TARGET_SIGCHLD:
434 case TARGET_SIGURG:
435 case TARGET_SIGWINCH:
436 /* Ignored by default. */
437 return 0;
438 case TARGET_SIGCONT:
439 case TARGET_SIGSTOP:
440 case TARGET_SIGTSTP:
441 case TARGET_SIGTTIN:
442 case TARGET_SIGTTOU:
443 /* Job control signals. */
444 return 0;
445 default:
446 return 1;
447 }
448}
449
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300450/* returns 1 if given signal should dump core if not handled */
451static int core_dump_signal(int sig)
452{
453 switch (sig) {
454 case TARGET_SIGABRT:
455 case TARGET_SIGFPE:
456 case TARGET_SIGILL:
457 case TARGET_SIGQUIT:
458 case TARGET_SIGSEGV:
459 case TARGET_SIGTRAP:
460 case TARGET_SIGBUS:
461 return (1);
462 default:
463 return (0);
464 }
465}
466
bellard31e31b82003-02-18 22:55:36 +0000467void signal_init(void)
468{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100469 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000470 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000471 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000472 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000473 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000474
bellard9e5f5282003-07-13 17:33:54 +0000475 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200476 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000477 if (host_to_target_signal_table[i] == 0)
478 host_to_target_signal_table[i] = i;
479 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200480 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000481 j = host_to_target_signal_table[i];
482 target_to_host_signal_table[j] = i;
483 }
ths3b46e622007-09-17 08:09:54 +0000484
Peter Maydell3d3efba2016-05-27 15:51:49 +0100485 /* Set the signal mask from the host mask. */
486 sigprocmask(0, 0, &ts->signal_mask);
487
bellard9de5e442003-03-23 16:49:39 +0000488 /* set all host signal handlers. ALL signals are blocked during
489 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000490 memset(sigact_table, 0, sizeof(sigact_table));
491
bellard9de5e442003-03-23 16:49:39 +0000492 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000493 act.sa_flags = SA_SIGINFO;
494 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000495 for(i = 1; i <= TARGET_NSIG; i++) {
496 host_sig = target_to_host_signal(i);
497 sigaction(host_sig, NULL, &oact);
498 if (oact.sa_sigaction == (void *)SIG_IGN) {
499 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
500 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
501 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
502 }
503 /* If there's already a handler installed then something has
504 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000505 /* Install some handlers for our own use. We need at least
506 SIGSEGV and SIGBUS, to detect exceptions. We can not just
507 trap all signals because it affects syscall interrupt
508 behavior. But do trap all default-fatal signals. */
509 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000510 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000511 }
bellard31e31b82003-02-18 22:55:36 +0000512}
513
Peter Maydellc599d4d2016-07-28 16:44:49 +0100514/* Force a synchronously taken signal. The kernel force_sig() function
515 * also forces the signal to "not blocked, not ignored", but for QEMU
516 * that work is done in process_pending_signals().
517 */
518static void force_sig(int sig)
519{
520 CPUState *cpu = thread_cpu;
521 CPUArchState *env = cpu->env_ptr;
522 target_siginfo_t info;
523
524 info.si_signo = sig;
525 info.si_errno = 0;
526 info.si_code = TARGET_SI_KERNEL;
527 info._sifields._kill._pid = 0;
528 info._sifields._kill._uid = 0;
529 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
530}
Peter Maydell09391662016-07-28 16:44:47 +0100531
532/* Force a SIGSEGV if we couldn't write to memory trying to set
533 * up the signal frame. oldsig is the signal we were trying to handle
534 * at the point of failure.
535 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300536#if !defined(TARGET_RISCV)
Peter Maydell09391662016-07-28 16:44:47 +0100537static void force_sigsegv(int oldsig)
538{
Peter Maydell09391662016-07-28 16:44:47 +0100539 if (oldsig == SIGSEGV) {
540 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100541 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100542 */
543 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
544 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100545 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100546}
bellard66fb9762003-03-23 01:06:05 +0000547
Michael Clark47ae93c2018-03-03 01:31:11 +1300548#endif
549
bellard9de5e442003-03-23 16:49:39 +0000550/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100551static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000552{
Andreas Färber0429a972013-08-26 18:14:44 +0200553 CPUState *cpu = thread_cpu;
554 CPUArchState *env = cpu->env_ptr;
555 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300556 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000557 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100558
Riku Voipio66393fb2009-12-04 15:16:32 +0200559 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100560 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200561 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000562
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300563 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200564 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300565 stop_all_tasks();
566 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200567 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 }
569 if (core_dumped) {
570 /* we already dumped the core of target process, we don't want
571 * a coredump of qemu itself */
572 struct rlimit nodump;
573 getrlimit(RLIMIT_CORE, &nodump);
574 nodump.rlim_cur=0;
575 setrlimit(RLIMIT_CORE, &nodump);
576 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200577 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300578 }
579
Stefan Weil0c587512011-04-28 17:20:32 +0200580 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000581 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
582 * a negative value. To get the proper exit code we need to
583 * actually die from an uncaught signal. Here the default signal
584 * handler is installed, we send ourself a signal and we wait for
585 * it to arrive. */
586 sigfillset(&act.sa_mask);
587 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000588 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000589 sigaction(host_sig, &act, NULL);
590
591 /* For some reason raise(host_sig) doesn't send the signal when
592 * statically linked on x86-64. */
593 kill(getpid(), host_sig);
594
595 /* Make sure the signal isn't masked (just reuse the mask inside
596 of act) */
597 sigdelset(&act.sa_mask, host_sig);
598 sigsuspend(&act.sa_mask);
599
600 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000601 abort();
bellard66fb9762003-03-23 01:06:05 +0000602}
603
bellard9de5e442003-03-23 16:49:39 +0000604/* queue a signal so that it will be send to the virtual CPU as soon
605 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100606int queue_signal(CPUArchState *env, int sig, int si_type,
607 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000608{
Andreas Färber0429a972013-08-26 18:14:44 +0200609 CPUState *cpu = ENV_GET_CPU(env);
610 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000611
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100612 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000613
Peter Maydell9d2803f2016-07-28 16:44:46 +0100614 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100615
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100616 ts->sync_signal.info = *info;
617 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100618 /* signal that a new signal is pending */
619 atomic_set(&ts->signal_pending, 1);
620 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000621}
622
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100623#ifndef HAVE_SAFE_SYSCALL
624static inline void rewind_if_in_safe_syscall(void *puc)
625{
626 /* Default version: never rewind */
627}
628#endif
629
ths5fafdf22007-09-16 21:08:06 +0000630static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000631 void *puc)
632{
Andreas Färbera2247f82013-06-09 19:47:04 +0200633 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100634 CPUState *cpu = ENV_GET_CPU(env);
635 TaskState *ts = cpu->opaque;
636
bellard9de5e442003-03-23 16:49:39 +0000637 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500638 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100639 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100640 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000641
642 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000643 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000644 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000645 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000646 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000647 return;
648 }
649
650 /* get target signal number */
651 sig = host_to_target_signal(host_signum);
652 if (sig < 1 || sig > TARGET_NSIG)
653 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100654 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100655
656 rewind_if_in_safe_syscall(puc);
657
bellard9de5e442003-03-23 16:49:39 +0000658 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100659 k = &ts->sigtab[sig - 1];
660 k->info = tinfo;
661 k->pending = sig;
662 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100663
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100664 /* Block host signals until target signal handler entered. We
665 * can't block SIGSEGV or SIGBUS while we're executing guest
666 * code in case the guest code provokes one in the window between
667 * now and it getting out to the main loop. Signals will be
668 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100669 *
670 * WARNING: we cannot use sigfillset() here because the uc_sigmask
671 * field is a kernel sigset_t, which is much smaller than the
672 * libc sigset_t which sigfillset() operates on. Using sigfillset()
673 * would write 0xff bytes off the end of the structure and trash
674 * data on the struct.
675 * We can't use sizeof(uc->uc_sigmask) either, because the libc
676 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100677 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100678 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100679 sigdelset(&uc->uc_sigmask, SIGSEGV);
680 sigdelset(&uc->uc_sigmask, SIGBUS);
681
682 /* interrupt the virtual CPU as soon as possible */
683 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000684}
685
ths0da46a62007-10-20 20:23:07 +0000686/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000687/* compare linux/kernel/signal.c:do_sigaltstack() */
688abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000689{
690 int ret;
691 struct target_sigaltstack oss;
692
693 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000694 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000695 {
696 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
697 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
698 __put_user(sas_ss_flags(sp), &oss.ss_flags);
699 }
700
bellard579a97f2007-11-11 14:26:47 +0000701 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000702 {
bellard579a97f2007-11-11 14:26:47 +0000703 struct target_sigaltstack *uss;
704 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500705 size_t minstacksize = TARGET_MINSIGSTKSZ;
706
707#if defined(TARGET_PPC64)
708 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
709 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
710 if (get_ppc64_abi(image) > 1) {
711 minstacksize = 4096;
712 }
713#endif
thsa04e1342007-09-27 13:57:58 +0000714
ths0da46a62007-10-20 20:23:07 +0000715 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300716 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000717 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300718 }
719 __get_user(ss.ss_sp, &uss->ss_sp);
720 __get_user(ss.ss_size, &uss->ss_size);
721 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000722 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000723
ths0da46a62007-10-20 20:23:07 +0000724 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000725 if (on_sig_stack(sp))
726 goto out;
727
ths0da46a62007-10-20 20:23:07 +0000728 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000729 if (ss.ss_flags != TARGET_SS_DISABLE
730 && ss.ss_flags != TARGET_SS_ONSTACK
731 && ss.ss_flags != 0)
732 goto out;
733
734 if (ss.ss_flags == TARGET_SS_DISABLE) {
735 ss.ss_size = 0;
736 ss.ss_sp = 0;
737 } else {
ths0da46a62007-10-20 20:23:07 +0000738 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500739 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000740 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500741 }
thsa04e1342007-09-27 13:57:58 +0000742 }
743
744 target_sigaltstack_used.ss_sp = ss.ss_sp;
745 target_sigaltstack_used.ss_size = ss.ss_size;
746 }
747
bellard579a97f2007-11-11 14:26:47 +0000748 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000749 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000750 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000751 goto out;
thsa04e1342007-09-27 13:57:58 +0000752 }
753
754 ret = 0;
755out:
756 return ret;
757}
758
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100759/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000760int do_sigaction(int sig, const struct target_sigaction *act,
761 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000762{
pbrook624f7972008-05-31 16:11:38 +0000763 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000764 struct sigaction act1;
765 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000766 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000767
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100768 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
769 return -TARGET_EINVAL;
770 }
771
772 if (block_signals()) {
773 return -TARGET_ERESTARTSYS;
774 }
775
bellard66fb9762003-03-23 01:06:05 +0000776 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000777 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800778 __put_user(k->_sa_handler, &oact->_sa_handler);
779 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100780#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000782#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800783 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000784 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000785 }
786 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000787 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800788 __get_user(k->_sa_handler, &act->_sa_handler);
789 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100790#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000792#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800793 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000794 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000795
796 /* we update the host linux signal state */
797 host_sig = target_to_host_signal(sig);
798 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
799 sigfillset(&act1.sa_mask);
800 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000801 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000802 act1.sa_flags |= SA_RESTART;
803 /* NOTE: it is important to update the host kernel signal
804 ignore state to avoid getting unexpected interrupted
805 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000806 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000807 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000808 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000809 if (fatal_signal (sig))
810 act1.sa_sigaction = host_signal_handler;
811 else
812 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000813 } else {
814 act1.sa_sigaction = host_signal_handler;
815 }
ths0da46a62007-10-20 20:23:07 +0000816 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000817 }
bellard66fb9762003-03-23 01:06:05 +0000818 }
ths0da46a62007-10-20 20:23:07 +0000819 return ret;
bellard66fb9762003-03-23 01:06:05 +0000820}
bellard31e31b82003-02-18 22:55:36 +0000821
Pranith Kumar1c1df012017-02-26 11:53:44 -0500822#if defined(TARGET_I386)
823/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000824
825struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100826 uint16_t significand[4];
827 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000828};
829
830struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100831 uint16_t significand[4];
832 uint16_t exponent;
833 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000834};
835
836struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500837 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000838};
839
Pranith Kumar1c1df012017-02-26 11:53:44 -0500840struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100841 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500842 uint32_t cw;
843 uint32_t sw;
844 uint32_t tag;
845 uint32_t ipoff;
846 uint32_t cssel;
847 uint32_t dataoff;
848 uint32_t datasel;
849 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100850 uint16_t status;
851 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000852
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100853 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500854 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
855 uint32_t mxcsr;
856 uint32_t reserved;
857 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
858 struct target_xmmreg xmm[8];
859 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000860};
861
Pranith Kumar1c1df012017-02-26 11:53:44 -0500862struct target_fpstate_64 {
863 /* FXSAVE format */
864 uint16_t cw;
865 uint16_t sw;
866 uint16_t twd;
867 uint16_t fop;
868 uint64_t rip;
869 uint64_t rdp;
870 uint32_t mxcsr;
871 uint32_t mxcsr_mask;
872 uint32_t st_space[32];
873 uint32_t xmm_space[64];
874 uint32_t reserved[24];
875};
bellard66fb9762003-03-23 01:06:05 +0000876
Pranith Kumar1c1df012017-02-26 11:53:44 -0500877#ifndef TARGET_X86_64
878# define target_fpstate target_fpstate_32
879#else
880# define target_fpstate target_fpstate_64
881#endif
882
883struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100884 uint16_t gs, __gsh;
885 uint16_t fs, __fsh;
886 uint16_t es, __esh;
887 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500888 uint32_t edi;
889 uint32_t esi;
890 uint32_t ebp;
891 uint32_t esp;
892 uint32_t ebx;
893 uint32_t edx;
894 uint32_t ecx;
895 uint32_t eax;
896 uint32_t trapno;
897 uint32_t err;
898 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100899 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500900 uint32_t eflags;
901 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500903 uint32_t fpstate; /* pointer */
904 uint32_t oldmask;
905 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000906};
907
Pranith Kumar1c1df012017-02-26 11:53:44 -0500908struct target_sigcontext_64 {
909 uint64_t r8;
910 uint64_t r9;
911 uint64_t r10;
912 uint64_t r11;
913 uint64_t r12;
914 uint64_t r13;
915 uint64_t r14;
916 uint64_t r15;
917
918 uint64_t rdi;
919 uint64_t rsi;
920 uint64_t rbp;
921 uint64_t rbx;
922 uint64_t rdx;
923 uint64_t rax;
924 uint64_t rcx;
925 uint64_t rsp;
926 uint64_t rip;
927
928 uint64_t eflags;
929
930 uint16_t cs;
931 uint16_t gs;
932 uint16_t fs;
933 uint16_t ss;
934
935 uint64_t err;
936 uint64_t trapno;
937 uint64_t oldmask;
938 uint64_t cr2;
939
940 uint64_t fpstate; /* pointer */
941 uint64_t padding[8];
942};
943
944#ifndef TARGET_X86_64
945# define target_sigcontext target_sigcontext_32
946#else
947# define target_sigcontext target_sigcontext_64
948#endif
949
950/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000951struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100952 abi_ulong tuc_flags;
953 abi_ulong tuc_link;
954 target_stack_t tuc_stack;
955 struct target_sigcontext tuc_mcontext;
956 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000957};
958
Pranith Kumar1c1df012017-02-26 11:53:44 -0500959#ifndef TARGET_X86_64
960struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000961 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000962 int sig;
963 struct target_sigcontext sc;
964 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000965 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000966 char retcode[8];
967};
968
Pranith Kumar1c1df012017-02-26 11:53:44 -0500969struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000970 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000971 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000972 abi_ulong pinfo;
973 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000974 struct target_siginfo info;
975 struct target_ucontext uc;
976 struct target_fpstate fpstate;
977 char retcode[8];
978};
979
Pranith Kumar1c1df012017-02-26 11:53:44 -0500980#else
981
982struct rt_sigframe {
983 abi_ulong pretcode;
984 struct target_ucontext uc;
985 struct target_siginfo info;
986 struct target_fpstate fpstate;
987};
988
989#endif
990
bellard66fb9762003-03-23 01:06:05 +0000991/*
992 * Set up a signal frame.
993 */
994
bellard66fb9762003-03-23 01:06:05 +0000995/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300996static void setup_sigcontext(struct target_sigcontext *sc,
997 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
998 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000999{
Andreas Färber27103422013-08-26 08:31:06 +02001000 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -05001001#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +02001002 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +00001003
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001004 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001005 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
1006 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
1007 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
1008 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
1009 __put_user(env->regs[R_EDI], &sc->edi);
1010 __put_user(env->regs[R_ESI], &sc->esi);
1011 __put_user(env->regs[R_EBP], &sc->ebp);
1012 __put_user(env->regs[R_ESP], &sc->esp);
1013 __put_user(env->regs[R_EBX], &sc->ebx);
1014 __put_user(env->regs[R_EDX], &sc->edx);
1015 __put_user(env->regs[R_ECX], &sc->ecx);
1016 __put_user(env->regs[R_EAX], &sc->eax);
1017 __put_user(cs->exception_index, &sc->trapno);
1018 __put_user(env->error_code, &sc->err);
1019 __put_user(env->eip, &sc->eip);
1020 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1021 __put_user(env->eflags, &sc->eflags);
1022 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1023 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001024
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001025 cpu_x86_fsave(env, fpstate_addr, 1);
1026 fpstate->status = fpstate->sw;
1027 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001028 __put_user(magic, &fpstate->magic);
1029 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001030
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001031 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001032 __put_user(mask, &sc->oldmask);
1033 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001034#else
1035 __put_user(env->regs[R_EDI], &sc->rdi);
1036 __put_user(env->regs[R_ESI], &sc->rsi);
1037 __put_user(env->regs[R_EBP], &sc->rbp);
1038 __put_user(env->regs[R_ESP], &sc->rsp);
1039 __put_user(env->regs[R_EBX], &sc->rbx);
1040 __put_user(env->regs[R_EDX], &sc->rdx);
1041 __put_user(env->regs[R_ECX], &sc->rcx);
1042 __put_user(env->regs[R_EAX], &sc->rax);
1043
1044 __put_user(env->regs[8], &sc->r8);
1045 __put_user(env->regs[9], &sc->r9);
1046 __put_user(env->regs[10], &sc->r10);
1047 __put_user(env->regs[11], &sc->r11);
1048 __put_user(env->regs[12], &sc->r12);
1049 __put_user(env->regs[13], &sc->r13);
1050 __put_user(env->regs[14], &sc->r14);
1051 __put_user(env->regs[15], &sc->r15);
1052
1053 __put_user(cs->exception_index, &sc->trapno);
1054 __put_user(env->error_code, &sc->err);
1055 __put_user(env->eip, &sc->rip);
1056
1057 __put_user(env->eflags, &sc->eflags);
1058 __put_user(env->segs[R_CS].selector, &sc->cs);
1059 __put_user((uint16_t)0, &sc->gs);
1060 __put_user((uint16_t)0, &sc->fs);
1061 __put_user(env->segs[R_SS].selector, &sc->ss);
1062
1063 __put_user(mask, &sc->oldmask);
1064 __put_user(env->cr[2], &sc->cr2);
1065
1066 /* fpstate_addr must be 16 byte aligned for fxsave */
1067 assert(!(fpstate_addr & 0xf));
1068
1069 cpu_x86_fxsave(env, fpstate_addr);
1070 __put_user(fpstate_addr, &sc->fpstate);
1071#endif
bellard66fb9762003-03-23 01:06:05 +00001072}
1073
1074/*
1075 * Determine which stack to use..
1076 */
1077
bellard579a97f2007-11-11 14:26:47 +00001078static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001079get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001080{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001081 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001082
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001083 /* Default to using normal stack */
1084 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001085#ifdef TARGET_X86_64
1086 esp -= 128; /* this is the redzone */
1087#endif
1088
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001089 /* This is the X/Open sanctioned signal stack switching. */
1090 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1091 if (sas_ss_flags(esp) == 0) {
1092 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001093 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001094 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001095#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001096 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001097 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001098 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1099 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001100 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001102#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001103 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001104
1105#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001107#else
1108 return ((esp - frame_size) & (~15ul)) - 8;
1109#endif
bellard66fb9762003-03-23 01:06:05 +00001110}
1111
Pranith Kumar1c1df012017-02-26 11:53:44 -05001112#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001113/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001114static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001115 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001116{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001117 abi_ulong frame_addr;
1118 struct sigframe *frame;
1119 int i;
bellard66fb9762003-03-23 01:06:05 +00001120
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001121 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1122 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1125 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001126
Peter Maydellb6e2c932015-01-08 12:19:43 +00001127 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001128
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001129 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1130 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001131
Riku Voipio7df2fa32014-04-23 10:34:53 +03001132 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1133 __put_user(set->sig[i], &frame->extramask[i - 1]);
1134 }
bellard66fb9762003-03-23 01:06:05 +00001135
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001136 /* Set up to return from userspace. If provided, use a stub
1137 already in userspace. */
1138 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001139 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001140 } else {
1141 uint16_t val16;
1142 abi_ulong retcode_addr;
1143 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001144 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001145 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1146 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001147 __put_user(val16, (uint16_t *)(frame->retcode+0));
1148 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001149 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001150 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001151 }
bellard66fb9762003-03-23 01:06:05 +00001152
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001153 /* Set up registers for signal handler */
1154 env->regs[R_ESP] = frame_addr;
1155 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001156
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001157 cpu_x86_load_seg(env, R_DS, __USER_DS);
1158 cpu_x86_load_seg(env, R_ES, __USER_DS);
1159 cpu_x86_load_seg(env, R_SS, __USER_DS);
1160 cpu_x86_load_seg(env, R_CS, __USER_CS);
1161 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001162
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001163 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001164
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001165 return;
bellard66fb9762003-03-23 01:06:05 +00001166
1167give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001168 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001169}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001170#endif
bellard66fb9762003-03-23 01:06:05 +00001171
Pranith Kumar1c1df012017-02-26 11:53:44 -05001172/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001173static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001174 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001175 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001176{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001177 abi_ulong frame_addr;
1178#ifndef TARGET_X86_64
1179 abi_ulong addr;
1180#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001181 struct rt_sigframe *frame;
1182 int i;
bellard66fb9762003-03-23 01:06:05 +00001183
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001184 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1185 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001186
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001187 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1188 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001189
Pranith Kumar1c1df012017-02-26 11:53:44 -05001190 /* These fields are only in rt_sigframe on 32 bit */
1191#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001192 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001193 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001194 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001195 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001196 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001197#endif
1198 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1199 tswap_siginfo(&frame->info, info);
1200 }
bellard66fb9762003-03-23 01:06:05 +00001201
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001202 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001203 __put_user(0, &frame->uc.tuc_flags);
1204 __put_user(0, &frame->uc.tuc_link);
1205 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1206 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1207 &frame->uc.tuc_stack.ss_flags);
1208 __put_user(target_sigaltstack_used.ss_size,
1209 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001210 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1211 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1212
Riku Voipio0188fad2014-04-23 13:34:15 +03001213 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1214 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1215 }
bellard66fb9762003-03-23 01:06:05 +00001216
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001217 /* Set up to return from userspace. If provided, use a stub
1218 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001219#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001220 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001221 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001222 } else {
1223 uint16_t val16;
1224 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001225 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001226 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001227 __put_user(0xb8, (char *)(frame->retcode+0));
1228 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001229 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001230 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001231 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001232#else
1233 /* XXX: Would be slightly better to return -EFAULT here if test fails
1234 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1235 __put_user(ka->sa_restorer, &frame->pretcode);
1236#endif
bellard66fb9762003-03-23 01:06:05 +00001237
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001238 /* Set up registers for signal handler */
1239 env->regs[R_ESP] = frame_addr;
1240 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001241
Pranith Kumar1c1df012017-02-26 11:53:44 -05001242#ifndef TARGET_X86_64
1243 env->regs[R_EAX] = sig;
1244 env->regs[R_EDX] = (unsigned long)&frame->info;
1245 env->regs[R_ECX] = (unsigned long)&frame->uc;
1246#else
1247 env->regs[R_EAX] = 0;
1248 env->regs[R_EDI] = sig;
1249 env->regs[R_ESI] = (unsigned long)&frame->info;
1250 env->regs[R_EDX] = (unsigned long)&frame->uc;
1251#endif
1252
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001253 cpu_x86_load_seg(env, R_DS, __USER_DS);
1254 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001255 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001256 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001257 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001258
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001259 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001260
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001261 return;
bellard66fb9762003-03-23 01:06:05 +00001262
1263give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001264 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001265}
1266
1267static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001268restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001269{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001270 unsigned int err = 0;
1271 abi_ulong fpstate_addr;
1272 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001273
Pranith Kumar1c1df012017-02-26 11:53:44 -05001274#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001275 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1276 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1277 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1278 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001279
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001280 env->regs[R_EDI] = tswapl(sc->edi);
1281 env->regs[R_ESI] = tswapl(sc->esi);
1282 env->regs[R_EBP] = tswapl(sc->ebp);
1283 env->regs[R_ESP] = tswapl(sc->esp);
1284 env->regs[R_EBX] = tswapl(sc->ebx);
1285 env->regs[R_EDX] = tswapl(sc->edx);
1286 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001287 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001288
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001289 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001290#else
1291 env->regs[8] = tswapl(sc->r8);
1292 env->regs[9] = tswapl(sc->r9);
1293 env->regs[10] = tswapl(sc->r10);
1294 env->regs[11] = tswapl(sc->r11);
1295 env->regs[12] = tswapl(sc->r12);
1296 env->regs[13] = tswapl(sc->r13);
1297 env->regs[14] = tswapl(sc->r14);
1298 env->regs[15] = tswapl(sc->r15);
1299
1300 env->regs[R_EDI] = tswapl(sc->rdi);
1301 env->regs[R_ESI] = tswapl(sc->rsi);
1302 env->regs[R_EBP] = tswapl(sc->rbp);
1303 env->regs[R_EBX] = tswapl(sc->rbx);
1304 env->regs[R_EDX] = tswapl(sc->rdx);
1305 env->regs[R_EAX] = tswapl(sc->rax);
1306 env->regs[R_ECX] = tswapl(sc->rcx);
1307 env->regs[R_ESP] = tswapl(sc->rsp);
1308
1309 env->eip = tswapl(sc->rip);
1310#endif
bellard66fb9762003-03-23 01:06:05 +00001311
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001312 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1313 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 tmpflags = tswapl(sc->eflags);
1316 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1317 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001318
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001319 fpstate_addr = tswapl(sc->fpstate);
1320 if (fpstate_addr != 0) {
1321 if (!access_ok(VERIFY_READ, fpstate_addr,
1322 sizeof(struct target_fpstate)))
1323 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001324#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001325 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001326#else
1327 cpu_x86_fxrstor(env, fpstate_addr);
1328#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001329 }
bellard66fb9762003-03-23 01:06:05 +00001330
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001331 return err;
bellard66fb9762003-03-23 01:06:05 +00001332badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001333 return 1;
bellard66fb9762003-03-23 01:06:05 +00001334}
1335
Pranith Kumar1c1df012017-02-26 11:53:44 -05001336/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1337#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001338long do_sigreturn(CPUX86State *env)
1339{
bellard579a97f2007-11-11 14:26:47 +00001340 struct sigframe *frame;
1341 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001342 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001343 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001344 int i;
bellard66fb9762003-03-23 01:06:05 +00001345
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001346 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001347 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1348 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001349 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001350 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001351 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001352 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001353 }
bellard66fb9762003-03-23 01:06:05 +00001354
bellard92319442004-06-19 16:58:13 +00001355 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001356 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001357
bellard66fb9762003-03-23 01:06:05 +00001358 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001359 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001360 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001361 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001362 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001363
1364badframe:
bellard579a97f2007-11-11 14:26:47 +00001365 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001366 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001367 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001368}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001369#endif
bellard66fb9762003-03-23 01:06:05 +00001370
1371long do_rt_sigreturn(CPUX86State *env)
1372{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001373 abi_ulong frame_addr;
1374 struct rt_sigframe *frame;
1375 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001376
Pranith Kumar1c1df012017-02-26 11:53:44 -05001377 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001378 trace_user_do_rt_sigreturn(env, frame_addr);
1379 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1380 goto badframe;
1381 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001382 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001383
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001384 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001385 goto badframe;
1386 }
bellard66fb9762003-03-23 01:06:05 +00001387
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001388 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1389 get_sp_from_cpustate(env)) == -EFAULT) {
1390 goto badframe;
1391 }
thsa04e1342007-09-27 13:57:58 +00001392
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001393 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001394 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001395
1396badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001397 unlock_user_struct(frame, frame_addr, 0);
1398 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001399 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001400}
1401
Andreas Schwab1744aea2013-09-03 20:12:16 +01001402#elif defined(TARGET_AARCH64)
1403
1404struct target_sigcontext {
1405 uint64_t fault_address;
1406 /* AArch64 registers */
1407 uint64_t regs[31];
1408 uint64_t sp;
1409 uint64_t pc;
1410 uint64_t pstate;
1411 /* 4K reserved for FP/SIMD state and future expansion */
1412 char __reserved[4096] __attribute__((__aligned__(16)));
1413};
1414
1415struct target_ucontext {
1416 abi_ulong tuc_flags;
1417 abi_ulong tuc_link;
1418 target_stack_t tuc_stack;
1419 target_sigset_t tuc_sigmask;
1420 /* glibc uses a 1024-bit sigset_t */
1421 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1422 /* last for future expansion */
1423 struct target_sigcontext tuc_mcontext;
1424};
1425
1426/*
1427 * Header to be used at the beginning of structures extending the user
1428 * context. Such structures must be placed after the rt_sigframe on the stack
1429 * and be 16-byte aligned. The last structure must be a dummy one with the
1430 * magic and size set to 0.
1431 */
1432struct target_aarch64_ctx {
1433 uint32_t magic;
1434 uint32_t size;
1435};
1436
1437#define TARGET_FPSIMD_MAGIC 0x46508001
1438
1439struct target_fpsimd_context {
1440 struct target_aarch64_ctx head;
1441 uint32_t fpsr;
1442 uint32_t fpcr;
1443 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1444};
1445
Richard Henderson7a53fb92018-03-09 17:09:43 +00001446#define TARGET_EXTRA_MAGIC 0x45585401
1447
1448struct target_extra_context {
1449 struct target_aarch64_ctx head;
1450 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
1451 uint32_t size; /* size in bytes of the extra space */
1452 uint32_t reserved[3];
1453};
1454
Richard Henderson8c5931d2018-03-09 17:09:44 +00001455#define TARGET_SVE_MAGIC 0x53564501
1456
1457struct target_sve_context {
1458 struct target_aarch64_ctx head;
1459 uint16_t vl;
1460 uint16_t reserved[3];
1461 /* The actual SVE data immediately follows. It is layed out
1462 * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
1463 * the original struct pointer.
1464 */
1465};
1466
1467#define TARGET_SVE_VQ_BYTES 16
1468
1469#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
1470#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
1471
1472#define TARGET_SVE_SIG_REGS_OFFSET \
1473 QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
1474#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
1475 (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
1476#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
1477 (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
1478#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
1479 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
1480#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
1481 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
1482
Andreas Schwab1744aea2013-09-03 20:12:16 +01001483struct target_rt_sigframe {
1484 struct target_siginfo info;
1485 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001486};
1487
1488struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001489 uint64_t fp;
1490 uint64_t lr;
1491 uint32_t tramp[2];
1492};
1493
Richard Henderson3b505bb2018-03-09 17:09:43 +00001494static void target_setup_general_frame(struct target_rt_sigframe *sf,
1495 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001496{
1497 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001498
Richard Henderson3b505bb2018-03-09 17:09:43 +00001499 __put_user(0, &sf->uc.tuc_flags);
1500 __put_user(0, &sf->uc.tuc_link);
1501
1502 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1503 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1504 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001505
1506 for (i = 0; i < 31; i++) {
1507 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1508 }
1509 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1510 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001511 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001512
Peter Maydell7af03922014-05-01 18:36:17 +01001513 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001514
1515 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1516 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1517 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001518}
1519
1520static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1521 CPUARMState *env)
1522{
1523 int i;
1524
1525 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1526 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1527 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1528 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001529
1530 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001531 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001532#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001533 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1534 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001535#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001536 __put_user(q[0], &fpsimd->vregs[i * 2]);
1537 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001538#endif
1539 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001540}
1541
Richard Henderson7a53fb92018-03-09 17:09:43 +00001542static void target_setup_extra_record(struct target_extra_context *extra,
1543 uint64_t datap, uint32_t extra_size)
1544{
1545 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
1546 __put_user(sizeof(struct target_extra_context), &extra->head.size);
1547 __put_user(datap, &extra->datap);
1548 __put_user(extra_size, &extra->size);
1549}
1550
Richard Henderson3b505bb2018-03-09 17:09:43 +00001551static void target_setup_end_record(struct target_aarch64_ctx *end)
1552{
1553 __put_user(0, &end->magic);
1554 __put_user(0, &end->size);
1555}
1556
Richard Henderson8c5931d2018-03-09 17:09:44 +00001557static void target_setup_sve_record(struct target_sve_context *sve,
1558 CPUARMState *env, int vq, int size)
1559{
1560 int i, j;
1561
1562 __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
1563 __put_user(size, &sve->head.size);
1564 __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
1565
1566 /* Note that SVE regs are stored as a byte stream, with each byte element
1567 * at a subsequent address. This corresponds to a little-endian store
1568 * of our 64-bit hunks.
1569 */
1570 for (i = 0; i < 32; ++i) {
1571 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1572 for (j = 0; j < vq * 2; ++j) {
1573 __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
1574 }
1575 }
1576 for (i = 0; i <= 16; ++i) {
1577 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1578 for (j = 0; j < vq; ++j) {
1579 uint64_t r = env->vfp.pregs[i].p[j >> 2];
1580 __put_user_e(r >> ((j & 3) * 16), p + j, le);
1581 }
1582 }
1583}
1584
Richard Henderson3b505bb2018-03-09 17:09:43 +00001585static void target_restore_general_frame(CPUARMState *env,
1586 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001587{
1588 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001589 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001590 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001591
1592 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001593 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001594
1595 for (i = 0; i < 31; i++) {
1596 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1597 }
1598
1599 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1600 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001601 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1602 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001603}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001604
Richard Henderson3b505bb2018-03-09 17:09:43 +00001605static void target_restore_fpsimd_record(CPUARMState *env,
1606 struct target_fpsimd_context *fpsimd)
1607{
1608 uint32_t fpsr, fpcr;
1609 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001610
Richard Henderson3b505bb2018-03-09 17:09:43 +00001611 __get_user(fpsr, &fpsimd->fpsr);
1612 vfp_set_fpsr(env, fpsr);
1613 __get_user(fpcr, &fpsimd->fpcr);
1614 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001615
Peter Maydell4cf23482014-03-02 19:36:38 +00001616 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001617 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001618#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001619 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1620 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001621#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001622 __get_user(q[0], &fpsimd->vregs[i * 2]);
1623 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001624#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001625 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001626}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001627
Richard Henderson8c5931d2018-03-09 17:09:44 +00001628static void target_restore_sve_record(CPUARMState *env,
1629 struct target_sve_context *sve, int vq)
1630{
1631 int i, j;
1632
1633 /* Note that SVE regs are stored as a byte stream, with each byte element
1634 * at a subsequent address. This corresponds to a little-endian load
1635 * of our 64-bit hunks.
1636 */
1637 for (i = 0; i < 32; ++i) {
1638 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1639 for (j = 0; j < vq * 2; ++j) {
1640 __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
1641 }
1642 }
1643 for (i = 0; i <= 16; ++i) {
1644 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1645 for (j = 0; j < vq; ++j) {
1646 uint16_t r;
1647 __get_user_e(r, p + j, le);
1648 if (j & 3) {
1649 env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
1650 } else {
1651 env->vfp.pregs[i].p[j >> 2] = r;
1652 }
1653 }
1654 }
1655}
1656
Richard Henderson3b505bb2018-03-09 17:09:43 +00001657static int target_restore_sigframe(CPUARMState *env,
1658 struct target_rt_sigframe *sf)
1659{
Richard Henderson7a53fb92018-03-09 17:09:43 +00001660 struct target_aarch64_ctx *ctx, *extra = NULL;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001661 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001662 struct target_sve_context *sve = NULL;
Richard Henderson7a53fb92018-03-09 17:09:43 +00001663 uint64_t extra_datap = 0;
1664 bool used_extra = false;
1665 bool err = false;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001666 int vq = 0, sve_size = 0;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001667
1668 target_restore_general_frame(env, sf);
1669
Richard Hendersone1eecd12018-03-09 17:09:43 +00001670 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1671 while (ctx) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001672 uint32_t magic, size, extra_size;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001673
1674 __get_user(magic, &ctx->magic);
1675 __get_user(size, &ctx->size);
1676 switch (magic) {
1677 case 0:
1678 if (size != 0) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001679 err = true;
1680 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001681 }
Richard Henderson7a53fb92018-03-09 17:09:43 +00001682 if (used_extra) {
1683 ctx = NULL;
1684 } else {
1685 ctx = extra;
1686 used_extra = true;
1687 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001688 continue;
1689
1690 case TARGET_FPSIMD_MAGIC:
1691 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001692 err = true;
1693 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001694 }
1695 fpsimd = (struct target_fpsimd_context *)ctx;
1696 break;
1697
Richard Henderson8c5931d2018-03-09 17:09:44 +00001698 case TARGET_SVE_MAGIC:
1699 if (arm_feature(env, ARM_FEATURE_SVE)) {
1700 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1701 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1702 if (!sve && size == sve_size) {
1703 sve = (struct target_sve_context *)ctx;
1704 break;
1705 }
1706 }
1707 err = true;
1708 goto exit;
1709
Richard Henderson7a53fb92018-03-09 17:09:43 +00001710 case TARGET_EXTRA_MAGIC:
1711 if (extra || size != sizeof(struct target_extra_context)) {
1712 err = true;
1713 goto exit;
1714 }
1715 __get_user(extra_datap,
1716 &((struct target_extra_context *)ctx)->datap);
1717 __get_user(extra_size,
1718 &((struct target_extra_context *)ctx)->size);
1719 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
1720 break;
1721
Richard Hendersone1eecd12018-03-09 17:09:43 +00001722 default:
1723 /* Unknown record -- we certainly didn't generate it.
1724 * Did we in fact get out of sync?
1725 */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001726 err = true;
1727 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001728 }
1729 ctx = (void *)ctx + size;
1730 }
1731
1732 /* Require FPSIMD always. */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001733 if (fpsimd) {
1734 target_restore_fpsimd_record(env, fpsimd);
1735 } else {
1736 err = true;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001737 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001738
Richard Henderson8c5931d2018-03-09 17:09:44 +00001739 /* SVE data, if present, overwrites FPSIMD data. */
1740 if (sve) {
1741 target_restore_sve_record(env, sve, vq);
1742 }
1743
Richard Henderson7a53fb92018-03-09 17:09:43 +00001744 exit:
1745 unlock_user(extra, extra_datap, 0);
1746 return err;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001747}
1748
Richard Henderson8c5931d2018-03-09 17:09:44 +00001749static abi_ulong get_sigframe(struct target_sigaction *ka,
1750 CPUARMState *env, int size)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001751{
1752 abi_ulong sp;
1753
1754 sp = env->xregs[31];
1755
1756 /*
1757 * This is the X/Open sanctioned signal stack switching.
1758 */
Riku Voipiob545f632014-07-15 17:01:55 +03001759 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001760 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1761 }
1762
Richard Henderson8c5931d2018-03-09 17:09:44 +00001763 sp = (sp - size) & ~15;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001764
1765 return sp;
1766}
1767
Richard Henderson8c5931d2018-03-09 17:09:44 +00001768typedef struct {
1769 int total_size;
1770 int extra_base;
1771 int extra_size;
1772 int std_end_ofs;
1773 int extra_ofs;
1774 int extra_end_ofs;
1775} target_sigframe_layout;
1776
1777static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
1778{
1779 /* Make sure there will always be space for the end marker. */
1780 const int std_size = sizeof(struct target_rt_sigframe)
1781 - sizeof(struct target_aarch64_ctx);
1782 int this_loc = l->total_size;
1783
1784 if (l->extra_base) {
1785 /* Once we have begun an extra space, all allocations go there. */
1786 l->extra_size += this_size;
1787 } else if (this_size + this_loc > std_size) {
1788 /* This allocation does not fit in the standard space. */
1789 /* Allocate the extra record. */
1790 l->extra_ofs = this_loc;
1791 l->total_size += sizeof(struct target_extra_context);
1792
1793 /* Allocate the standard end record. */
1794 l->std_end_ofs = l->total_size;
1795 l->total_size += sizeof(struct target_aarch64_ctx);
1796
1797 /* Allocate the requested record. */
1798 l->extra_base = this_loc = l->total_size;
1799 l->extra_size = this_size;
1800 }
1801 l->total_size += this_size;
1802
1803 return this_loc;
1804}
1805
Andreas Schwab1744aea2013-09-03 20:12:16 +01001806static void target_setup_frame(int usig, struct target_sigaction *ka,
1807 target_siginfo_t *info, target_sigset_t *set,
1808 CPUARMState *env)
1809{
Richard Henderson8c5931d2018-03-09 17:09:44 +00001810 target_sigframe_layout layout = {
1811 /* Begin with the size pointing to the reserved space. */
1812 .total_size = offsetof(struct target_rt_sigframe,
1813 uc.tuc_mcontext.__reserved),
1814 };
1815 int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001816 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001817 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001818 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001819
Richard Henderson8c5931d2018-03-09 17:09:44 +00001820 /* FPSIMD record is always in the standard space. */
1821 fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
1822 &layout);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001823
Richard Henderson8c5931d2018-03-09 17:09:44 +00001824 /* SVE state needs saving only if it exists. */
1825 if (arm_feature(env, ARM_FEATURE_SVE)) {
1826 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1827 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1828 sve_ofs = alloc_sigframe_space(sve_size, &layout);
1829 }
1830
1831 if (layout.extra_ofs) {
1832 /* Reserve space for the extra end marker. The standard end marker
1833 * will have been allocated when we allocated the extra record.
1834 */
1835 layout.extra_end_ofs
1836 = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
1837 } else {
1838 /* Reserve space for the standard end marker.
1839 * Do not use alloc_sigframe_space because we cheat
1840 * std_size therein to reserve space for this.
1841 */
1842 layout.std_end_ofs = layout.total_size;
1843 layout.total_size += sizeof(struct target_aarch64_ctx);
1844 }
1845
1846 /* Reserve space for the return code. On a real system this would
1847 * be within the VDSO. So, despite the name this is not a "real"
1848 * record within the frame.
1849 */
1850 fr_ofs = layout.total_size;
1851 layout.total_size += sizeof(struct target_rt_frame_record);
1852
Peter Maydell7f0f4202018-04-10 13:02:25 +01001853 /* We must always provide at least the standard 4K reserved space,
1854 * even if we don't use all of it (this is part of the ABI)
1855 */
1856 layout.total_size = MAX(layout.total_size,
1857 sizeof(struct target_rt_sigframe));
1858
Richard Henderson8c5931d2018-03-09 17:09:44 +00001859 frame_addr = get_sigframe(ka, env, layout.total_size);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001860 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001861 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1862 goto give_sigsegv;
1863 }
1864
Richard Henderson3b505bb2018-03-09 17:09:43 +00001865 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001866 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson8c5931d2018-03-09 17:09:44 +00001867 target_setup_end_record((void *)frame + layout.std_end_ofs);
1868 if (layout.extra_ofs) {
1869 target_setup_extra_record((void *)frame + layout.extra_ofs,
1870 frame_addr + layout.extra_base,
1871 layout.extra_size);
1872 target_setup_end_record((void *)frame + layout.extra_end_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001873 }
Richard Henderson8c5931d2018-03-09 17:09:44 +00001874 if (sve_ofs) {
1875 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001876 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001877
1878 /* Set up the stack frame for unwinding. */
1879 fr = (void *)frame + fr_ofs;
1880 __put_user(env->xregs[29], &fr->fp);
1881 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001882
Michael Matz8a3ae912014-03-02 19:36:39 +00001883 if (ka->sa_flags & TARGET_SA_RESTORER) {
1884 return_addr = ka->sa_restorer;
1885 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001886 /*
1887 * mov x8,#__NR_rt_sigreturn; svc #0
1888 * Since these are instructions they need to be put as little-endian
1889 * regardless of target default or current CPU endianness.
1890 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001891 __put_user_e(0xd2801168, &fr->tramp[0], le);
1892 __put_user_e(0xd4000001, &fr->tramp[1], le);
1893 return_addr = frame_addr + fr_ofs
1894 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001895 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001896 env->xregs[0] = usig;
1897 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001898 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001899 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001900 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001901 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001902 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001903 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1904 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1905 }
1906
1907 unlock_user_struct(frame, frame_addr, 1);
1908 return;
1909
1910 give_sigsegv:
1911 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001912 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001913}
1914
1915static void setup_rt_frame(int sig, struct target_sigaction *ka,
1916 target_siginfo_t *info, target_sigset_t *set,
1917 CPUARMState *env)
1918{
1919 target_setup_frame(sig, ka, info, set, env);
1920}
1921
1922static void setup_frame(int sig, struct target_sigaction *ka,
1923 target_sigset_t *set, CPUARMState *env)
1924{
1925 target_setup_frame(sig, ka, 0, set, env);
1926}
1927
1928long do_rt_sigreturn(CPUARMState *env)
1929{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001930 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001931 abi_ulong frame_addr = env->xregs[31];
1932
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001933 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001934 if (frame_addr & 15) {
1935 goto badframe;
1936 }
1937
1938 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1939 goto badframe;
1940 }
1941
1942 if (target_restore_sigframe(env, frame)) {
1943 goto badframe;
1944 }
1945
1946 if (do_sigaltstack(frame_addr +
1947 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1948 0, get_sp_from_cpustate(env)) == -EFAULT) {
1949 goto badframe;
1950 }
1951
1952 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001953 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001954
1955 badframe:
1956 unlock_user_struct(frame, frame_addr, 0);
1957 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001958 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001959}
1960
1961long do_sigreturn(CPUARMState *env)
1962{
1963 return do_rt_sigreturn(env);
1964}
1965
bellard43fff232003-07-09 19:31:39 +00001966#elif defined(TARGET_ARM)
1967
1968struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001969 abi_ulong trap_no;
1970 abi_ulong error_code;
1971 abi_ulong oldmask;
1972 abi_ulong arm_r0;
1973 abi_ulong arm_r1;
1974 abi_ulong arm_r2;
1975 abi_ulong arm_r3;
1976 abi_ulong arm_r4;
1977 abi_ulong arm_r5;
1978 abi_ulong arm_r6;
1979 abi_ulong arm_r7;
1980 abi_ulong arm_r8;
1981 abi_ulong arm_r9;
1982 abi_ulong arm_r10;
1983 abi_ulong arm_fp;
1984 abi_ulong arm_ip;
1985 abi_ulong arm_sp;
1986 abi_ulong arm_lr;
1987 abi_ulong arm_pc;
1988 abi_ulong arm_cpsr;
1989 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001990};
1991
pbrooka745ec62008-05-06 15:36:17 +00001992struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001993 abi_ulong tuc_flags;
1994 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001995 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001996 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001997 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001998};
1999
pbrooka745ec62008-05-06 15:36:17 +00002000struct target_ucontext_v2 {
2001 abi_ulong tuc_flags;
2002 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05002003 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00002004 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05002005 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00002006 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00002007 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
2008};
2009
Peter Maydell0d871bd2010-11-24 15:20:05 +00002010struct target_user_vfp {
2011 uint64_t fpregs[32];
2012 abi_ulong fpscr;
2013};
2014
2015struct target_user_vfp_exc {
2016 abi_ulong fpexc;
2017 abi_ulong fpinst;
2018 abi_ulong fpinst2;
2019};
2020
2021struct target_vfp_sigframe {
2022 abi_ulong magic;
2023 abi_ulong size;
2024 struct target_user_vfp ufp;
2025 struct target_user_vfp_exc ufp_exc;
2026} __attribute__((__aligned__(8)));
2027
Peter Maydell08e11252010-11-24 15:20:07 +00002028struct target_iwmmxt_sigframe {
2029 abi_ulong magic;
2030 abi_ulong size;
2031 uint64_t regs[16];
2032 /* Note that not all the coprocessor control registers are stored here */
2033 uint32_t wcssf;
2034 uint32_t wcasf;
2035 uint32_t wcgr0;
2036 uint32_t wcgr1;
2037 uint32_t wcgr2;
2038 uint32_t wcgr3;
2039} __attribute__((__aligned__(8)));
2040
Peter Maydell0d871bd2010-11-24 15:20:05 +00002041#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00002042#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00002043
pbrooka8c33202008-05-07 23:22:46 +00002044struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002045{
2046 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00002047 abi_ulong extramask[TARGET_NSIG_WORDS-1];
2048 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002049};
2050
pbrooka8c33202008-05-07 23:22:46 +00002051struct sigframe_v2
2052{
2053 struct target_ucontext_v2 uc;
2054 abi_ulong retcode;
2055};
2056
pbrooka745ec62008-05-06 15:36:17 +00002057struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002058{
bellardf8b0aa22007-11-11 23:03:42 +00002059 abi_ulong pinfo;
2060 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00002061 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00002062 struct target_ucontext_v1 uc;
2063 abi_ulong retcode;
2064};
2065
2066struct rt_sigframe_v2
2067{
2068 struct target_siginfo info;
2069 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00002070 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002071};
2072
2073#define TARGET_CONFIG_CPU_32 1
2074
2075/*
2076 * For ARM syscalls, we encode the syscall number into the instruction.
2077 */
2078#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
2079#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
2080
2081/*
2082 * For Thumb syscalls, we pass the syscall number via r7. We therefore
2083 * need two 16-bit instructions.
2084 */
2085#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
2086#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
2087
blueswir1992f48a2007-10-14 16:27:31 +00002088static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00002089 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
2090 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
2091};
2092
2093
Andreas Färber05390242012-02-25 03:37:53 +01002094static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00002095{
2096 return 1;
2097}
2098
pbrooka8c33202008-05-07 23:22:46 +00002099static void
bellard43fff232003-07-09 19:31:39 +00002100setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002101 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00002102{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002103 __put_user(env->regs[0], &sc->arm_r0);
2104 __put_user(env->regs[1], &sc->arm_r1);
2105 __put_user(env->regs[2], &sc->arm_r2);
2106 __put_user(env->regs[3], &sc->arm_r3);
2107 __put_user(env->regs[4], &sc->arm_r4);
2108 __put_user(env->regs[5], &sc->arm_r5);
2109 __put_user(env->regs[6], &sc->arm_r6);
2110 __put_user(env->regs[7], &sc->arm_r7);
2111 __put_user(env->regs[8], &sc->arm_r8);
2112 __put_user(env->regs[9], &sc->arm_r9);
2113 __put_user(env->regs[10], &sc->arm_r10);
2114 __put_user(env->regs[11], &sc->arm_fp);
2115 __put_user(env->regs[12], &sc->arm_ip);
2116 __put_user(env->regs[13], &sc->arm_sp);
2117 __put_user(env->regs[14], &sc->arm_lr);
2118 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002119#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002120 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00002121#endif
2122
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002123 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
2124 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
2125 __put_user(/* current->thread.address */ 0, &sc->fault_address);
2126 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00002127}
2128
bellard579a97f2007-11-11 14:26:47 +00002129static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002130get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00002131{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002132 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00002133
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002134 /*
2135 * This is the X/Open sanctioned signal stack switching.
2136 */
2137 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
2138 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2139 }
2140 /*
2141 * ATPCS B01 mandates 8-byte alignment
2142 */
2143 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00002144}
2145
Riku Voipio0188fad2014-04-23 13:34:15 +03002146static void
Andreas Färber05390242012-02-25 03:37:53 +01002147setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002148 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00002149{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002150 abi_ulong handler = ka->_sa_handler;
2151 abi_ulong retcode;
2152 int thumb = handler & 1;
2153 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01002154
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002155 cpsr &= ~CPSR_IT;
2156 if (thumb) {
2157 cpsr |= CPSR_T;
2158 } else {
2159 cpsr &= ~CPSR_T;
2160 }
bellard43fff232003-07-09 19:31:39 +00002161
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002162 if (ka->sa_flags & TARGET_SA_RESTORER) {
2163 retcode = ka->sa_restorer;
2164 } else {
2165 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00002166
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002167 if (ka->sa_flags & TARGET_SA_SIGINFO) {
2168 idx += 2;
2169 }
bellard43fff232003-07-09 19:31:39 +00002170
Riku Voipio0188fad2014-04-23 13:34:15 +03002171 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02002172
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002173 retcode = rc_addr + thumb;
2174 }
bellard43fff232003-07-09 19:31:39 +00002175
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002176 env->regs[0] = usig;
2177 env->regs[13] = frame_addr;
2178 env->regs[14] = retcode;
2179 env->regs[15] = handler & (thumb ? ~1 : ~3);
2180 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002181}
2182
Andreas Färber05390242012-02-25 03:37:53 +01002183static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002184{
2185 int i;
2186 struct target_vfp_sigframe *vfpframe;
2187 vfpframe = (struct target_vfp_sigframe *)regspace;
2188 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2189 __put_user(sizeof(*vfpframe), &vfpframe->size);
2190 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002191 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002192 }
2193 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2194 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2195 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2196 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2197 return (abi_ulong*)(vfpframe+1);
2198}
2199
Andreas Färber05390242012-02-25 03:37:53 +01002200static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2201 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002202{
2203 int i;
2204 struct target_iwmmxt_sigframe *iwmmxtframe;
2205 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2206 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2207 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2208 for (i = 0; i < 16; i++) {
2209 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2210 }
2211 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2212 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2213 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2214 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2215 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2216 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2217 return (abi_ulong*)(iwmmxtframe+1);
2218}
2219
pbrooka8c33202008-05-07 23:22:46 +00002220static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002221 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002222{
pbrooka8c33202008-05-07 23:22:46 +00002223 struct target_sigaltstack stack;
2224 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002225 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002226
2227 /* Clear all the bits of the ucontext we don't use. */
2228 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2229
2230 memset(&stack, 0, sizeof(stack));
2231 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2232 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2233 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2234 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2235
2236 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002237 /* Save coprocessor signal frame. */
2238 regspace = uc->tuc_regspace;
2239 if (arm_feature(env, ARM_FEATURE_VFP)) {
2240 regspace = setup_sigframe_v2_vfp(regspace, env);
2241 }
Peter Maydell08e11252010-11-24 15:20:07 +00002242 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2243 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2244 }
2245
Peter Maydell0d871bd2010-11-24 15:20:05 +00002246 /* Write terminating magic word */
2247 __put_user(0, regspace);
2248
pbrooka8c33202008-05-07 23:22:46 +00002249 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2250 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2251 }
2252}
2253
2254/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002255static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002256 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002257{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002258 struct sigframe_v1 *frame;
2259 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2260 int i;
bellard43fff232003-07-09 19:31:39 +00002261
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002262 trace_user_setup_frame(regs, frame_addr);
2263 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002264 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002265 }
bellard579a97f2007-11-11 14:26:47 +00002266
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002267 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002268
Riku Voipio0188fad2014-04-23 13:34:15 +03002269 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2270 __put_user(set->sig[i], &frame->extramask[i - 1]);
2271 }
bellard43fff232003-07-09 19:31:39 +00002272
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002273 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2274 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002275
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002276 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002277 return;
2278sigsegv:
2279 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002280}
2281
pbrook624f7972008-05-31 16:11:38 +00002282static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002283 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002284{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 struct sigframe_v2 *frame;
2286 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002287
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002288 trace_user_setup_frame(regs, frame_addr);
2289 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002290 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002291 }
pbrooka8c33202008-05-07 23:22:46 +00002292
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002293 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002294
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002295 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2296 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002297
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002298 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002299 return;
2300sigsegv:
2301 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002302}
2303
pbrook624f7972008-05-31 16:11:38 +00002304static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002305 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002306{
2307 if (get_osversion() >= 0x020612) {
2308 setup_frame_v2(usig, ka, set, regs);
2309 } else {
2310 setup_frame_v1(usig, ka, set, regs);
2311 }
bellard43fff232003-07-09 19:31:39 +00002312}
2313
bellard579a97f2007-11-11 14:26:47 +00002314/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002315static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002316 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002317 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002318{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002319 struct rt_sigframe_v1 *frame;
2320 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2321 struct target_sigaltstack stack;
2322 int i;
2323 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002324
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002325 trace_user_setup_rt_frame(env, frame_addr);
2326 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002327 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002328 }
bellardedf779f2004-02-22 13:40:13 +00002329
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002330 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2331 __put_user(info_addr, &frame->pinfo);
2332 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2333 __put_user(uc_addr, &frame->puc);
2334 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002335
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002336 /* Clear all the bits of the ucontext we don't use. */
2337 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002338
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002339 memset(&stack, 0, sizeof(stack));
2340 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2341 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2342 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2343 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002344
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002345 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2346 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2347 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2348 }
bellard43fff232003-07-09 19:31:39 +00002349
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002350 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2351 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002352
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002353 env->regs[1] = info_addr;
2354 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002355
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002356 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002357 return;
2358sigsegv:
2359 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002360}
2361
pbrook624f7972008-05-31 16:11:38 +00002362static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002363 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002364 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002365{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002366 struct rt_sigframe_v2 *frame;
2367 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2368 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002369
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002370 trace_user_setup_rt_frame(env, frame_addr);
2371 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002372 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002373 }
pbrooka745ec62008-05-06 15:36:17 +00002374
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002375 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2376 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2377 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002378
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002379 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002380
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002381 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2382 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002383
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002384 env->regs[1] = info_addr;
2385 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002386
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002387 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002388 return;
2389sigsegv:
2390 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002391}
2392
pbrook624f7972008-05-31 16:11:38 +00002393static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002394 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002395 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002396{
2397 if (get_osversion() >= 0x020612) {
2398 setup_rt_frame_v2(usig, ka, info, set, env);
2399 } else {
2400 setup_rt_frame_v1(usig, ka, info, set, env);
2401 }
2402}
2403
bellard43fff232003-07-09 19:31:39 +00002404static int
Andreas Färber05390242012-02-25 03:37:53 +01002405restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002406{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002407 int err = 0;
2408 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002409
Riku Voipio1d8b5122014-04-23 10:26:05 +03002410 __get_user(env->regs[0], &sc->arm_r0);
2411 __get_user(env->regs[1], &sc->arm_r1);
2412 __get_user(env->regs[2], &sc->arm_r2);
2413 __get_user(env->regs[3], &sc->arm_r3);
2414 __get_user(env->regs[4], &sc->arm_r4);
2415 __get_user(env->regs[5], &sc->arm_r5);
2416 __get_user(env->regs[6], &sc->arm_r6);
2417 __get_user(env->regs[7], &sc->arm_r7);
2418 __get_user(env->regs[8], &sc->arm_r8);
2419 __get_user(env->regs[9], &sc->arm_r9);
2420 __get_user(env->regs[10], &sc->arm_r10);
2421 __get_user(env->regs[11], &sc->arm_fp);
2422 __get_user(env->regs[12], &sc->arm_ip);
2423 __get_user(env->regs[13], &sc->arm_sp);
2424 __get_user(env->regs[14], &sc->arm_lr);
2425 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002426#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002427 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002428 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002429#endif
2430
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002431 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002432
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002433 return err;
bellard43fff232003-07-09 19:31:39 +00002434}
2435
Andreas Färber05390242012-02-25 03:37:53 +01002436static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002437{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002438 abi_ulong frame_addr;
2439 struct sigframe_v1 *frame = NULL;
2440 target_sigset_t set;
2441 sigset_t host_set;
2442 int i;
bellard43fff232003-07-09 19:31:39 +00002443
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002444 /*
2445 * Since we stacked the signal on a 64-bit boundary,
2446 * then 'sp' should be word aligned here. If it's
2447 * not, then the user is trying to mess with us.
2448 */
2449 frame_addr = env->regs[13];
2450 trace_user_do_sigreturn(env, frame_addr);
2451 if (frame_addr & 7) {
2452 goto badframe;
2453 }
Peter Maydell978fae92013-07-29 12:00:32 +01002454
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002455 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2456 goto badframe;
2457 }
bellard43fff232003-07-09 19:31:39 +00002458
Riku Voipiof5f601a2014-04-23 13:00:17 +03002459 __get_user(set.sig[0], &frame->sc.oldmask);
2460 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2461 __get_user(set.sig[i], &frame->extramask[i - 1]);
2462 }
bellard43fff232003-07-09 19:31:39 +00002463
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002464 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002465 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002466
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002467 if (restore_sigcontext(env, &frame->sc)) {
2468 goto badframe;
2469 }
bellard43fff232003-07-09 19:31:39 +00002470
2471#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002472 /* Send SIGTRAP if we're single-stepping */
2473 if (ptrace_cancel_bpt(current))
2474 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002475#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002476 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002477 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002478
2479badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002480 force_sig(TARGET_SIGSEGV);
2481 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002482}
2483
Andreas Färber05390242012-02-25 03:37:53 +01002484static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002485{
2486 int i;
2487 abi_ulong magic, sz;
2488 uint32_t fpscr, fpexc;
2489 struct target_vfp_sigframe *vfpframe;
2490 vfpframe = (struct target_vfp_sigframe *)regspace;
2491
2492 __get_user(magic, &vfpframe->magic);
2493 __get_user(sz, &vfpframe->size);
2494 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2495 return 0;
2496 }
2497 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002498 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002499 }
2500 __get_user(fpscr, &vfpframe->ufp.fpscr);
2501 vfp_set_fpscr(env, fpscr);
2502 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2503 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2504 * and the exception flag is cleared
2505 */
2506 fpexc |= (1 << 30);
2507 fpexc &= ~((1 << 31) | (1 << 28));
2508 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2509 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2510 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2511 return (abi_ulong*)(vfpframe + 1);
2512}
2513
Andreas Färber05390242012-02-25 03:37:53 +01002514static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2515 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002516{
2517 int i;
2518 abi_ulong magic, sz;
2519 struct target_iwmmxt_sigframe *iwmmxtframe;
2520 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2521
2522 __get_user(magic, &iwmmxtframe->magic);
2523 __get_user(sz, &iwmmxtframe->size);
2524 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2525 return 0;
2526 }
2527 for (i = 0; i < 16; i++) {
2528 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2529 }
2530 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2531 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2532 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2533 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2534 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2535 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2536 return (abi_ulong*)(iwmmxtframe + 1);
2537}
2538
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002539static int do_sigframe_return_v2(CPUARMState *env,
2540 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002541 struct target_ucontext_v2 *uc)
2542{
2543 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002544 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002545
2546 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002547 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002548
2549 if (restore_sigcontext(env, &uc->tuc_mcontext))
2550 return 1;
2551
Peter Maydell5f9099d2010-11-24 15:20:06 +00002552 /* Restore coprocessor signal frame */
2553 regspace = uc->tuc_regspace;
2554 if (arm_feature(env, ARM_FEATURE_VFP)) {
2555 regspace = restore_sigframe_v2_vfp(env, regspace);
2556 if (!regspace) {
2557 return 1;
2558 }
2559 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002560 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2561 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2562 if (!regspace) {
2563 return 1;
2564 }
2565 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002566
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002567 if (do_sigaltstack(context_addr
2568 + offsetof(struct target_ucontext_v2, tuc_stack),
2569 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002570 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002571 }
pbrooka8c33202008-05-07 23:22:46 +00002572
2573#if 0
2574 /* Send SIGTRAP if we're single-stepping */
2575 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002576 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002577#endif
2578
2579 return 0;
2580}
2581
Andreas Färber05390242012-02-25 03:37:53 +01002582static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002583{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002584 abi_ulong frame_addr;
2585 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002586
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002587 /*
2588 * Since we stacked the signal on a 64-bit boundary,
2589 * then 'sp' should be word aligned here. If it's
2590 * not, then the user is trying to mess with us.
2591 */
2592 frame_addr = env->regs[13];
2593 trace_user_do_sigreturn(env, frame_addr);
2594 if (frame_addr & 7) {
2595 goto badframe;
2596 }
Peter Maydell978fae92013-07-29 12:00:32 +01002597
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002598 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2599 goto badframe;
2600 }
pbrooka8c33202008-05-07 23:22:46 +00002601
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002602 if (do_sigframe_return_v2(env,
2603 frame_addr
2604 + offsetof(struct sigframe_v2, uc),
2605 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002606 goto badframe;
2607 }
pbrooka8c33202008-05-07 23:22:46 +00002608
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002609 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002610 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002611
2612badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002613 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002614 force_sig(TARGET_SIGSEGV);
2615 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002616}
2617
Andreas Färber05390242012-02-25 03:37:53 +01002618long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002619{
2620 if (get_osversion() >= 0x020612) {
2621 return do_sigreturn_v2(env);
2622 } else {
2623 return do_sigreturn_v1(env);
2624 }
2625}
2626
Andreas Färber05390242012-02-25 03:37:53 +01002627static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002628{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002629 abi_ulong frame_addr;
2630 struct rt_sigframe_v1 *frame = NULL;
2631 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002632
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002633 /*
2634 * Since we stacked the signal on a 64-bit boundary,
2635 * then 'sp' should be word aligned here. If it's
2636 * not, then the user is trying to mess with us.
2637 */
2638 frame_addr = env->regs[13];
2639 trace_user_do_rt_sigreturn(env, frame_addr);
2640 if (frame_addr & 7) {
2641 goto badframe;
2642 }
Peter Maydell978fae92013-07-29 12:00:32 +01002643
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002644 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2645 goto badframe;
2646 }
bellard43fff232003-07-09 19:31:39 +00002647
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002648 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002649 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002650
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002651 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2652 goto badframe;
2653 }
bellard43fff232003-07-09 19:31:39 +00002654
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002655 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2656 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002657
bellard43fff232003-07-09 19:31:39 +00002658#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002659 /* Send SIGTRAP if we're single-stepping */
2660 if (ptrace_cancel_bpt(current))
2661 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002662#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002663 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002664 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002665
2666badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002667 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002668 force_sig(TARGET_SIGSEGV);
2669 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002670}
2671
Andreas Färber05390242012-02-25 03:37:53 +01002672static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002673{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002674 abi_ulong frame_addr;
2675 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002676
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002677 /*
2678 * Since we stacked the signal on a 64-bit boundary,
2679 * then 'sp' should be word aligned here. If it's
2680 * not, then the user is trying to mess with us.
2681 */
2682 frame_addr = env->regs[13];
2683 trace_user_do_rt_sigreturn(env, frame_addr);
2684 if (frame_addr & 7) {
2685 goto badframe;
2686 }
Peter Maydell978fae92013-07-29 12:00:32 +01002687
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002688 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2689 goto badframe;
2690 }
pbrooka745ec62008-05-06 15:36:17 +00002691
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002692 if (do_sigframe_return_v2(env,
2693 frame_addr
2694 + offsetof(struct rt_sigframe_v2, uc),
2695 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002696 goto badframe;
2697 }
pbrooka745ec62008-05-06 15:36:17 +00002698
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002699 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002700 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002701
2702badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002703 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002704 force_sig(TARGET_SIGSEGV);
2705 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002706}
2707
Andreas Färber05390242012-02-25 03:37:53 +01002708long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002709{
2710 if (get_osversion() >= 0x020612) {
2711 return do_rt_sigreturn_v2(env);
2712 } else {
2713 return do_rt_sigreturn_v1(env);
2714 }
2715}
2716
bellard6d5e2162004-09-30 22:04:13 +00002717#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002718
bellard6d5e2162004-09-30 22:04:13 +00002719#define __SUNOS_MAXWIN 31
2720
2721/* This is what SunOS does, so shall I. */
2722struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002723 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002724
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002725 abi_ulong sigc_mask; /* sigmask to restore */
2726 abi_ulong sigc_sp; /* stack pointer */
2727 abi_ulong sigc_pc; /* program counter */
2728 abi_ulong sigc_npc; /* next program counter */
2729 abi_ulong sigc_psr; /* for condition codes etc */
2730 abi_ulong sigc_g1; /* User uses these two registers */
2731 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002732
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002733 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002734 * at the time of the signal.
2735 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002736 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002737
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002738 /* stack ptrs for each regwin buf */
2739 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002740
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002741 /* Windows to restore after signal */
2742 struct {
2743 abi_ulong locals[8];
2744 abi_ulong ins[8];
2745 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002746};
2747/* A Sparc stack frame */
2748struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002749 abi_ulong locals[8];
2750 abi_ulong ins[8];
2751 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002752 * since we never need to access them ourselves.
2753 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002754 char *structptr;
2755 abi_ulong xargs[6];
2756 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002757};
2758
2759typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002760 struct {
2761 abi_ulong psr;
2762 abi_ulong pc;
2763 abi_ulong npc;
2764 abi_ulong y;
2765 abi_ulong u_regs[16]; /* globals and ins */
2766 } si_regs;
2767 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002768} __siginfo_t;
2769
2770typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002771 abi_ulong si_float_regs[32];
2772 unsigned long si_fsr;
2773 unsigned long si_fpqdepth;
2774 struct {
2775 unsigned long *insn_addr;
2776 unsigned long insn;
2777 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002778} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002779
2780
2781struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002782 struct sparc_stackf ss;
2783 __siginfo_t info;
2784 abi_ulong fpu_save;
2785 abi_ulong insns[2] __attribute__ ((aligned (8)));
2786 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2787 abi_ulong extra_size; /* Should be 0 */
2788 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002789};
2790struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002791 struct sparc_stackf ss;
2792 siginfo_t info;
2793 abi_ulong regs[20];
2794 sigset_t mask;
2795 abi_ulong fpu_save;
2796 unsigned int insns[2];
2797 stack_t stack;
2798 unsigned int extra_size; /* Should be 0 */
2799 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002800};
2801
bellarde80cfcf2004-12-19 23:18:01 +00002802#define UREG_O0 16
2803#define UREG_O6 22
2804#define UREG_I0 0
2805#define UREG_I1 1
2806#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002807#define UREG_I3 3
2808#define UREG_I4 4
2809#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002810#define UREG_I6 6
2811#define UREG_I7 7
2812#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002813#define UREG_FP UREG_I6
2814#define UREG_SP UREG_O6
2815
pbrook624f7972008-05-31 16:11:38 +00002816static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002817 CPUSPARCState *env,
2818 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002819{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002820 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002821
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002822 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002823
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002824 /* This is the X/Open sanctioned signal stack switching. */
2825 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2826 if (!on_sig_stack(sp)
2827 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2828 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2829 }
2830 }
2831 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002832}
2833
2834static int
Andreas Färber05390242012-02-25 03:37:53 +01002835setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002836{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002837 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002838
Riku Voipio1d8b5122014-04-23 10:26:05 +03002839 __put_user(env->psr, &si->si_regs.psr);
2840 __put_user(env->pc, &si->si_regs.pc);
2841 __put_user(env->npc, &si->si_regs.npc);
2842 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002843 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002844 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002845 }
2846 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002847 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002848 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002849 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002850 return err;
bellard6d5e2162004-09-30 22:04:13 +00002851}
bellarde80cfcf2004-12-19 23:18:01 +00002852
bellard80a9d032005-01-03 23:31:27 +00002853#if 0
bellard6d5e2162004-09-30 22:04:13 +00002854static int
2855setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002856 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002857{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002858 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002859
Riku Voipio1d8b5122014-04-23 10:26:05 +03002860 __put_user(mask, &sc->sigc_mask);
2861 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2862 __put_user(env->pc, &sc->sigc_pc);
2863 __put_user(env->npc, &sc->sigc_npc);
2864 __put_user(env->psr, &sc->sigc_psr);
2865 __put_user(env->gregs[1], &sc->sigc_g1);
2866 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002867
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002868 return err;
bellard6d5e2162004-09-30 22:04:13 +00002869}
bellard80a9d032005-01-03 23:31:27 +00002870#endif
bellard6d5e2162004-09-30 22:04:13 +00002871#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2872
pbrook624f7972008-05-31 16:11:38 +00002873static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002874 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002875{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002876 abi_ulong sf_addr;
2877 struct target_signal_frame *sf;
2878 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002879
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002880 /* 1. Make sure everything is clean */
2881 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002882
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002883 sigframe_size = NF_ALIGNEDSZ;
2884 sf_addr = get_sigframe(ka, env, sigframe_size);
2885 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002886
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002887 sf = lock_user(VERIFY_WRITE, sf_addr,
2888 sizeof(struct target_signal_frame), 0);
2889 if (!sf) {
2890 goto sigsegv;
2891 }
bellard6d5e2162004-09-30 22:04:13 +00002892#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002893 if (invalid_frame_pointer(sf, sigframe_size))
2894 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002895#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002896 /* 2. Save the current process state */
2897 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002898 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002899
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002900 //save_fpu_state(regs, &sf->fpu_state);
2901 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002902
Riku Voipio1d8b5122014-04-23 10:26:05 +03002903 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002904 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002905 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002906 }
bellard6d5e2162004-09-30 22:04:13 +00002907
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002908 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002909 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002910 }
2911 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002912 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002913 }
2914 if (err)
2915 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002916
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002917 /* 3. signal handler back-trampoline and parameters */
2918 env->regwptr[UREG_FP] = sf_addr;
2919 env->regwptr[UREG_I0] = sig;
2920 env->regwptr[UREG_I1] = sf_addr +
2921 offsetof(struct target_signal_frame, info);
2922 env->regwptr[UREG_I2] = sf_addr +
2923 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002924
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002925 /* 4. signal handler */
2926 env->pc = ka->_sa_handler;
2927 env->npc = (env->pc + 4);
2928 /* 5. return to kernel instructions */
Laurent Vivier5de154e2018-04-02 12:24:52 +02002929 if (ka->ka_restorer) {
2930 env->regwptr[UREG_I7] = ka->ka_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002931 } else {
2932 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002933
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002934 env->regwptr[UREG_I7] = sf_addr +
2935 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002936
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002937 /* mov __NR_sigreturn, %g1 */
2938 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002939 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002940
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002941 /* t 0x10 */
2942 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002943 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002944 if (err)
2945 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002946
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002947 /* Flush instruction space. */
2948 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2949 // tb_flush(env);
2950 }
2951 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2952 return;
bellard459a4012007-11-11 19:45:10 +00002953#if 0
2954sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002955 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002956#endif
bellard6d5e2162004-09-30 22:04:13 +00002957sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002958 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002959 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002960}
bellard6d5e2162004-09-30 22:04:13 +00002961
pbrook624f7972008-05-31 16:11:38 +00002962static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002963 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002964 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002965{
2966 fprintf(stderr, "setup_rt_frame: not implemented\n");
2967}
2968
Andreas Färber05390242012-02-25 03:37:53 +01002969long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002970{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002971 abi_ulong sf_addr;
2972 struct target_signal_frame *sf;
2973 uint32_t up_psr, pc, npc;
2974 target_sigset_t set;
2975 sigset_t host_set;
2976 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002977
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002978 sf_addr = env->regwptr[UREG_FP];
2979 trace_user_do_sigreturn(env, sf_addr);
2980 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2981 goto segv_and_exit;
2982 }
bellard6d5e2162004-09-30 22:04:13 +00002983
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002984 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002985
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002986 if (sf_addr & 3)
2987 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002988
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002989 __get_user(pc, &sf->info.si_regs.pc);
2990 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002991
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002992 if ((pc | npc) & 3) {
2993 goto segv_and_exit;
2994 }
bellard6d5e2162004-09-30 22:04:13 +00002995
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002996 /* 2. Restore the state */
2997 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002998
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002999 /* User can only change condition codes and FPU enabling in %psr. */
3000 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
3001 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00003002
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003003 env->pc = pc;
3004 env->npc = npc;
3005 __get_user(env->y, &sf->info.si_regs.y);
3006 for (i=0; i < 8; i++) {
3007 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
3008 }
3009 for (i=0; i < 8; i++) {
3010 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
3011 }
bellard6d5e2162004-09-30 22:04:13 +00003012
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003013 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01003014 * __get_user(fpu_save, &sf->fpu_save);
3015 * if (fpu_save)
3016 * err |= restore_fpu_state(env, fpu_save);
3017 */
bellard6d5e2162004-09-30 22:04:13 +00003018
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003019 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00003020 * the races which exist anyways.
3021 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003022 __get_user(set.sig[0], &sf->info.si_mask);
3023 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3024 __get_user(set.sig[i], &sf->extramask[i - 1]);
3025 }
bellarde80cfcf2004-12-19 23:18:01 +00003026
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003027 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003028 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00003029
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003030 if (err) {
3031 goto segv_and_exit;
3032 }
3033 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01003034 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003035
3036segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003037 unlock_user_struct(sf, sf_addr, 0);
3038 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003039 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003040}
3041
Andreas Färber05390242012-02-25 03:37:53 +01003042long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00003043{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003044 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00003045 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00003046 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00003047}
3048
bellard459a4012007-11-11 19:45:10 +00003049#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00003050#define SPARC_MC_TSTATE 0
3051#define SPARC_MC_PC 1
3052#define SPARC_MC_NPC 2
3053#define SPARC_MC_Y 3
3054#define SPARC_MC_G1 4
3055#define SPARC_MC_G2 5
3056#define SPARC_MC_G3 6
3057#define SPARC_MC_G4 7
3058#define SPARC_MC_G5 8
3059#define SPARC_MC_G6 9
3060#define SPARC_MC_G7 10
3061#define SPARC_MC_O0 11
3062#define SPARC_MC_O1 12
3063#define SPARC_MC_O2 13
3064#define SPARC_MC_O3 14
3065#define SPARC_MC_O4 15
3066#define SPARC_MC_O5 16
3067#define SPARC_MC_O6 17
3068#define SPARC_MC_O7 18
3069#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00003070
Anthony Liguoric227f092009-10-01 16:12:16 -05003071typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003072typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00003073
3074struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00003075 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003076 uint32_t mcfq_insn;
3077};
3078
3079struct target_mc_fpu {
3080 union {
3081 uint32_t sregs[32];
3082 uint64_t dregs[32];
3083 //uint128_t qregs[16];
3084 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00003085 abi_ulong mcfpu_fsr;
3086 abi_ulong mcfpu_fprs;
3087 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00003088 struct target_mc_fq *mcfpu_fq;
3089 unsigned char mcfpu_qcnt;
3090 unsigned char mcfpu_qentsz;
3091 unsigned char mcfpu_enab;
3092};
Anthony Liguoric227f092009-10-01 16:12:16 -05003093typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003094
3095typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05003096 target_mc_gregset_t mc_gregs;
3097 target_mc_greg_t mc_fp;
3098 target_mc_greg_t mc_i7;
3099 target_mc_fpu_t mc_fpregs;
3100} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003101
3102struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003103 struct target_ucontext *tuc_link;
3104 abi_ulong tuc_flags;
3105 target_sigset_t tuc_sigmask;
3106 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003107};
3108
3109/* A V9 register window */
3110struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00003111 abi_ulong locals[8];
3112 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00003113};
3114
3115#define TARGET_STACK_BIAS 2047
3116
3117/* {set, get}context() needed for 64-bit SparcLinux userland. */
3118void sparc64_set_context(CPUSPARCState *env)
3119{
bellard459a4012007-11-11 19:45:10 +00003120 abi_ulong ucp_addr;
3121 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003122 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00003123 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00003124 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003125 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00003126
bellard459a4012007-11-11 19:45:10 +00003127 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003128 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00003129 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003130 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02003131 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003132 __get_user(pc, &((*grp)[SPARC_MC_PC]));
3133 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003134 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00003135 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003136 }
blueswir15bfb56b2007-10-05 17:01:51 +00003137 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05003138 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003139 sigset_t set;
3140
3141 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003142 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00003143 } else {
bellard459a4012007-11-11 19:45:10 +00003144 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003145 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00003146 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003147 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003148 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003149 }
blueswir15bfb56b2007-10-05 17:01:51 +00003150 }
3151 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003152 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00003153 }
3154 env->pc = pc;
3155 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003156 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
3157 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00003158 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00003159 cpu_put_ccr(env, tstate >> 32);
3160 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00003161 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
3162 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
3163 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
3164 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
3165 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
3166 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
3167 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
3168 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
3169 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
3170 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
3171 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
3172 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
3173 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
3174 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
3175 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003176
Riku Voipio1d8b5122014-04-23 10:26:05 +03003177 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3178 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003179
bellard459a4012007-11-11 19:45:10 +00003180 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003181 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3182 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003183 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003184 }
3185 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3186 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003187 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003188 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003189 /* FIXME this does not match how the kernel handles the FPU in
3190 * its sparc64_set_context implementation. In particular the FPU
3191 * is only restored if fenab is non-zero in:
3192 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3193 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003194 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003195 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003196 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3197 for (i = 0; i < 64; i++, src++) {
3198 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003199 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003200 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003201 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003202 }
3203 }
bellard459a4012007-11-11 19:45:10 +00003204 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003205 __get_user(env->fsr,
3206 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3207 __get_user(env->gsr,
3208 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003209 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003210 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003211do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003212 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003213 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003214}
3215
3216void sparc64_get_context(CPUSPARCState *env)
3217{
bellard459a4012007-11-11 19:45:10 +00003218 abi_ulong ucp_addr;
3219 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003220 target_mc_gregset_t *grp;
3221 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003222 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003223 int err;
3224 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003225 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003226 sigset_t set;
3227
bellard459a4012007-11-11 19:45:10 +00003228 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003229 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003230 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003231 }
bellard459a4012007-11-11 19:45:10 +00003232
Aurelien Jarno60e99242010-03-29 02:12:51 +02003233 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003234 grp = &mcp->mc_gregs;
3235
3236 /* Skip over the trap instruction, first. */
3237 env->pc = env->npc;
3238 env->npc += 4;
3239
Peter Maydell3d3efba2016-05-27 15:51:49 +01003240 /* If we're only reading the signal mask then do_sigprocmask()
3241 * is guaranteed not to fail, which is important because we don't
3242 * have any way to signal a failure or restart this operation since
3243 * this is not a normal syscall.
3244 */
3245 err = do_sigprocmask(0, NULL, &set);
3246 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003247 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003248 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003249 __put_user(target_set.sig[0],
3250 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003251 } else {
3252 abi_ulong *src, *dst;
3253 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003254 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003255 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003256 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003257 }
blueswir15bfb56b2007-10-05 17:01:51 +00003258 if (err)
3259 goto do_sigsegv;
3260 }
3261
bellard459a4012007-11-11 19:45:10 +00003262 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003263 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3264 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3265 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3266 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3267 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3268 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3269 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3270 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3271 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3272 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3273 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3274 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3275 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3276 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3277 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3278 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3279 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3280 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3281 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003282
bellard459a4012007-11-11 19:45:10 +00003283 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3284 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003285 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3286 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003287 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003288 }
3289 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3290 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003291 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003292 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003293 __put_user(fp, &(mcp->mc_fp));
3294 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003295
bellard459a4012007-11-11 19:45:10 +00003296 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003297 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3298 for (i = 0; i < 64; i++, dst++) {
3299 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003300 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003301 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003302 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003303 }
3304 }
bellard459a4012007-11-11 19:45:10 +00003305 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003306 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3307 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3308 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003309
3310 if (err)
3311 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003312 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003313 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003314do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003315 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003316 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003317}
3318#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003319#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003320
Richard Hendersonff970902013-02-10 10:30:42 -08003321# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003322struct target_sigcontext {
3323 uint32_t sc_regmask; /* Unused */
3324 uint32_t sc_status;
3325 uint64_t sc_pc;
3326 uint64_t sc_regs[32];
3327 uint64_t sc_fpregs[32];
3328 uint32_t sc_ownedfp; /* Unused */
3329 uint32_t sc_fpc_csr;
3330 uint32_t sc_fpc_eir; /* Unused */
3331 uint32_t sc_used_math;
3332 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003333 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003334 uint64_t sc_mdhi;
3335 uint64_t sc_mdlo;
3336 target_ulong sc_hi1; /* Was sc_cause */
3337 target_ulong sc_lo1; /* Was sc_badvaddr */
3338 target_ulong sc_hi2; /* Was sc_sigset[4] */
3339 target_ulong sc_lo2;
3340 target_ulong sc_hi3;
3341 target_ulong sc_lo3;
3342};
Richard Hendersonff970902013-02-10 10:30:42 -08003343# else /* N32 || N64 */
3344struct target_sigcontext {
3345 uint64_t sc_regs[32];
3346 uint64_t sc_fpregs[32];
3347 uint64_t sc_mdhi;
3348 uint64_t sc_hi1;
3349 uint64_t sc_hi2;
3350 uint64_t sc_hi3;
3351 uint64_t sc_mdlo;
3352 uint64_t sc_lo1;
3353 uint64_t sc_lo2;
3354 uint64_t sc_lo3;
3355 uint64_t sc_pc;
3356 uint32_t sc_fpc_csr;
3357 uint32_t sc_used_math;
3358 uint32_t sc_dsp;
3359 uint32_t sc_reserved;
3360};
3361# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003362
3363struct sigframe {
3364 uint32_t sf_ass[4]; /* argument save space for o32 */
3365 uint32_t sf_code[2]; /* signal trampoline */
3366 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003367 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003368};
3369
pbrook0b1bcb02009-04-21 01:41:10 +00003370struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003371 target_ulong tuc_flags;
3372 target_ulong tuc_link;
3373 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003374 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003375 struct target_sigcontext tuc_mcontext;
3376 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003377};
3378
3379struct target_rt_sigframe {
3380 uint32_t rs_ass[4]; /* argument save space for o32 */
3381 uint32_t rs_code[2]; /* signal trampoline */
3382 struct target_siginfo rs_info;
3383 struct target_ucontext rs_uc;
3384};
3385
bellard106ec872006-06-27 21:08:10 +00003386/* Install trampoline to jump back from signal handler */
3387static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3388{
Richard Henderson084d0492013-02-10 10:30:44 -08003389 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003390
3391 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003392 * Set up the return code ...
3393 *
3394 * li v0, __NR__foo_sigreturn
3395 * syscall
3396 */
bellard106ec872006-06-27 21:08:10 +00003397
Riku Voipio1d8b5122014-04-23 10:26:05 +03003398 __put_user(0x24020000 + syscall, tramp + 0);
3399 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003400 return err;
3401}
3402
Riku Voipio41ecc722014-04-23 11:01:00 +03003403static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003404 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003405{
Richard Henderson084d0492013-02-10 10:30:44 -08003406 int i;
bellard106ec872006-06-27 21:08:10 +00003407
Riku Voipio1d8b5122014-04-23 10:26:05 +03003408 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003409 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003410
Richard Henderson084d0492013-02-10 10:30:44 -08003411 __put_user(0, &sc->sc_regs[0]);
3412 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003413 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003414 }
bellard106ec872006-06-27 21:08:10 +00003415
Riku Voipio1d8b5122014-04-23 10:26:05 +03003416 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3417 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003418
Richard Henderson084d0492013-02-10 10:30:44 -08003419 /* Rather than checking for dsp existence, always copy. The storage
3420 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003421 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3422 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3423 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3424 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3425 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3426 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003427 {
3428 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003429 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003430 }
Richard Henderson084d0492013-02-10 10:30:44 -08003431
Riku Voipio1d8b5122014-04-23 10:26:05 +03003432 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003433
3434 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003435 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003436 }
bellard106ec872006-06-27 21:08:10 +00003437}
3438
Riku Voipio016d2e12014-04-23 11:19:48 +03003439static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003440restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003441{
Richard Henderson084d0492013-02-10 10:30:44 -08003442 int i;
bellard106ec872006-06-27 21:08:10 +00003443
Riku Voipio1d8b5122014-04-23 10:26:05 +03003444 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003445
Riku Voipio1d8b5122014-04-23 10:26:05 +03003446 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3447 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003448
Richard Henderson084d0492013-02-10 10:30:44 -08003449 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003450 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003451 }
3452
Riku Voipio1d8b5122014-04-23 10:26:05 +03003453 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3454 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3455 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3456 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3457 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3458 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003459 {
3460 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003461 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003462 cpu_wrdsp(dsp, 0x3ff, regs);
3463 }
3464
3465 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003466 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003467 }
bellard106ec872006-06-27 21:08:10 +00003468}
Richard Hendersonff970902013-02-10 10:30:42 -08003469
bellard106ec872006-06-27 21:08:10 +00003470/*
3471 * Determine which stack to use..
3472 */
bellard579a97f2007-11-11 14:26:47 +00003473static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003474get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003475{
3476 unsigned long sp;
3477
3478 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003479 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003480
3481 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003482 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003483 * above the user stack, 16-bytes before the next lowest
3484 * 16 byte boundary. Try to avoid trashing it.
3485 */
3486 sp -= 32;
3487
bellard106ec872006-06-27 21:08:10 +00003488 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003489 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003490 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3491 }
bellard106ec872006-06-27 21:08:10 +00003492
bellard579a97f2007-11-11 14:26:47 +00003493 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003494}
3495
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003496static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3497{
3498 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3499 env->hflags &= ~MIPS_HFLAG_M16;
3500 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3501 env->active_tc.PC &= ~(target_ulong) 1;
3502 }
3503}
3504
Richard Hendersonff970902013-02-10 10:30:42 -08003505# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003506/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003507static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003508 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003509{
3510 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003511 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003512 int i;
3513
bellard579a97f2007-11-11 14:26:47 +00003514 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003515 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003516 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3517 goto give_sigsegv;
3518 }
bellard106ec872006-06-27 21:08:10 +00003519
3520 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3521
Riku Voipio41ecc722014-04-23 11:01:00 +03003522 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003523
3524 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003525 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003526 }
3527
3528 /*
3529 * Arguments to signal handler:
3530 *
3531 * a0 = signal number
3532 * a1 = 0 (should be cause)
3533 * a2 = pointer to struct sigcontext
3534 *
3535 * $25 and PC point to the signal handler, $29 points to the
3536 * struct sigframe.
3537 */
thsb5dc7732008-06-27 10:02:35 +00003538 regs->active_tc.gpr[ 4] = sig;
3539 regs->active_tc.gpr[ 5] = 0;
3540 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3541 regs->active_tc.gpr[29] = frame_addr;
3542 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003543 /* The original kernel code sets CP0_EPC to the handler
3544 * since it returns to userland using eret
3545 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003546 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003547 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003548 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003549 return;
3550
3551give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003552 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003553}
3554
Andreas Färber05390242012-02-25 03:37:53 +01003555long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003556{
ths388bb212007-05-13 13:58:00 +00003557 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003558 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003559 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003560 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003561 int i;
bellard106ec872006-06-27 21:08:10 +00003562
thsb5dc7732008-06-27 10:02:35 +00003563 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003564 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003565 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003566 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003567
ths388bb212007-05-13 13:58:00 +00003568 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003569 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003570 }
bellard106ec872006-06-27 21:08:10 +00003571
ths388bb212007-05-13 13:58:00 +00003572 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003573 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003574
Riku Voipio016d2e12014-04-23 11:19:48 +03003575 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003576
3577#if 0
ths388bb212007-05-13 13:58:00 +00003578 /*
3579 * Don't let your children do this ...
3580 */
3581 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003582 "move\t$29, %0\n\t"
3583 "j\tsyscall_exit"
3584 :/* no outputs */
3585 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003586 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003587#endif
ths3b46e622007-09-17 08:09:54 +00003588
thsb5dc7732008-06-27 10:02:35 +00003589 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003590 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003591 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003592 * maybe a problem with nested signals ? */
3593 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003594 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003595
3596badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003597 force_sig(TARGET_SIGSEGV);
3598 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003599}
Richard Hendersonff970902013-02-10 10:30:42 -08003600# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003601
pbrook624f7972008-05-31 16:11:38 +00003602static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003603 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003604 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003605{
pbrook0b1bcb02009-04-21 01:41:10 +00003606 struct target_rt_sigframe *frame;
3607 abi_ulong frame_addr;
3608 int i;
3609
3610 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003611 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003612 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3613 goto give_sigsegv;
3614 }
pbrook0b1bcb02009-04-21 01:41:10 +00003615
3616 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3617
Peter Maydellf6c7a052015-01-08 12:19:48 +00003618 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003619
Aurelien Jarno60e99242010-03-29 02:12:51 +02003620 __put_user(0, &frame->rs_uc.tuc_flags);
3621 __put_user(0, &frame->rs_uc.tuc_link);
3622 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3623 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003624 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003625 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003626
Aurelien Jarno60e99242010-03-29 02:12:51 +02003627 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003628
3629 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003630 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003631 }
3632
3633 /*
3634 * Arguments to signal handler:
3635 *
3636 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003637 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003638 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003639 *
3640 * $25 and PC point to the signal handler, $29 points to the
3641 * struct sigframe.
3642 */
3643 env->active_tc.gpr[ 4] = sig;
3644 env->active_tc.gpr[ 5] = frame_addr
3645 + offsetof(struct target_rt_sigframe, rs_info);
3646 env->active_tc.gpr[ 6] = frame_addr
3647 + offsetof(struct target_rt_sigframe, rs_uc);
3648 env->active_tc.gpr[29] = frame_addr;
3649 env->active_tc.gpr[31] = frame_addr
3650 + offsetof(struct target_rt_sigframe, rs_code);
3651 /* The original kernel code sets CP0_EPC to the handler
3652 * since it returns to userland using eret
3653 * we cannot do this here, and we must set PC directly */
3654 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003655 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003656 unlock_user_struct(frame, frame_addr, 1);
3657 return;
3658
3659give_sigsegv:
3660 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003661 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003662}
3663
Andreas Färber05390242012-02-25 03:37:53 +01003664long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003665{
pbrook0b1bcb02009-04-21 01:41:10 +00003666 struct target_rt_sigframe *frame;
3667 abi_ulong frame_addr;
3668 sigset_t blocked;
3669
pbrook0b1bcb02009-04-21 01:41:10 +00003670 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003671 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003672 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3673 goto badframe;
3674 }
pbrook0b1bcb02009-04-21 01:41:10 +00003675
Aurelien Jarno60e99242010-03-29 02:12:51 +02003676 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003677 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003678
Riku Voipio016d2e12014-04-23 11:19:48 +03003679 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003680
3681 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003682 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3683 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003684 goto badframe;
3685
3686 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003687 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003688 /* I am not sure this is right, but it seems to work
3689 * maybe a problem with nested signals ? */
3690 env->CP0_EPC = 0;
3691 return -TARGET_QEMU_ESIGRETURN;
3692
3693badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003694 force_sig(TARGET_SIGSEGV);
3695 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003696}
bellard6d5e2162004-09-30 22:04:13 +00003697
thsc3b5bc82007-12-02 06:31:25 +00003698#elif defined(TARGET_SH4)
3699
3700/*
3701 * code and data structures from linux kernel:
3702 * include/asm-sh/sigcontext.h
3703 * arch/sh/kernel/signal.c
3704 */
3705
3706struct target_sigcontext {
3707 target_ulong oldmask;
3708
3709 /* CPU registers */
3710 target_ulong sc_gregs[16];
3711 target_ulong sc_pc;
3712 target_ulong sc_pr;
3713 target_ulong sc_sr;
3714 target_ulong sc_gbr;
3715 target_ulong sc_mach;
3716 target_ulong sc_macl;
3717
3718 /* FPU registers */
3719 target_ulong sc_fpregs[16];
3720 target_ulong sc_xfpregs[16];
3721 unsigned int sc_fpscr;
3722 unsigned int sc_fpul;
3723 unsigned int sc_ownedfp;
3724};
3725
3726struct target_sigframe
3727{
3728 struct target_sigcontext sc;
3729 target_ulong extramask[TARGET_NSIG_WORDS-1];
3730 uint16_t retcode[3];
3731};
3732
3733
3734struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003735 target_ulong tuc_flags;
3736 struct target_ucontext *tuc_link;
3737 target_stack_t tuc_stack;
3738 struct target_sigcontext tuc_mcontext;
3739 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003740};
3741
3742struct target_rt_sigframe
3743{
3744 struct target_siginfo info;
3745 struct target_ucontext uc;
3746 uint16_t retcode[3];
3747};
3748
3749
3750#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3751#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3752
pbrook624f7972008-05-31 16:11:38 +00003753static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003754 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003755{
pbrook624f7972008-05-31 16:11:38 +00003756 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003757 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3758 }
3759
3760 return (sp - frame_size) & -8ul;
3761}
3762
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003763/* Notice when we're in the middle of a gUSA region and reset.
3764 Note that this will only occur for !parallel_cpus, as we will
3765 translate such sequences differently in a parallel context. */
3766static void unwind_gusa(CPUSH4State *regs)
3767{
3768 /* If the stack pointer is sufficiently negative, and we haven't
3769 completed the sequence, then reset to the entry to the region. */
3770 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3771 However, the page mappings in qemu linux-user aren't as restricted
3772 and we wind up with the normal stack mapped above 0xF0000000.
3773 That said, there is no reason why the kernel should be allowing
3774 a gUSA region that spans 1GB. Use a tighter check here, for what
3775 can actually be enabled by the immediate move. */
3776 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3777 /* Reset the PC to before the gUSA region, as computed from
3778 R0 = region end, SP = -(region size), plus one more for the
3779 insn that actually initializes SP to the region size. */
3780 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3781
3782 /* Reset the SP to the saved version in R1. */
3783 regs->gregs[15] = regs->gregs[1];
3784 }
3785}
3786
Riku Voipio41ecc722014-04-23 11:01:00 +03003787static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003788 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003789{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003790 int i;
thsc3b5bc82007-12-02 06:31:25 +00003791
Riku Voipio1d8b5122014-04-23 10:26:05 +03003792#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003793 COPY(gregs[0]); COPY(gregs[1]);
3794 COPY(gregs[2]); COPY(gregs[3]);
3795 COPY(gregs[4]); COPY(gregs[5]);
3796 COPY(gregs[6]); COPY(gregs[7]);
3797 COPY(gregs[8]); COPY(gregs[9]);
3798 COPY(gregs[10]); COPY(gregs[11]);
3799 COPY(gregs[12]); COPY(gregs[13]);
3800 COPY(gregs[14]); COPY(gregs[15]);
3801 COPY(gbr); COPY(mach);
3802 COPY(macl); COPY(pr);
3803 COPY(sr); COPY(pc);
3804#undef COPY
3805
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003806 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003807 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003808 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003809 __put_user(regs->fpscr, &sc->sc_fpscr);
3810 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003811
3812 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003813 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003814}
3815
Timothy E Baldwinba412492016-05-12 18:47:35 +01003816static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003817{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003818 int i;
thsc3b5bc82007-12-02 06:31:25 +00003819
Riku Voipio1d8b5122014-04-23 10:26:05 +03003820#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003821 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003822 COPY(gregs[2]); COPY(gregs[3]);
3823 COPY(gregs[4]); COPY(gregs[5]);
3824 COPY(gregs[6]); COPY(gregs[7]);
3825 COPY(gregs[8]); COPY(gregs[9]);
3826 COPY(gregs[10]); COPY(gregs[11]);
3827 COPY(gregs[12]); COPY(gregs[13]);
3828 COPY(gregs[14]); COPY(gregs[15]);
3829 COPY(gbr); COPY(mach);
3830 COPY(macl); COPY(pr);
3831 COPY(sr); COPY(pc);
3832#undef COPY
3833
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003834 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003835 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003836 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003837 __get_user(regs->fpscr, &sc->sc_fpscr);
3838 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003839
3840 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003841 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003842}
3843
pbrook624f7972008-05-31 16:11:38 +00003844static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003845 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003846{
3847 struct target_sigframe *frame;
3848 abi_ulong frame_addr;
3849 int i;
thsc3b5bc82007-12-02 06:31:25 +00003850
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003851 unwind_gusa(regs);
3852
thsc3b5bc82007-12-02 06:31:25 +00003853 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003854 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003855 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3856 goto give_sigsegv;
3857 }
thsc3b5bc82007-12-02 06:31:25 +00003858
Riku Voipio41ecc722014-04-23 11:01:00 +03003859 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003860
3861 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003862 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003863 }
3864
3865 /* Set up to return from userspace. If provided, use a stub
3866 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003867 if (ka->sa_flags & TARGET_SA_RESTORER) {
3868 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003869 } else {
3870 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003871 abi_ulong retcode_addr = frame_addr +
3872 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003873 __put_user(MOVW(2), &frame->retcode[0]);
3874 __put_user(TRAP_NOARG, &frame->retcode[1]);
3875 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003876 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003877 }
3878
thsc3b5bc82007-12-02 06:31:25 +00003879 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003880 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003881 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003882 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003883 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003884 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003885 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003886
3887 unlock_user_struct(frame, frame_addr, 1);
3888 return;
3889
3890give_sigsegv:
3891 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003892 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003893}
3894
pbrook624f7972008-05-31 16:11:38 +00003895static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003896 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003897 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003898{
3899 struct target_rt_sigframe *frame;
3900 abi_ulong frame_addr;
3901 int i;
thsc3b5bc82007-12-02 06:31:25 +00003902
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003903 unwind_gusa(regs);
3904
thsc3b5bc82007-12-02 06:31:25 +00003905 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003906 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003907 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3908 goto give_sigsegv;
3909 }
thsc3b5bc82007-12-02 06:31:25 +00003910
Peter Maydellf6c7a052015-01-08 12:19:48 +00003911 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003912
3913 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003914 __put_user(0, &frame->uc.tuc_flags);
3915 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3916 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3917 &frame->uc.tuc_stack.ss_sp);
3918 __put_user(sas_ss_flags(regs->gregs[15]),
3919 &frame->uc.tuc_stack.ss_flags);
3920 __put_user(target_sigaltstack_used.ss_size,
3921 &frame->uc.tuc_stack.ss_size);
3922 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003923 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003924 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003925 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003926 }
3927
3928 /* Set up to return from userspace. If provided, use a stub
3929 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003930 if (ka->sa_flags & TARGET_SA_RESTORER) {
3931 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003932 } else {
3933 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003934 abi_ulong retcode_addr = frame_addr +
3935 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003936 __put_user(MOVW(2), &frame->retcode[0]);
3937 __put_user(TRAP_NOARG, &frame->retcode[1]);
3938 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003939 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003940 }
3941
thsc3b5bc82007-12-02 06:31:25 +00003942 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003943 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003944 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003945 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3946 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003947 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003948 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003949
3950 unlock_user_struct(frame, frame_addr, 1);
3951 return;
3952
3953give_sigsegv:
3954 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003955 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003956}
3957
Andreas Färber05390242012-02-25 03:37:53 +01003958long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003959{
3960 struct target_sigframe *frame;
3961 abi_ulong frame_addr;
3962 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003963 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003964 int i;
3965 int err = 0;
3966
thsc3b5bc82007-12-02 06:31:25 +00003967 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003968 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003969 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3970 goto badframe;
3971 }
thsc3b5bc82007-12-02 06:31:25 +00003972
Riku Voipio1d8b5122014-04-23 10:26:05 +03003973 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003974 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003975 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003976 }
3977
3978 if (err)
3979 goto badframe;
3980
3981 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003982 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003983
Timothy E Baldwinba412492016-05-12 18:47:35 +01003984 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003985
3986 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003987 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003988
3989badframe:
3990 unlock_user_struct(frame, frame_addr, 0);
3991 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003992 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003993}
3994
Andreas Färber05390242012-02-25 03:37:53 +01003995long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003996{
3997 struct target_rt_sigframe *frame;
3998 abi_ulong frame_addr;
3999 sigset_t blocked;
4000
thsc3b5bc82007-12-02 06:31:25 +00004001 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004002 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004003 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4004 goto badframe;
4005 }
thsc3b5bc82007-12-02 06:31:25 +00004006
Aurelien Jarno60e99242010-03-29 02:12:51 +02004007 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004008 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00004009
Timothy E Baldwinba412492016-05-12 18:47:35 +01004010 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00004011
4012 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004013 offsetof(struct target_rt_sigframe, uc.tuc_stack),
4014 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00004015 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004016 }
thsc3b5bc82007-12-02 06:31:25 +00004017
4018 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01004019 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004020
4021badframe:
4022 unlock_user_struct(frame, frame_addr, 0);
4023 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004024 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004025}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004026#elif defined(TARGET_MICROBLAZE)
4027
4028struct target_sigcontext {
4029 struct target_pt_regs regs; /* needs to be first */
4030 uint32_t oldmask;
4031};
4032
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004033struct target_stack_t {
4034 abi_ulong ss_sp;
4035 int ss_flags;
4036 unsigned int ss_size;
4037};
4038
4039struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08004040 abi_ulong tuc_flags;
4041 abi_ulong tuc_link;
4042 struct target_stack_t tuc_stack;
4043 struct target_sigcontext tuc_mcontext;
4044 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004045};
4046
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004047/* Signal frames. */
4048struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004049 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004050 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4051 uint32_t tramp[2];
4052};
4053
4054struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00004055 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004056 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004057 uint32_t tramp[2];
4058};
4059
Andreas Färber05390242012-02-25 03:37:53 +01004060static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004061{
4062 __put_user(env->regs[0], &sc->regs.r0);
4063 __put_user(env->regs[1], &sc->regs.r1);
4064 __put_user(env->regs[2], &sc->regs.r2);
4065 __put_user(env->regs[3], &sc->regs.r3);
4066 __put_user(env->regs[4], &sc->regs.r4);
4067 __put_user(env->regs[5], &sc->regs.r5);
4068 __put_user(env->regs[6], &sc->regs.r6);
4069 __put_user(env->regs[7], &sc->regs.r7);
4070 __put_user(env->regs[8], &sc->regs.r8);
4071 __put_user(env->regs[9], &sc->regs.r9);
4072 __put_user(env->regs[10], &sc->regs.r10);
4073 __put_user(env->regs[11], &sc->regs.r11);
4074 __put_user(env->regs[12], &sc->regs.r12);
4075 __put_user(env->regs[13], &sc->regs.r13);
4076 __put_user(env->regs[14], &sc->regs.r14);
4077 __put_user(env->regs[15], &sc->regs.r15);
4078 __put_user(env->regs[16], &sc->regs.r16);
4079 __put_user(env->regs[17], &sc->regs.r17);
4080 __put_user(env->regs[18], &sc->regs.r18);
4081 __put_user(env->regs[19], &sc->regs.r19);
4082 __put_user(env->regs[20], &sc->regs.r20);
4083 __put_user(env->regs[21], &sc->regs.r21);
4084 __put_user(env->regs[22], &sc->regs.r22);
4085 __put_user(env->regs[23], &sc->regs.r23);
4086 __put_user(env->regs[24], &sc->regs.r24);
4087 __put_user(env->regs[25], &sc->regs.r25);
4088 __put_user(env->regs[26], &sc->regs.r26);
4089 __put_user(env->regs[27], &sc->regs.r27);
4090 __put_user(env->regs[28], &sc->regs.r28);
4091 __put_user(env->regs[29], &sc->regs.r29);
4092 __put_user(env->regs[30], &sc->regs.r30);
4093 __put_user(env->regs[31], &sc->regs.r31);
4094 __put_user(env->sregs[SR_PC], &sc->regs.pc);
4095}
4096
Andreas Färber05390242012-02-25 03:37:53 +01004097static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004098{
4099 __get_user(env->regs[0], &sc->regs.r0);
4100 __get_user(env->regs[1], &sc->regs.r1);
4101 __get_user(env->regs[2], &sc->regs.r2);
4102 __get_user(env->regs[3], &sc->regs.r3);
4103 __get_user(env->regs[4], &sc->regs.r4);
4104 __get_user(env->regs[5], &sc->regs.r5);
4105 __get_user(env->regs[6], &sc->regs.r6);
4106 __get_user(env->regs[7], &sc->regs.r7);
4107 __get_user(env->regs[8], &sc->regs.r8);
4108 __get_user(env->regs[9], &sc->regs.r9);
4109 __get_user(env->regs[10], &sc->regs.r10);
4110 __get_user(env->regs[11], &sc->regs.r11);
4111 __get_user(env->regs[12], &sc->regs.r12);
4112 __get_user(env->regs[13], &sc->regs.r13);
4113 __get_user(env->regs[14], &sc->regs.r14);
4114 __get_user(env->regs[15], &sc->regs.r15);
4115 __get_user(env->regs[16], &sc->regs.r16);
4116 __get_user(env->regs[17], &sc->regs.r17);
4117 __get_user(env->regs[18], &sc->regs.r18);
4118 __get_user(env->regs[19], &sc->regs.r19);
4119 __get_user(env->regs[20], &sc->regs.r20);
4120 __get_user(env->regs[21], &sc->regs.r21);
4121 __get_user(env->regs[22], &sc->regs.r22);
4122 __get_user(env->regs[23], &sc->regs.r23);
4123 __get_user(env->regs[24], &sc->regs.r24);
4124 __get_user(env->regs[25], &sc->regs.r25);
4125 __get_user(env->regs[26], &sc->regs.r26);
4126 __get_user(env->regs[27], &sc->regs.r27);
4127 __get_user(env->regs[28], &sc->regs.r28);
4128 __get_user(env->regs[29], &sc->regs.r29);
4129 __get_user(env->regs[30], &sc->regs.r30);
4130 __get_user(env->regs[31], &sc->regs.r31);
4131 __get_user(env->sregs[SR_PC], &sc->regs.pc);
4132}
4133
4134static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004135 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004136{
4137 abi_ulong sp = env->regs[1];
4138
Riku Voipiob545f632014-07-15 17:01:55 +03004139 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004140 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03004141 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004142
4143 return ((sp - frame_size) & -8UL);
4144}
4145
4146static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004147 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004148{
4149 struct target_signal_frame *frame;
4150 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004151 int i;
4152
4153 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004154 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004155 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4156 goto badframe;
4157
4158 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004159 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004160
4161 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03004162 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004163 }
4164
Richard Hendersonf711df62010-11-22 14:57:52 -08004165 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004166
4167 /* Set up to return from userspace. If provided, use a stub
4168 already in userspace. */
4169 /* minus 8 is offset to cater for "rtsd r15,8" offset */
4170 if (ka->sa_flags & TARGET_SA_RESTORER) {
4171 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
4172 } else {
4173 uint32_t t;
4174 /* Note, these encodings are _big endian_! */
4175 /* addi r12, r0, __NR_sigreturn */
4176 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004177 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004178 /* brki r14, 0x8 */
4179 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004180 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004181
4182 /* Return from sighandler will jump to the tramp.
4183 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004184 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4185 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004186 }
4187
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004188 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004189 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004190 /* Signal handler args: */
4191 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004192 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004193 /* arg 1: sigcontext */
4194 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004195
4196 /* Offset of 4 to handle microblaze rtid r14, 0 */
4197 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4198
4199 unlock_user_struct(frame, frame_addr, 1);
4200 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004201badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004202 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004203}
4204
4205static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004206 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004207 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004208{
4209 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4210}
4211
Andreas Färber05390242012-02-25 03:37:53 +01004212long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004213{
4214 struct target_signal_frame *frame;
4215 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004216 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004217 sigset_t set;
4218 int i;
4219
4220 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004221 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004222 /* Make sure the guest isn't playing games. */
4223 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4224 goto badframe;
4225
4226 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004227 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004228 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004229 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004230 }
4231 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004232 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004233
Richard Hendersonf711df62010-11-22 14:57:52 -08004234 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004235 /* We got here through a sigreturn syscall, our path back is via an
4236 rtb insn so setup r14 for that. */
4237 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004238
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004239 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004240 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004241badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004242 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004243 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004244}
4245
Andreas Färber05390242012-02-25 03:37:53 +01004246long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004247{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004248 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004249 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4250 return -TARGET_ENOSYS;
4251}
4252
edgar_iglb6d3abd2008-02-28 11:29:27 +00004253#elif defined(TARGET_CRIS)
4254
4255struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004256 struct target_pt_regs regs; /* needs to be first */
4257 uint32_t oldmask;
4258 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004259};
4260
4261/* Signal frames. */
4262struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004263 struct target_sigcontext sc;
4264 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4265 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004266};
4267
4268struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004269 siginfo_t *pinfo;
4270 void *puc;
4271 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004272 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004273 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004274};
4275
Andreas Färber05390242012-02-25 03:37:53 +01004276static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004277{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004278 __put_user(env->regs[0], &sc->regs.r0);
4279 __put_user(env->regs[1], &sc->regs.r1);
4280 __put_user(env->regs[2], &sc->regs.r2);
4281 __put_user(env->regs[3], &sc->regs.r3);
4282 __put_user(env->regs[4], &sc->regs.r4);
4283 __put_user(env->regs[5], &sc->regs.r5);
4284 __put_user(env->regs[6], &sc->regs.r6);
4285 __put_user(env->regs[7], &sc->regs.r7);
4286 __put_user(env->regs[8], &sc->regs.r8);
4287 __put_user(env->regs[9], &sc->regs.r9);
4288 __put_user(env->regs[10], &sc->regs.r10);
4289 __put_user(env->regs[11], &sc->regs.r11);
4290 __put_user(env->regs[12], &sc->regs.r12);
4291 __put_user(env->regs[13], &sc->regs.r13);
4292 __put_user(env->regs[14], &sc->usp);
4293 __put_user(env->regs[15], &sc->regs.acr);
4294 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4295 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4296 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004297}
edgar_igl9664d922008-03-03 22:23:53 +00004298
Andreas Färber05390242012-02-25 03:37:53 +01004299static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004300{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004301 __get_user(env->regs[0], &sc->regs.r0);
4302 __get_user(env->regs[1], &sc->regs.r1);
4303 __get_user(env->regs[2], &sc->regs.r2);
4304 __get_user(env->regs[3], &sc->regs.r3);
4305 __get_user(env->regs[4], &sc->regs.r4);
4306 __get_user(env->regs[5], &sc->regs.r5);
4307 __get_user(env->regs[6], &sc->regs.r6);
4308 __get_user(env->regs[7], &sc->regs.r7);
4309 __get_user(env->regs[8], &sc->regs.r8);
4310 __get_user(env->regs[9], &sc->regs.r9);
4311 __get_user(env->regs[10], &sc->regs.r10);
4312 __get_user(env->regs[11], &sc->regs.r11);
4313 __get_user(env->regs[12], &sc->regs.r12);
4314 __get_user(env->regs[13], &sc->regs.r13);
4315 __get_user(env->regs[14], &sc->usp);
4316 __get_user(env->regs[15], &sc->regs.acr);
4317 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4318 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4319 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004320}
4321
Andreas Färber05390242012-02-25 03:37:53 +01004322static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004323{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004324 abi_ulong sp;
4325 /* Align the stack downwards to 4. */
4326 sp = (env->regs[R_SP] & ~3);
4327 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004328}
4329
pbrook624f7972008-05-31 16:11:38 +00004330static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004331 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004332{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004333 struct target_signal_frame *frame;
4334 abi_ulong frame_addr;
4335 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004336
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004337 frame_addr = get_sigframe(env, sizeof *frame);
4338 trace_user_setup_frame(env, frame_addr);
4339 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4340 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004341
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004342 /*
4343 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4344 * use this trampoline anymore but it sets it up for GDB.
4345 * In QEMU, using the trampoline simplifies things a bit so we use it.
4346 *
4347 * This is movu.w __NR_sigreturn, r9; break 13;
4348 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004349 __put_user(0x9c5f, frame->retcode+0);
4350 __put_user(TARGET_NR_sigreturn,
4351 frame->retcode + 1);
4352 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004353
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004354 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004355 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004356
Riku Voipio0188fad2014-04-23 13:34:15 +03004357 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4358 __put_user(set->sig[i], &frame->extramask[i - 1]);
4359 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004360
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004361 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004362
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004363 /* Move the stack and setup the arguments for the handler. */
4364 env->regs[R_SP] = frame_addr;
4365 env->regs[10] = sig;
4366 env->pc = (unsigned long) ka->_sa_handler;
4367 /* Link SRP so the guest returns through the trampoline. */
4368 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004369
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004370 unlock_user_struct(frame, frame_addr, 1);
4371 return;
4372badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004373 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004374}
4375
pbrook624f7972008-05-31 16:11:38 +00004376static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004377 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004378 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004379{
4380 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4381}
4382
Andreas Färber05390242012-02-25 03:37:53 +01004383long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004384{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004385 struct target_signal_frame *frame;
4386 abi_ulong frame_addr;
4387 target_sigset_t target_set;
4388 sigset_t set;
4389 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004390
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004391 frame_addr = env->regs[R_SP];
4392 trace_user_do_sigreturn(env, frame_addr);
4393 /* Make sure the guest isn't playing games. */
4394 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4395 goto badframe;
4396 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004397
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004398 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004399 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004400 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004401 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004402 }
4403 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004404 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004405
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004406 restore_sigcontext(&frame->sc, env);
4407 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004408 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004409badframe:
4410 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004411 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004412}
4413
Andreas Färber05390242012-02-25 03:37:53 +01004414long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004415{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004416 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004417 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4418 return -TARGET_ENOSYS;
4419}
thsc3b5bc82007-12-02 06:31:25 +00004420
Marek Vasuta0a839b2017-01-18 23:01:42 +01004421#elif defined(TARGET_NIOS2)
4422
4423#define MCONTEXT_VERSION 2
4424
4425struct target_sigcontext {
4426 int version;
4427 unsigned long gregs[32];
4428};
4429
4430struct target_ucontext {
4431 abi_ulong tuc_flags;
4432 abi_ulong tuc_link;
4433 target_stack_t tuc_stack;
4434 struct target_sigcontext tuc_mcontext;
4435 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4436};
4437
4438struct target_rt_sigframe {
4439 struct target_siginfo info;
4440 struct target_ucontext uc;
4441};
4442
4443static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4444{
4445 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4446#ifdef CONFIG_STACK_GROWSUP
4447 return target_sigaltstack_used.ss_sp;
4448#else
4449 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4450#endif
4451 }
4452 return sp;
4453}
4454
4455static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4456{
4457 unsigned long *gregs = uc->tuc_mcontext.gregs;
4458
4459 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4460 __put_user(env->regs[1], &gregs[0]);
4461 __put_user(env->regs[2], &gregs[1]);
4462 __put_user(env->regs[3], &gregs[2]);
4463 __put_user(env->regs[4], &gregs[3]);
4464 __put_user(env->regs[5], &gregs[4]);
4465 __put_user(env->regs[6], &gregs[5]);
4466 __put_user(env->regs[7], &gregs[6]);
4467 __put_user(env->regs[8], &gregs[7]);
4468 __put_user(env->regs[9], &gregs[8]);
4469 __put_user(env->regs[10], &gregs[9]);
4470 __put_user(env->regs[11], &gregs[10]);
4471 __put_user(env->regs[12], &gregs[11]);
4472 __put_user(env->regs[13], &gregs[12]);
4473 __put_user(env->regs[14], &gregs[13]);
4474 __put_user(env->regs[15], &gregs[14]);
4475 __put_user(env->regs[16], &gregs[15]);
4476 __put_user(env->regs[17], &gregs[16]);
4477 __put_user(env->regs[18], &gregs[17]);
4478 __put_user(env->regs[19], &gregs[18]);
4479 __put_user(env->regs[20], &gregs[19]);
4480 __put_user(env->regs[21], &gregs[20]);
4481 __put_user(env->regs[22], &gregs[21]);
4482 __put_user(env->regs[23], &gregs[22]);
4483 __put_user(env->regs[R_RA], &gregs[23]);
4484 __put_user(env->regs[R_FP], &gregs[24]);
4485 __put_user(env->regs[R_GP], &gregs[25]);
4486 __put_user(env->regs[R_EA], &gregs[27]);
4487 __put_user(env->regs[R_SP], &gregs[28]);
4488
4489 return 0;
4490}
4491
4492static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4493 int *pr2)
4494{
4495 int temp;
4496 abi_ulong off, frame_addr = env->regs[R_SP];
4497 unsigned long *gregs = uc->tuc_mcontext.gregs;
4498 int err;
4499
4500 /* Always make any pending restarted system calls return -EINTR */
4501 /* current->restart_block.fn = do_no_restart_syscall; */
4502
4503 __get_user(temp, &uc->tuc_mcontext.version);
4504 if (temp != MCONTEXT_VERSION) {
4505 return 1;
4506 }
4507
4508 /* restore passed registers */
4509 __get_user(env->regs[1], &gregs[0]);
4510 __get_user(env->regs[2], &gregs[1]);
4511 __get_user(env->regs[3], &gregs[2]);
4512 __get_user(env->regs[4], &gregs[3]);
4513 __get_user(env->regs[5], &gregs[4]);
4514 __get_user(env->regs[6], &gregs[5]);
4515 __get_user(env->regs[7], &gregs[6]);
4516 __get_user(env->regs[8], &gregs[7]);
4517 __get_user(env->regs[9], &gregs[8]);
4518 __get_user(env->regs[10], &gregs[9]);
4519 __get_user(env->regs[11], &gregs[10]);
4520 __get_user(env->regs[12], &gregs[11]);
4521 __get_user(env->regs[13], &gregs[12]);
4522 __get_user(env->regs[14], &gregs[13]);
4523 __get_user(env->regs[15], &gregs[14]);
4524 __get_user(env->regs[16], &gregs[15]);
4525 __get_user(env->regs[17], &gregs[16]);
4526 __get_user(env->regs[18], &gregs[17]);
4527 __get_user(env->regs[19], &gregs[18]);
4528 __get_user(env->regs[20], &gregs[19]);
4529 __get_user(env->regs[21], &gregs[20]);
4530 __get_user(env->regs[22], &gregs[21]);
4531 __get_user(env->regs[23], &gregs[22]);
4532 /* gregs[23] is handled below */
4533 /* Verify, should this be settable */
4534 __get_user(env->regs[R_FP], &gregs[24]);
4535 /* Verify, should this be settable */
4536 __get_user(env->regs[R_GP], &gregs[25]);
4537 /* Not really necessary no user settable bits */
4538 __get_user(temp, &gregs[26]);
4539 __get_user(env->regs[R_EA], &gregs[27]);
4540
4541 __get_user(env->regs[R_RA], &gregs[23]);
4542 __get_user(env->regs[R_SP], &gregs[28]);
4543
4544 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4545 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4546 if (err == -EFAULT) {
4547 return 1;
4548 }
4549
4550 *pr2 = env->regs[2];
4551 return 0;
4552}
4553
4554static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4555 size_t frame_size)
4556{
4557 unsigned long usp;
4558
4559 /* Default to using normal stack. */
4560 usp = env->regs[R_SP];
4561
4562 /* This is the X/Open sanctioned signal stack switching. */
4563 usp = sigsp(usp, ka);
4564
4565 /* Verify, is it 32 or 64 bit aligned */
4566 return (void *)((usp - frame_size) & -8UL);
4567}
4568
4569static void setup_rt_frame(int sig, struct target_sigaction *ka,
4570 target_siginfo_t *info,
4571 target_sigset_t *set,
4572 CPUNios2State *env)
4573{
4574 struct target_rt_sigframe *frame;
4575 int i, err = 0;
4576
4577 frame = get_sigframe(ka, env, sizeof(*frame));
4578
4579 if (ka->sa_flags & SA_SIGINFO) {
4580 tswap_siginfo(&frame->info, info);
4581 }
4582
4583 /* Create the ucontext. */
4584 __put_user(0, &frame->uc.tuc_flags);
4585 __put_user(0, &frame->uc.tuc_link);
4586 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4587 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4588 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4589 err |= rt_setup_ucontext(&frame->uc, env);
4590 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4591 __put_user((abi_ulong)set->sig[i],
4592 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4593 }
4594
4595 if (err) {
4596 goto give_sigsegv;
4597 }
4598
4599 /* Set up to return from userspace; jump to fixed address sigreturn
4600 trampoline on kuser page. */
4601 env->regs[R_RA] = (unsigned long) (0x1044);
4602
4603 /* Set up registers for signal handler */
4604 env->regs[R_SP] = (unsigned long) frame;
4605 env->regs[4] = (unsigned long) sig;
4606 env->regs[5] = (unsigned long) &frame->info;
4607 env->regs[6] = (unsigned long) &frame->uc;
4608 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4609 return;
4610
4611give_sigsegv:
4612 if (sig == TARGET_SIGSEGV) {
4613 ka->_sa_handler = TARGET_SIG_DFL;
4614 }
4615 force_sigsegv(sig);
4616 return;
4617}
4618
4619long do_sigreturn(CPUNios2State *env)
4620{
4621 trace_user_do_sigreturn(env, 0);
4622 fprintf(stderr, "do_sigreturn: not implemented\n");
4623 return -TARGET_ENOSYS;
4624}
4625
4626long do_rt_sigreturn(CPUNios2State *env)
4627{
4628 /* Verify, can we follow the stack back */
4629 abi_ulong frame_addr = env->regs[R_SP];
4630 struct target_rt_sigframe *frame;
4631 sigset_t set;
4632 int rval;
4633
4634 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4635 goto badframe;
4636 }
4637
4638 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4639 do_sigprocmask(SIG_SETMASK, &set, NULL);
4640
4641 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4642 goto badframe;
4643 }
4644
4645 unlock_user_struct(frame, frame_addr, 0);
4646 return rval;
4647
4648badframe:
4649 unlock_user_struct(frame, frame_addr, 0);
4650 force_sig(TARGET_SIGSEGV);
4651 return 0;
4652}
4653/* TARGET_NIOS2 */
4654
Jia Liud9627832012-07-20 15:50:52 +08004655#elif defined(TARGET_OPENRISC)
4656
4657struct target_sigcontext {
4658 struct target_pt_regs regs;
4659 abi_ulong oldmask;
4660 abi_ulong usp;
4661};
4662
4663struct target_ucontext {
4664 abi_ulong tuc_flags;
4665 abi_ulong tuc_link;
4666 target_stack_t tuc_stack;
4667 struct target_sigcontext tuc_mcontext;
4668 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4669};
4670
4671struct target_rt_sigframe {
4672 abi_ulong pinfo;
4673 uint64_t puc;
4674 struct target_siginfo info;
4675 struct target_sigcontext sc;
4676 struct target_ucontext uc;
4677 unsigned char retcode[16]; /* trampoline code */
4678};
4679
4680/* This is the asm-generic/ucontext.h version */
4681#if 0
4682static int restore_sigcontext(CPUOpenRISCState *regs,
4683 struct target_sigcontext *sc)
4684{
4685 unsigned int err = 0;
4686 unsigned long old_usp;
4687
4688 /* Alwys make any pending restarted system call return -EINTR */
4689 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4690
4691 /* restore the regs from &sc->regs (same as sc, since regs is first)
4692 * (sc is already checked for VERIFY_READ since the sigframe was
4693 * checked in sys_sigreturn previously)
4694 */
4695
4696 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4697 goto badframe;
4698 }
4699
4700 /* make sure the U-flag is set so user-mode cannot fool us */
4701
4702 regs->sr &= ~SR_SM;
4703
4704 /* restore the old USP as it was before we stacked the sc etc.
4705 * (we cannot just pop the sigcontext since we aligned the sp and
4706 * stuff after pushing it)
4707 */
4708
Riku Voipio1d8b5122014-04-23 10:26:05 +03004709 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004710 phx_signal("old_usp 0x%lx", old_usp);
4711
4712 __PHX__ REALLY /* ??? */
4713 wrusp(old_usp);
4714 regs->gpr[1] = old_usp;
4715
4716 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4717 * after this completes, but we don't use that mechanism. maybe we can
4718 * use it now ?
4719 */
4720
4721 return err;
4722
4723badframe:
4724 return 1;
4725}
4726#endif
4727
4728/* Set up a signal frame. */
4729
Riku Voipio41ecc722014-04-23 11:01:00 +03004730static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004731 CPUOpenRISCState *regs,
4732 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004733{
Stafford Horned89e71e2017-04-06 06:44:56 +09004734 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004735
4736 /* copy the regs. they are first in sc so we can use sc directly */
4737
Riku Voipio1d8b5122014-04-23 10:26:05 +03004738 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004739
4740 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4741 the signal handler. The frametype will be restored to its previous
4742 value in restore_sigcontext. */
4743 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4744
4745 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004746 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004747 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004748}
4749
4750static inline unsigned long align_sigframe(unsigned long sp)
4751{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004752 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004753}
4754
4755static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4756 CPUOpenRISCState *regs,
4757 size_t frame_size)
4758{
Stafford Horned89e71e2017-04-06 06:44:56 +09004759 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004760 int onsigstack = on_sig_stack(sp);
4761
4762 /* redzone */
4763 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004764 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004765 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4766 }
4767
4768 sp = align_sigframe(sp - frame_size);
4769
4770 /*
4771 * If we are on the alternate signal stack and would overflow it, don't.
4772 * Return an always-bogus address instead so we will die with SIGSEGV.
4773 */
4774
4775 if (onsigstack && !likely(on_sig_stack(sp))) {
4776 return -1L;
4777 }
4778
4779 return sp;
4780}
4781
Jia Liud9627832012-07-20 15:50:52 +08004782static void setup_rt_frame(int sig, struct target_sigaction *ka,
4783 target_siginfo_t *info,
4784 target_sigset_t *set, CPUOpenRISCState *env)
4785{
4786 int err = 0;
4787 abi_ulong frame_addr;
4788 unsigned long return_ip;
4789 struct target_rt_sigframe *frame;
4790 abi_ulong info_addr, uc_addr;
4791
Jia Liud9627832012-07-20 15:50:52 +08004792 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004793 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004794 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4795 goto give_sigsegv;
4796 }
4797
4798 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004799 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004800 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004801 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004802
4803 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004804 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004805 }
4806
Khem Raj04b33e22017-06-28 13:44:52 -07004807 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004808 __put_user(0, &frame->uc.tuc_flags);
4809 __put_user(0, &frame->uc.tuc_link);
4810 __put_user(target_sigaltstack_used.ss_sp,
4811 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004812 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4813 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004814 __put_user(target_sigaltstack_used.ss_size,
4815 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004816 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004817
4818 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4819
Jia Liud9627832012-07-20 15:50:52 +08004820 /* trampoline - the desired return ip is the retcode itself */
4821 return_ip = (unsigned long)&frame->retcode;
4822 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004823 __put_user(0xa960, (short *)(frame->retcode + 0));
4824 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4825 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4826 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004827
4828 if (err) {
4829 goto give_sigsegv;
4830 }
4831
4832 /* TODO what is the current->exec_domain stuff and invmap ? */
4833
4834 /* Set up registers for signal handler */
4835 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004836 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4837 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4838 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4839 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004840
4841 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004842 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004843
4844 return;
4845
4846give_sigsegv:
4847 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004848 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004849}
4850
4851long do_sigreturn(CPUOpenRISCState *env)
4852{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004853 trace_user_do_sigreturn(env, 0);
4854 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004855 return -TARGET_ENOSYS;
4856}
4857
4858long do_rt_sigreturn(CPUOpenRISCState *env)
4859{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004860 trace_user_do_rt_sigreturn(env, 0);
4861 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004862 return -TARGET_ENOSYS;
4863}
4864/* TARGET_OPENRISC */
4865
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004866#elif defined(TARGET_S390X)
4867
4868#define __NUM_GPRS 16
4869#define __NUM_FPRS 16
4870#define __NUM_ACRS 16
4871
4872#define S390_SYSCALL_SIZE 2
4873#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4874
4875#define _SIGCONTEXT_NSIG 64
4876#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4877#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4878#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4879#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4880#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4881
4882typedef struct {
4883 target_psw_t psw;
4884 target_ulong gprs[__NUM_GPRS];
4885 unsigned int acrs[__NUM_ACRS];
4886} target_s390_regs_common;
4887
4888typedef struct {
4889 unsigned int fpc;
4890 double fprs[__NUM_FPRS];
4891} target_s390_fp_regs;
4892
4893typedef struct {
4894 target_s390_regs_common regs;
4895 target_s390_fp_regs fpregs;
4896} target_sigregs;
4897
4898struct target_sigcontext {
4899 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4900 target_sigregs *sregs;
4901};
4902
4903typedef struct {
4904 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4905 struct target_sigcontext sc;
4906 target_sigregs sregs;
4907 int signo;
4908 uint8_t retcode[S390_SYSCALL_SIZE];
4909} sigframe;
4910
4911struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004912 target_ulong tuc_flags;
4913 struct target_ucontext *tuc_link;
4914 target_stack_t tuc_stack;
4915 target_sigregs tuc_mcontext;
4916 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004917};
4918
4919typedef struct {
4920 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4921 uint8_t retcode[S390_SYSCALL_SIZE];
4922 struct target_siginfo info;
4923 struct target_ucontext uc;
4924} rt_sigframe;
4925
4926static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004927get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004928{
4929 abi_ulong sp;
4930
4931 /* Default to using normal stack */
4932 sp = env->regs[15];
4933
4934 /* This is the X/Open sanctioned signal stack switching. */
4935 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4936 if (!sas_ss_flags(sp)) {
4937 sp = target_sigaltstack_used.ss_sp +
4938 target_sigaltstack_used.ss_size;
4939 }
4940 }
4941
4942 /* This is the legacy signal stack switching. */
4943 else if (/* FIXME !user_mode(regs) */ 0 &&
4944 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4945 ka->sa_restorer) {
4946 sp = (abi_ulong) ka->sa_restorer;
4947 }
4948
4949 return (sp - frame_size) & -8ul;
4950}
4951
Andreas Färber05390242012-02-25 03:37:53 +01004952static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004953{
4954 int i;
4955 //save_access_regs(current->thread.acrs); FIXME
4956
4957 /* Copy a 'clean' PSW mask to the user to avoid leaking
4958 information about whether PER is currently on. */
4959 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4960 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4961 for (i = 0; i < 16; i++) {
4962 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4963 }
4964 for (i = 0; i < 16; i++) {
4965 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4966 }
4967 /*
4968 * We have to store the fp registers to current->thread.fp_regs
4969 * to merge them with the emulated registers.
4970 */
4971 //save_fp_regs(&current->thread.fp_regs); FIXME
4972 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004973 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004974 }
4975}
4976
4977static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004978 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004979{
4980 sigframe *frame;
4981 abi_ulong frame_addr;
4982
4983 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004984 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004985 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004986 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004987 }
4988
Riku Voipio0188fad2014-04-23 13:34:15 +03004989 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004990
4991 save_sigregs(env, &frame->sregs);
4992
4993 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4994 (abi_ulong *)&frame->sc.sregs);
4995
4996 /* Set up to return from userspace. If provided, use a stub
4997 already in userspace. */
4998 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004999 env->regs[14] = (unsigned long)
5000 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005001 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03005002 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
5003 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005004 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
5005 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005006 }
5007
5008 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005009 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005010
5011 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005012 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005013 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5014
5015 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005016 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005017
5018 /* We forgot to include these in the sigcontext.
5019 To avoid breaking binary compatibility, they are passed as args. */
5020 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
5021 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
5022
5023 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02005024 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005025 unlock_user_struct(frame, frame_addr, 1);
5026 return;
5027
5028give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005029 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005030}
5031
5032static void setup_rt_frame(int sig, struct target_sigaction *ka,
5033 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005034 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005035{
5036 int i;
5037 rt_sigframe *frame;
5038 abi_ulong frame_addr;
5039
5040 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005041 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005042 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5043 goto give_sigsegv;
5044 }
5045
Peter Maydellf6c7a052015-01-08 12:19:48 +00005046 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005047
5048 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005049 __put_user(0, &frame->uc.tuc_flags);
5050 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
5051 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005052 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005053 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005054 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5055 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005056 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
5057 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005058 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005059 }
5060
5061 /* Set up to return from userspace. If provided, use a stub
5062 already in userspace. */
5063 if (ka->sa_flags & TARGET_SA_RESTORER) {
5064 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
5065 } else {
5066 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03005067 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
5068 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005069 }
5070
5071 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005072 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005073
5074 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005075 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005076 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5077
5078 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005079 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
5080 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005081 return;
5082
5083give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005084 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005085}
5086
5087static int
Andreas Färber05390242012-02-25 03:37:53 +01005088restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005089{
5090 int err = 0;
5091 int i;
5092
5093 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005094 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005095 }
5096
Riku Voipio1d8b5122014-04-23 10:26:05 +03005097 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005098 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
5099 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005100 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005101 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
5102
5103 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005104 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005105 }
5106 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04005107 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005108 }
5109
5110 return err;
5111}
5112
Andreas Färber05390242012-02-25 03:37:53 +01005113long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005114{
5115 sigframe *frame;
5116 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005117 target_sigset_t target_set;
5118 sigset_t set;
5119
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005120 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005121 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5122 goto badframe;
5123 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03005124 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005125
5126 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005127 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005128
5129 if (restore_sigregs(env, &frame->sregs)) {
5130 goto badframe;
5131 }
5132
5133 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005134 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005135
5136badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005137 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005138 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005139}
5140
Andreas Färber05390242012-02-25 03:37:53 +01005141long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005142{
5143 rt_sigframe *frame;
5144 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005145 sigset_t set;
5146
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005147 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005148 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5149 goto badframe;
5150 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005151 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005152
Peter Maydell9eede5b2016-05-27 15:51:46 +01005153 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005154
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005155 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005156 goto badframe;
5157 }
5158
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005159 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005160 get_sp_from_cpustate(env)) == -EFAULT) {
5161 goto badframe;
5162 }
5163 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005164 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005165
5166badframe:
5167 unlock_user_struct(frame, frame_addr, 0);
5168 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005169 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005170}
5171
Tom Musta61e75fe2014-06-30 08:13:38 -05005172#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07005173
5174/* Size of dummy stack frame allocated when calling signal handler.
5175 See arch/powerpc/include/asm/ptrace.h. */
5176#if defined(TARGET_PPC64)
5177#define SIGNAL_FRAMESIZE 128
5178#else
5179#define SIGNAL_FRAMESIZE 64
5180#endif
5181
Tom Musta61e75fe2014-06-30 08:13:38 -05005182/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5183 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5184struct target_mcontext {
5185 target_ulong mc_gregs[48];
5186 /* Includes fpscr. */
5187 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005188#if defined(TARGET_PPC64)
5189 /* Pointer to the vector regs */
5190 target_ulong v_regs;
5191#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005192 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005193#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005194 /* We need to handle Altivec and SPE at the same time, which no
5195 kernel needs to do. Fortunately, the kernel defines this bit to
5196 be Altivec-register-large all the time, rather than trying to
5197 twiddle it based on the specific platform. */
5198 union {
5199 /* SPE vector registers. One extra for SPEFSCR. */
5200 uint32_t spe[33];
5201 /* Altivec vector registers. The packing of VSCR and VRSAVE
5202 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005203 them apart; PPC32 stuffs them together.
5204 We also need to account for the VSX registers on PPC64
5205 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005206#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005207#define QEMU_NVRREG (34 + 16)
5208 /* On ppc64, this mcontext structure is naturally *unaligned*,
5209 * or rather it is aligned on a 8 bytes boundary but not on
5210 * a 16 bytes one. This pad fixes it up. This is also why the
5211 * vector regs are referenced by the v_regs pointer above so
5212 * any amount of padding can be added here
5213 */
5214 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005215#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005216 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005217#define QEMU_NVRREG 33
5218#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005219 /* We cannot use ppc_avr_t here as we do *not* want the implied
5220 * 16-bytes alignment that would result from it. This would have
5221 * the effect of making the whole struct target_mcontext aligned
5222 * which breaks the layout of struct target_ucontext on ppc64.
5223 */
5224 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005225#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005226 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005227};
5228
Nathan Froydbcd49332009-05-12 19:13:18 -07005229/* See arch/powerpc/include/asm/sigcontext.h. */
5230struct target_sigcontext {
5231 target_ulong _unused[4];
5232 int32_t signal;
5233#if defined(TARGET_PPC64)
5234 int32_t pad0;
5235#endif
5236 target_ulong handler;
5237 target_ulong oldmask;
5238 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005239#if defined(TARGET_PPC64)
5240 struct target_mcontext mcontext;
5241#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005242};
5243
5244/* Indices for target_mcontext.mc_gregs, below.
5245 See arch/powerpc/include/asm/ptrace.h for details. */
5246enum {
5247 TARGET_PT_R0 = 0,
5248 TARGET_PT_R1 = 1,
5249 TARGET_PT_R2 = 2,
5250 TARGET_PT_R3 = 3,
5251 TARGET_PT_R4 = 4,
5252 TARGET_PT_R5 = 5,
5253 TARGET_PT_R6 = 6,
5254 TARGET_PT_R7 = 7,
5255 TARGET_PT_R8 = 8,
5256 TARGET_PT_R9 = 9,
5257 TARGET_PT_R10 = 10,
5258 TARGET_PT_R11 = 11,
5259 TARGET_PT_R12 = 12,
5260 TARGET_PT_R13 = 13,
5261 TARGET_PT_R14 = 14,
5262 TARGET_PT_R15 = 15,
5263 TARGET_PT_R16 = 16,
5264 TARGET_PT_R17 = 17,
5265 TARGET_PT_R18 = 18,
5266 TARGET_PT_R19 = 19,
5267 TARGET_PT_R20 = 20,
5268 TARGET_PT_R21 = 21,
5269 TARGET_PT_R22 = 22,
5270 TARGET_PT_R23 = 23,
5271 TARGET_PT_R24 = 24,
5272 TARGET_PT_R25 = 25,
5273 TARGET_PT_R26 = 26,
5274 TARGET_PT_R27 = 27,
5275 TARGET_PT_R28 = 28,
5276 TARGET_PT_R29 = 29,
5277 TARGET_PT_R30 = 30,
5278 TARGET_PT_R31 = 31,
5279 TARGET_PT_NIP = 32,
5280 TARGET_PT_MSR = 33,
5281 TARGET_PT_ORIG_R3 = 34,
5282 TARGET_PT_CTR = 35,
5283 TARGET_PT_LNK = 36,
5284 TARGET_PT_XER = 37,
5285 TARGET_PT_CCR = 38,
5286 /* Yes, there are two registers with #39. One is 64-bit only. */
5287 TARGET_PT_MQ = 39,
5288 TARGET_PT_SOFTE = 39,
5289 TARGET_PT_TRAP = 40,
5290 TARGET_PT_DAR = 41,
5291 TARGET_PT_DSISR = 42,
5292 TARGET_PT_RESULT = 43,
5293 TARGET_PT_REGS_COUNT = 44
5294};
5295
Nathan Froydbcd49332009-05-12 19:13:18 -07005296
5297struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005298 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005299 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005300 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005301#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005302 int32_t tuc_pad[7];
5303 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005304 points to uc_mcontext field */
5305#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005306 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005307#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005308 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005309 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005310#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005311 int32_t tuc_maskext[30];
5312 int32_t tuc_pad2[3];
5313 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005314#endif
5315};
5316
5317/* See arch/powerpc/kernel/signal_32.c. */
5318struct target_sigframe {
5319 struct target_sigcontext sctx;
5320 struct target_mcontext mctx;
5321 int32_t abigap[56];
5322};
5323
Tom Musta61e75fe2014-06-30 08:13:38 -05005324#if defined(TARGET_PPC64)
5325
5326#define TARGET_TRAMP_SIZE 6
5327
5328struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005329 /* sys_rt_sigreturn requires the ucontext be the first field */
5330 struct target_ucontext uc;
5331 target_ulong _unused[2];
5332 uint32_t trampoline[TARGET_TRAMP_SIZE];
5333 target_ulong pinfo; /* struct siginfo __user * */
5334 target_ulong puc; /* void __user * */
5335 struct target_siginfo info;
5336 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5337 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005338} __attribute__((aligned(16)));
5339
5340#else
5341
Nathan Froydbcd49332009-05-12 19:13:18 -07005342struct target_rt_sigframe {
5343 struct target_siginfo info;
5344 struct target_ucontext uc;
5345 int32_t abigap[56];
5346};
5347
Tom Musta61e75fe2014-06-30 08:13:38 -05005348#endif
5349
Tom Musta8d6ab332014-06-30 08:13:39 -05005350#if defined(TARGET_PPC64)
5351
5352struct target_func_ptr {
5353 target_ulong entry;
5354 target_ulong toc;
5355};
5356
5357#endif
5358
Nathan Froydbcd49332009-05-12 19:13:18 -07005359/* We use the mc_pad field for the signal return trampoline. */
5360#define tramp mc_pad
5361
5362/* See arch/powerpc/kernel/signal.c. */
5363static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005364 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005365 int frame_size)
5366{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005367 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005368
5369 oldsp = env->gpr[1];
5370
5371 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005372 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005373 oldsp = (target_sigaltstack_used.ss_sp
5374 + target_sigaltstack_used.ss_size);
5375 }
5376
Eduardo Habkost9be38592016-06-13 18:57:58 -03005377 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005378}
5379
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005380#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5381 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5382#define PPC_VEC_HI 0
5383#define PPC_VEC_LO 1
5384#else
5385#define PPC_VEC_HI 1
5386#define PPC_VEC_LO 0
5387#endif
5388
5389
Tom Musta76781082014-06-30 08:13:37 -05005390static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005391{
5392 target_ulong msr = env->msr;
5393 int i;
5394 target_ulong ccr = 0;
5395
5396 /* In general, the kernel attempts to be intelligent about what it
5397 needs to save for Altivec/FP/SPE registers. We don't care that
5398 much, so we just go ahead and save everything. */
5399
5400 /* Save general registers. */
5401 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005402 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005403 }
Riku Voipioc650c002014-04-23 13:53:45 +03005404 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5405 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5406 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5407 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005408
5409 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5410 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5411 }
Riku Voipioc650c002014-04-23 13:53:45 +03005412 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005413
5414 /* Save Altivec registers if necessary. */
5415 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005416 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005417 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005418 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005419 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005420
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005421 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5422 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005423 }
5424 /* Set MSR_VR in the saved MSR value to indicate that
5425 frame->mc_vregs contains valid data. */
5426 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005427#if defined(TARGET_PPC64)
5428 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5429 /* 64-bit needs to put a pointer to the vectors in the frame */
5430 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5431#else
5432 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5433#endif
5434 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5435 }
5436
5437 /* Save VSX second halves */
5438 if (env->insns_flags2 & PPC2_VSX) {
5439 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5440 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5441 __put_user(env->vsr[i], &vsregs[i]);
5442 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005443 }
5444
5445 /* Save floating point registers. */
5446 if (env->insns_flags & PPC_FLOAT) {
5447 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005448 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005449 }
Riku Voipioc650c002014-04-23 13:53:45 +03005450 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005451 }
5452
5453 /* Save SPE registers. The kernel only saves the high half. */
5454 if (env->insns_flags & PPC_SPE) {
5455#if defined(TARGET_PPC64)
5456 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005457 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005458 }
5459#else
5460 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005461 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005462 }
5463#endif
5464 /* Set MSR_SPE in the saved MSR value to indicate that
5465 frame->mc_vregs contains valid data. */
5466 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005467 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005468 }
5469
5470 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005471 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005472}
Nathan Froydbcd49332009-05-12 19:13:18 -07005473
Tom Musta76781082014-06-30 08:13:37 -05005474static void encode_trampoline(int sigret, uint32_t *tramp)
5475{
Nathan Froydbcd49332009-05-12 19:13:18 -07005476 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5477 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005478 __put_user(0x38000000 | sigret, &tramp[0]);
5479 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005480 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005481}
5482
Riku Voipioc650c002014-04-23 13:53:45 +03005483static void restore_user_regs(CPUPPCState *env,
5484 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005485{
5486 target_ulong save_r2 = 0;
5487 target_ulong msr;
5488 target_ulong ccr;
5489
5490 int i;
5491
5492 if (!sig) {
5493 save_r2 = env->gpr[2];
5494 }
5495
5496 /* Restore general registers. */
5497 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005498 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005499 }
Riku Voipioc650c002014-04-23 13:53:45 +03005500 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5501 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5502 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5503 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5504 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005505
5506 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5507 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5508 }
5509
5510 if (!sig) {
5511 env->gpr[2] = save_r2;
5512 }
5513 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005514 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005515
5516 /* If doing signal return, restore the previous little-endian mode. */
5517 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005518 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005519
5520 /* Restore Altivec registers if necessary. */
5521 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005522 ppc_avr_t *v_regs;
5523 uint32_t *vrsave;
5524#if defined(TARGET_PPC64)
5525 uint64_t v_addr;
5526 /* 64-bit needs to recover the pointer to the vectors from the frame */
5527 __get_user(v_addr, &frame->v_regs);
5528 v_regs = g2h(v_addr);
5529#else
5530 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5531#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005532 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005533 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005534 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005535
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005536 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5537 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005538 }
5539 /* Set MSR_VEC in the saved MSR value to indicate that
5540 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005541#if defined(TARGET_PPC64)
5542 vrsave = (uint32_t *)&v_regs[33];
5543#else
5544 vrsave = (uint32_t *)&v_regs[32];
5545#endif
5546 __get_user(env->spr[SPR_VRSAVE], vrsave);
5547 }
5548
5549 /* Restore VSX second halves */
5550 if (env->insns_flags2 & PPC2_VSX) {
5551 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5552 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5553 __get_user(env->vsr[i], &vsregs[i]);
5554 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005555 }
5556
5557 /* Restore floating point registers. */
5558 if (env->insns_flags & PPC_FLOAT) {
5559 uint64_t fpscr;
5560 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005561 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005562 }
Riku Voipioc650c002014-04-23 13:53:45 +03005563 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005564 env->fpscr = (uint32_t) fpscr;
5565 }
5566
5567 /* Save SPE registers. The kernel only saves the high half. */
5568 if (env->insns_flags & PPC_SPE) {
5569#if defined(TARGET_PPC64)
5570 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5571 uint32_t hi;
5572
Riku Voipioc650c002014-04-23 13:53:45 +03005573 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005574 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5575 }
5576#else
5577 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005578 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005579 }
5580#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005581 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005582 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005583}
5584
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005585#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005586static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005587 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005588{
5589 struct target_sigframe *frame;
5590 struct target_sigcontext *sc;
5591 target_ulong frame_addr, newsp;
5592 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005593
5594 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005595 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005596 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5597 goto sigsegv;
5598 sc = &frame->sctx;
5599
Riku Voipio1d8b5122014-04-23 10:26:05 +03005600 __put_user(ka->_sa_handler, &sc->handler);
5601 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005602 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005603 __put_user(h2g(&frame->mctx), &sc->regs);
5604 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005605
5606 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005607 save_user_regs(env, &frame->mctx);
5608
5609 /* Construct the trampoline code on the stack. */
5610 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005611
5612 /* The kernel checks for the presence of a VDSO here. We don't
5613 emulate a vdso, so use a sigreturn system call. */
5614 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5615
5616 /* Turn off all fp exceptions. */
5617 env->fpscr = 0;
5618
5619 /* Create a stack frame for the caller of the handler. */
5620 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005621 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005622
5623 if (err)
5624 goto sigsegv;
5625
5626 /* Set up registers for signal handler. */
5627 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005628 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005629 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005630
Nathan Froydbcd49332009-05-12 19:13:18 -07005631 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005632
Nathan Froydbcd49332009-05-12 19:13:18 -07005633 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005634 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005635
5636 unlock_user_struct(frame, frame_addr, 1);
5637 return;
5638
5639sigsegv:
5640 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005641 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005642}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005643#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005644
5645static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005646 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005647 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005648{
5649 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005650 uint32_t *trampptr = 0;
5651 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005652 target_ulong rt_sf_addr, newsp = 0;
5653 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005654#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005655 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005656 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5657#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005658
5659 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5660 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5661 goto sigsegv;
5662
Peter Maydellf6c7a052015-01-08 12:19:48 +00005663 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005664
Riku Voipio1d8b5122014-04-23 10:26:05 +03005665 __put_user(0, &rt_sf->uc.tuc_flags);
5666 __put_user(0, &rt_sf->uc.tuc_link);
5667 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5668 &rt_sf->uc.tuc_stack.ss_sp);
5669 __put_user(sas_ss_flags(env->gpr[1]),
5670 &rt_sf->uc.tuc_stack.ss_flags);
5671 __put_user(target_sigaltstack_used.ss_size,
5672 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005673#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005674 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5675 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005676#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005677 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005678 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005679 }
5680
Tom Musta61e75fe2014-06-30 08:13:38 -05005681#if defined(TARGET_PPC64)
5682 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5683 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005684
5685 sc = &rt_sf->uc.tuc_sigcontext;
5686 __put_user(h2g(mctx), &sc->regs);
5687 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005688#else
5689 mctx = &rt_sf->uc.tuc_mcontext;
5690 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5691#endif
5692
5693 save_user_regs(env, mctx);
5694 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005695
5696 /* The kernel checks for the presence of a VDSO here. We don't
5697 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005698 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005699
5700 /* Turn off all fp exceptions. */
5701 env->fpscr = 0;
5702
5703 /* Create a stack frame for the caller of the handler. */
5704 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005705 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005706
5707 if (err)
5708 goto sigsegv;
5709
5710 /* Set up registers for signal handler. */
5711 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005712 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005713 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5714 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5715 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005716
5717#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005718 if (get_ppc64_abi(image) < 2) {
5719 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5720 struct target_func_ptr *handler =
5721 (struct target_func_ptr *)g2h(ka->_sa_handler);
5722 env->nip = tswapl(handler->entry);
5723 env->gpr[2] = tswapl(handler->toc);
5724 } else {
5725 /* ELFv2 PPC64 function pointers are entry points, but R12
5726 * must also be set */
5727 env->nip = tswapl((target_ulong) ka->_sa_handler);
5728 env->gpr[12] = env->nip;
5729 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005730#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005731 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005732#endif
5733
Nathan Froydbcd49332009-05-12 19:13:18 -07005734 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005735 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005736
5737 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5738 return;
5739
5740sigsegv:
5741 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005742 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005743
5744}
5745
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005746#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005747long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005748{
5749 struct target_sigcontext *sc = NULL;
5750 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005751 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005752 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005753 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005754
5755 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5756 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5757 goto sigsegv;
5758
5759#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005760 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005761#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005762 __get_user(set.sig[0], &sc->oldmask);
5763 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005764#endif
5765 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005766 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005767
Riku Voipiof5f601a2014-04-23 13:00:17 +03005768 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005769 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5770 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005771 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005772
5773 unlock_user_struct(sr, sr_addr, 1);
5774 unlock_user_struct(sc, sc_addr, 1);
5775 return -TARGET_QEMU_ESIGRETURN;
5776
5777sigsegv:
5778 unlock_user_struct(sr, sr_addr, 1);
5779 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005780 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005781 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005782}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005783#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005784
5785/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005786static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005787{
5788 struct target_mcontext *mcp;
5789 target_ulong mcp_addr;
5790 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005791 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005792
Aurelien Jarno60e99242010-03-29 02:12:51 +02005793 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005794 sizeof (set)))
5795 return 1;
5796
Tom Musta19774ec2014-06-30 08:13:40 -05005797#if defined(TARGET_PPC64)
5798 mcp_addr = h2g(ucp) +
5799 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5800#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005801 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005802#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005803
5804 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5805 return 1;
5806
5807 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005808 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005809 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005810
5811 unlock_user_struct(mcp, mcp_addr, 1);
5812 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005813}
5814
Andreas Färber05390242012-02-25 03:37:53 +01005815long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005816{
5817 struct target_rt_sigframe *rt_sf = NULL;
5818 target_ulong rt_sf_addr;
5819
5820 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5821 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5822 goto sigsegv;
5823
5824 if (do_setcontext(&rt_sf->uc, env, 1))
5825 goto sigsegv;
5826
5827 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005828 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005829 0, env->gpr[1]);
5830
5831 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5832 return -TARGET_QEMU_ESIGRETURN;
5833
5834sigsegv:
5835 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005836 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005837 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005838}
5839
Laurent Vivier492a8742009-08-03 16:12:17 +02005840#elif defined(TARGET_M68K)
5841
5842struct target_sigcontext {
5843 abi_ulong sc_mask;
5844 abi_ulong sc_usp;
5845 abi_ulong sc_d0;
5846 abi_ulong sc_d1;
5847 abi_ulong sc_a0;
5848 abi_ulong sc_a1;
5849 unsigned short sc_sr;
5850 abi_ulong sc_pc;
5851};
5852
5853struct target_sigframe
5854{
5855 abi_ulong pretcode;
5856 int sig;
5857 int code;
5858 abi_ulong psc;
5859 char retcode[8];
5860 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5861 struct target_sigcontext sc;
5862};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005863
Anthony Liguoric227f092009-10-01 16:12:16 -05005864typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005865#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005866typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005867
5868typedef struct target_fpregset {
5869 int f_fpcntl[3];
5870 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005871} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005872
5873struct target_mcontext {
5874 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005875 target_gregset_t gregs;
5876 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005877};
5878
5879#define TARGET_MCONTEXT_VERSION 2
5880
5881struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005882 abi_ulong tuc_flags;
5883 abi_ulong tuc_link;
5884 target_stack_t tuc_stack;
5885 struct target_mcontext tuc_mcontext;
5886 abi_long tuc_filler[80];
5887 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005888};
5889
5890struct target_rt_sigframe
5891{
5892 abi_ulong pretcode;
5893 int sig;
5894 abi_ulong pinfo;
5895 abi_ulong puc;
5896 char retcode[8];
5897 struct target_siginfo info;
5898 struct target_ucontext uc;
5899};
Laurent Vivier492a8742009-08-03 16:12:17 +02005900
Riku Voipio41ecc722014-04-23 11:01:00 +03005901static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005902 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005903{
Laurent Vivieref597602018-01-04 02:28:59 +01005904 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005905 __put_user(mask, &sc->sc_mask);
5906 __put_user(env->aregs[7], &sc->sc_usp);
5907 __put_user(env->dregs[0], &sc->sc_d0);
5908 __put_user(env->dregs[1], &sc->sc_d1);
5909 __put_user(env->aregs[0], &sc->sc_a0);
5910 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005911 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005912 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005913}
5914
Riku Voipio016d2e12014-04-23 11:19:48 +03005915static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005916restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005917{
Laurent Vivier492a8742009-08-03 16:12:17 +02005918 int temp;
5919
Riku Voipio1d8b5122014-04-23 10:26:05 +03005920 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005921 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005922 __get_user(env->dregs[1], &sc->sc_d1);
5923 __get_user(env->aregs[0], &sc->sc_a0);
5924 __get_user(env->aregs[1], &sc->sc_a1);
5925 __get_user(env->pc, &sc->sc_pc);
5926 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005927 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005928}
5929
5930/*
5931 * Determine which stack to use..
5932 */
5933static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005934get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5935 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005936{
5937 unsigned long sp;
5938
5939 sp = regs->aregs[7];
5940
5941 /* This is the X/Open sanctioned signal stack switching. */
5942 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5943 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5944 }
5945
5946 return ((sp - frame_size) & -8UL);
5947}
5948
5949static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005950 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005951{
5952 struct target_sigframe *frame;
5953 abi_ulong frame_addr;
5954 abi_ulong retcode_addr;
5955 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005956 int i;
5957
5958 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005959 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005960 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5961 goto give_sigsegv;
5962 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005963
Riku Voipio1d8b5122014-04-23 10:26:05 +03005964 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005965
5966 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005967 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005968
Riku Voipio41ecc722014-04-23 11:01:00 +03005969 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005970
5971 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005972 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005973 }
5974
5975 /* Set up to return from userspace. */
5976
5977 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005978 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005979
5980 /* moveq #,d0; trap #0 */
5981
Riku Voipio1d8b5122014-04-23 10:26:05 +03005982 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005983 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005984
Laurent Vivier492a8742009-08-03 16:12:17 +02005985 /* Set up to return from userspace */
5986
5987 env->aregs[7] = frame_addr;
5988 env->pc = ka->_sa_handler;
5989
5990 unlock_user_struct(frame, frame_addr, 1);
5991 return;
5992
5993give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005994 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005995}
5996
Laurent Vivieree46a462017-09-14 18:35:05 +02005997static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5998 CPUM68KState *env)
5999{
6000 int i;
6001 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6002
6003 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
6004 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
6005 /* fpiar is not emulated */
6006
6007 for (i = 0; i < 8; i++) {
6008 uint32_t high = env->fregs[i].d.high << 16;
6009 __put_user(high, &fpregs->f_fpregs[i * 3]);
6010 __put_user(env->fregs[i].d.low,
6011 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6012 }
6013}
6014
Laurent Vivier71811552009-08-03 16:12:18 +02006015static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01006016 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02006017{
Aurelien Jarno60e99242010-03-29 02:12:51 +02006018 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01006019 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02006020
Riku Voipio1d8b5122014-04-23 10:26:05 +03006021 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
6022 __put_user(env->dregs[0], &gregs[0]);
6023 __put_user(env->dregs[1], &gregs[1]);
6024 __put_user(env->dregs[2], &gregs[2]);
6025 __put_user(env->dregs[3], &gregs[3]);
6026 __put_user(env->dregs[4], &gregs[4]);
6027 __put_user(env->dregs[5], &gregs[5]);
6028 __put_user(env->dregs[6], &gregs[6]);
6029 __put_user(env->dregs[7], &gregs[7]);
6030 __put_user(env->aregs[0], &gregs[8]);
6031 __put_user(env->aregs[1], &gregs[9]);
6032 __put_user(env->aregs[2], &gregs[10]);
6033 __put_user(env->aregs[3], &gregs[11]);
6034 __put_user(env->aregs[4], &gregs[12]);
6035 __put_user(env->aregs[5], &gregs[13]);
6036 __put_user(env->aregs[6], &gregs[14]);
6037 __put_user(env->aregs[7], &gregs[15]);
6038 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006039 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02006040
Laurent Vivieree46a462017-09-14 18:35:05 +02006041 target_rt_save_fpu_state(uc, env);
6042
Riku Voipio1d8b5122014-04-23 10:26:05 +03006043 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006044}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006045
Laurent Vivieree46a462017-09-14 18:35:05 +02006046static inline void target_rt_restore_fpu_state(CPUM68KState *env,
6047 struct target_ucontext *uc)
6048{
6049 int i;
6050 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6051 uint32_t fpcr;
6052
6053 __get_user(fpcr, &fpregs->f_fpcntl[0]);
6054 cpu_m68k_set_fpcr(env, fpcr);
6055 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
6056 /* fpiar is not emulated */
6057
6058 for (i = 0; i < 8; i++) {
6059 uint32_t high;
6060 __get_user(high, &fpregs->f_fpregs[i * 3]);
6061 env->fregs[i].d.high = high >> 16;
6062 __get_user(env->fregs[i].d.low,
6063 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6064 }
6065}
6066
Andreas Färber05390242012-02-25 03:37:53 +01006067static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006068 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02006069{
6070 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02006071 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02006072
Riku Voipio1d8b5122014-04-23 10:26:05 +03006073 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02006074 if (temp != TARGET_MCONTEXT_VERSION)
6075 goto badframe;
6076
6077 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03006078 __get_user(env->dregs[0], &gregs[0]);
6079 __get_user(env->dregs[1], &gregs[1]);
6080 __get_user(env->dregs[2], &gregs[2]);
6081 __get_user(env->dregs[3], &gregs[3]);
6082 __get_user(env->dregs[4], &gregs[4]);
6083 __get_user(env->dregs[5], &gregs[5]);
6084 __get_user(env->dregs[6], &gregs[6]);
6085 __get_user(env->dregs[7], &gregs[7]);
6086 __get_user(env->aregs[0], &gregs[8]);
6087 __get_user(env->aregs[1], &gregs[9]);
6088 __get_user(env->aregs[2], &gregs[10]);
6089 __get_user(env->aregs[3], &gregs[11]);
6090 __get_user(env->aregs[4], &gregs[12]);
6091 __get_user(env->aregs[5], &gregs[13]);
6092 __get_user(env->aregs[6], &gregs[14]);
6093 __get_user(env->aregs[7], &gregs[15]);
6094 __get_user(env->pc, &gregs[16]);
6095 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006096 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02006097
Laurent Vivieree46a462017-09-14 18:35:05 +02006098 target_rt_restore_fpu_state(env, uc);
6099
Riku Voipio1d8b5122014-04-23 10:26:05 +03006100 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006101
6102badframe:
6103 return 1;
6104}
6105
Laurent Vivier492a8742009-08-03 16:12:17 +02006106static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006107 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006108 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006109{
Laurent Vivier71811552009-08-03 16:12:18 +02006110 struct target_rt_sigframe *frame;
6111 abi_ulong frame_addr;
6112 abi_ulong retcode_addr;
6113 abi_ulong info_addr;
6114 abi_ulong uc_addr;
6115 int err = 0;
6116 int i;
6117
6118 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006119 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006120 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6121 goto give_sigsegv;
6122 }
Laurent Vivier71811552009-08-03 16:12:18 +02006123
Riku Voipio1d8b5122014-04-23 10:26:05 +03006124 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02006125
6126 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006127 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02006128
6129 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006130 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02006131
Peter Maydellf6c7a052015-01-08 12:19:48 +00006132 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02006133
6134 /* Create the ucontext */
6135
Riku Voipio1d8b5122014-04-23 10:26:05 +03006136 __put_user(0, &frame->uc.tuc_flags);
6137 __put_user(0, &frame->uc.tuc_link);
6138 __put_user(target_sigaltstack_used.ss_sp,
6139 &frame->uc.tuc_stack.ss_sp);
6140 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006141 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006142 __put_user(target_sigaltstack_used.ss_size,
6143 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02006144 err |= target_rt_setup_ucontext(&frame->uc, env);
6145
6146 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006147 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02006148
6149 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03006150 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02006151 }
6152
6153 /* Set up to return from userspace. */
6154
6155 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006156 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02006157
6158 /* moveq #,d0; notb d0; trap #0 */
6159
Riku Voipio1d8b5122014-04-23 10:26:05 +03006160 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00006161 (uint32_t *)(frame->retcode + 0));
6162 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02006163
6164 if (err)
6165 goto give_sigsegv;
6166
6167 /* Set up to return from userspace */
6168
6169 env->aregs[7] = frame_addr;
6170 env->pc = ka->_sa_handler;
6171
6172 unlock_user_struct(frame, frame_addr, 1);
6173 return;
6174
6175give_sigsegv:
6176 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006177 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006178}
6179
Andreas Färber05390242012-02-25 03:37:53 +01006180long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006181{
6182 struct target_sigframe *frame;
6183 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006184 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006185 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006186 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006187
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006188 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006189 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6190 goto badframe;
6191
6192 /* set blocked signals */
6193
Riku Voipiof5f601a2014-04-23 13:00:17 +03006194 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006195
6196 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006197 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006198 }
6199
6200 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006201 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006202
6203 /* restore registers */
6204
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006205 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006206
6207 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006208 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006209
6210badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006211 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006212 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006213}
6214
Andreas Färber05390242012-02-25 03:37:53 +01006215long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006216{
Laurent Vivier71811552009-08-03 16:12:18 +02006217 struct target_rt_sigframe *frame;
6218 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006219 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006220
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006221 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006222 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6223 goto badframe;
6224
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006225 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006226 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006227
6228 /* restore registers */
6229
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006230 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006231 goto badframe;
6232
6233 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006234 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006235 0, get_sp_from_cpustate(env)) == -EFAULT)
6236 goto badframe;
6237
6238 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006239 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006240
6241badframe:
6242 unlock_user_struct(frame, frame_addr, 0);
6243 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006244 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006245}
6246
Richard Henderson6049f4f2009-12-27 18:30:03 -08006247#elif defined(TARGET_ALPHA)
6248
6249struct target_sigcontext {
6250 abi_long sc_onstack;
6251 abi_long sc_mask;
6252 abi_long sc_pc;
6253 abi_long sc_ps;
6254 abi_long sc_regs[32];
6255 abi_long sc_ownedfp;
6256 abi_long sc_fpregs[32];
6257 abi_ulong sc_fpcr;
6258 abi_ulong sc_fp_control;
6259 abi_ulong sc_reserved1;
6260 abi_ulong sc_reserved2;
6261 abi_ulong sc_ssize;
6262 abi_ulong sc_sbase;
6263 abi_ulong sc_traparg_a0;
6264 abi_ulong sc_traparg_a1;
6265 abi_ulong sc_traparg_a2;
6266 abi_ulong sc_fp_trap_pc;
6267 abi_ulong sc_fp_trigger_sum;
6268 abi_ulong sc_fp_trigger_inst;
6269};
6270
6271struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006272 abi_ulong tuc_flags;
6273 abi_ulong tuc_link;
6274 abi_ulong tuc_osf_sigmask;
6275 target_stack_t tuc_stack;
6276 struct target_sigcontext tuc_mcontext;
6277 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006278};
6279
6280struct target_sigframe {
6281 struct target_sigcontext sc;
6282 unsigned int retcode[3];
6283};
6284
6285struct target_rt_sigframe {
6286 target_siginfo_t info;
6287 struct target_ucontext uc;
6288 unsigned int retcode[3];
6289};
6290
6291#define INSN_MOV_R30_R16 0x47fe0410
6292#define INSN_LDI_R0 0x201f0000
6293#define INSN_CALLSYS 0x00000083
6294
Riku Voipio41ecc722014-04-23 11:01:00 +03006295static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006296 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006297{
Riku Voipio41ecc722014-04-23 11:01:00 +03006298 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006299
Riku Voipio1d8b5122014-04-23 10:26:05 +03006300 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6301 __put_user(set->sig[0], &sc->sc_mask);
6302 __put_user(env->pc, &sc->sc_pc);
6303 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006304
6305 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006306 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006307 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006308 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006309
6310 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006311 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006312 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006313 __put_user(0, &sc->sc_fpregs[31]);
6314 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006315
Riku Voipio1d8b5122014-04-23 10:26:05 +03006316 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6317 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6318 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006319}
6320
Riku Voipio016d2e12014-04-23 11:19:48 +03006321static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006322 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006323{
6324 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006325 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006326
Riku Voipio1d8b5122014-04-23 10:26:05 +03006327 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006328
6329 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006330 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006331 }
6332 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006333 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006334 }
6335
Riku Voipio1d8b5122014-04-23 10:26:05 +03006336 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006337 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006338}
6339
6340static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006341 CPUAlphaState *env,
6342 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006343{
6344 abi_ulong sp = env->ir[IR_SP];
6345
6346 /* This is the X/Open sanctioned signal stack switching. */
6347 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6348 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6349 }
6350 return (sp - framesize) & -32;
6351}
6352
6353static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006354 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006355{
6356 abi_ulong frame_addr, r26;
6357 struct target_sigframe *frame;
6358 int err = 0;
6359
6360 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006361 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006362 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6363 goto give_sigsegv;
6364 }
6365
Riku Voipio41ecc722014-04-23 11:01:00 +03006366 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006367
6368 if (ka->sa_restorer) {
6369 r26 = ka->sa_restorer;
6370 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006371 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6372 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6373 &frame->retcode[1]);
6374 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006375 /* imb() */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006376 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006377 }
6378
6379 unlock_user_struct(frame, frame_addr, 1);
6380
6381 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006382give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006383 force_sigsegv(sig);
6384 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006385 }
6386
6387 env->ir[IR_RA] = r26;
6388 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6389 env->ir[IR_A0] = sig;
6390 env->ir[IR_A1] = 0;
6391 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6392 env->ir[IR_SP] = frame_addr;
6393}
6394
6395static void setup_rt_frame(int sig, struct target_sigaction *ka,
6396 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006397 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006398{
6399 abi_ulong frame_addr, r26;
6400 struct target_rt_sigframe *frame;
6401 int i, err = 0;
6402
6403 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006404 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006405 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6406 goto give_sigsegv;
6407 }
6408
Peter Maydellf6c7a052015-01-08 12:19:48 +00006409 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006410
Riku Voipio1d8b5122014-04-23 10:26:05 +03006411 __put_user(0, &frame->uc.tuc_flags);
6412 __put_user(0, &frame->uc.tuc_link);
6413 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6414 __put_user(target_sigaltstack_used.ss_sp,
6415 &frame->uc.tuc_stack.ss_sp);
6416 __put_user(sas_ss_flags(env->ir[IR_SP]),
6417 &frame->uc.tuc_stack.ss_flags);
6418 __put_user(target_sigaltstack_used.ss_size,
6419 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006420 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006421 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006422 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006423 }
6424
6425 if (ka->sa_restorer) {
6426 r26 = ka->sa_restorer;
6427 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006428 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6429 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6430 &frame->retcode[1]);
6431 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006432 /* imb(); */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006433 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006434 }
6435
6436 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006437give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006438 force_sigsegv(sig);
6439 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006440 }
6441
6442 env->ir[IR_RA] = r26;
6443 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6444 env->ir[IR_A0] = sig;
6445 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6446 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6447 env->ir[IR_SP] = frame_addr;
6448}
6449
Andreas Färber05390242012-02-25 03:37:53 +01006450long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006451{
6452 struct target_sigcontext *sc;
6453 abi_ulong sc_addr = env->ir[IR_A0];
6454 target_sigset_t target_set;
6455 sigset_t set;
6456
6457 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6458 goto badframe;
6459 }
6460
6461 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006462 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006463
6464 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006465 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006466
Riku Voipio016d2e12014-04-23 11:19:48 +03006467 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006468 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006469 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006470
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006471badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006472 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006473 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006474}
6475
Andreas Färber05390242012-02-25 03:37:53 +01006476long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006477{
6478 abi_ulong frame_addr = env->ir[IR_A0];
6479 struct target_rt_sigframe *frame;
6480 sigset_t set;
6481
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006482 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006483 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6484 goto badframe;
6485 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006486 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006487 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006488
Riku Voipio016d2e12014-04-23 11:19:48 +03006489 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006490 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006491 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006492 0, env->ir[IR_SP]) == -EFAULT) {
6493 goto badframe;
6494 }
6495
6496 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006497 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006498
6499
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006500badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006501 unlock_user_struct(frame, frame_addr, 0);
6502 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006503 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006504}
6505
Chen Gangbf0f60a2015-09-27 08:10:18 +08006506#elif defined(TARGET_TILEGX)
6507
6508struct target_sigcontext {
6509 union {
6510 /* General-purpose registers. */
6511 abi_ulong gregs[56];
6512 struct {
6513 abi_ulong __gregs[53];
6514 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6515 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6516 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6517 };
6518 };
6519 abi_ulong pc; /* Program counter. */
6520 abi_ulong ics; /* In Interrupt Critical Section? */
6521 abi_ulong faultnum; /* Fault number. */
6522 abi_ulong pad[5];
6523};
6524
6525struct target_ucontext {
6526 abi_ulong tuc_flags;
6527 abi_ulong tuc_link;
6528 target_stack_t tuc_stack;
6529 struct target_sigcontext tuc_mcontext;
6530 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6531};
6532
6533struct target_rt_sigframe {
6534 unsigned char save_area[16]; /* caller save area */
6535 struct target_siginfo info;
6536 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006537 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006538};
6539
Chen Gangf1d9d102016-03-29 21:53:49 +08006540#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6541#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6542
6543
Chen Gangbf0f60a2015-09-27 08:10:18 +08006544static void setup_sigcontext(struct target_sigcontext *sc,
6545 CPUArchState *env, int signo)
6546{
6547 int i;
6548
6549 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6550 __put_user(env->regs[i], &sc->gregs[i]);
6551 }
6552
6553 __put_user(env->pc, &sc->pc);
6554 __put_user(0, &sc->ics);
6555 __put_user(signo, &sc->faultnum);
6556}
6557
6558static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6559{
6560 int i;
6561
6562 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6563 __get_user(env->regs[i], &sc->gregs[i]);
6564 }
6565
6566 __get_user(env->pc, &sc->pc);
6567}
6568
6569static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6570 size_t frame_size)
6571{
6572 unsigned long sp = env->regs[TILEGX_R_SP];
6573
6574 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6575 return -1UL;
6576 }
6577
6578 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6579 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6580 }
6581
6582 sp -= frame_size;
6583 sp &= -16UL;
6584 return sp;
6585}
6586
6587static void setup_rt_frame(int sig, struct target_sigaction *ka,
6588 target_siginfo_t *info,
6589 target_sigset_t *set, CPUArchState *env)
6590{
6591 abi_ulong frame_addr;
6592 struct target_rt_sigframe *frame;
6593 unsigned long restorer;
6594
6595 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006596 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006597 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6598 goto give_sigsegv;
6599 }
6600
6601 /* Always write at least the signal number for the stack backtracer. */
6602 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6603 /* At sigreturn time, restore the callee-save registers too. */
6604 tswap_siginfo(&frame->info, info);
6605 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6606 } else {
6607 __put_user(info->si_signo, &frame->info.si_signo);
6608 }
6609
6610 /* Create the ucontext. */
6611 __put_user(0, &frame->uc.tuc_flags);
6612 __put_user(0, &frame->uc.tuc_link);
6613 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6614 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6615 &frame->uc.tuc_stack.ss_flags);
6616 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6617 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6618
Chen Gangbf0f60a2015-09-27 08:10:18 +08006619 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006620 restorer = (unsigned long) ka->sa_restorer;
6621 } else {
6622 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6623 __put_user(INSN_SWINT1, &frame->retcode[1]);
6624 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006625 }
6626 env->pc = (unsigned long) ka->_sa_handler;
6627 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6628 env->regs[TILEGX_R_LR] = restorer;
6629 env->regs[0] = (unsigned long) sig;
6630 env->regs[1] = (unsigned long) &frame->info;
6631 env->regs[2] = (unsigned long) &frame->uc;
6632 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6633
6634 unlock_user_struct(frame, frame_addr, 1);
6635 return;
6636
6637give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006638 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006639}
6640
6641long do_rt_sigreturn(CPUTLGState *env)
6642{
6643 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6644 struct target_rt_sigframe *frame;
6645 sigset_t set;
6646
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006647 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006648 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6649 goto badframe;
6650 }
6651 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006652 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006653
6654 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6655 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6656 uc.tuc_stack),
6657 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6658 goto badframe;
6659 }
6660
6661 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006662 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006663
6664
6665 badframe:
6666 unlock_user_struct(frame, frame_addr, 0);
6667 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006668 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006669}
6670
Michael Clark47ae93c2018-03-03 01:31:11 +13006671#elif defined(TARGET_RISCV)
6672
6673/* Signal handler invocation must be transparent for the code being
6674 interrupted. Complete CPU (hart) state is saved on entry and restored
6675 before returning from the handler. Process sigmask is also saved to block
6676 signals while the handler is running. The handler gets its own stack,
6677 which also doubles as storage for the CPU state and sigmask.
6678
6679 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6680
6681struct target_sigcontext {
6682 abi_long pc;
6683 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6684 uint64_t fpr[32];
6685 uint32_t fcsr;
6686}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6687
6688struct target_ucontext {
6689 unsigned long uc_flags;
6690 struct target_ucontext *uc_link;
6691 target_stack_t uc_stack;
6692 struct target_sigcontext uc_mcontext;
6693 target_sigset_t uc_sigmask;
6694};
6695
6696struct target_rt_sigframe {
6697 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6698 struct target_siginfo info;
6699 struct target_ucontext uc;
6700};
6701
6702static abi_ulong get_sigframe(struct target_sigaction *ka,
6703 CPURISCVState *regs, size_t framesize)
6704{
6705 abi_ulong sp = regs->gpr[xSP];
6706 int onsigstack = on_sig_stack(sp);
6707
6708 /* redzone */
6709 /* This is the X/Open sanctioned signal stack switching. */
6710 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6711 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6712 }
6713
6714 sp -= framesize;
6715 sp &= ~3UL; /* align sp on 4-byte boundary */
6716
6717 /* If we are on the alternate signal stack and would overflow it, don't.
6718 Return an always-bogus address instead so we will die with SIGSEGV. */
6719 if (onsigstack && !likely(on_sig_stack(sp))) {
6720 return -1L;
6721 }
6722
6723 return sp;
6724}
6725
6726static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6727{
6728 int i;
6729
6730 __put_user(env->pc, &sc->pc);
6731
6732 for (i = 1; i < 32; i++) {
6733 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6734 }
6735 for (i = 0; i < 32; i++) {
6736 __put_user(env->fpr[i], &sc->fpr[i]);
6737 }
6738
6739 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6740 __put_user(fcsr, &sc->fcsr);
6741}
6742
6743static void setup_ucontext(struct target_ucontext *uc,
6744 CPURISCVState *env, target_sigset_t *set)
6745{
6746 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6747 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6748 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6749
6750 __put_user(0, &(uc->uc_flags));
6751 __put_user(0, &(uc->uc_link));
6752
6753 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6754 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6755 __put_user(ss_size, &(uc->uc_stack.ss_size));
6756
6757 int i;
6758 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6759 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6760 }
6761
6762 setup_sigcontext(&uc->uc_mcontext, env);
6763}
6764
6765static inline void install_sigtramp(uint32_t *tramp)
6766{
6767 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6768 __put_user(0x00000073, tramp + 1); /* ecall */
6769}
6770
6771static void setup_rt_frame(int sig, struct target_sigaction *ka,
6772 target_siginfo_t *info,
6773 target_sigset_t *set, CPURISCVState *env)
6774{
6775 abi_ulong frame_addr;
6776 struct target_rt_sigframe *frame;
6777
6778 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6779 trace_user_setup_rt_frame(env, frame_addr);
6780
6781 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6782 goto badframe;
6783 }
6784
6785 setup_ucontext(&frame->uc, env, set);
6786 tswap_siginfo(&frame->info, info);
6787 install_sigtramp(frame->tramp);
6788
6789 env->pc = ka->_sa_handler;
6790 env->gpr[xSP] = frame_addr;
6791 env->gpr[xA0] = sig;
6792 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6793 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6794 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6795
6796 return;
6797
6798badframe:
6799 unlock_user_struct(frame, frame_addr, 1);
6800 if (sig == TARGET_SIGSEGV) {
6801 ka->_sa_handler = TARGET_SIG_DFL;
6802 }
6803 force_sig(TARGET_SIGSEGV);
6804}
6805
6806static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6807{
6808 int i;
6809
6810 __get_user(env->pc, &sc->pc);
6811
6812 for (i = 1; i < 32; ++i) {
6813 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6814 }
6815 for (i = 0; i < 32; ++i) {
6816 __get_user(env->fpr[i], &sc->fpr[i]);
6817 }
6818
6819 uint32_t fcsr;
6820 __get_user(fcsr, &sc->fcsr);
6821 csr_write_helper(env, fcsr, CSR_FCSR);
6822}
6823
6824static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6825{
6826 sigset_t blocked;
6827 target_sigset_t target_set;
6828 int i;
6829
6830 target_sigemptyset(&target_set);
6831 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6832 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6833 }
6834
6835 target_to_host_sigset_internal(&blocked, &target_set);
6836 set_sigmask(&blocked);
6837
6838 restore_sigcontext(env, &uc->uc_mcontext);
6839}
6840
6841long do_rt_sigreturn(CPURISCVState *env)
6842{
6843 struct target_rt_sigframe *frame;
6844 abi_ulong frame_addr;
6845
6846 frame_addr = env->gpr[xSP];
6847 trace_user_do_sigreturn(env, frame_addr);
6848 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6849 goto badframe;
6850 }
6851
6852 restore_ucontext(env, &frame->uc);
6853
6854 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6855 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6856 goto badframe;
6857 }
6858
6859 unlock_user_struct(frame, frame_addr, 0);
6860 return -TARGET_QEMU_ESIGRETURN;
6861
6862badframe:
6863 unlock_user_struct(frame, frame_addr, 0);
6864 force_sig(TARGET_SIGSEGV);
6865 return 0;
6866}
6867
Richard Henderson1659e382016-12-15 09:59:01 -08006868#elif defined(TARGET_HPPA)
6869
6870struct target_sigcontext {
6871 abi_ulong sc_flags;
6872 abi_ulong sc_gr[32];
6873 uint64_t sc_fr[32];
6874 abi_ulong sc_iasq[2];
6875 abi_ulong sc_iaoq[2];
6876 abi_ulong sc_sar;
6877};
6878
6879struct target_ucontext {
6880 abi_uint tuc_flags;
6881 abi_ulong tuc_link;
6882 target_stack_t tuc_stack;
6883 abi_uint pad[1];
6884 struct target_sigcontext tuc_mcontext;
6885 target_sigset_t tuc_sigmask;
6886};
6887
6888struct target_rt_sigframe {
6889 abi_uint tramp[9];
6890 target_siginfo_t info;
6891 struct target_ucontext uc;
6892 /* hidden location of upper halves of pa2.0 64-bit gregs */
6893};
6894
6895static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6896{
6897 int flags = 0;
6898 int i;
6899
6900 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6901
6902 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6903 /* In the gateway page, executing a syscall. */
6904 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6905 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6906 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6907 } else {
6908 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6909 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6910 }
6911 __put_user(0, &sc->sc_iasq[0]);
6912 __put_user(0, &sc->sc_iasq[1]);
6913 __put_user(flags, &sc->sc_flags);
6914
6915 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6916 for (i = 1; i < 32; ++i) {
6917 __put_user(env->gr[i], &sc->sc_gr[i]);
6918 }
6919
6920 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6921 for (i = 1; i < 32; ++i) {
6922 __put_user(env->fr[i], &sc->sc_fr[i]);
6923 }
6924
Richard Henderson35136a72017-10-10 21:19:34 -07006925 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006926}
6927
6928static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6929{
6930 target_ulong psw;
6931 int i;
6932
6933 __get_user(psw, &sc->sc_gr[0]);
6934 cpu_hppa_put_psw(env, psw);
6935
6936 for (i = 1; i < 32; ++i) {
6937 __get_user(env->gr[i], &sc->sc_gr[i]);
6938 }
6939 for (i = 0; i < 32; ++i) {
6940 __get_user(env->fr[i], &sc->sc_fr[i]);
6941 }
6942 cpu_hppa_loaded_fr0(env);
6943
6944 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6945 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006946 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006947}
6948
6949/* No, this doesn't look right, but it's copied straight from the kernel. */
6950#define PARISC_RT_SIGFRAME_SIZE32 \
6951 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6952
6953static void setup_rt_frame(int sig, struct target_sigaction *ka,
6954 target_siginfo_t *info,
6955 target_sigset_t *set, CPUArchState *env)
6956{
6957 abi_ulong frame_addr, sp, haddr;
6958 struct target_rt_sigframe *frame;
6959 int i;
6960
6961 sp = env->gr[30];
6962 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6963 if (sas_ss_flags(sp) == 0) {
6964 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6965 }
6966 }
6967 frame_addr = QEMU_ALIGN_UP(sp, 64);
6968 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6969
6970 trace_user_setup_rt_frame(env, frame_addr);
6971
6972 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6973 goto give_sigsegv;
6974 }
6975
6976 tswap_siginfo(&frame->info, info);
6977 frame->uc.tuc_flags = 0;
6978 frame->uc.tuc_link = 0;
6979
6980 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6981 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6982 &frame->uc.tuc_stack.ss_flags);
6983 __put_user(target_sigaltstack_used.ss_size,
6984 &frame->uc.tuc_stack.ss_size);
6985
6986 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6987 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6988 }
6989
6990 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6991
6992 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6993 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6994 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6995 __put_user(0x08000240, frame->tramp + 3); /* nop */
6996
6997 unlock_user_struct(frame, frame_addr, 1);
6998
6999 env->gr[2] = h2g(frame->tramp);
7000 env->gr[30] = sp;
7001 env->gr[26] = sig;
7002 env->gr[25] = h2g(&frame->info);
7003 env->gr[24] = h2g(&frame->uc);
7004
7005 haddr = ka->_sa_handler;
7006 if (haddr & 2) {
7007 /* Function descriptor. */
7008 target_ulong *fdesc, dest;
7009
7010 haddr &= -4;
7011 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
7012 goto give_sigsegv;
7013 }
7014 __get_user(dest, fdesc);
7015 __get_user(env->gr[19], fdesc + 1);
7016 unlock_user_struct(fdesc, haddr, 1);
7017 haddr = dest;
7018 }
7019 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02007020 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08007021 return;
7022
7023 give_sigsegv:
7024 force_sigsegv(sig);
7025}
7026
7027long do_rt_sigreturn(CPUArchState *env)
7028{
7029 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
7030 struct target_rt_sigframe *frame;
7031 sigset_t set;
7032
7033 trace_user_do_rt_sigreturn(env, frame_addr);
7034 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7035 goto badframe;
7036 }
7037 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7038 set_sigmask(&set);
7039
7040 restore_sigcontext(env, &frame->uc.tuc_mcontext);
7041 unlock_user_struct(frame, frame_addr, 0);
7042
7043 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
7044 uc.tuc_stack),
7045 0, env->gr[30]) == -EFAULT) {
7046 goto badframe;
7047 }
7048
7049 unlock_user_struct(frame, frame_addr, 0);
7050 return -TARGET_QEMU_ESIGRETURN;
7051
7052 badframe:
7053 force_sig(TARGET_SIGSEGV);
7054 return -TARGET_QEMU_ESIGRETURN;
7055}
7056
Max Filippovba7651f2017-01-25 10:54:11 -08007057#elif defined(TARGET_XTENSA)
7058
7059struct target_sigcontext {
7060 abi_ulong sc_pc;
7061 abi_ulong sc_ps;
7062 abi_ulong sc_lbeg;
7063 abi_ulong sc_lend;
7064 abi_ulong sc_lcount;
7065 abi_ulong sc_sar;
7066 abi_ulong sc_acclo;
7067 abi_ulong sc_acchi;
7068 abi_ulong sc_a[16];
7069 abi_ulong sc_xtregs;
7070};
7071
7072struct target_ucontext {
7073 abi_ulong tuc_flags;
7074 abi_ulong tuc_link;
7075 target_stack_t tuc_stack;
7076 struct target_sigcontext tuc_mcontext;
7077 target_sigset_t tuc_sigmask;
7078};
7079
7080struct target_rt_sigframe {
7081 target_siginfo_t info;
7082 struct target_ucontext uc;
7083 /* TODO: xtregs */
7084 uint8_t retcode[6];
7085 abi_ulong window[4];
7086};
7087
7088static abi_ulong get_sigframe(struct target_sigaction *sa,
7089 CPUXtensaState *env,
7090 unsigned long framesize)
7091{
7092 abi_ulong sp = env->regs[1];
7093
7094 /* This is the X/Open sanctioned signal stack switching. */
7095 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
7096 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
7097 }
7098 return (sp - framesize) & -16;
7099}
7100
7101static int flush_window_regs(CPUXtensaState *env)
7102{
Max Filippovba7651f2017-01-25 10:54:11 -08007103 uint32_t wb = env->sregs[WINDOW_BASE];
Max Filippov20ef6672018-03-28 00:25:22 -07007104 uint32_t ws = xtensa_replicate_windowstart(env) >> (wb + 1);
7105 unsigned d = ctz32(ws) + 1;
7106 unsigned i;
7107 int ret = 0;
Max Filippovba7651f2017-01-25 10:54:11 -08007108
Max Filippov20ef6672018-03-28 00:25:22 -07007109 for (i = d; i < env->config->nareg / 4; i += d) {
7110 uint32_t ssp, osp;
7111 unsigned j;
Max Filippovba7651f2017-01-25 10:54:11 -08007112
Max Filippov20ef6672018-03-28 00:25:22 -07007113 ws >>= d;
7114 xtensa_rotate_window(env, d);
Max Filippovba7651f2017-01-25 10:54:11 -08007115
7116 if (ws & 0x1) {
Max Filippov20ef6672018-03-28 00:25:22 -07007117 ssp = env->regs[5];
Max Filippovba7651f2017-01-25 10:54:11 -08007118 d = 1;
7119 } else if (ws & 0x2) {
Max Filippov20ef6672018-03-28 00:25:22 -07007120 ssp = env->regs[9];
7121 ret |= get_user_ual(osp, env->regs[1] - 12);
7122 osp -= 32;
Max Filippovba7651f2017-01-25 10:54:11 -08007123 d = 2;
Max Filippovba7651f2017-01-25 10:54:11 -08007124 } else if (ws & 0x4) {
Max Filippov20ef6672018-03-28 00:25:22 -07007125 ssp = env->regs[13];
7126 ret |= get_user_ual(osp, env->regs[1] - 12);
7127 osp -= 48;
Max Filippovba7651f2017-01-25 10:54:11 -08007128 d = 3;
Max Filippovba7651f2017-01-25 10:54:11 -08007129 } else {
7130 g_assert_not_reached();
7131 }
Max Filippov20ef6672018-03-28 00:25:22 -07007132
7133 for (j = 0; j < 4; ++j) {
7134 ret |= put_user_ual(env->regs[j], ssp - 16 + j * 4);
Max Filippovba7651f2017-01-25 10:54:11 -08007135 }
Max Filippov20ef6672018-03-28 00:25:22 -07007136 for (j = 4; j < d * 4; ++j) {
7137 ret |= put_user_ual(env->regs[j], osp - 16 + j * 4);
7138 }
Max Filippovba7651f2017-01-25 10:54:11 -08007139 }
Max Filippov20ef6672018-03-28 00:25:22 -07007140 xtensa_rotate_window(env, d);
7141 g_assert(env->sregs[WINDOW_BASE] == wb);
Max Filippovba7651f2017-01-25 10:54:11 -08007142 return ret == 0;
7143}
7144
7145static int setup_sigcontext(struct target_rt_sigframe *frame,
7146 CPUXtensaState *env)
7147{
7148 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7149 int i;
7150
7151 __put_user(env->pc, &sc->sc_pc);
7152 __put_user(env->sregs[PS], &sc->sc_ps);
7153 __put_user(env->sregs[LBEG], &sc->sc_lbeg);
7154 __put_user(env->sregs[LEND], &sc->sc_lend);
7155 __put_user(env->sregs[LCOUNT], &sc->sc_lcount);
7156 if (!flush_window_regs(env)) {
7157 return 0;
7158 }
7159 for (i = 0; i < 16; ++i) {
7160 __put_user(env->regs[i], sc->sc_a + i);
7161 }
7162 __put_user(0, &sc->sc_xtregs);
7163 /* TODO: xtregs */
7164 return 1;
7165}
7166
7167static void setup_rt_frame(int sig, struct target_sigaction *ka,
7168 target_siginfo_t *info,
7169 target_sigset_t *set, CPUXtensaState *env)
7170{
7171 abi_ulong frame_addr;
7172 struct target_rt_sigframe *frame;
7173 uint32_t ra;
7174 int i;
7175
7176 frame_addr = get_sigframe(ka, env, sizeof(*frame));
7177 trace_user_setup_rt_frame(env, frame_addr);
7178
7179 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
7180 goto give_sigsegv;
7181 }
7182
7183 if (ka->sa_flags & SA_SIGINFO) {
7184 tswap_siginfo(&frame->info, info);
7185 }
7186
7187 __put_user(0, &frame->uc.tuc_flags);
7188 __put_user(0, &frame->uc.tuc_link);
7189 __put_user(target_sigaltstack_used.ss_sp,
7190 &frame->uc.tuc_stack.ss_sp);
7191 __put_user(sas_ss_flags(env->regs[1]),
7192 &frame->uc.tuc_stack.ss_flags);
7193 __put_user(target_sigaltstack_used.ss_size,
7194 &frame->uc.tuc_stack.ss_size);
7195 if (!setup_sigcontext(frame, env)) {
7196 unlock_user_struct(frame, frame_addr, 0);
7197 goto give_sigsegv;
7198 }
7199 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
7200 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7201 }
7202
7203 if (ka->sa_flags & TARGET_SA_RESTORER) {
7204 ra = ka->sa_restorer;
7205 } else {
7206 ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
7207#ifdef TARGET_WORDS_BIGENDIAN
7208 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7209 __put_user(0x22, &frame->retcode[0]);
7210 __put_user(0x0a, &frame->retcode[1]);
7211 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7212 /* Generate instruction: SYSCALL */
7213 __put_user(0x00, &frame->retcode[3]);
7214 __put_user(0x05, &frame->retcode[4]);
7215 __put_user(0x00, &frame->retcode[5]);
7216#else
7217 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7218 __put_user(0x22, &frame->retcode[0]);
7219 __put_user(0xa0, &frame->retcode[1]);
7220 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7221 /* Generate instruction: SYSCALL */
7222 __put_user(0x00, &frame->retcode[3]);
7223 __put_user(0x50, &frame->retcode[4]);
7224 __put_user(0x00, &frame->retcode[5]);
7225#endif
7226 }
7227 env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
7228 if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
7229 env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
7230 }
7231 memset(env->regs, 0, sizeof(env->regs));
7232 env->pc = ka->_sa_handler;
7233 env->regs[1] = frame_addr;
7234 env->sregs[WINDOW_BASE] = 0;
7235 env->sregs[WINDOW_START] = 1;
7236
7237 env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
7238 env->regs[6] = sig;
7239 env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
7240 env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
7241 unlock_user_struct(frame, frame_addr, 1);
7242 return;
7243
7244give_sigsegv:
7245 force_sigsegv(sig);
7246 return;
7247}
7248
7249static void restore_sigcontext(CPUXtensaState *env,
7250 struct target_rt_sigframe *frame)
7251{
7252 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7253 uint32_t ps;
7254 int i;
7255
7256 __get_user(env->pc, &sc->sc_pc);
7257 __get_user(ps, &sc->sc_ps);
7258 __get_user(env->sregs[LBEG], &sc->sc_lbeg);
7259 __get_user(env->sregs[LEND], &sc->sc_lend);
7260 __get_user(env->sregs[LCOUNT], &sc->sc_lcount);
7261
7262 env->sregs[WINDOW_BASE] = 0;
7263 env->sregs[WINDOW_START] = 1;
7264 env->sregs[PS] = deposit32(env->sregs[PS],
7265 PS_CALLINC_SHIFT,
7266 PS_CALLINC_LEN,
7267 extract32(ps, PS_CALLINC_SHIFT,
7268 PS_CALLINC_LEN));
7269 for (i = 0; i < 16; ++i) {
7270 __get_user(env->regs[i], sc->sc_a + i);
7271 }
7272 /* TODO: xtregs */
7273}
7274
7275long do_rt_sigreturn(CPUXtensaState *env)
7276{
7277 abi_ulong frame_addr = env->regs[1];
7278 struct target_rt_sigframe *frame;
7279 sigset_t set;
7280
7281 trace_user_do_rt_sigreturn(env, frame_addr);
7282 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7283 goto badframe;
7284 }
7285 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7286 set_sigmask(&set);
7287
7288 restore_sigcontext(env, frame);
7289
7290 if (do_sigaltstack(frame_addr +
7291 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7292 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) {
7293 goto badframe;
7294 }
7295 unlock_user_struct(frame, frame_addr, 0);
7296 return -TARGET_QEMU_ESIGRETURN;
7297
7298badframe:
7299 unlock_user_struct(frame, frame_addr, 0);
7300 force_sig(TARGET_SIGSEGV);
7301 return -TARGET_QEMU_ESIGRETURN;
7302}
7303
bellardb346ff42003-06-15 20:05:50 +00007304#else
Peter Maydellf8b985d2018-03-08 14:47:33 +00007305#error Target needs to add support for signal handling
bellard66fb9762003-03-23 01:06:05 +00007306#endif
7307
Peter Maydell31efaef2016-07-06 15:09:29 +01007308static void handle_pending_signal(CPUArchState *cpu_env, int sig,
7309 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01007310{
7311 CPUState *cpu = ENV_GET_CPU(cpu_env);
7312 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007313 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01007314 target_sigset_t target_old_set;
7315 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01007316 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01007317
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01007318 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00007319 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007320 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00007321
Andreas Färberdb6b81d2013-06-27 19:49:31 +02007322 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00007323 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00007324 sa = NULL;
7325 handler = TARGET_SIG_IGN;
7326 } else {
7327 sa = &sigact_table[sig - 1];
7328 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00007329 }
bellard66fb9762003-03-23 01:06:05 +00007330
Peter Maydell0cb581d2016-07-18 18:12:24 +01007331 if (do_strace) {
7332 print_taken_signal(sig, &k->info);
7333 }
7334
bellard66fb9762003-03-23 01:06:05 +00007335 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00007336 /* default handler : ignore some signal. The other are job control or fatal */
7337 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
7338 kill(getpid(),SIGSTOP);
7339 } else if (sig != TARGET_SIGCHLD &&
7340 sig != TARGET_SIGURG &&
7341 sig != TARGET_SIGWINCH &&
7342 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007343 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007344 }
7345 } else if (handler == TARGET_SIG_IGN) {
7346 /* ignore sig */
7347 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007348 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007349 } else {
bellard9de5e442003-03-23 16:49:39 +00007350 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007351 sigset_t *blocked_set;
7352
pbrook624f7972008-05-31 16:11:38 +00007353 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00007354 /* SA_NODEFER indicates that the current signal should not be
7355 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00007356 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00007357 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00007358
bellard9de5e442003-03-23 16:49:39 +00007359 /* save the previous blocked signal state to restore it at the
7360 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007361 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
7362
7363 /* block signals in the handler */
7364 blocked_set = ts->in_sigsuspend ?
7365 &ts->sigsuspend_mask : &ts->signal_mask;
7366 sigorset(&ts->signal_mask, blocked_set, &set);
7367 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00007368
bellardbc8a22c2003-03-30 21:02:40 +00007369 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00007370#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00007371 {
7372 CPUX86State *env = cpu_env;
7373 if (env->eflags & VM_MASK)
7374 save_v86_state(env);
7375 }
7376#endif
bellard9de5e442003-03-23 16:49:39 +00007377 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08007378#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10007379 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01007380 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13007381 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
Max Filippovba7651f2017-01-25 10:54:11 -08007382 || defined(TARGET_RISCV) || defined(TARGET_XTENSA)
Richard Hendersonff970902013-02-10 10:30:42 -08007383 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007384 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007385#else
pbrook624f7972008-05-31 16:11:38 +00007386 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007387 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00007388 else
pbrook624f7972008-05-31 16:11:38 +00007389 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007390#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01007391 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00007392 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01007393 }
bellard31e31b82003-02-18 22:55:36 +00007394 }
bellard31e31b82003-02-18 22:55:36 +00007395}
Peter Maydelle902d582016-05-27 15:51:44 +01007396
7397void process_pending_signals(CPUArchState *cpu_env)
7398{
7399 CPUState *cpu = ENV_GET_CPU(cpu_env);
7400 int sig;
7401 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007402 sigset_t set;
7403 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007404
Peter Maydell3d3efba2016-05-27 15:51:49 +01007405 while (atomic_read(&ts->signal_pending)) {
7406 /* FIXME: This is not threadsafe. */
7407 sigfillset(&set);
7408 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007409
Peter Maydell8bd37732016-07-28 16:44:45 +01007410 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007411 sig = ts->sync_signal.pending;
7412 if (sig) {
7413 /* Synchronous signals are forced,
7414 * see force_sig_info() and callers in Linux
7415 * Note that not all of our queue_signal() calls in QEMU correspond
7416 * to force_sig_info() calls in Linux (some are send_sig_info()).
7417 * However it seems like a kernel bug to me to allow the process
7418 * to block a synchronous signal since it could then just end up
7419 * looping round and round indefinitely.
7420 */
7421 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7422 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7423 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7424 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7425 }
7426
Peter Maydell31efaef2016-07-06 15:09:29 +01007427 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007428 }
7429
Peter Maydell3d3efba2016-05-27 15:51:49 +01007430 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7431 blocked_set = ts->in_sigsuspend ?
7432 &ts->sigsuspend_mask : &ts->signal_mask;
7433
7434 if (ts->sigtab[sig - 1].pending &&
7435 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007436 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007437 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007438 /* Restart scan from the beginning, as handle_pending_signal
7439 * might have resulted in a new synchronous signal (eg SIGSEGV).
7440 */
7441 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007442 }
Peter Maydelle902d582016-05-27 15:51:44 +01007443 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007444
7445 /* if no signal is pending, unblock signals and recheck (the act
7446 * of unblocking might cause us to take another host signal which
7447 * will set signal_pending again).
7448 */
7449 atomic_set(&ts->signal_pending, 0);
7450 ts->in_sigsuspend = 0;
7451 set = ts->signal_mask;
7452 sigdelset(&set, SIGSEGV);
7453 sigdelset(&set, SIGBUS);
7454 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007455 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007456 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007457}