blob: b283270391380c7c6ad311deb76935ef7087cc86 [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
Peter Maydellaac8f552018-04-12 15:02:22 +01001846 /* We must always provide at least the standard 4K reserved space,
1847 * even if we don't use all of it (this is part of the ABI)
1848 */
1849 layout.total_size = MAX(layout.total_size,
1850 sizeof(struct target_rt_sigframe));
1851
Richard Henderson8c5931d2018-03-09 17:09:44 +00001852 /* Reserve space for the return code. On a real system this would
1853 * be within the VDSO. So, despite the name this is not a "real"
1854 * record within the frame.
1855 */
1856 fr_ofs = layout.total_size;
1857 layout.total_size += sizeof(struct target_rt_frame_record);
1858
1859 frame_addr = get_sigframe(ka, env, layout.total_size);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001860 trace_user_setup_frame(env, frame_addr);
Peter Maydellbb3ba352018-04-16 16:19:23 +01001861 frame = lock_user(VERIFY_WRITE, frame_addr, layout.total_size, 0);
1862 if (!frame) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001863 goto give_sigsegv;
1864 }
1865
Richard Henderson3b505bb2018-03-09 17:09:43 +00001866 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001867 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson8c5931d2018-03-09 17:09:44 +00001868 target_setup_end_record((void *)frame + layout.std_end_ofs);
1869 if (layout.extra_ofs) {
1870 target_setup_extra_record((void *)frame + layout.extra_ofs,
1871 frame_addr + layout.extra_base,
1872 layout.extra_size);
1873 target_setup_end_record((void *)frame + layout.extra_end_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001874 }
Richard Henderson8c5931d2018-03-09 17:09:44 +00001875 if (sve_ofs) {
1876 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001877 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001878
1879 /* Set up the stack frame for unwinding. */
1880 fr = (void *)frame + fr_ofs;
1881 __put_user(env->xregs[29], &fr->fp);
1882 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001883
Michael Matz8a3ae912014-03-02 19:36:39 +00001884 if (ka->sa_flags & TARGET_SA_RESTORER) {
1885 return_addr = ka->sa_restorer;
1886 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001887 /*
1888 * mov x8,#__NR_rt_sigreturn; svc #0
1889 * Since these are instructions they need to be put as little-endian
1890 * regardless of target default or current CPU endianness.
1891 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001892 __put_user_e(0xd2801168, &fr->tramp[0], le);
1893 __put_user_e(0xd4000001, &fr->tramp[1], le);
1894 return_addr = frame_addr + fr_ofs
1895 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001896 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001897 env->xregs[0] = usig;
1898 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001899 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001900 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001901 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001902 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001903 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001904 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1905 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1906 }
1907
Peter Maydellbb3ba352018-04-16 16:19:23 +01001908 unlock_user(frame, frame_addr, layout.total_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001909 return;
1910
1911 give_sigsegv:
Peter Maydellbb3ba352018-04-16 16:19:23 +01001912 unlock_user(frame, frame_addr, layout.total_size);
Peter Maydell09391662016-07-28 16:44:47 +01001913 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001914}
1915
1916static void setup_rt_frame(int sig, struct target_sigaction *ka,
1917 target_siginfo_t *info, target_sigset_t *set,
1918 CPUARMState *env)
1919{
1920 target_setup_frame(sig, ka, info, set, env);
1921}
1922
1923static void setup_frame(int sig, struct target_sigaction *ka,
1924 target_sigset_t *set, CPUARMState *env)
1925{
1926 target_setup_frame(sig, ka, 0, set, env);
1927}
1928
1929long do_rt_sigreturn(CPUARMState *env)
1930{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001931 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001932 abi_ulong frame_addr = env->xregs[31];
1933
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001934 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001935 if (frame_addr & 15) {
1936 goto badframe;
1937 }
1938
1939 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1940 goto badframe;
1941 }
1942
1943 if (target_restore_sigframe(env, frame)) {
1944 goto badframe;
1945 }
1946
1947 if (do_sigaltstack(frame_addr +
1948 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1949 0, get_sp_from_cpustate(env)) == -EFAULT) {
1950 goto badframe;
1951 }
1952
1953 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001954 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001955
1956 badframe:
1957 unlock_user_struct(frame, frame_addr, 0);
1958 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001959 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001960}
1961
1962long do_sigreturn(CPUARMState *env)
1963{
1964 return do_rt_sigreturn(env);
1965}
1966
bellard43fff232003-07-09 19:31:39 +00001967#elif defined(TARGET_ARM)
1968
1969struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001970 abi_ulong trap_no;
1971 abi_ulong error_code;
1972 abi_ulong oldmask;
1973 abi_ulong arm_r0;
1974 abi_ulong arm_r1;
1975 abi_ulong arm_r2;
1976 abi_ulong arm_r3;
1977 abi_ulong arm_r4;
1978 abi_ulong arm_r5;
1979 abi_ulong arm_r6;
1980 abi_ulong arm_r7;
1981 abi_ulong arm_r8;
1982 abi_ulong arm_r9;
1983 abi_ulong arm_r10;
1984 abi_ulong arm_fp;
1985 abi_ulong arm_ip;
1986 abi_ulong arm_sp;
1987 abi_ulong arm_lr;
1988 abi_ulong arm_pc;
1989 abi_ulong arm_cpsr;
1990 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001991};
1992
pbrooka745ec62008-05-06 15:36:17 +00001993struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001994 abi_ulong tuc_flags;
1995 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001996 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001997 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001998 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001999};
2000
pbrooka745ec62008-05-06 15:36:17 +00002001struct target_ucontext_v2 {
2002 abi_ulong tuc_flags;
2003 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05002004 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00002005 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05002006 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00002007 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00002008 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
2009};
2010
Peter Maydell0d871bd2010-11-24 15:20:05 +00002011struct target_user_vfp {
2012 uint64_t fpregs[32];
2013 abi_ulong fpscr;
2014};
2015
2016struct target_user_vfp_exc {
2017 abi_ulong fpexc;
2018 abi_ulong fpinst;
2019 abi_ulong fpinst2;
2020};
2021
2022struct target_vfp_sigframe {
2023 abi_ulong magic;
2024 abi_ulong size;
2025 struct target_user_vfp ufp;
2026 struct target_user_vfp_exc ufp_exc;
2027} __attribute__((__aligned__(8)));
2028
Peter Maydell08e11252010-11-24 15:20:07 +00002029struct target_iwmmxt_sigframe {
2030 abi_ulong magic;
2031 abi_ulong size;
2032 uint64_t regs[16];
2033 /* Note that not all the coprocessor control registers are stored here */
2034 uint32_t wcssf;
2035 uint32_t wcasf;
2036 uint32_t wcgr0;
2037 uint32_t wcgr1;
2038 uint32_t wcgr2;
2039 uint32_t wcgr3;
2040} __attribute__((__aligned__(8)));
2041
Peter Maydell0d871bd2010-11-24 15:20:05 +00002042#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00002043#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00002044
pbrooka8c33202008-05-07 23:22:46 +00002045struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002046{
2047 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00002048 abi_ulong extramask[TARGET_NSIG_WORDS-1];
2049 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002050};
2051
pbrooka8c33202008-05-07 23:22:46 +00002052struct sigframe_v2
2053{
2054 struct target_ucontext_v2 uc;
2055 abi_ulong retcode;
2056};
2057
pbrooka745ec62008-05-06 15:36:17 +00002058struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002059{
bellardf8b0aa22007-11-11 23:03:42 +00002060 abi_ulong pinfo;
2061 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00002062 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00002063 struct target_ucontext_v1 uc;
2064 abi_ulong retcode;
2065};
2066
2067struct rt_sigframe_v2
2068{
2069 struct target_siginfo info;
2070 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00002071 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002072};
2073
2074#define TARGET_CONFIG_CPU_32 1
2075
2076/*
2077 * For ARM syscalls, we encode the syscall number into the instruction.
2078 */
2079#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
2080#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
2081
2082/*
2083 * For Thumb syscalls, we pass the syscall number via r7. We therefore
2084 * need two 16-bit instructions.
2085 */
2086#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
2087#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
2088
blueswir1992f48a2007-10-14 16:27:31 +00002089static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00002090 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
2091 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
2092};
2093
2094
Andreas Färber05390242012-02-25 03:37:53 +01002095static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00002096{
2097 return 1;
2098}
2099
pbrooka8c33202008-05-07 23:22:46 +00002100static void
bellard43fff232003-07-09 19:31:39 +00002101setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002102 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00002103{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002104 __put_user(env->regs[0], &sc->arm_r0);
2105 __put_user(env->regs[1], &sc->arm_r1);
2106 __put_user(env->regs[2], &sc->arm_r2);
2107 __put_user(env->regs[3], &sc->arm_r3);
2108 __put_user(env->regs[4], &sc->arm_r4);
2109 __put_user(env->regs[5], &sc->arm_r5);
2110 __put_user(env->regs[6], &sc->arm_r6);
2111 __put_user(env->regs[7], &sc->arm_r7);
2112 __put_user(env->regs[8], &sc->arm_r8);
2113 __put_user(env->regs[9], &sc->arm_r9);
2114 __put_user(env->regs[10], &sc->arm_r10);
2115 __put_user(env->regs[11], &sc->arm_fp);
2116 __put_user(env->regs[12], &sc->arm_ip);
2117 __put_user(env->regs[13], &sc->arm_sp);
2118 __put_user(env->regs[14], &sc->arm_lr);
2119 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002120#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002121 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00002122#endif
2123
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002124 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
2125 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
2126 __put_user(/* current->thread.address */ 0, &sc->fault_address);
2127 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00002128}
2129
bellard579a97f2007-11-11 14:26:47 +00002130static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002131get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00002132{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002133 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00002134
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002135 /*
2136 * This is the X/Open sanctioned signal stack switching.
2137 */
2138 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
2139 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2140 }
2141 /*
2142 * ATPCS B01 mandates 8-byte alignment
2143 */
2144 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00002145}
2146
Riku Voipio0188fad2014-04-23 13:34:15 +03002147static void
Andreas Färber05390242012-02-25 03:37:53 +01002148setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002149 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00002150{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002151 abi_ulong handler = ka->_sa_handler;
2152 abi_ulong retcode;
2153 int thumb = handler & 1;
2154 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01002155
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002156 cpsr &= ~CPSR_IT;
2157 if (thumb) {
2158 cpsr |= CPSR_T;
2159 } else {
2160 cpsr &= ~CPSR_T;
2161 }
bellard43fff232003-07-09 19:31:39 +00002162
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002163 if (ka->sa_flags & TARGET_SA_RESTORER) {
2164 retcode = ka->sa_restorer;
2165 } else {
2166 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00002167
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002168 if (ka->sa_flags & TARGET_SA_SIGINFO) {
2169 idx += 2;
2170 }
bellard43fff232003-07-09 19:31:39 +00002171
Riku Voipio0188fad2014-04-23 13:34:15 +03002172 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02002173
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002174 retcode = rc_addr + thumb;
2175 }
bellard43fff232003-07-09 19:31:39 +00002176
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002177 env->regs[0] = usig;
2178 env->regs[13] = frame_addr;
2179 env->regs[14] = retcode;
2180 env->regs[15] = handler & (thumb ? ~1 : ~3);
2181 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002182}
2183
Andreas Färber05390242012-02-25 03:37:53 +01002184static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002185{
2186 int i;
2187 struct target_vfp_sigframe *vfpframe;
2188 vfpframe = (struct target_vfp_sigframe *)regspace;
2189 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2190 __put_user(sizeof(*vfpframe), &vfpframe->size);
2191 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002192 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002193 }
2194 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2195 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2196 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2197 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2198 return (abi_ulong*)(vfpframe+1);
2199}
2200
Andreas Färber05390242012-02-25 03:37:53 +01002201static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2202 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002203{
2204 int i;
2205 struct target_iwmmxt_sigframe *iwmmxtframe;
2206 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2207 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2208 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2209 for (i = 0; i < 16; i++) {
2210 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2211 }
2212 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2213 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2214 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2215 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2216 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2217 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2218 return (abi_ulong*)(iwmmxtframe+1);
2219}
2220
pbrooka8c33202008-05-07 23:22:46 +00002221static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002222 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002223{
pbrooka8c33202008-05-07 23:22:46 +00002224 struct target_sigaltstack stack;
2225 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002226 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002227
2228 /* Clear all the bits of the ucontext we don't use. */
2229 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2230
2231 memset(&stack, 0, sizeof(stack));
2232 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2233 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2234 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2235 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2236
2237 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002238 /* Save coprocessor signal frame. */
2239 regspace = uc->tuc_regspace;
2240 if (arm_feature(env, ARM_FEATURE_VFP)) {
2241 regspace = setup_sigframe_v2_vfp(regspace, env);
2242 }
Peter Maydell08e11252010-11-24 15:20:07 +00002243 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2244 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2245 }
2246
Peter Maydell0d871bd2010-11-24 15:20:05 +00002247 /* Write terminating magic word */
2248 __put_user(0, regspace);
2249
pbrooka8c33202008-05-07 23:22:46 +00002250 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2251 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2252 }
2253}
2254
2255/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002256static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002257 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002258{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002259 struct sigframe_v1 *frame;
2260 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2261 int i;
bellard43fff232003-07-09 19:31:39 +00002262
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002263 trace_user_setup_frame(regs, frame_addr);
2264 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002265 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002266 }
bellard579a97f2007-11-11 14:26:47 +00002267
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002268 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002269
Riku Voipio0188fad2014-04-23 13:34:15 +03002270 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2271 __put_user(set->sig[i], &frame->extramask[i - 1]);
2272 }
bellard43fff232003-07-09 19:31:39 +00002273
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002274 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2275 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002276
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002277 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002278 return;
2279sigsegv:
2280 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002281}
2282
pbrook624f7972008-05-31 16:11:38 +00002283static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002284 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002285{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002286 struct sigframe_v2 *frame;
2287 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002288
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002289 trace_user_setup_frame(regs, frame_addr);
2290 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002291 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002292 }
pbrooka8c33202008-05-07 23:22:46 +00002293
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002294 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002295
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002296 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2297 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002298
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002299 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002300 return;
2301sigsegv:
2302 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002303}
2304
pbrook624f7972008-05-31 16:11:38 +00002305static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002306 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002307{
2308 if (get_osversion() >= 0x020612) {
2309 setup_frame_v2(usig, ka, set, regs);
2310 } else {
2311 setup_frame_v1(usig, ka, set, regs);
2312 }
bellard43fff232003-07-09 19:31:39 +00002313}
2314
bellard579a97f2007-11-11 14:26:47 +00002315/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002316static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002317 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002318 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002319{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002320 struct rt_sigframe_v1 *frame;
2321 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2322 struct target_sigaltstack stack;
2323 int i;
2324 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002325
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002326 trace_user_setup_rt_frame(env, frame_addr);
2327 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002328 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002329 }
bellardedf779f2004-02-22 13:40:13 +00002330
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002331 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2332 __put_user(info_addr, &frame->pinfo);
2333 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2334 __put_user(uc_addr, &frame->puc);
2335 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002336
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002337 /* Clear all the bits of the ucontext we don't use. */
2338 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002339
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002340 memset(&stack, 0, sizeof(stack));
2341 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2342 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2343 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2344 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002345
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002346 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2347 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2348 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2349 }
bellard43fff232003-07-09 19:31:39 +00002350
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002351 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2352 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002353
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002354 env->regs[1] = info_addr;
2355 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002356
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002357 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002358 return;
2359sigsegv:
2360 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002361}
2362
pbrook624f7972008-05-31 16:11:38 +00002363static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002364 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002365 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002366{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002367 struct rt_sigframe_v2 *frame;
2368 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2369 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002370
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002371 trace_user_setup_rt_frame(env, frame_addr);
2372 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002373 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002374 }
pbrooka745ec62008-05-06 15:36:17 +00002375
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002376 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2377 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2378 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002379
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002380 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002381
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002382 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2383 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002384
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002385 env->regs[1] = info_addr;
2386 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002387
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002388 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002389 return;
2390sigsegv:
2391 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002392}
2393
pbrook624f7972008-05-31 16:11:38 +00002394static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002395 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002396 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002397{
2398 if (get_osversion() >= 0x020612) {
2399 setup_rt_frame_v2(usig, ka, info, set, env);
2400 } else {
2401 setup_rt_frame_v1(usig, ka, info, set, env);
2402 }
2403}
2404
bellard43fff232003-07-09 19:31:39 +00002405static int
Andreas Färber05390242012-02-25 03:37:53 +01002406restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002407{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002408 int err = 0;
2409 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002410
Riku Voipio1d8b5122014-04-23 10:26:05 +03002411 __get_user(env->regs[0], &sc->arm_r0);
2412 __get_user(env->regs[1], &sc->arm_r1);
2413 __get_user(env->regs[2], &sc->arm_r2);
2414 __get_user(env->regs[3], &sc->arm_r3);
2415 __get_user(env->regs[4], &sc->arm_r4);
2416 __get_user(env->regs[5], &sc->arm_r5);
2417 __get_user(env->regs[6], &sc->arm_r6);
2418 __get_user(env->regs[7], &sc->arm_r7);
2419 __get_user(env->regs[8], &sc->arm_r8);
2420 __get_user(env->regs[9], &sc->arm_r9);
2421 __get_user(env->regs[10], &sc->arm_r10);
2422 __get_user(env->regs[11], &sc->arm_fp);
2423 __get_user(env->regs[12], &sc->arm_ip);
2424 __get_user(env->regs[13], &sc->arm_sp);
2425 __get_user(env->regs[14], &sc->arm_lr);
2426 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002427#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002428 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002429 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002430#endif
2431
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002432 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002433
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002434 return err;
bellard43fff232003-07-09 19:31:39 +00002435}
2436
Andreas Färber05390242012-02-25 03:37:53 +01002437static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002438{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002439 abi_ulong frame_addr;
2440 struct sigframe_v1 *frame = NULL;
2441 target_sigset_t set;
2442 sigset_t host_set;
2443 int i;
bellard43fff232003-07-09 19:31:39 +00002444
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002445 /*
2446 * Since we stacked the signal on a 64-bit boundary,
2447 * then 'sp' should be word aligned here. If it's
2448 * not, then the user is trying to mess with us.
2449 */
2450 frame_addr = env->regs[13];
2451 trace_user_do_sigreturn(env, frame_addr);
2452 if (frame_addr & 7) {
2453 goto badframe;
2454 }
Peter Maydell978fae92013-07-29 12:00:32 +01002455
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002456 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2457 goto badframe;
2458 }
bellard43fff232003-07-09 19:31:39 +00002459
Riku Voipiof5f601a2014-04-23 13:00:17 +03002460 __get_user(set.sig[0], &frame->sc.oldmask);
2461 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2462 __get_user(set.sig[i], &frame->extramask[i - 1]);
2463 }
bellard43fff232003-07-09 19:31:39 +00002464
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002465 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002466 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002467
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002468 if (restore_sigcontext(env, &frame->sc)) {
2469 goto badframe;
2470 }
bellard43fff232003-07-09 19:31:39 +00002471
2472#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002473 /* Send SIGTRAP if we're single-stepping */
2474 if (ptrace_cancel_bpt(current))
2475 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002476#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002477 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002478 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002479
2480badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002481 force_sig(TARGET_SIGSEGV);
2482 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002483}
2484
Andreas Färber05390242012-02-25 03:37:53 +01002485static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002486{
2487 int i;
2488 abi_ulong magic, sz;
2489 uint32_t fpscr, fpexc;
2490 struct target_vfp_sigframe *vfpframe;
2491 vfpframe = (struct target_vfp_sigframe *)regspace;
2492
2493 __get_user(magic, &vfpframe->magic);
2494 __get_user(sz, &vfpframe->size);
2495 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2496 return 0;
2497 }
2498 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002499 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002500 }
2501 __get_user(fpscr, &vfpframe->ufp.fpscr);
2502 vfp_set_fpscr(env, fpscr);
2503 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2504 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2505 * and the exception flag is cleared
2506 */
2507 fpexc |= (1 << 30);
2508 fpexc &= ~((1 << 31) | (1 << 28));
2509 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2510 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2511 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2512 return (abi_ulong*)(vfpframe + 1);
2513}
2514
Andreas Färber05390242012-02-25 03:37:53 +01002515static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2516 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002517{
2518 int i;
2519 abi_ulong magic, sz;
2520 struct target_iwmmxt_sigframe *iwmmxtframe;
2521 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2522
2523 __get_user(magic, &iwmmxtframe->magic);
2524 __get_user(sz, &iwmmxtframe->size);
2525 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2526 return 0;
2527 }
2528 for (i = 0; i < 16; i++) {
2529 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2530 }
2531 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2532 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2533 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2534 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2535 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2536 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2537 return (abi_ulong*)(iwmmxtframe + 1);
2538}
2539
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002540static int do_sigframe_return_v2(CPUARMState *env,
2541 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002542 struct target_ucontext_v2 *uc)
2543{
2544 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002545 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002546
2547 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002548 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002549
2550 if (restore_sigcontext(env, &uc->tuc_mcontext))
2551 return 1;
2552
Peter Maydell5f9099d2010-11-24 15:20:06 +00002553 /* Restore coprocessor signal frame */
2554 regspace = uc->tuc_regspace;
2555 if (arm_feature(env, ARM_FEATURE_VFP)) {
2556 regspace = restore_sigframe_v2_vfp(env, regspace);
2557 if (!regspace) {
2558 return 1;
2559 }
2560 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002561 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2562 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2563 if (!regspace) {
2564 return 1;
2565 }
2566 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002567
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002568 if (do_sigaltstack(context_addr
2569 + offsetof(struct target_ucontext_v2, tuc_stack),
2570 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002571 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002572 }
pbrooka8c33202008-05-07 23:22:46 +00002573
2574#if 0
2575 /* Send SIGTRAP if we're single-stepping */
2576 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002577 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002578#endif
2579
2580 return 0;
2581}
2582
Andreas Färber05390242012-02-25 03:37:53 +01002583static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002584{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002585 abi_ulong frame_addr;
2586 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002587
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002588 /*
2589 * Since we stacked the signal on a 64-bit boundary,
2590 * then 'sp' should be word aligned here. If it's
2591 * not, then the user is trying to mess with us.
2592 */
2593 frame_addr = env->regs[13];
2594 trace_user_do_sigreturn(env, frame_addr);
2595 if (frame_addr & 7) {
2596 goto badframe;
2597 }
Peter Maydell978fae92013-07-29 12:00:32 +01002598
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002599 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2600 goto badframe;
2601 }
pbrooka8c33202008-05-07 23:22:46 +00002602
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002603 if (do_sigframe_return_v2(env,
2604 frame_addr
2605 + offsetof(struct sigframe_v2, uc),
2606 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002607 goto badframe;
2608 }
pbrooka8c33202008-05-07 23:22:46 +00002609
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002610 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002611 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002612
2613badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002614 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002615 force_sig(TARGET_SIGSEGV);
2616 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002617}
2618
Andreas Färber05390242012-02-25 03:37:53 +01002619long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002620{
2621 if (get_osversion() >= 0x020612) {
2622 return do_sigreturn_v2(env);
2623 } else {
2624 return do_sigreturn_v1(env);
2625 }
2626}
2627
Andreas Färber05390242012-02-25 03:37:53 +01002628static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002629{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002630 abi_ulong frame_addr;
2631 struct rt_sigframe_v1 *frame = NULL;
2632 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002633
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002634 /*
2635 * Since we stacked the signal on a 64-bit boundary,
2636 * then 'sp' should be word aligned here. If it's
2637 * not, then the user is trying to mess with us.
2638 */
2639 frame_addr = env->regs[13];
2640 trace_user_do_rt_sigreturn(env, frame_addr);
2641 if (frame_addr & 7) {
2642 goto badframe;
2643 }
Peter Maydell978fae92013-07-29 12:00:32 +01002644
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002645 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2646 goto badframe;
2647 }
bellard43fff232003-07-09 19:31:39 +00002648
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002649 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002650 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002651
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002652 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2653 goto badframe;
2654 }
bellard43fff232003-07-09 19:31:39 +00002655
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002656 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2657 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002658
bellard43fff232003-07-09 19:31:39 +00002659#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002660 /* Send SIGTRAP if we're single-stepping */
2661 if (ptrace_cancel_bpt(current))
2662 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002663#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002664 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002665 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002666
2667badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002668 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002669 force_sig(TARGET_SIGSEGV);
2670 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002671}
2672
Andreas Färber05390242012-02-25 03:37:53 +01002673static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002674{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002675 abi_ulong frame_addr;
2676 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002677
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002678 /*
2679 * Since we stacked the signal on a 64-bit boundary,
2680 * then 'sp' should be word aligned here. If it's
2681 * not, then the user is trying to mess with us.
2682 */
2683 frame_addr = env->regs[13];
2684 trace_user_do_rt_sigreturn(env, frame_addr);
2685 if (frame_addr & 7) {
2686 goto badframe;
2687 }
Peter Maydell978fae92013-07-29 12:00:32 +01002688
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002689 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2690 goto badframe;
2691 }
pbrooka745ec62008-05-06 15:36:17 +00002692
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002693 if (do_sigframe_return_v2(env,
2694 frame_addr
2695 + offsetof(struct rt_sigframe_v2, uc),
2696 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002697 goto badframe;
2698 }
pbrooka745ec62008-05-06 15:36:17 +00002699
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002700 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002701 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002702
2703badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002704 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002705 force_sig(TARGET_SIGSEGV);
2706 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002707}
2708
Andreas Färber05390242012-02-25 03:37:53 +01002709long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002710{
2711 if (get_osversion() >= 0x020612) {
2712 return do_rt_sigreturn_v2(env);
2713 } else {
2714 return do_rt_sigreturn_v1(env);
2715 }
2716}
2717
bellard6d5e2162004-09-30 22:04:13 +00002718#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002719
bellard6d5e2162004-09-30 22:04:13 +00002720#define __SUNOS_MAXWIN 31
2721
2722/* This is what SunOS does, so shall I. */
2723struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002724 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002725
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002726 abi_ulong sigc_mask; /* sigmask to restore */
2727 abi_ulong sigc_sp; /* stack pointer */
2728 abi_ulong sigc_pc; /* program counter */
2729 abi_ulong sigc_npc; /* next program counter */
2730 abi_ulong sigc_psr; /* for condition codes etc */
2731 abi_ulong sigc_g1; /* User uses these two registers */
2732 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002733
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002734 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002735 * at the time of the signal.
2736 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002737 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002738
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002739 /* stack ptrs for each regwin buf */
2740 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002741
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002742 /* Windows to restore after signal */
2743 struct {
2744 abi_ulong locals[8];
2745 abi_ulong ins[8];
2746 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002747};
2748/* A Sparc stack frame */
2749struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002750 abi_ulong locals[8];
2751 abi_ulong ins[8];
2752 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002753 * since we never need to access them ourselves.
2754 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002755 char *structptr;
2756 abi_ulong xargs[6];
2757 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002758};
2759
2760typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002761 struct {
2762 abi_ulong psr;
2763 abi_ulong pc;
2764 abi_ulong npc;
2765 abi_ulong y;
2766 abi_ulong u_regs[16]; /* globals and ins */
2767 } si_regs;
2768 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002769} __siginfo_t;
2770
2771typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002772 abi_ulong si_float_regs[32];
2773 unsigned long si_fsr;
2774 unsigned long si_fpqdepth;
2775 struct {
2776 unsigned long *insn_addr;
2777 unsigned long insn;
2778 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002779} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002780
2781
2782struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002783 struct sparc_stackf ss;
2784 __siginfo_t info;
2785 abi_ulong fpu_save;
2786 abi_ulong insns[2] __attribute__ ((aligned (8)));
2787 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2788 abi_ulong extra_size; /* Should be 0 */
2789 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002790};
2791struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002792 struct sparc_stackf ss;
2793 siginfo_t info;
2794 abi_ulong regs[20];
2795 sigset_t mask;
2796 abi_ulong fpu_save;
2797 unsigned int insns[2];
2798 stack_t stack;
2799 unsigned int extra_size; /* Should be 0 */
2800 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002801};
2802
bellarde80cfcf2004-12-19 23:18:01 +00002803#define UREG_O0 16
2804#define UREG_O6 22
2805#define UREG_I0 0
2806#define UREG_I1 1
2807#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002808#define UREG_I3 3
2809#define UREG_I4 4
2810#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002811#define UREG_I6 6
2812#define UREG_I7 7
2813#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002814#define UREG_FP UREG_I6
2815#define UREG_SP UREG_O6
2816
pbrook624f7972008-05-31 16:11:38 +00002817static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002818 CPUSPARCState *env,
2819 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002820{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002821 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002822
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002823 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002824
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002825 /* This is the X/Open sanctioned signal stack switching. */
2826 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2827 if (!on_sig_stack(sp)
2828 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2829 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2830 }
2831 }
2832 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002833}
2834
2835static int
Andreas Färber05390242012-02-25 03:37:53 +01002836setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002837{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002838 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002839
Riku Voipio1d8b5122014-04-23 10:26:05 +03002840 __put_user(env->psr, &si->si_regs.psr);
2841 __put_user(env->pc, &si->si_regs.pc);
2842 __put_user(env->npc, &si->si_regs.npc);
2843 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002844 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002845 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002846 }
2847 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002848 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002849 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002850 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002851 return err;
bellard6d5e2162004-09-30 22:04:13 +00002852}
bellarde80cfcf2004-12-19 23:18:01 +00002853
bellard80a9d032005-01-03 23:31:27 +00002854#if 0
bellard6d5e2162004-09-30 22:04:13 +00002855static int
2856setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002857 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002858{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002859 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002860
Riku Voipio1d8b5122014-04-23 10:26:05 +03002861 __put_user(mask, &sc->sigc_mask);
2862 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2863 __put_user(env->pc, &sc->sigc_pc);
2864 __put_user(env->npc, &sc->sigc_npc);
2865 __put_user(env->psr, &sc->sigc_psr);
2866 __put_user(env->gregs[1], &sc->sigc_g1);
2867 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002868
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002869 return err;
bellard6d5e2162004-09-30 22:04:13 +00002870}
bellard80a9d032005-01-03 23:31:27 +00002871#endif
bellard6d5e2162004-09-30 22:04:13 +00002872#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2873
pbrook624f7972008-05-31 16:11:38 +00002874static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002875 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002876{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002877 abi_ulong sf_addr;
2878 struct target_signal_frame *sf;
2879 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002880
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002881 /* 1. Make sure everything is clean */
2882 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002883
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002884 sigframe_size = NF_ALIGNEDSZ;
2885 sf_addr = get_sigframe(ka, env, sigframe_size);
2886 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002887
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002888 sf = lock_user(VERIFY_WRITE, sf_addr,
2889 sizeof(struct target_signal_frame), 0);
2890 if (!sf) {
2891 goto sigsegv;
2892 }
bellard6d5e2162004-09-30 22:04:13 +00002893#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002894 if (invalid_frame_pointer(sf, sigframe_size))
2895 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002896#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002897 /* 2. Save the current process state */
2898 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002899 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002900
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002901 //save_fpu_state(regs, &sf->fpu_state);
2902 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002903
Riku Voipio1d8b5122014-04-23 10:26:05 +03002904 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002905 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002906 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002907 }
bellard6d5e2162004-09-30 22:04:13 +00002908
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002909 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002910 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002911 }
2912 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002913 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002914 }
2915 if (err)
2916 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002917
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002918 /* 3. signal handler back-trampoline and parameters */
2919 env->regwptr[UREG_FP] = sf_addr;
2920 env->regwptr[UREG_I0] = sig;
2921 env->regwptr[UREG_I1] = sf_addr +
2922 offsetof(struct target_signal_frame, info);
2923 env->regwptr[UREG_I2] = sf_addr +
2924 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002925
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002926 /* 4. signal handler */
2927 env->pc = ka->_sa_handler;
2928 env->npc = (env->pc + 4);
2929 /* 5. return to kernel instructions */
Laurent Vivier5de154e2018-04-02 12:24:52 +02002930 if (ka->ka_restorer) {
2931 env->regwptr[UREG_I7] = ka->ka_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002932 } else {
2933 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002934
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002935 env->regwptr[UREG_I7] = sf_addr +
2936 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002937
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002938 /* mov __NR_sigreturn, %g1 */
2939 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002940 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002941
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002942 /* t 0x10 */
2943 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002944 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002945 if (err)
2946 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002947
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002948 /* Flush instruction space. */
2949 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2950 // tb_flush(env);
2951 }
2952 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2953 return;
bellard459a4012007-11-11 19:45:10 +00002954#if 0
2955sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002956 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002957#endif
bellard6d5e2162004-09-30 22:04:13 +00002958sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002959 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002960 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002961}
bellard6d5e2162004-09-30 22:04:13 +00002962
pbrook624f7972008-05-31 16:11:38 +00002963static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002964 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002965 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002966{
2967 fprintf(stderr, "setup_rt_frame: not implemented\n");
2968}
2969
Andreas Färber05390242012-02-25 03:37:53 +01002970long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002971{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002972 abi_ulong sf_addr;
2973 struct target_signal_frame *sf;
2974 uint32_t up_psr, pc, npc;
2975 target_sigset_t set;
2976 sigset_t host_set;
2977 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002978
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002979 sf_addr = env->regwptr[UREG_FP];
2980 trace_user_do_sigreturn(env, sf_addr);
2981 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2982 goto segv_and_exit;
2983 }
bellard6d5e2162004-09-30 22:04:13 +00002984
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002985 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002986
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002987 if (sf_addr & 3)
2988 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002989
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002990 __get_user(pc, &sf->info.si_regs.pc);
2991 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002992
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002993 if ((pc | npc) & 3) {
2994 goto segv_and_exit;
2995 }
bellard6d5e2162004-09-30 22:04:13 +00002996
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002997 /* 2. Restore the state */
2998 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002999
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003000 /* User can only change condition codes and FPU enabling in %psr. */
3001 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
3002 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00003003
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003004 env->pc = pc;
3005 env->npc = npc;
3006 __get_user(env->y, &sf->info.si_regs.y);
3007 for (i=0; i < 8; i++) {
3008 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
3009 }
3010 for (i=0; i < 8; i++) {
3011 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
3012 }
bellard6d5e2162004-09-30 22:04:13 +00003013
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003014 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01003015 * __get_user(fpu_save, &sf->fpu_save);
3016 * if (fpu_save)
3017 * err |= restore_fpu_state(env, fpu_save);
3018 */
bellard6d5e2162004-09-30 22:04:13 +00003019
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003020 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00003021 * the races which exist anyways.
3022 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003023 __get_user(set.sig[0], &sf->info.si_mask);
3024 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3025 __get_user(set.sig[i], &sf->extramask[i - 1]);
3026 }
bellarde80cfcf2004-12-19 23:18:01 +00003027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003028 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003029 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00003030
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003031 if (err) {
3032 goto segv_and_exit;
3033 }
3034 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01003035 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003036
3037segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003038 unlock_user_struct(sf, sf_addr, 0);
3039 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003040 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003041}
3042
Andreas Färber05390242012-02-25 03:37:53 +01003043long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00003044{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003045 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00003046 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00003047 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00003048}
3049
bellard459a4012007-11-11 19:45:10 +00003050#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00003051#define SPARC_MC_TSTATE 0
3052#define SPARC_MC_PC 1
3053#define SPARC_MC_NPC 2
3054#define SPARC_MC_Y 3
3055#define SPARC_MC_G1 4
3056#define SPARC_MC_G2 5
3057#define SPARC_MC_G3 6
3058#define SPARC_MC_G4 7
3059#define SPARC_MC_G5 8
3060#define SPARC_MC_G6 9
3061#define SPARC_MC_G7 10
3062#define SPARC_MC_O0 11
3063#define SPARC_MC_O1 12
3064#define SPARC_MC_O2 13
3065#define SPARC_MC_O3 14
3066#define SPARC_MC_O4 15
3067#define SPARC_MC_O5 16
3068#define SPARC_MC_O6 17
3069#define SPARC_MC_O7 18
3070#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00003071
Anthony Liguoric227f092009-10-01 16:12:16 -05003072typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003073typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00003074
3075struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00003076 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003077 uint32_t mcfq_insn;
3078};
3079
3080struct target_mc_fpu {
3081 union {
3082 uint32_t sregs[32];
3083 uint64_t dregs[32];
3084 //uint128_t qregs[16];
3085 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00003086 abi_ulong mcfpu_fsr;
3087 abi_ulong mcfpu_fprs;
3088 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00003089 struct target_mc_fq *mcfpu_fq;
3090 unsigned char mcfpu_qcnt;
3091 unsigned char mcfpu_qentsz;
3092 unsigned char mcfpu_enab;
3093};
Anthony Liguoric227f092009-10-01 16:12:16 -05003094typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003095
3096typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05003097 target_mc_gregset_t mc_gregs;
3098 target_mc_greg_t mc_fp;
3099 target_mc_greg_t mc_i7;
3100 target_mc_fpu_t mc_fpregs;
3101} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003102
3103struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003104 struct target_ucontext *tuc_link;
3105 abi_ulong tuc_flags;
3106 target_sigset_t tuc_sigmask;
3107 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003108};
3109
3110/* A V9 register window */
3111struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00003112 abi_ulong locals[8];
3113 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00003114};
3115
3116#define TARGET_STACK_BIAS 2047
3117
3118/* {set, get}context() needed for 64-bit SparcLinux userland. */
3119void sparc64_set_context(CPUSPARCState *env)
3120{
bellard459a4012007-11-11 19:45:10 +00003121 abi_ulong ucp_addr;
3122 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003123 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00003124 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00003125 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003126 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00003127
bellard459a4012007-11-11 19:45:10 +00003128 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003129 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00003130 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003131 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02003132 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003133 __get_user(pc, &((*grp)[SPARC_MC_PC]));
3134 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003135 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00003136 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003137 }
blueswir15bfb56b2007-10-05 17:01:51 +00003138 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05003139 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003140 sigset_t set;
3141
3142 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003143 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00003144 } else {
bellard459a4012007-11-11 19:45:10 +00003145 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003146 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00003147 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003148 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003149 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003150 }
blueswir15bfb56b2007-10-05 17:01:51 +00003151 }
3152 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003153 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00003154 }
3155 env->pc = pc;
3156 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003157 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
3158 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00003159 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00003160 cpu_put_ccr(env, tstate >> 32);
3161 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00003162 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
3163 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
3164 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
3165 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
3166 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
3167 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
3168 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
3169 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
3170 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
3171 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
3172 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
3173 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
3174 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
3175 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
3176 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003177
Riku Voipio1d8b5122014-04-23 10:26:05 +03003178 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3179 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003180
bellard459a4012007-11-11 19:45:10 +00003181 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003182 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3183 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003184 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003185 }
3186 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3187 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003188 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003189 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003190 /* FIXME this does not match how the kernel handles the FPU in
3191 * its sparc64_set_context implementation. In particular the FPU
3192 * is only restored if fenab is non-zero in:
3193 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3194 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003195 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003196 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003197 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3198 for (i = 0; i < 64; i++, src++) {
3199 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003200 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003201 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003202 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003203 }
3204 }
bellard459a4012007-11-11 19:45:10 +00003205 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003206 __get_user(env->fsr,
3207 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3208 __get_user(env->gsr,
3209 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003210 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003211 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003212do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003213 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003214 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003215}
3216
3217void sparc64_get_context(CPUSPARCState *env)
3218{
bellard459a4012007-11-11 19:45:10 +00003219 abi_ulong ucp_addr;
3220 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003221 target_mc_gregset_t *grp;
3222 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003223 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003224 int err;
3225 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003226 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003227 sigset_t set;
3228
bellard459a4012007-11-11 19:45:10 +00003229 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003230 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003231 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003232 }
bellard459a4012007-11-11 19:45:10 +00003233
Aurelien Jarno60e99242010-03-29 02:12:51 +02003234 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003235 grp = &mcp->mc_gregs;
3236
3237 /* Skip over the trap instruction, first. */
3238 env->pc = env->npc;
3239 env->npc += 4;
3240
Peter Maydell3d3efba2016-05-27 15:51:49 +01003241 /* If we're only reading the signal mask then do_sigprocmask()
3242 * is guaranteed not to fail, which is important because we don't
3243 * have any way to signal a failure or restart this operation since
3244 * this is not a normal syscall.
3245 */
3246 err = do_sigprocmask(0, NULL, &set);
3247 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003248 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003249 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003250 __put_user(target_set.sig[0],
3251 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003252 } else {
3253 abi_ulong *src, *dst;
3254 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003255 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003256 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003257 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003258 }
blueswir15bfb56b2007-10-05 17:01:51 +00003259 if (err)
3260 goto do_sigsegv;
3261 }
3262
bellard459a4012007-11-11 19:45:10 +00003263 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003264 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3265 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3266 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3267 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3268 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3269 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3270 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3271 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3272 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3273 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3274 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3275 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3276 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3277 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3278 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3279 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3280 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3281 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3282 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003283
bellard459a4012007-11-11 19:45:10 +00003284 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3285 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003286 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3287 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003288 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003289 }
3290 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3291 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003292 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003293 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003294 __put_user(fp, &(mcp->mc_fp));
3295 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003296
bellard459a4012007-11-11 19:45:10 +00003297 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003298 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3299 for (i = 0; i < 64; i++, dst++) {
3300 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003301 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003302 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003303 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003304 }
3305 }
bellard459a4012007-11-11 19:45:10 +00003306 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003307 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3308 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3309 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003310
3311 if (err)
3312 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003313 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003314 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003315do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003316 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003317 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003318}
3319#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003320#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003321
Richard Hendersonff970902013-02-10 10:30:42 -08003322# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003323struct target_sigcontext {
3324 uint32_t sc_regmask; /* Unused */
3325 uint32_t sc_status;
3326 uint64_t sc_pc;
3327 uint64_t sc_regs[32];
3328 uint64_t sc_fpregs[32];
3329 uint32_t sc_ownedfp; /* Unused */
3330 uint32_t sc_fpc_csr;
3331 uint32_t sc_fpc_eir; /* Unused */
3332 uint32_t sc_used_math;
3333 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003334 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003335 uint64_t sc_mdhi;
3336 uint64_t sc_mdlo;
3337 target_ulong sc_hi1; /* Was sc_cause */
3338 target_ulong sc_lo1; /* Was sc_badvaddr */
3339 target_ulong sc_hi2; /* Was sc_sigset[4] */
3340 target_ulong sc_lo2;
3341 target_ulong sc_hi3;
3342 target_ulong sc_lo3;
3343};
Richard Hendersonff970902013-02-10 10:30:42 -08003344# else /* N32 || N64 */
3345struct target_sigcontext {
3346 uint64_t sc_regs[32];
3347 uint64_t sc_fpregs[32];
3348 uint64_t sc_mdhi;
3349 uint64_t sc_hi1;
3350 uint64_t sc_hi2;
3351 uint64_t sc_hi3;
3352 uint64_t sc_mdlo;
3353 uint64_t sc_lo1;
3354 uint64_t sc_lo2;
3355 uint64_t sc_lo3;
3356 uint64_t sc_pc;
3357 uint32_t sc_fpc_csr;
3358 uint32_t sc_used_math;
3359 uint32_t sc_dsp;
3360 uint32_t sc_reserved;
3361};
3362# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003363
3364struct sigframe {
3365 uint32_t sf_ass[4]; /* argument save space for o32 */
3366 uint32_t sf_code[2]; /* signal trampoline */
3367 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003368 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003369};
3370
pbrook0b1bcb02009-04-21 01:41:10 +00003371struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003372 target_ulong tuc_flags;
3373 target_ulong tuc_link;
3374 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003375 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003376 struct target_sigcontext tuc_mcontext;
3377 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003378};
3379
3380struct target_rt_sigframe {
3381 uint32_t rs_ass[4]; /* argument save space for o32 */
3382 uint32_t rs_code[2]; /* signal trampoline */
3383 struct target_siginfo rs_info;
3384 struct target_ucontext rs_uc;
3385};
3386
bellard106ec872006-06-27 21:08:10 +00003387/* Install trampoline to jump back from signal handler */
3388static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3389{
Richard Henderson084d0492013-02-10 10:30:44 -08003390 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003391
3392 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003393 * Set up the return code ...
3394 *
3395 * li v0, __NR__foo_sigreturn
3396 * syscall
3397 */
bellard106ec872006-06-27 21:08:10 +00003398
Riku Voipio1d8b5122014-04-23 10:26:05 +03003399 __put_user(0x24020000 + syscall, tramp + 0);
3400 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003401 return err;
3402}
3403
Riku Voipio41ecc722014-04-23 11:01:00 +03003404static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003405 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003406{
Richard Henderson084d0492013-02-10 10:30:44 -08003407 int i;
bellard106ec872006-06-27 21:08:10 +00003408
Riku Voipio1d8b5122014-04-23 10:26:05 +03003409 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003410 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003411
Richard Henderson084d0492013-02-10 10:30:44 -08003412 __put_user(0, &sc->sc_regs[0]);
3413 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003414 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003415 }
bellard106ec872006-06-27 21:08:10 +00003416
Riku Voipio1d8b5122014-04-23 10:26:05 +03003417 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3418 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003419
Richard Henderson084d0492013-02-10 10:30:44 -08003420 /* Rather than checking for dsp existence, always copy. The storage
3421 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003422 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3423 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3424 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3425 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3426 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3427 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003428 {
3429 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003430 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003431 }
Richard Henderson084d0492013-02-10 10:30:44 -08003432
Riku Voipio1d8b5122014-04-23 10:26:05 +03003433 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003434
3435 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003436 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003437 }
bellard106ec872006-06-27 21:08:10 +00003438}
3439
Riku Voipio016d2e12014-04-23 11:19:48 +03003440static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003441restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003442{
Richard Henderson084d0492013-02-10 10:30:44 -08003443 int i;
bellard106ec872006-06-27 21:08:10 +00003444
Riku Voipio1d8b5122014-04-23 10:26:05 +03003445 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003446
Riku Voipio1d8b5122014-04-23 10:26:05 +03003447 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3448 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003449
Richard Henderson084d0492013-02-10 10:30:44 -08003450 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003451 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003452 }
3453
Riku Voipio1d8b5122014-04-23 10:26:05 +03003454 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3455 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3456 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3457 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3458 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3459 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003460 {
3461 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003462 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003463 cpu_wrdsp(dsp, 0x3ff, regs);
3464 }
3465
3466 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003467 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003468 }
bellard106ec872006-06-27 21:08:10 +00003469}
Richard Hendersonff970902013-02-10 10:30:42 -08003470
bellard106ec872006-06-27 21:08:10 +00003471/*
3472 * Determine which stack to use..
3473 */
bellard579a97f2007-11-11 14:26:47 +00003474static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003475get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003476{
3477 unsigned long sp;
3478
3479 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003480 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003481
3482 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003483 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003484 * above the user stack, 16-bytes before the next lowest
3485 * 16 byte boundary. Try to avoid trashing it.
3486 */
3487 sp -= 32;
3488
bellard106ec872006-06-27 21:08:10 +00003489 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003490 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003491 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3492 }
bellard106ec872006-06-27 21:08:10 +00003493
bellard579a97f2007-11-11 14:26:47 +00003494 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003495}
3496
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003497static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3498{
3499 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3500 env->hflags &= ~MIPS_HFLAG_M16;
3501 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3502 env->active_tc.PC &= ~(target_ulong) 1;
3503 }
3504}
3505
Richard Hendersonff970902013-02-10 10:30:42 -08003506# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003507/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003508static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003509 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003510{
3511 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003512 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003513 int i;
3514
bellard579a97f2007-11-11 14:26:47 +00003515 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003516 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003517 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3518 goto give_sigsegv;
3519 }
bellard106ec872006-06-27 21:08:10 +00003520
3521 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3522
Riku Voipio41ecc722014-04-23 11:01:00 +03003523 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003524
3525 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003526 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003527 }
3528
3529 /*
3530 * Arguments to signal handler:
3531 *
3532 * a0 = signal number
3533 * a1 = 0 (should be cause)
3534 * a2 = pointer to struct sigcontext
3535 *
3536 * $25 and PC point to the signal handler, $29 points to the
3537 * struct sigframe.
3538 */
thsb5dc7732008-06-27 10:02:35 +00003539 regs->active_tc.gpr[ 4] = sig;
3540 regs->active_tc.gpr[ 5] = 0;
3541 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3542 regs->active_tc.gpr[29] = frame_addr;
3543 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003544 /* The original kernel code sets CP0_EPC to the handler
3545 * since it returns to userland using eret
3546 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003547 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003548 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003549 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003550 return;
3551
3552give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003553 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003554}
3555
Andreas Färber05390242012-02-25 03:37:53 +01003556long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003557{
ths388bb212007-05-13 13:58:00 +00003558 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003559 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003560 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003561 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003562 int i;
bellard106ec872006-06-27 21:08:10 +00003563
thsb5dc7732008-06-27 10:02:35 +00003564 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003565 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003566 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003567 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003568
ths388bb212007-05-13 13:58:00 +00003569 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003570 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003571 }
bellard106ec872006-06-27 21:08:10 +00003572
ths388bb212007-05-13 13:58:00 +00003573 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003574 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003575
Riku Voipio016d2e12014-04-23 11:19:48 +03003576 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003577
3578#if 0
ths388bb212007-05-13 13:58:00 +00003579 /*
3580 * Don't let your children do this ...
3581 */
3582 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003583 "move\t$29, %0\n\t"
3584 "j\tsyscall_exit"
3585 :/* no outputs */
3586 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003587 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003588#endif
ths3b46e622007-09-17 08:09:54 +00003589
thsb5dc7732008-06-27 10:02:35 +00003590 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003591 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003592 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003593 * maybe a problem with nested signals ? */
3594 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003595 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003596
3597badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003598 force_sig(TARGET_SIGSEGV);
3599 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003600}
Richard Hendersonff970902013-02-10 10:30:42 -08003601# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003602
pbrook624f7972008-05-31 16:11:38 +00003603static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003604 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003605 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003606{
pbrook0b1bcb02009-04-21 01:41:10 +00003607 struct target_rt_sigframe *frame;
3608 abi_ulong frame_addr;
3609 int i;
3610
3611 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003612 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003613 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3614 goto give_sigsegv;
3615 }
pbrook0b1bcb02009-04-21 01:41:10 +00003616
3617 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3618
Peter Maydellf6c7a052015-01-08 12:19:48 +00003619 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003620
Aurelien Jarno60e99242010-03-29 02:12:51 +02003621 __put_user(0, &frame->rs_uc.tuc_flags);
3622 __put_user(0, &frame->rs_uc.tuc_link);
3623 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3624 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003625 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003626 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003627
Aurelien Jarno60e99242010-03-29 02:12:51 +02003628 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003629
3630 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003631 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003632 }
3633
3634 /*
3635 * Arguments to signal handler:
3636 *
3637 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003638 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003639 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003640 *
3641 * $25 and PC point to the signal handler, $29 points to the
3642 * struct sigframe.
3643 */
3644 env->active_tc.gpr[ 4] = sig;
3645 env->active_tc.gpr[ 5] = frame_addr
3646 + offsetof(struct target_rt_sigframe, rs_info);
3647 env->active_tc.gpr[ 6] = frame_addr
3648 + offsetof(struct target_rt_sigframe, rs_uc);
3649 env->active_tc.gpr[29] = frame_addr;
3650 env->active_tc.gpr[31] = frame_addr
3651 + offsetof(struct target_rt_sigframe, rs_code);
3652 /* The original kernel code sets CP0_EPC to the handler
3653 * since it returns to userland using eret
3654 * we cannot do this here, and we must set PC directly */
3655 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003656 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003657 unlock_user_struct(frame, frame_addr, 1);
3658 return;
3659
3660give_sigsegv:
3661 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003662 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003663}
3664
Andreas Färber05390242012-02-25 03:37:53 +01003665long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003666{
pbrook0b1bcb02009-04-21 01:41:10 +00003667 struct target_rt_sigframe *frame;
3668 abi_ulong frame_addr;
3669 sigset_t blocked;
3670
pbrook0b1bcb02009-04-21 01:41:10 +00003671 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003672 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003673 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3674 goto badframe;
3675 }
pbrook0b1bcb02009-04-21 01:41:10 +00003676
Aurelien Jarno60e99242010-03-29 02:12:51 +02003677 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003678 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003679
Riku Voipio016d2e12014-04-23 11:19:48 +03003680 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003681
3682 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003683 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3684 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003685 goto badframe;
3686
3687 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003688 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003689 /* I am not sure this is right, but it seems to work
3690 * maybe a problem with nested signals ? */
3691 env->CP0_EPC = 0;
3692 return -TARGET_QEMU_ESIGRETURN;
3693
3694badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003695 force_sig(TARGET_SIGSEGV);
3696 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003697}
bellard6d5e2162004-09-30 22:04:13 +00003698
thsc3b5bc82007-12-02 06:31:25 +00003699#elif defined(TARGET_SH4)
3700
3701/*
3702 * code and data structures from linux kernel:
3703 * include/asm-sh/sigcontext.h
3704 * arch/sh/kernel/signal.c
3705 */
3706
3707struct target_sigcontext {
3708 target_ulong oldmask;
3709
3710 /* CPU registers */
3711 target_ulong sc_gregs[16];
3712 target_ulong sc_pc;
3713 target_ulong sc_pr;
3714 target_ulong sc_sr;
3715 target_ulong sc_gbr;
3716 target_ulong sc_mach;
3717 target_ulong sc_macl;
3718
3719 /* FPU registers */
3720 target_ulong sc_fpregs[16];
3721 target_ulong sc_xfpregs[16];
3722 unsigned int sc_fpscr;
3723 unsigned int sc_fpul;
3724 unsigned int sc_ownedfp;
3725};
3726
3727struct target_sigframe
3728{
3729 struct target_sigcontext sc;
3730 target_ulong extramask[TARGET_NSIG_WORDS-1];
3731 uint16_t retcode[3];
3732};
3733
3734
3735struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003736 target_ulong tuc_flags;
3737 struct target_ucontext *tuc_link;
3738 target_stack_t tuc_stack;
3739 struct target_sigcontext tuc_mcontext;
3740 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003741};
3742
3743struct target_rt_sigframe
3744{
3745 struct target_siginfo info;
3746 struct target_ucontext uc;
3747 uint16_t retcode[3];
3748};
3749
3750
3751#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3752#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3753
pbrook624f7972008-05-31 16:11:38 +00003754static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003755 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003756{
pbrook624f7972008-05-31 16:11:38 +00003757 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003758 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3759 }
3760
3761 return (sp - frame_size) & -8ul;
3762}
3763
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003764/* Notice when we're in the middle of a gUSA region and reset.
3765 Note that this will only occur for !parallel_cpus, as we will
3766 translate such sequences differently in a parallel context. */
3767static void unwind_gusa(CPUSH4State *regs)
3768{
3769 /* If the stack pointer is sufficiently negative, and we haven't
3770 completed the sequence, then reset to the entry to the region. */
3771 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3772 However, the page mappings in qemu linux-user aren't as restricted
3773 and we wind up with the normal stack mapped above 0xF0000000.
3774 That said, there is no reason why the kernel should be allowing
3775 a gUSA region that spans 1GB. Use a tighter check here, for what
3776 can actually be enabled by the immediate move. */
3777 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3778 /* Reset the PC to before the gUSA region, as computed from
3779 R0 = region end, SP = -(region size), plus one more for the
3780 insn that actually initializes SP to the region size. */
3781 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3782
3783 /* Reset the SP to the saved version in R1. */
3784 regs->gregs[15] = regs->gregs[1];
3785 }
3786}
3787
Riku Voipio41ecc722014-04-23 11:01:00 +03003788static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003789 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003790{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003791 int i;
thsc3b5bc82007-12-02 06:31:25 +00003792
Riku Voipio1d8b5122014-04-23 10:26:05 +03003793#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003794 COPY(gregs[0]); COPY(gregs[1]);
3795 COPY(gregs[2]); COPY(gregs[3]);
3796 COPY(gregs[4]); COPY(gregs[5]);
3797 COPY(gregs[6]); COPY(gregs[7]);
3798 COPY(gregs[8]); COPY(gregs[9]);
3799 COPY(gregs[10]); COPY(gregs[11]);
3800 COPY(gregs[12]); COPY(gregs[13]);
3801 COPY(gregs[14]); COPY(gregs[15]);
3802 COPY(gbr); COPY(mach);
3803 COPY(macl); COPY(pr);
3804 COPY(sr); COPY(pc);
3805#undef COPY
3806
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003807 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003808 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003809 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003810 __put_user(regs->fpscr, &sc->sc_fpscr);
3811 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003812
3813 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003814 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003815}
3816
Timothy E Baldwinba412492016-05-12 18:47:35 +01003817static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003818{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003819 int i;
thsc3b5bc82007-12-02 06:31:25 +00003820
Riku Voipio1d8b5122014-04-23 10:26:05 +03003821#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003822 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003823 COPY(gregs[2]); COPY(gregs[3]);
3824 COPY(gregs[4]); COPY(gregs[5]);
3825 COPY(gregs[6]); COPY(gregs[7]);
3826 COPY(gregs[8]); COPY(gregs[9]);
3827 COPY(gregs[10]); COPY(gregs[11]);
3828 COPY(gregs[12]); COPY(gregs[13]);
3829 COPY(gregs[14]); COPY(gregs[15]);
3830 COPY(gbr); COPY(mach);
3831 COPY(macl); COPY(pr);
3832 COPY(sr); COPY(pc);
3833#undef COPY
3834
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003835 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003836 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003837 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003838 __get_user(regs->fpscr, &sc->sc_fpscr);
3839 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003840
3841 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003842 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003843}
3844
pbrook624f7972008-05-31 16:11:38 +00003845static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003846 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003847{
3848 struct target_sigframe *frame;
3849 abi_ulong frame_addr;
3850 int i;
thsc3b5bc82007-12-02 06:31:25 +00003851
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003852 unwind_gusa(regs);
3853
thsc3b5bc82007-12-02 06:31:25 +00003854 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003855 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003856 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3857 goto give_sigsegv;
3858 }
thsc3b5bc82007-12-02 06:31:25 +00003859
Riku Voipio41ecc722014-04-23 11:01:00 +03003860 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003861
3862 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003863 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003864 }
3865
3866 /* Set up to return from userspace. If provided, use a stub
3867 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003868 if (ka->sa_flags & TARGET_SA_RESTORER) {
3869 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003870 } else {
3871 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003872 abi_ulong retcode_addr = frame_addr +
3873 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003874 __put_user(MOVW(2), &frame->retcode[0]);
3875 __put_user(TRAP_NOARG, &frame->retcode[1]);
3876 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003877 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003878 }
3879
thsc3b5bc82007-12-02 06:31:25 +00003880 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003881 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003882 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003883 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003884 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003885 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003886 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003887
3888 unlock_user_struct(frame, frame_addr, 1);
3889 return;
3890
3891give_sigsegv:
3892 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003893 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003894}
3895
pbrook624f7972008-05-31 16:11:38 +00003896static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003897 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003898 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003899{
3900 struct target_rt_sigframe *frame;
3901 abi_ulong frame_addr;
3902 int i;
thsc3b5bc82007-12-02 06:31:25 +00003903
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003904 unwind_gusa(regs);
3905
thsc3b5bc82007-12-02 06:31:25 +00003906 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003907 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003908 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3909 goto give_sigsegv;
3910 }
thsc3b5bc82007-12-02 06:31:25 +00003911
Peter Maydellf6c7a052015-01-08 12:19:48 +00003912 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003913
3914 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003915 __put_user(0, &frame->uc.tuc_flags);
3916 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3917 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3918 &frame->uc.tuc_stack.ss_sp);
3919 __put_user(sas_ss_flags(regs->gregs[15]),
3920 &frame->uc.tuc_stack.ss_flags);
3921 __put_user(target_sigaltstack_used.ss_size,
3922 &frame->uc.tuc_stack.ss_size);
3923 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003924 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003925 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003926 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003927 }
3928
3929 /* Set up to return from userspace. If provided, use a stub
3930 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003931 if (ka->sa_flags & TARGET_SA_RESTORER) {
3932 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003933 } else {
3934 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003935 abi_ulong retcode_addr = frame_addr +
3936 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003937 __put_user(MOVW(2), &frame->retcode[0]);
3938 __put_user(TRAP_NOARG, &frame->retcode[1]);
3939 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003940 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003941 }
3942
thsc3b5bc82007-12-02 06:31:25 +00003943 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003944 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003945 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003946 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3947 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003948 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003949 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003950
3951 unlock_user_struct(frame, frame_addr, 1);
3952 return;
3953
3954give_sigsegv:
3955 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003956 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003957}
3958
Andreas Färber05390242012-02-25 03:37:53 +01003959long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003960{
3961 struct target_sigframe *frame;
3962 abi_ulong frame_addr;
3963 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003964 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003965 int i;
3966 int err = 0;
3967
thsc3b5bc82007-12-02 06:31:25 +00003968 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003969 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003970 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3971 goto badframe;
3972 }
thsc3b5bc82007-12-02 06:31:25 +00003973
Riku Voipio1d8b5122014-04-23 10:26:05 +03003974 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003975 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003976 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003977 }
3978
3979 if (err)
3980 goto badframe;
3981
3982 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003983 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003984
Timothy E Baldwinba412492016-05-12 18:47:35 +01003985 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003986
3987 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003988 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003989
3990badframe:
3991 unlock_user_struct(frame, frame_addr, 0);
3992 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003993 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003994}
3995
Andreas Färber05390242012-02-25 03:37:53 +01003996long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003997{
3998 struct target_rt_sigframe *frame;
3999 abi_ulong frame_addr;
4000 sigset_t blocked;
4001
thsc3b5bc82007-12-02 06:31:25 +00004002 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004003 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004004 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4005 goto badframe;
4006 }
thsc3b5bc82007-12-02 06:31:25 +00004007
Aurelien Jarno60e99242010-03-29 02:12:51 +02004008 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004009 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00004010
Timothy E Baldwinba412492016-05-12 18:47:35 +01004011 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00004012
4013 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004014 offsetof(struct target_rt_sigframe, uc.tuc_stack),
4015 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00004016 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004017 }
thsc3b5bc82007-12-02 06:31:25 +00004018
4019 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01004020 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004021
4022badframe:
4023 unlock_user_struct(frame, frame_addr, 0);
4024 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004025 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004026}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004027#elif defined(TARGET_MICROBLAZE)
4028
4029struct target_sigcontext {
4030 struct target_pt_regs regs; /* needs to be first */
4031 uint32_t oldmask;
4032};
4033
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004034struct target_stack_t {
4035 abi_ulong ss_sp;
4036 int ss_flags;
4037 unsigned int ss_size;
4038};
4039
4040struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08004041 abi_ulong tuc_flags;
4042 abi_ulong tuc_link;
4043 struct target_stack_t tuc_stack;
4044 struct target_sigcontext tuc_mcontext;
4045 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004046};
4047
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004048/* Signal frames. */
4049struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004050 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004051 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4052 uint32_t tramp[2];
4053};
4054
4055struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00004056 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004057 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004058 uint32_t tramp[2];
4059};
4060
Andreas Färber05390242012-02-25 03:37:53 +01004061static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004062{
4063 __put_user(env->regs[0], &sc->regs.r0);
4064 __put_user(env->regs[1], &sc->regs.r1);
4065 __put_user(env->regs[2], &sc->regs.r2);
4066 __put_user(env->regs[3], &sc->regs.r3);
4067 __put_user(env->regs[4], &sc->regs.r4);
4068 __put_user(env->regs[5], &sc->regs.r5);
4069 __put_user(env->regs[6], &sc->regs.r6);
4070 __put_user(env->regs[7], &sc->regs.r7);
4071 __put_user(env->regs[8], &sc->regs.r8);
4072 __put_user(env->regs[9], &sc->regs.r9);
4073 __put_user(env->regs[10], &sc->regs.r10);
4074 __put_user(env->regs[11], &sc->regs.r11);
4075 __put_user(env->regs[12], &sc->regs.r12);
4076 __put_user(env->regs[13], &sc->regs.r13);
4077 __put_user(env->regs[14], &sc->regs.r14);
4078 __put_user(env->regs[15], &sc->regs.r15);
4079 __put_user(env->regs[16], &sc->regs.r16);
4080 __put_user(env->regs[17], &sc->regs.r17);
4081 __put_user(env->regs[18], &sc->regs.r18);
4082 __put_user(env->regs[19], &sc->regs.r19);
4083 __put_user(env->regs[20], &sc->regs.r20);
4084 __put_user(env->regs[21], &sc->regs.r21);
4085 __put_user(env->regs[22], &sc->regs.r22);
4086 __put_user(env->regs[23], &sc->regs.r23);
4087 __put_user(env->regs[24], &sc->regs.r24);
4088 __put_user(env->regs[25], &sc->regs.r25);
4089 __put_user(env->regs[26], &sc->regs.r26);
4090 __put_user(env->regs[27], &sc->regs.r27);
4091 __put_user(env->regs[28], &sc->regs.r28);
4092 __put_user(env->regs[29], &sc->regs.r29);
4093 __put_user(env->regs[30], &sc->regs.r30);
4094 __put_user(env->regs[31], &sc->regs.r31);
4095 __put_user(env->sregs[SR_PC], &sc->regs.pc);
4096}
4097
Andreas Färber05390242012-02-25 03:37:53 +01004098static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004099{
4100 __get_user(env->regs[0], &sc->regs.r0);
4101 __get_user(env->regs[1], &sc->regs.r1);
4102 __get_user(env->regs[2], &sc->regs.r2);
4103 __get_user(env->regs[3], &sc->regs.r3);
4104 __get_user(env->regs[4], &sc->regs.r4);
4105 __get_user(env->regs[5], &sc->regs.r5);
4106 __get_user(env->regs[6], &sc->regs.r6);
4107 __get_user(env->regs[7], &sc->regs.r7);
4108 __get_user(env->regs[8], &sc->regs.r8);
4109 __get_user(env->regs[9], &sc->regs.r9);
4110 __get_user(env->regs[10], &sc->regs.r10);
4111 __get_user(env->regs[11], &sc->regs.r11);
4112 __get_user(env->regs[12], &sc->regs.r12);
4113 __get_user(env->regs[13], &sc->regs.r13);
4114 __get_user(env->regs[14], &sc->regs.r14);
4115 __get_user(env->regs[15], &sc->regs.r15);
4116 __get_user(env->regs[16], &sc->regs.r16);
4117 __get_user(env->regs[17], &sc->regs.r17);
4118 __get_user(env->regs[18], &sc->regs.r18);
4119 __get_user(env->regs[19], &sc->regs.r19);
4120 __get_user(env->regs[20], &sc->regs.r20);
4121 __get_user(env->regs[21], &sc->regs.r21);
4122 __get_user(env->regs[22], &sc->regs.r22);
4123 __get_user(env->regs[23], &sc->regs.r23);
4124 __get_user(env->regs[24], &sc->regs.r24);
4125 __get_user(env->regs[25], &sc->regs.r25);
4126 __get_user(env->regs[26], &sc->regs.r26);
4127 __get_user(env->regs[27], &sc->regs.r27);
4128 __get_user(env->regs[28], &sc->regs.r28);
4129 __get_user(env->regs[29], &sc->regs.r29);
4130 __get_user(env->regs[30], &sc->regs.r30);
4131 __get_user(env->regs[31], &sc->regs.r31);
4132 __get_user(env->sregs[SR_PC], &sc->regs.pc);
4133}
4134
4135static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004136 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004137{
4138 abi_ulong sp = env->regs[1];
4139
Riku Voipiob545f632014-07-15 17:01:55 +03004140 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004141 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03004142 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004143
4144 return ((sp - frame_size) & -8UL);
4145}
4146
4147static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004148 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004149{
4150 struct target_signal_frame *frame;
4151 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004152 int i;
4153
4154 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004155 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004156 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4157 goto badframe;
4158
4159 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004160 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004161
4162 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03004163 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004164 }
4165
Richard Hendersonf711df62010-11-22 14:57:52 -08004166 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004167
4168 /* Set up to return from userspace. If provided, use a stub
4169 already in userspace. */
4170 /* minus 8 is offset to cater for "rtsd r15,8" offset */
4171 if (ka->sa_flags & TARGET_SA_RESTORER) {
4172 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
4173 } else {
4174 uint32_t t;
4175 /* Note, these encodings are _big endian_! */
4176 /* addi r12, r0, __NR_sigreturn */
4177 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004178 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004179 /* brki r14, 0x8 */
4180 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004181 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004182
4183 /* Return from sighandler will jump to the tramp.
4184 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004185 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4186 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004187 }
4188
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004189 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004190 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004191 /* Signal handler args: */
4192 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004193 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004194 /* arg 1: sigcontext */
4195 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004196
4197 /* Offset of 4 to handle microblaze rtid r14, 0 */
4198 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4199
4200 unlock_user_struct(frame, frame_addr, 1);
4201 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004202badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004203 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004204}
4205
4206static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004207 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004208 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004209{
4210 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4211}
4212
Andreas Färber05390242012-02-25 03:37:53 +01004213long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004214{
4215 struct target_signal_frame *frame;
4216 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004217 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004218 sigset_t set;
4219 int i;
4220
4221 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004222 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004223 /* Make sure the guest isn't playing games. */
4224 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4225 goto badframe;
4226
4227 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004228 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004229 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004230 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004231 }
4232 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004233 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004234
Richard Hendersonf711df62010-11-22 14:57:52 -08004235 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004236 /* We got here through a sigreturn syscall, our path back is via an
4237 rtb insn so setup r14 for that. */
4238 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004239
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004240 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004241 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004242badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004243 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004244 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004245}
4246
Andreas Färber05390242012-02-25 03:37:53 +01004247long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004248{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004249 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004250 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4251 return -TARGET_ENOSYS;
4252}
4253
edgar_iglb6d3abd2008-02-28 11:29:27 +00004254#elif defined(TARGET_CRIS)
4255
4256struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004257 struct target_pt_regs regs; /* needs to be first */
4258 uint32_t oldmask;
4259 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004260};
4261
4262/* Signal frames. */
4263struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004264 struct target_sigcontext sc;
4265 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4266 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004267};
4268
4269struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004270 siginfo_t *pinfo;
4271 void *puc;
4272 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004273 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004274 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004275};
4276
Andreas Färber05390242012-02-25 03:37:53 +01004277static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004278{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004279 __put_user(env->regs[0], &sc->regs.r0);
4280 __put_user(env->regs[1], &sc->regs.r1);
4281 __put_user(env->regs[2], &sc->regs.r2);
4282 __put_user(env->regs[3], &sc->regs.r3);
4283 __put_user(env->regs[4], &sc->regs.r4);
4284 __put_user(env->regs[5], &sc->regs.r5);
4285 __put_user(env->regs[6], &sc->regs.r6);
4286 __put_user(env->regs[7], &sc->regs.r7);
4287 __put_user(env->regs[8], &sc->regs.r8);
4288 __put_user(env->regs[9], &sc->regs.r9);
4289 __put_user(env->regs[10], &sc->regs.r10);
4290 __put_user(env->regs[11], &sc->regs.r11);
4291 __put_user(env->regs[12], &sc->regs.r12);
4292 __put_user(env->regs[13], &sc->regs.r13);
4293 __put_user(env->regs[14], &sc->usp);
4294 __put_user(env->regs[15], &sc->regs.acr);
4295 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4296 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4297 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004298}
edgar_igl9664d922008-03-03 22:23:53 +00004299
Andreas Färber05390242012-02-25 03:37:53 +01004300static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004301{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004302 __get_user(env->regs[0], &sc->regs.r0);
4303 __get_user(env->regs[1], &sc->regs.r1);
4304 __get_user(env->regs[2], &sc->regs.r2);
4305 __get_user(env->regs[3], &sc->regs.r3);
4306 __get_user(env->regs[4], &sc->regs.r4);
4307 __get_user(env->regs[5], &sc->regs.r5);
4308 __get_user(env->regs[6], &sc->regs.r6);
4309 __get_user(env->regs[7], &sc->regs.r7);
4310 __get_user(env->regs[8], &sc->regs.r8);
4311 __get_user(env->regs[9], &sc->regs.r9);
4312 __get_user(env->regs[10], &sc->regs.r10);
4313 __get_user(env->regs[11], &sc->regs.r11);
4314 __get_user(env->regs[12], &sc->regs.r12);
4315 __get_user(env->regs[13], &sc->regs.r13);
4316 __get_user(env->regs[14], &sc->usp);
4317 __get_user(env->regs[15], &sc->regs.acr);
4318 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4319 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4320 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004321}
4322
Andreas Färber05390242012-02-25 03:37:53 +01004323static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004324{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004325 abi_ulong sp;
4326 /* Align the stack downwards to 4. */
4327 sp = (env->regs[R_SP] & ~3);
4328 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004329}
4330
pbrook624f7972008-05-31 16:11:38 +00004331static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004332 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004333{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004334 struct target_signal_frame *frame;
4335 abi_ulong frame_addr;
4336 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004337
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004338 frame_addr = get_sigframe(env, sizeof *frame);
4339 trace_user_setup_frame(env, frame_addr);
4340 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4341 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004342
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004343 /*
4344 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4345 * use this trampoline anymore but it sets it up for GDB.
4346 * In QEMU, using the trampoline simplifies things a bit so we use it.
4347 *
4348 * This is movu.w __NR_sigreturn, r9; break 13;
4349 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004350 __put_user(0x9c5f, frame->retcode+0);
4351 __put_user(TARGET_NR_sigreturn,
4352 frame->retcode + 1);
4353 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004354
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004355 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004356 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004357
Riku Voipio0188fad2014-04-23 13:34:15 +03004358 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4359 __put_user(set->sig[i], &frame->extramask[i - 1]);
4360 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004361
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004362 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004363
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004364 /* Move the stack and setup the arguments for the handler. */
4365 env->regs[R_SP] = frame_addr;
4366 env->regs[10] = sig;
4367 env->pc = (unsigned long) ka->_sa_handler;
4368 /* Link SRP so the guest returns through the trampoline. */
4369 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004370
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004371 unlock_user_struct(frame, frame_addr, 1);
4372 return;
4373badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004374 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004375}
4376
pbrook624f7972008-05-31 16:11:38 +00004377static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004378 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004379 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004380{
4381 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4382}
4383
Andreas Färber05390242012-02-25 03:37:53 +01004384long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004385{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004386 struct target_signal_frame *frame;
4387 abi_ulong frame_addr;
4388 target_sigset_t target_set;
4389 sigset_t set;
4390 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004391
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004392 frame_addr = env->regs[R_SP];
4393 trace_user_do_sigreturn(env, frame_addr);
4394 /* Make sure the guest isn't playing games. */
4395 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4396 goto badframe;
4397 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004398
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004399 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004400 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004401 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004402 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004403 }
4404 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004405 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004406
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004407 restore_sigcontext(&frame->sc, env);
4408 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004409 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004410badframe:
4411 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004412 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004413}
4414
Andreas Färber05390242012-02-25 03:37:53 +01004415long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004416{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004417 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004418 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4419 return -TARGET_ENOSYS;
4420}
thsc3b5bc82007-12-02 06:31:25 +00004421
Marek Vasuta0a839b2017-01-18 23:01:42 +01004422#elif defined(TARGET_NIOS2)
4423
4424#define MCONTEXT_VERSION 2
4425
4426struct target_sigcontext {
4427 int version;
4428 unsigned long gregs[32];
4429};
4430
4431struct target_ucontext {
4432 abi_ulong tuc_flags;
4433 abi_ulong tuc_link;
4434 target_stack_t tuc_stack;
4435 struct target_sigcontext tuc_mcontext;
4436 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4437};
4438
4439struct target_rt_sigframe {
4440 struct target_siginfo info;
4441 struct target_ucontext uc;
4442};
4443
4444static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4445{
4446 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4447#ifdef CONFIG_STACK_GROWSUP
4448 return target_sigaltstack_used.ss_sp;
4449#else
4450 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4451#endif
4452 }
4453 return sp;
4454}
4455
4456static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4457{
4458 unsigned long *gregs = uc->tuc_mcontext.gregs;
4459
4460 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4461 __put_user(env->regs[1], &gregs[0]);
4462 __put_user(env->regs[2], &gregs[1]);
4463 __put_user(env->regs[3], &gregs[2]);
4464 __put_user(env->regs[4], &gregs[3]);
4465 __put_user(env->regs[5], &gregs[4]);
4466 __put_user(env->regs[6], &gregs[5]);
4467 __put_user(env->regs[7], &gregs[6]);
4468 __put_user(env->regs[8], &gregs[7]);
4469 __put_user(env->regs[9], &gregs[8]);
4470 __put_user(env->regs[10], &gregs[9]);
4471 __put_user(env->regs[11], &gregs[10]);
4472 __put_user(env->regs[12], &gregs[11]);
4473 __put_user(env->regs[13], &gregs[12]);
4474 __put_user(env->regs[14], &gregs[13]);
4475 __put_user(env->regs[15], &gregs[14]);
4476 __put_user(env->regs[16], &gregs[15]);
4477 __put_user(env->regs[17], &gregs[16]);
4478 __put_user(env->regs[18], &gregs[17]);
4479 __put_user(env->regs[19], &gregs[18]);
4480 __put_user(env->regs[20], &gregs[19]);
4481 __put_user(env->regs[21], &gregs[20]);
4482 __put_user(env->regs[22], &gregs[21]);
4483 __put_user(env->regs[23], &gregs[22]);
4484 __put_user(env->regs[R_RA], &gregs[23]);
4485 __put_user(env->regs[R_FP], &gregs[24]);
4486 __put_user(env->regs[R_GP], &gregs[25]);
4487 __put_user(env->regs[R_EA], &gregs[27]);
4488 __put_user(env->regs[R_SP], &gregs[28]);
4489
4490 return 0;
4491}
4492
4493static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4494 int *pr2)
4495{
4496 int temp;
4497 abi_ulong off, frame_addr = env->regs[R_SP];
4498 unsigned long *gregs = uc->tuc_mcontext.gregs;
4499 int err;
4500
4501 /* Always make any pending restarted system calls return -EINTR */
4502 /* current->restart_block.fn = do_no_restart_syscall; */
4503
4504 __get_user(temp, &uc->tuc_mcontext.version);
4505 if (temp != MCONTEXT_VERSION) {
4506 return 1;
4507 }
4508
4509 /* restore passed registers */
4510 __get_user(env->regs[1], &gregs[0]);
4511 __get_user(env->regs[2], &gregs[1]);
4512 __get_user(env->regs[3], &gregs[2]);
4513 __get_user(env->regs[4], &gregs[3]);
4514 __get_user(env->regs[5], &gregs[4]);
4515 __get_user(env->regs[6], &gregs[5]);
4516 __get_user(env->regs[7], &gregs[6]);
4517 __get_user(env->regs[8], &gregs[7]);
4518 __get_user(env->regs[9], &gregs[8]);
4519 __get_user(env->regs[10], &gregs[9]);
4520 __get_user(env->regs[11], &gregs[10]);
4521 __get_user(env->regs[12], &gregs[11]);
4522 __get_user(env->regs[13], &gregs[12]);
4523 __get_user(env->regs[14], &gregs[13]);
4524 __get_user(env->regs[15], &gregs[14]);
4525 __get_user(env->regs[16], &gregs[15]);
4526 __get_user(env->regs[17], &gregs[16]);
4527 __get_user(env->regs[18], &gregs[17]);
4528 __get_user(env->regs[19], &gregs[18]);
4529 __get_user(env->regs[20], &gregs[19]);
4530 __get_user(env->regs[21], &gregs[20]);
4531 __get_user(env->regs[22], &gregs[21]);
4532 __get_user(env->regs[23], &gregs[22]);
4533 /* gregs[23] is handled below */
4534 /* Verify, should this be settable */
4535 __get_user(env->regs[R_FP], &gregs[24]);
4536 /* Verify, should this be settable */
4537 __get_user(env->regs[R_GP], &gregs[25]);
4538 /* Not really necessary no user settable bits */
4539 __get_user(temp, &gregs[26]);
4540 __get_user(env->regs[R_EA], &gregs[27]);
4541
4542 __get_user(env->regs[R_RA], &gregs[23]);
4543 __get_user(env->regs[R_SP], &gregs[28]);
4544
4545 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4546 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4547 if (err == -EFAULT) {
4548 return 1;
4549 }
4550
4551 *pr2 = env->regs[2];
4552 return 0;
4553}
4554
4555static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4556 size_t frame_size)
4557{
4558 unsigned long usp;
4559
4560 /* Default to using normal stack. */
4561 usp = env->regs[R_SP];
4562
4563 /* This is the X/Open sanctioned signal stack switching. */
4564 usp = sigsp(usp, ka);
4565
4566 /* Verify, is it 32 or 64 bit aligned */
4567 return (void *)((usp - frame_size) & -8UL);
4568}
4569
4570static void setup_rt_frame(int sig, struct target_sigaction *ka,
4571 target_siginfo_t *info,
4572 target_sigset_t *set,
4573 CPUNios2State *env)
4574{
4575 struct target_rt_sigframe *frame;
4576 int i, err = 0;
4577
4578 frame = get_sigframe(ka, env, sizeof(*frame));
4579
4580 if (ka->sa_flags & SA_SIGINFO) {
4581 tswap_siginfo(&frame->info, info);
4582 }
4583
4584 /* Create the ucontext. */
4585 __put_user(0, &frame->uc.tuc_flags);
4586 __put_user(0, &frame->uc.tuc_link);
4587 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4588 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4589 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4590 err |= rt_setup_ucontext(&frame->uc, env);
4591 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4592 __put_user((abi_ulong)set->sig[i],
4593 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4594 }
4595
4596 if (err) {
4597 goto give_sigsegv;
4598 }
4599
4600 /* Set up to return from userspace; jump to fixed address sigreturn
4601 trampoline on kuser page. */
4602 env->regs[R_RA] = (unsigned long) (0x1044);
4603
4604 /* Set up registers for signal handler */
4605 env->regs[R_SP] = (unsigned long) frame;
4606 env->regs[4] = (unsigned long) sig;
4607 env->regs[5] = (unsigned long) &frame->info;
4608 env->regs[6] = (unsigned long) &frame->uc;
4609 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4610 return;
4611
4612give_sigsegv:
4613 if (sig == TARGET_SIGSEGV) {
4614 ka->_sa_handler = TARGET_SIG_DFL;
4615 }
4616 force_sigsegv(sig);
4617 return;
4618}
4619
4620long do_sigreturn(CPUNios2State *env)
4621{
4622 trace_user_do_sigreturn(env, 0);
4623 fprintf(stderr, "do_sigreturn: not implemented\n");
4624 return -TARGET_ENOSYS;
4625}
4626
4627long do_rt_sigreturn(CPUNios2State *env)
4628{
4629 /* Verify, can we follow the stack back */
4630 abi_ulong frame_addr = env->regs[R_SP];
4631 struct target_rt_sigframe *frame;
4632 sigset_t set;
4633 int rval;
4634
4635 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4636 goto badframe;
4637 }
4638
4639 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4640 do_sigprocmask(SIG_SETMASK, &set, NULL);
4641
4642 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4643 goto badframe;
4644 }
4645
4646 unlock_user_struct(frame, frame_addr, 0);
4647 return rval;
4648
4649badframe:
4650 unlock_user_struct(frame, frame_addr, 0);
4651 force_sig(TARGET_SIGSEGV);
4652 return 0;
4653}
4654/* TARGET_NIOS2 */
4655
Jia Liud9627832012-07-20 15:50:52 +08004656#elif defined(TARGET_OPENRISC)
4657
4658struct target_sigcontext {
4659 struct target_pt_regs regs;
4660 abi_ulong oldmask;
4661 abi_ulong usp;
4662};
4663
4664struct target_ucontext {
4665 abi_ulong tuc_flags;
4666 abi_ulong tuc_link;
4667 target_stack_t tuc_stack;
4668 struct target_sigcontext tuc_mcontext;
4669 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4670};
4671
4672struct target_rt_sigframe {
4673 abi_ulong pinfo;
4674 uint64_t puc;
4675 struct target_siginfo info;
4676 struct target_sigcontext sc;
4677 struct target_ucontext uc;
4678 unsigned char retcode[16]; /* trampoline code */
4679};
4680
4681/* This is the asm-generic/ucontext.h version */
4682#if 0
4683static int restore_sigcontext(CPUOpenRISCState *regs,
4684 struct target_sigcontext *sc)
4685{
4686 unsigned int err = 0;
4687 unsigned long old_usp;
4688
4689 /* Alwys make any pending restarted system call return -EINTR */
4690 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4691
4692 /* restore the regs from &sc->regs (same as sc, since regs is first)
4693 * (sc is already checked for VERIFY_READ since the sigframe was
4694 * checked in sys_sigreturn previously)
4695 */
4696
4697 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4698 goto badframe;
4699 }
4700
4701 /* make sure the U-flag is set so user-mode cannot fool us */
4702
4703 regs->sr &= ~SR_SM;
4704
4705 /* restore the old USP as it was before we stacked the sc etc.
4706 * (we cannot just pop the sigcontext since we aligned the sp and
4707 * stuff after pushing it)
4708 */
4709
Riku Voipio1d8b5122014-04-23 10:26:05 +03004710 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004711 phx_signal("old_usp 0x%lx", old_usp);
4712
4713 __PHX__ REALLY /* ??? */
4714 wrusp(old_usp);
4715 regs->gpr[1] = old_usp;
4716
4717 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4718 * after this completes, but we don't use that mechanism. maybe we can
4719 * use it now ?
4720 */
4721
4722 return err;
4723
4724badframe:
4725 return 1;
4726}
4727#endif
4728
4729/* Set up a signal frame. */
4730
Riku Voipio41ecc722014-04-23 11:01:00 +03004731static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004732 CPUOpenRISCState *regs,
4733 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004734{
Stafford Horned89e71e2017-04-06 06:44:56 +09004735 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004736
4737 /* copy the regs. they are first in sc so we can use sc directly */
4738
Riku Voipio1d8b5122014-04-23 10:26:05 +03004739 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004740
4741 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4742 the signal handler. The frametype will be restored to its previous
4743 value in restore_sigcontext. */
4744 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4745
4746 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004747 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004748 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004749}
4750
4751static inline unsigned long align_sigframe(unsigned long sp)
4752{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004753 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004754}
4755
4756static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4757 CPUOpenRISCState *regs,
4758 size_t frame_size)
4759{
Stafford Horned89e71e2017-04-06 06:44:56 +09004760 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004761 int onsigstack = on_sig_stack(sp);
4762
4763 /* redzone */
4764 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004765 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004766 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4767 }
4768
4769 sp = align_sigframe(sp - frame_size);
4770
4771 /*
4772 * If we are on the alternate signal stack and would overflow it, don't.
4773 * Return an always-bogus address instead so we will die with SIGSEGV.
4774 */
4775
4776 if (onsigstack && !likely(on_sig_stack(sp))) {
4777 return -1L;
4778 }
4779
4780 return sp;
4781}
4782
Jia Liud9627832012-07-20 15:50:52 +08004783static void setup_rt_frame(int sig, struct target_sigaction *ka,
4784 target_siginfo_t *info,
4785 target_sigset_t *set, CPUOpenRISCState *env)
4786{
4787 int err = 0;
4788 abi_ulong frame_addr;
4789 unsigned long return_ip;
4790 struct target_rt_sigframe *frame;
4791 abi_ulong info_addr, uc_addr;
4792
Jia Liud9627832012-07-20 15:50:52 +08004793 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004794 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004795 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4796 goto give_sigsegv;
4797 }
4798
4799 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004800 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004801 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004802 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004803
4804 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004805 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004806 }
4807
Khem Raj04b33e22017-06-28 13:44:52 -07004808 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004809 __put_user(0, &frame->uc.tuc_flags);
4810 __put_user(0, &frame->uc.tuc_link);
4811 __put_user(target_sigaltstack_used.ss_sp,
4812 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004813 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4814 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004815 __put_user(target_sigaltstack_used.ss_size,
4816 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004817 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004818
4819 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4820
Jia Liud9627832012-07-20 15:50:52 +08004821 /* trampoline - the desired return ip is the retcode itself */
4822 return_ip = (unsigned long)&frame->retcode;
4823 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004824 __put_user(0xa960, (short *)(frame->retcode + 0));
4825 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4826 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4827 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004828
4829 if (err) {
4830 goto give_sigsegv;
4831 }
4832
4833 /* TODO what is the current->exec_domain stuff and invmap ? */
4834
4835 /* Set up registers for signal handler */
4836 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004837 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4838 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4839 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4840 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004841
4842 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004843 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004844
4845 return;
4846
4847give_sigsegv:
4848 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004849 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004850}
4851
4852long do_sigreturn(CPUOpenRISCState *env)
4853{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004854 trace_user_do_sigreturn(env, 0);
4855 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004856 return -TARGET_ENOSYS;
4857}
4858
4859long do_rt_sigreturn(CPUOpenRISCState *env)
4860{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004861 trace_user_do_rt_sigreturn(env, 0);
4862 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004863 return -TARGET_ENOSYS;
4864}
4865/* TARGET_OPENRISC */
4866
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004867#elif defined(TARGET_S390X)
4868
4869#define __NUM_GPRS 16
4870#define __NUM_FPRS 16
4871#define __NUM_ACRS 16
4872
4873#define S390_SYSCALL_SIZE 2
4874#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4875
4876#define _SIGCONTEXT_NSIG 64
4877#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4878#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4879#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4880#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4881#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4882
4883typedef struct {
4884 target_psw_t psw;
4885 target_ulong gprs[__NUM_GPRS];
4886 unsigned int acrs[__NUM_ACRS];
4887} target_s390_regs_common;
4888
4889typedef struct {
4890 unsigned int fpc;
4891 double fprs[__NUM_FPRS];
4892} target_s390_fp_regs;
4893
4894typedef struct {
4895 target_s390_regs_common regs;
4896 target_s390_fp_regs fpregs;
4897} target_sigregs;
4898
4899struct target_sigcontext {
4900 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4901 target_sigregs *sregs;
4902};
4903
4904typedef struct {
4905 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4906 struct target_sigcontext sc;
4907 target_sigregs sregs;
4908 int signo;
4909 uint8_t retcode[S390_SYSCALL_SIZE];
4910} sigframe;
4911
4912struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004913 target_ulong tuc_flags;
4914 struct target_ucontext *tuc_link;
4915 target_stack_t tuc_stack;
4916 target_sigregs tuc_mcontext;
4917 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004918};
4919
4920typedef struct {
4921 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4922 uint8_t retcode[S390_SYSCALL_SIZE];
4923 struct target_siginfo info;
4924 struct target_ucontext uc;
4925} rt_sigframe;
4926
4927static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004928get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004929{
4930 abi_ulong sp;
4931
4932 /* Default to using normal stack */
4933 sp = env->regs[15];
4934
4935 /* This is the X/Open sanctioned signal stack switching. */
4936 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4937 if (!sas_ss_flags(sp)) {
4938 sp = target_sigaltstack_used.ss_sp +
4939 target_sigaltstack_used.ss_size;
4940 }
4941 }
4942
4943 /* This is the legacy signal stack switching. */
4944 else if (/* FIXME !user_mode(regs) */ 0 &&
4945 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4946 ka->sa_restorer) {
4947 sp = (abi_ulong) ka->sa_restorer;
4948 }
4949
4950 return (sp - frame_size) & -8ul;
4951}
4952
Andreas Färber05390242012-02-25 03:37:53 +01004953static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004954{
4955 int i;
4956 //save_access_regs(current->thread.acrs); FIXME
4957
4958 /* Copy a 'clean' PSW mask to the user to avoid leaking
4959 information about whether PER is currently on. */
4960 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4961 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4962 for (i = 0; i < 16; i++) {
4963 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4964 }
4965 for (i = 0; i < 16; i++) {
4966 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4967 }
4968 /*
4969 * We have to store the fp registers to current->thread.fp_regs
4970 * to merge them with the emulated registers.
4971 */
4972 //save_fp_regs(&current->thread.fp_regs); FIXME
4973 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004974 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004975 }
4976}
4977
4978static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004979 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004980{
4981 sigframe *frame;
4982 abi_ulong frame_addr;
4983
4984 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004985 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004986 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004987 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004988 }
4989
Riku Voipio0188fad2014-04-23 13:34:15 +03004990 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004991
4992 save_sigregs(env, &frame->sregs);
4993
4994 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4995 (abi_ulong *)&frame->sc.sregs);
4996
4997 /* Set up to return from userspace. If provided, use a stub
4998 already in userspace. */
4999 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005000 env->regs[14] = (unsigned long)
5001 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005002 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03005003 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
5004 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005005 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
5006 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005007 }
5008
5009 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005010 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005011
5012 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005013 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005014 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5015
5016 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005017 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005018
5019 /* We forgot to include these in the sigcontext.
5020 To avoid breaking binary compatibility, they are passed as args. */
5021 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
5022 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
5023
5024 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02005025 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005026 unlock_user_struct(frame, frame_addr, 1);
5027 return;
5028
5029give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005030 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005031}
5032
5033static void setup_rt_frame(int sig, struct target_sigaction *ka,
5034 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005035 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005036{
5037 int i;
5038 rt_sigframe *frame;
5039 abi_ulong frame_addr;
5040
5041 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005042 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005043 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5044 goto give_sigsegv;
5045 }
5046
Peter Maydellf6c7a052015-01-08 12:19:48 +00005047 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005048
5049 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005050 __put_user(0, &frame->uc.tuc_flags);
5051 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
5052 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005053 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005054 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005055 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5056 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005057 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
5058 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005059 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005060 }
5061
5062 /* Set up to return from userspace. If provided, use a stub
5063 already in userspace. */
5064 if (ka->sa_flags & TARGET_SA_RESTORER) {
5065 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
5066 } else {
5067 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03005068 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
5069 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005070 }
5071
5072 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005073 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005074
5075 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005076 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005077 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5078
5079 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005080 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
5081 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005082 return;
5083
5084give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005085 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005086}
5087
5088static int
Andreas Färber05390242012-02-25 03:37:53 +01005089restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005090{
5091 int err = 0;
5092 int i;
5093
5094 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005095 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005096 }
5097
Riku Voipio1d8b5122014-04-23 10:26:05 +03005098 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005099 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
5100 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005101 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005102 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
5103
5104 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005105 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005106 }
5107 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04005108 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005109 }
5110
5111 return err;
5112}
5113
Andreas Färber05390242012-02-25 03:37:53 +01005114long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005115{
5116 sigframe *frame;
5117 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005118 target_sigset_t target_set;
5119 sigset_t set;
5120
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005121 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005122 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5123 goto badframe;
5124 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03005125 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005126
5127 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005128 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005129
5130 if (restore_sigregs(env, &frame->sregs)) {
5131 goto badframe;
5132 }
5133
5134 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005135 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005136
5137badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005138 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005139 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005140}
5141
Andreas Färber05390242012-02-25 03:37:53 +01005142long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005143{
5144 rt_sigframe *frame;
5145 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005146 sigset_t set;
5147
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005148 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005149 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5150 goto badframe;
5151 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005152 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005153
Peter Maydell9eede5b2016-05-27 15:51:46 +01005154 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005155
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005156 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005157 goto badframe;
5158 }
5159
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005160 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005161 get_sp_from_cpustate(env)) == -EFAULT) {
5162 goto badframe;
5163 }
5164 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005165 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005166
5167badframe:
5168 unlock_user_struct(frame, frame_addr, 0);
5169 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005170 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005171}
5172
Tom Musta61e75fe2014-06-30 08:13:38 -05005173#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07005174
5175/* Size of dummy stack frame allocated when calling signal handler.
5176 See arch/powerpc/include/asm/ptrace.h. */
5177#if defined(TARGET_PPC64)
5178#define SIGNAL_FRAMESIZE 128
5179#else
5180#define SIGNAL_FRAMESIZE 64
5181#endif
5182
Tom Musta61e75fe2014-06-30 08:13:38 -05005183/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5184 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5185struct target_mcontext {
5186 target_ulong mc_gregs[48];
5187 /* Includes fpscr. */
5188 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005189#if defined(TARGET_PPC64)
5190 /* Pointer to the vector regs */
5191 target_ulong v_regs;
5192#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005193 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005194#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005195 /* We need to handle Altivec and SPE at the same time, which no
5196 kernel needs to do. Fortunately, the kernel defines this bit to
5197 be Altivec-register-large all the time, rather than trying to
5198 twiddle it based on the specific platform. */
5199 union {
5200 /* SPE vector registers. One extra for SPEFSCR. */
5201 uint32_t spe[33];
5202 /* Altivec vector registers. The packing of VSCR and VRSAVE
5203 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005204 them apart; PPC32 stuffs them together.
5205 We also need to account for the VSX registers on PPC64
5206 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005207#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005208#define QEMU_NVRREG (34 + 16)
5209 /* On ppc64, this mcontext structure is naturally *unaligned*,
5210 * or rather it is aligned on a 8 bytes boundary but not on
5211 * a 16 bytes one. This pad fixes it up. This is also why the
5212 * vector regs are referenced by the v_regs pointer above so
5213 * any amount of padding can be added here
5214 */
5215 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005216#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005217 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005218#define QEMU_NVRREG 33
5219#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005220 /* We cannot use ppc_avr_t here as we do *not* want the implied
5221 * 16-bytes alignment that would result from it. This would have
5222 * the effect of making the whole struct target_mcontext aligned
5223 * which breaks the layout of struct target_ucontext on ppc64.
5224 */
5225 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005226#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005227 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005228};
5229
Nathan Froydbcd49332009-05-12 19:13:18 -07005230/* See arch/powerpc/include/asm/sigcontext.h. */
5231struct target_sigcontext {
5232 target_ulong _unused[4];
5233 int32_t signal;
5234#if defined(TARGET_PPC64)
5235 int32_t pad0;
5236#endif
5237 target_ulong handler;
5238 target_ulong oldmask;
5239 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005240#if defined(TARGET_PPC64)
5241 struct target_mcontext mcontext;
5242#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005243};
5244
5245/* Indices for target_mcontext.mc_gregs, below.
5246 See arch/powerpc/include/asm/ptrace.h for details. */
5247enum {
5248 TARGET_PT_R0 = 0,
5249 TARGET_PT_R1 = 1,
5250 TARGET_PT_R2 = 2,
5251 TARGET_PT_R3 = 3,
5252 TARGET_PT_R4 = 4,
5253 TARGET_PT_R5 = 5,
5254 TARGET_PT_R6 = 6,
5255 TARGET_PT_R7 = 7,
5256 TARGET_PT_R8 = 8,
5257 TARGET_PT_R9 = 9,
5258 TARGET_PT_R10 = 10,
5259 TARGET_PT_R11 = 11,
5260 TARGET_PT_R12 = 12,
5261 TARGET_PT_R13 = 13,
5262 TARGET_PT_R14 = 14,
5263 TARGET_PT_R15 = 15,
5264 TARGET_PT_R16 = 16,
5265 TARGET_PT_R17 = 17,
5266 TARGET_PT_R18 = 18,
5267 TARGET_PT_R19 = 19,
5268 TARGET_PT_R20 = 20,
5269 TARGET_PT_R21 = 21,
5270 TARGET_PT_R22 = 22,
5271 TARGET_PT_R23 = 23,
5272 TARGET_PT_R24 = 24,
5273 TARGET_PT_R25 = 25,
5274 TARGET_PT_R26 = 26,
5275 TARGET_PT_R27 = 27,
5276 TARGET_PT_R28 = 28,
5277 TARGET_PT_R29 = 29,
5278 TARGET_PT_R30 = 30,
5279 TARGET_PT_R31 = 31,
5280 TARGET_PT_NIP = 32,
5281 TARGET_PT_MSR = 33,
5282 TARGET_PT_ORIG_R3 = 34,
5283 TARGET_PT_CTR = 35,
5284 TARGET_PT_LNK = 36,
5285 TARGET_PT_XER = 37,
5286 TARGET_PT_CCR = 38,
5287 /* Yes, there are two registers with #39. One is 64-bit only. */
5288 TARGET_PT_MQ = 39,
5289 TARGET_PT_SOFTE = 39,
5290 TARGET_PT_TRAP = 40,
5291 TARGET_PT_DAR = 41,
5292 TARGET_PT_DSISR = 42,
5293 TARGET_PT_RESULT = 43,
5294 TARGET_PT_REGS_COUNT = 44
5295};
5296
Nathan Froydbcd49332009-05-12 19:13:18 -07005297
5298struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005299 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005300 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005301 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005302#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005303 int32_t tuc_pad[7];
5304 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005305 points to uc_mcontext field */
5306#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005307 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005308#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005309 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005310 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005311#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005312 int32_t tuc_maskext[30];
5313 int32_t tuc_pad2[3];
5314 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005315#endif
5316};
5317
5318/* See arch/powerpc/kernel/signal_32.c. */
5319struct target_sigframe {
5320 struct target_sigcontext sctx;
5321 struct target_mcontext mctx;
5322 int32_t abigap[56];
5323};
5324
Tom Musta61e75fe2014-06-30 08:13:38 -05005325#if defined(TARGET_PPC64)
5326
5327#define TARGET_TRAMP_SIZE 6
5328
5329struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005330 /* sys_rt_sigreturn requires the ucontext be the first field */
5331 struct target_ucontext uc;
5332 target_ulong _unused[2];
5333 uint32_t trampoline[TARGET_TRAMP_SIZE];
5334 target_ulong pinfo; /* struct siginfo __user * */
5335 target_ulong puc; /* void __user * */
5336 struct target_siginfo info;
5337 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5338 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005339} __attribute__((aligned(16)));
5340
5341#else
5342
Nathan Froydbcd49332009-05-12 19:13:18 -07005343struct target_rt_sigframe {
5344 struct target_siginfo info;
5345 struct target_ucontext uc;
5346 int32_t abigap[56];
5347};
5348
Tom Musta61e75fe2014-06-30 08:13:38 -05005349#endif
5350
Tom Musta8d6ab332014-06-30 08:13:39 -05005351#if defined(TARGET_PPC64)
5352
5353struct target_func_ptr {
5354 target_ulong entry;
5355 target_ulong toc;
5356};
5357
5358#endif
5359
Nathan Froydbcd49332009-05-12 19:13:18 -07005360/* We use the mc_pad field for the signal return trampoline. */
5361#define tramp mc_pad
5362
5363/* See arch/powerpc/kernel/signal.c. */
5364static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005365 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005366 int frame_size)
5367{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005368 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005369
5370 oldsp = env->gpr[1];
5371
5372 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005373 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005374 oldsp = (target_sigaltstack_used.ss_sp
5375 + target_sigaltstack_used.ss_size);
5376 }
5377
Eduardo Habkost9be38592016-06-13 18:57:58 -03005378 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005379}
5380
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005381#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5382 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5383#define PPC_VEC_HI 0
5384#define PPC_VEC_LO 1
5385#else
5386#define PPC_VEC_HI 1
5387#define PPC_VEC_LO 0
5388#endif
5389
5390
Tom Musta76781082014-06-30 08:13:37 -05005391static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005392{
5393 target_ulong msr = env->msr;
5394 int i;
5395 target_ulong ccr = 0;
5396
5397 /* In general, the kernel attempts to be intelligent about what it
5398 needs to save for Altivec/FP/SPE registers. We don't care that
5399 much, so we just go ahead and save everything. */
5400
5401 /* Save general registers. */
5402 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005403 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005404 }
Riku Voipioc650c002014-04-23 13:53:45 +03005405 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5406 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5407 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5408 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005409
5410 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5411 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5412 }
Riku Voipioc650c002014-04-23 13:53:45 +03005413 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005414
5415 /* Save Altivec registers if necessary. */
5416 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005417 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005418 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005419 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005420 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005421
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005422 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5423 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005424 }
5425 /* Set MSR_VR in the saved MSR value to indicate that
5426 frame->mc_vregs contains valid data. */
5427 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005428#if defined(TARGET_PPC64)
5429 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5430 /* 64-bit needs to put a pointer to the vectors in the frame */
5431 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5432#else
5433 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5434#endif
5435 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5436 }
5437
5438 /* Save VSX second halves */
5439 if (env->insns_flags2 & PPC2_VSX) {
5440 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5441 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5442 __put_user(env->vsr[i], &vsregs[i]);
5443 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005444 }
5445
5446 /* Save floating point registers. */
5447 if (env->insns_flags & PPC_FLOAT) {
5448 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005449 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005450 }
Riku Voipioc650c002014-04-23 13:53:45 +03005451 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005452 }
5453
5454 /* Save SPE registers. The kernel only saves the high half. */
5455 if (env->insns_flags & PPC_SPE) {
5456#if defined(TARGET_PPC64)
5457 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005458 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005459 }
5460#else
5461 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005462 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005463 }
5464#endif
5465 /* Set MSR_SPE in the saved MSR value to indicate that
5466 frame->mc_vregs contains valid data. */
5467 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005468 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005469 }
5470
5471 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005472 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005473}
Nathan Froydbcd49332009-05-12 19:13:18 -07005474
Tom Musta76781082014-06-30 08:13:37 -05005475static void encode_trampoline(int sigret, uint32_t *tramp)
5476{
Nathan Froydbcd49332009-05-12 19:13:18 -07005477 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5478 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005479 __put_user(0x38000000 | sigret, &tramp[0]);
5480 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005481 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005482}
5483
Riku Voipioc650c002014-04-23 13:53:45 +03005484static void restore_user_regs(CPUPPCState *env,
5485 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005486{
5487 target_ulong save_r2 = 0;
5488 target_ulong msr;
5489 target_ulong ccr;
5490
5491 int i;
5492
5493 if (!sig) {
5494 save_r2 = env->gpr[2];
5495 }
5496
5497 /* Restore general registers. */
5498 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005499 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005500 }
Riku Voipioc650c002014-04-23 13:53:45 +03005501 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5502 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5503 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5504 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5505 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005506
5507 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5508 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5509 }
5510
5511 if (!sig) {
5512 env->gpr[2] = save_r2;
5513 }
5514 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005515 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005516
5517 /* If doing signal return, restore the previous little-endian mode. */
5518 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005519 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005520
5521 /* Restore Altivec registers if necessary. */
5522 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005523 ppc_avr_t *v_regs;
5524 uint32_t *vrsave;
5525#if defined(TARGET_PPC64)
5526 uint64_t v_addr;
5527 /* 64-bit needs to recover the pointer to the vectors from the frame */
5528 __get_user(v_addr, &frame->v_regs);
5529 v_regs = g2h(v_addr);
5530#else
5531 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5532#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005533 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005534 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005535 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005536
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005537 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5538 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005539 }
5540 /* Set MSR_VEC in the saved MSR value to indicate that
5541 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005542#if defined(TARGET_PPC64)
5543 vrsave = (uint32_t *)&v_regs[33];
5544#else
5545 vrsave = (uint32_t *)&v_regs[32];
5546#endif
5547 __get_user(env->spr[SPR_VRSAVE], vrsave);
5548 }
5549
5550 /* Restore VSX second halves */
5551 if (env->insns_flags2 & PPC2_VSX) {
5552 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5553 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5554 __get_user(env->vsr[i], &vsregs[i]);
5555 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005556 }
5557
5558 /* Restore floating point registers. */
5559 if (env->insns_flags & PPC_FLOAT) {
5560 uint64_t fpscr;
5561 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005562 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005563 }
Riku Voipioc650c002014-04-23 13:53:45 +03005564 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005565 env->fpscr = (uint32_t) fpscr;
5566 }
5567
5568 /* Save SPE registers. The kernel only saves the high half. */
5569 if (env->insns_flags & PPC_SPE) {
5570#if defined(TARGET_PPC64)
5571 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5572 uint32_t hi;
5573
Riku Voipioc650c002014-04-23 13:53:45 +03005574 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005575 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5576 }
5577#else
5578 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005579 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005580 }
5581#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005582 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005583 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005584}
5585
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005586#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005587static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005588 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005589{
5590 struct target_sigframe *frame;
5591 struct target_sigcontext *sc;
5592 target_ulong frame_addr, newsp;
5593 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005594
5595 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005596 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005597 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5598 goto sigsegv;
5599 sc = &frame->sctx;
5600
Riku Voipio1d8b5122014-04-23 10:26:05 +03005601 __put_user(ka->_sa_handler, &sc->handler);
5602 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005603 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005604 __put_user(h2g(&frame->mctx), &sc->regs);
5605 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005606
5607 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005608 save_user_regs(env, &frame->mctx);
5609
5610 /* Construct the trampoline code on the stack. */
5611 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005612
5613 /* The kernel checks for the presence of a VDSO here. We don't
5614 emulate a vdso, so use a sigreturn system call. */
5615 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5616
5617 /* Turn off all fp exceptions. */
5618 env->fpscr = 0;
5619
5620 /* Create a stack frame for the caller of the handler. */
5621 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005622 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005623
5624 if (err)
5625 goto sigsegv;
5626
5627 /* Set up registers for signal handler. */
5628 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005629 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005630 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005631
Nathan Froydbcd49332009-05-12 19:13:18 -07005632 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005633
Nathan Froydbcd49332009-05-12 19:13:18 -07005634 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005635 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005636
5637 unlock_user_struct(frame, frame_addr, 1);
5638 return;
5639
5640sigsegv:
5641 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005642 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005643}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005644#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005645
5646static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005647 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005648 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005649{
5650 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005651 uint32_t *trampptr = 0;
5652 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005653 target_ulong rt_sf_addr, newsp = 0;
5654 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005655#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005656 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005657 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5658#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005659
5660 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5661 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5662 goto sigsegv;
5663
Peter Maydellf6c7a052015-01-08 12:19:48 +00005664 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005665
Riku Voipio1d8b5122014-04-23 10:26:05 +03005666 __put_user(0, &rt_sf->uc.tuc_flags);
5667 __put_user(0, &rt_sf->uc.tuc_link);
5668 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5669 &rt_sf->uc.tuc_stack.ss_sp);
5670 __put_user(sas_ss_flags(env->gpr[1]),
5671 &rt_sf->uc.tuc_stack.ss_flags);
5672 __put_user(target_sigaltstack_used.ss_size,
5673 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005674#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005675 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5676 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005677#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005678 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005679 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005680 }
5681
Tom Musta61e75fe2014-06-30 08:13:38 -05005682#if defined(TARGET_PPC64)
5683 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5684 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005685
5686 sc = &rt_sf->uc.tuc_sigcontext;
5687 __put_user(h2g(mctx), &sc->regs);
5688 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005689#else
5690 mctx = &rt_sf->uc.tuc_mcontext;
5691 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5692#endif
5693
5694 save_user_regs(env, mctx);
5695 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005696
5697 /* The kernel checks for the presence of a VDSO here. We don't
5698 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005699 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005700
5701 /* Turn off all fp exceptions. */
5702 env->fpscr = 0;
5703
5704 /* Create a stack frame for the caller of the handler. */
5705 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005706 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005707
5708 if (err)
5709 goto sigsegv;
5710
5711 /* Set up registers for signal handler. */
5712 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005713 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005714 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5715 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5716 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005717
5718#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005719 if (get_ppc64_abi(image) < 2) {
5720 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5721 struct target_func_ptr *handler =
5722 (struct target_func_ptr *)g2h(ka->_sa_handler);
5723 env->nip = tswapl(handler->entry);
5724 env->gpr[2] = tswapl(handler->toc);
5725 } else {
5726 /* ELFv2 PPC64 function pointers are entry points, but R12
5727 * must also be set */
5728 env->nip = tswapl((target_ulong) ka->_sa_handler);
5729 env->gpr[12] = env->nip;
5730 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005731#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005732 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005733#endif
5734
Nathan Froydbcd49332009-05-12 19:13:18 -07005735 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005736 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005737
5738 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5739 return;
5740
5741sigsegv:
5742 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005743 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005744
5745}
5746
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005747#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005748long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005749{
5750 struct target_sigcontext *sc = NULL;
5751 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005752 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005753 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005754 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005755
5756 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5757 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5758 goto sigsegv;
5759
5760#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005761 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005762#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005763 __get_user(set.sig[0], &sc->oldmask);
5764 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005765#endif
5766 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005767 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005768
Riku Voipiof5f601a2014-04-23 13:00:17 +03005769 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005770 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5771 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005772 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005773
5774 unlock_user_struct(sr, sr_addr, 1);
5775 unlock_user_struct(sc, sc_addr, 1);
5776 return -TARGET_QEMU_ESIGRETURN;
5777
5778sigsegv:
5779 unlock_user_struct(sr, sr_addr, 1);
5780 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005781 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005782 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005783}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005784#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005785
5786/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005787static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005788{
5789 struct target_mcontext *mcp;
5790 target_ulong mcp_addr;
5791 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005792 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005793
Aurelien Jarno60e99242010-03-29 02:12:51 +02005794 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005795 sizeof (set)))
5796 return 1;
5797
Tom Musta19774ec2014-06-30 08:13:40 -05005798#if defined(TARGET_PPC64)
5799 mcp_addr = h2g(ucp) +
5800 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5801#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005802 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005803#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005804
5805 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5806 return 1;
5807
5808 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005809 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005810 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005811
5812 unlock_user_struct(mcp, mcp_addr, 1);
5813 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005814}
5815
Andreas Färber05390242012-02-25 03:37:53 +01005816long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005817{
5818 struct target_rt_sigframe *rt_sf = NULL;
5819 target_ulong rt_sf_addr;
5820
5821 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5822 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5823 goto sigsegv;
5824
5825 if (do_setcontext(&rt_sf->uc, env, 1))
5826 goto sigsegv;
5827
5828 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005829 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005830 0, env->gpr[1]);
5831
5832 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5833 return -TARGET_QEMU_ESIGRETURN;
5834
5835sigsegv:
5836 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005837 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005838 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005839}
5840
Laurent Vivier492a8742009-08-03 16:12:17 +02005841#elif defined(TARGET_M68K)
5842
5843struct target_sigcontext {
5844 abi_ulong sc_mask;
5845 abi_ulong sc_usp;
5846 abi_ulong sc_d0;
5847 abi_ulong sc_d1;
5848 abi_ulong sc_a0;
5849 abi_ulong sc_a1;
5850 unsigned short sc_sr;
5851 abi_ulong sc_pc;
5852};
5853
5854struct target_sigframe
5855{
5856 abi_ulong pretcode;
5857 int sig;
5858 int code;
5859 abi_ulong psc;
5860 char retcode[8];
5861 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5862 struct target_sigcontext sc;
5863};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005864
Anthony Liguoric227f092009-10-01 16:12:16 -05005865typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005866#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005867typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005868
5869typedef struct target_fpregset {
5870 int f_fpcntl[3];
5871 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005872} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005873
5874struct target_mcontext {
5875 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005876 target_gregset_t gregs;
5877 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005878};
5879
5880#define TARGET_MCONTEXT_VERSION 2
5881
5882struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005883 abi_ulong tuc_flags;
5884 abi_ulong tuc_link;
5885 target_stack_t tuc_stack;
5886 struct target_mcontext tuc_mcontext;
5887 abi_long tuc_filler[80];
5888 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005889};
5890
5891struct target_rt_sigframe
5892{
5893 abi_ulong pretcode;
5894 int sig;
5895 abi_ulong pinfo;
5896 abi_ulong puc;
5897 char retcode[8];
5898 struct target_siginfo info;
5899 struct target_ucontext uc;
5900};
Laurent Vivier492a8742009-08-03 16:12:17 +02005901
Riku Voipio41ecc722014-04-23 11:01:00 +03005902static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005903 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005904{
Laurent Vivieref597602018-01-04 02:28:59 +01005905 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005906 __put_user(mask, &sc->sc_mask);
5907 __put_user(env->aregs[7], &sc->sc_usp);
5908 __put_user(env->dregs[0], &sc->sc_d0);
5909 __put_user(env->dregs[1], &sc->sc_d1);
5910 __put_user(env->aregs[0], &sc->sc_a0);
5911 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005912 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005913 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005914}
5915
Riku Voipio016d2e12014-04-23 11:19:48 +03005916static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005917restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005918{
Laurent Vivier492a8742009-08-03 16:12:17 +02005919 int temp;
5920
Riku Voipio1d8b5122014-04-23 10:26:05 +03005921 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005922 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005923 __get_user(env->dregs[1], &sc->sc_d1);
5924 __get_user(env->aregs[0], &sc->sc_a0);
5925 __get_user(env->aregs[1], &sc->sc_a1);
5926 __get_user(env->pc, &sc->sc_pc);
5927 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005928 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005929}
5930
5931/*
5932 * Determine which stack to use..
5933 */
5934static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005935get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5936 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005937{
5938 unsigned long sp;
5939
5940 sp = regs->aregs[7];
5941
5942 /* This is the X/Open sanctioned signal stack switching. */
5943 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5944 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5945 }
5946
5947 return ((sp - frame_size) & -8UL);
5948}
5949
5950static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005951 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005952{
5953 struct target_sigframe *frame;
5954 abi_ulong frame_addr;
5955 abi_ulong retcode_addr;
5956 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005957 int i;
5958
5959 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005960 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005961 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5962 goto give_sigsegv;
5963 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005964
Riku Voipio1d8b5122014-04-23 10:26:05 +03005965 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005966
5967 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005968 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005969
Riku Voipio41ecc722014-04-23 11:01:00 +03005970 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005971
5972 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005973 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005974 }
5975
5976 /* Set up to return from userspace. */
5977
5978 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005979 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005980
5981 /* moveq #,d0; trap #0 */
5982
Riku Voipio1d8b5122014-04-23 10:26:05 +03005983 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005984 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005985
Laurent Vivier492a8742009-08-03 16:12:17 +02005986 /* Set up to return from userspace */
5987
5988 env->aregs[7] = frame_addr;
5989 env->pc = ka->_sa_handler;
5990
5991 unlock_user_struct(frame, frame_addr, 1);
5992 return;
5993
5994give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005995 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005996}
5997
Laurent Vivieree46a462017-09-14 18:35:05 +02005998static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5999 CPUM68KState *env)
6000{
6001 int i;
6002 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6003
6004 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
6005 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
6006 /* fpiar is not emulated */
6007
6008 for (i = 0; i < 8; i++) {
6009 uint32_t high = env->fregs[i].d.high << 16;
6010 __put_user(high, &fpregs->f_fpregs[i * 3]);
6011 __put_user(env->fregs[i].d.low,
6012 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6013 }
6014}
6015
Laurent Vivier71811552009-08-03 16:12:18 +02006016static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01006017 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02006018{
Aurelien Jarno60e99242010-03-29 02:12:51 +02006019 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01006020 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02006021
Riku Voipio1d8b5122014-04-23 10:26:05 +03006022 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
6023 __put_user(env->dregs[0], &gregs[0]);
6024 __put_user(env->dregs[1], &gregs[1]);
6025 __put_user(env->dregs[2], &gregs[2]);
6026 __put_user(env->dregs[3], &gregs[3]);
6027 __put_user(env->dregs[4], &gregs[4]);
6028 __put_user(env->dregs[5], &gregs[5]);
6029 __put_user(env->dregs[6], &gregs[6]);
6030 __put_user(env->dregs[7], &gregs[7]);
6031 __put_user(env->aregs[0], &gregs[8]);
6032 __put_user(env->aregs[1], &gregs[9]);
6033 __put_user(env->aregs[2], &gregs[10]);
6034 __put_user(env->aregs[3], &gregs[11]);
6035 __put_user(env->aregs[4], &gregs[12]);
6036 __put_user(env->aregs[5], &gregs[13]);
6037 __put_user(env->aregs[6], &gregs[14]);
6038 __put_user(env->aregs[7], &gregs[15]);
6039 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006040 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02006041
Laurent Vivieree46a462017-09-14 18:35:05 +02006042 target_rt_save_fpu_state(uc, env);
6043
Riku Voipio1d8b5122014-04-23 10:26:05 +03006044 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006045}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006046
Laurent Vivieree46a462017-09-14 18:35:05 +02006047static inline void target_rt_restore_fpu_state(CPUM68KState *env,
6048 struct target_ucontext *uc)
6049{
6050 int i;
6051 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6052 uint32_t fpcr;
6053
6054 __get_user(fpcr, &fpregs->f_fpcntl[0]);
6055 cpu_m68k_set_fpcr(env, fpcr);
6056 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
6057 /* fpiar is not emulated */
6058
6059 for (i = 0; i < 8; i++) {
6060 uint32_t high;
6061 __get_user(high, &fpregs->f_fpregs[i * 3]);
6062 env->fregs[i].d.high = high >> 16;
6063 __get_user(env->fregs[i].d.low,
6064 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6065 }
6066}
6067
Andreas Färber05390242012-02-25 03:37:53 +01006068static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006069 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02006070{
6071 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02006072 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02006073
Riku Voipio1d8b5122014-04-23 10:26:05 +03006074 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02006075 if (temp != TARGET_MCONTEXT_VERSION)
6076 goto badframe;
6077
6078 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03006079 __get_user(env->dregs[0], &gregs[0]);
6080 __get_user(env->dregs[1], &gregs[1]);
6081 __get_user(env->dregs[2], &gregs[2]);
6082 __get_user(env->dregs[3], &gregs[3]);
6083 __get_user(env->dregs[4], &gregs[4]);
6084 __get_user(env->dregs[5], &gregs[5]);
6085 __get_user(env->dregs[6], &gregs[6]);
6086 __get_user(env->dregs[7], &gregs[7]);
6087 __get_user(env->aregs[0], &gregs[8]);
6088 __get_user(env->aregs[1], &gregs[9]);
6089 __get_user(env->aregs[2], &gregs[10]);
6090 __get_user(env->aregs[3], &gregs[11]);
6091 __get_user(env->aregs[4], &gregs[12]);
6092 __get_user(env->aregs[5], &gregs[13]);
6093 __get_user(env->aregs[6], &gregs[14]);
6094 __get_user(env->aregs[7], &gregs[15]);
6095 __get_user(env->pc, &gregs[16]);
6096 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006097 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02006098
Laurent Vivieree46a462017-09-14 18:35:05 +02006099 target_rt_restore_fpu_state(env, uc);
6100
Riku Voipio1d8b5122014-04-23 10:26:05 +03006101 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006102
6103badframe:
6104 return 1;
6105}
6106
Laurent Vivier492a8742009-08-03 16:12:17 +02006107static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006108 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006109 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006110{
Laurent Vivier71811552009-08-03 16:12:18 +02006111 struct target_rt_sigframe *frame;
6112 abi_ulong frame_addr;
6113 abi_ulong retcode_addr;
6114 abi_ulong info_addr;
6115 abi_ulong uc_addr;
6116 int err = 0;
6117 int i;
6118
6119 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006120 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006121 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6122 goto give_sigsegv;
6123 }
Laurent Vivier71811552009-08-03 16:12:18 +02006124
Riku Voipio1d8b5122014-04-23 10:26:05 +03006125 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02006126
6127 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006128 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02006129
6130 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006131 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02006132
Peter Maydellf6c7a052015-01-08 12:19:48 +00006133 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02006134
6135 /* Create the ucontext */
6136
Riku Voipio1d8b5122014-04-23 10:26:05 +03006137 __put_user(0, &frame->uc.tuc_flags);
6138 __put_user(0, &frame->uc.tuc_link);
6139 __put_user(target_sigaltstack_used.ss_sp,
6140 &frame->uc.tuc_stack.ss_sp);
6141 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006142 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006143 __put_user(target_sigaltstack_used.ss_size,
6144 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02006145 err |= target_rt_setup_ucontext(&frame->uc, env);
6146
6147 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006148 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02006149
6150 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03006151 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02006152 }
6153
6154 /* Set up to return from userspace. */
6155
6156 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006157 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02006158
6159 /* moveq #,d0; notb d0; trap #0 */
6160
Riku Voipio1d8b5122014-04-23 10:26:05 +03006161 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00006162 (uint32_t *)(frame->retcode + 0));
6163 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02006164
6165 if (err)
6166 goto give_sigsegv;
6167
6168 /* Set up to return from userspace */
6169
6170 env->aregs[7] = frame_addr;
6171 env->pc = ka->_sa_handler;
6172
6173 unlock_user_struct(frame, frame_addr, 1);
6174 return;
6175
6176give_sigsegv:
6177 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006178 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006179}
6180
Andreas Färber05390242012-02-25 03:37:53 +01006181long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006182{
6183 struct target_sigframe *frame;
6184 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006185 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006186 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006187 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006188
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006189 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006190 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6191 goto badframe;
6192
6193 /* set blocked signals */
6194
Riku Voipiof5f601a2014-04-23 13:00:17 +03006195 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006196
6197 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006198 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006199 }
6200
6201 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006202 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006203
6204 /* restore registers */
6205
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006206 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006207
6208 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006209 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006210
6211badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006212 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006213 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006214}
6215
Andreas Färber05390242012-02-25 03:37:53 +01006216long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006217{
Laurent Vivier71811552009-08-03 16:12:18 +02006218 struct target_rt_sigframe *frame;
6219 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006220 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006221
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006222 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006223 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6224 goto badframe;
6225
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006226 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006227 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006228
6229 /* restore registers */
6230
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006231 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006232 goto badframe;
6233
6234 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006235 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006236 0, get_sp_from_cpustate(env)) == -EFAULT)
6237 goto badframe;
6238
6239 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006240 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006241
6242badframe:
6243 unlock_user_struct(frame, frame_addr, 0);
6244 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006245 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006246}
6247
Richard Henderson6049f4f2009-12-27 18:30:03 -08006248#elif defined(TARGET_ALPHA)
6249
6250struct target_sigcontext {
6251 abi_long sc_onstack;
6252 abi_long sc_mask;
6253 abi_long sc_pc;
6254 abi_long sc_ps;
6255 abi_long sc_regs[32];
6256 abi_long sc_ownedfp;
6257 abi_long sc_fpregs[32];
6258 abi_ulong sc_fpcr;
6259 abi_ulong sc_fp_control;
6260 abi_ulong sc_reserved1;
6261 abi_ulong sc_reserved2;
6262 abi_ulong sc_ssize;
6263 abi_ulong sc_sbase;
6264 abi_ulong sc_traparg_a0;
6265 abi_ulong sc_traparg_a1;
6266 abi_ulong sc_traparg_a2;
6267 abi_ulong sc_fp_trap_pc;
6268 abi_ulong sc_fp_trigger_sum;
6269 abi_ulong sc_fp_trigger_inst;
6270};
6271
6272struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006273 abi_ulong tuc_flags;
6274 abi_ulong tuc_link;
6275 abi_ulong tuc_osf_sigmask;
6276 target_stack_t tuc_stack;
6277 struct target_sigcontext tuc_mcontext;
6278 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006279};
6280
6281struct target_sigframe {
6282 struct target_sigcontext sc;
6283 unsigned int retcode[3];
6284};
6285
6286struct target_rt_sigframe {
6287 target_siginfo_t info;
6288 struct target_ucontext uc;
6289 unsigned int retcode[3];
6290};
6291
6292#define INSN_MOV_R30_R16 0x47fe0410
6293#define INSN_LDI_R0 0x201f0000
6294#define INSN_CALLSYS 0x00000083
6295
Riku Voipio41ecc722014-04-23 11:01:00 +03006296static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006297 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006298{
Riku Voipio41ecc722014-04-23 11:01:00 +03006299 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006300
Riku Voipio1d8b5122014-04-23 10:26:05 +03006301 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6302 __put_user(set->sig[0], &sc->sc_mask);
6303 __put_user(env->pc, &sc->sc_pc);
6304 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006305
6306 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006307 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006308 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006309 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006310
6311 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006312 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006313 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006314 __put_user(0, &sc->sc_fpregs[31]);
6315 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006316
Riku Voipio1d8b5122014-04-23 10:26:05 +03006317 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6318 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6319 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006320}
6321
Riku Voipio016d2e12014-04-23 11:19:48 +03006322static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006323 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006324{
6325 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006326 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006327
Riku Voipio1d8b5122014-04-23 10:26:05 +03006328 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006329
6330 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006331 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006332 }
6333 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006334 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006335 }
6336
Riku Voipio1d8b5122014-04-23 10:26:05 +03006337 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006338 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006339}
6340
6341static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006342 CPUAlphaState *env,
6343 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006344{
6345 abi_ulong sp = env->ir[IR_SP];
6346
6347 /* This is the X/Open sanctioned signal stack switching. */
6348 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6349 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6350 }
6351 return (sp - framesize) & -32;
6352}
6353
6354static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006355 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006356{
6357 abi_ulong frame_addr, r26;
6358 struct target_sigframe *frame;
6359 int err = 0;
6360
6361 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006362 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006363 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6364 goto give_sigsegv;
6365 }
6366
Riku Voipio41ecc722014-04-23 11:01:00 +03006367 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006368
6369 if (ka->sa_restorer) {
6370 r26 = ka->sa_restorer;
6371 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006372 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6373 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6374 &frame->retcode[1]);
6375 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006376 /* imb() */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006377 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006378 }
6379
6380 unlock_user_struct(frame, frame_addr, 1);
6381
6382 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006383give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006384 force_sigsegv(sig);
6385 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006386 }
6387
6388 env->ir[IR_RA] = r26;
6389 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6390 env->ir[IR_A0] = sig;
6391 env->ir[IR_A1] = 0;
6392 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6393 env->ir[IR_SP] = frame_addr;
6394}
6395
6396static void setup_rt_frame(int sig, struct target_sigaction *ka,
6397 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006398 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006399{
6400 abi_ulong frame_addr, r26;
6401 struct target_rt_sigframe *frame;
6402 int i, err = 0;
6403
6404 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006405 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006406 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6407 goto give_sigsegv;
6408 }
6409
Peter Maydellf6c7a052015-01-08 12:19:48 +00006410 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006411
Riku Voipio1d8b5122014-04-23 10:26:05 +03006412 __put_user(0, &frame->uc.tuc_flags);
6413 __put_user(0, &frame->uc.tuc_link);
6414 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6415 __put_user(target_sigaltstack_used.ss_sp,
6416 &frame->uc.tuc_stack.ss_sp);
6417 __put_user(sas_ss_flags(env->ir[IR_SP]),
6418 &frame->uc.tuc_stack.ss_flags);
6419 __put_user(target_sigaltstack_used.ss_size,
6420 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006421 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006422 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006423 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006424 }
6425
6426 if (ka->sa_restorer) {
6427 r26 = ka->sa_restorer;
6428 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006429 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6430 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6431 &frame->retcode[1]);
6432 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006433 /* imb(); */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006434 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006435 }
6436
6437 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006438give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006439 force_sigsegv(sig);
6440 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006441 }
6442
6443 env->ir[IR_RA] = r26;
6444 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6445 env->ir[IR_A0] = sig;
6446 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6447 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6448 env->ir[IR_SP] = frame_addr;
6449}
6450
Andreas Färber05390242012-02-25 03:37:53 +01006451long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006452{
6453 struct target_sigcontext *sc;
6454 abi_ulong sc_addr = env->ir[IR_A0];
6455 target_sigset_t target_set;
6456 sigset_t set;
6457
6458 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6459 goto badframe;
6460 }
6461
6462 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006463 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006464
6465 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006466 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006467
Riku Voipio016d2e12014-04-23 11:19:48 +03006468 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006469 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006470 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006471
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006472badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006473 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006474 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006475}
6476
Andreas Färber05390242012-02-25 03:37:53 +01006477long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006478{
6479 abi_ulong frame_addr = env->ir[IR_A0];
6480 struct target_rt_sigframe *frame;
6481 sigset_t set;
6482
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006483 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006484 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6485 goto badframe;
6486 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006487 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006488 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006489
Riku Voipio016d2e12014-04-23 11:19:48 +03006490 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006491 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006492 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006493 0, env->ir[IR_SP]) == -EFAULT) {
6494 goto badframe;
6495 }
6496
6497 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006498 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006499
6500
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006501badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006502 unlock_user_struct(frame, frame_addr, 0);
6503 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006504 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006505}
6506
Chen Gangbf0f60a2015-09-27 08:10:18 +08006507#elif defined(TARGET_TILEGX)
6508
6509struct target_sigcontext {
6510 union {
6511 /* General-purpose registers. */
6512 abi_ulong gregs[56];
6513 struct {
6514 abi_ulong __gregs[53];
6515 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6516 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6517 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6518 };
6519 };
6520 abi_ulong pc; /* Program counter. */
6521 abi_ulong ics; /* In Interrupt Critical Section? */
6522 abi_ulong faultnum; /* Fault number. */
6523 abi_ulong pad[5];
6524};
6525
6526struct target_ucontext {
6527 abi_ulong tuc_flags;
6528 abi_ulong tuc_link;
6529 target_stack_t tuc_stack;
6530 struct target_sigcontext tuc_mcontext;
6531 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6532};
6533
6534struct target_rt_sigframe {
6535 unsigned char save_area[16]; /* caller save area */
6536 struct target_siginfo info;
6537 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006538 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006539};
6540
Chen Gangf1d9d102016-03-29 21:53:49 +08006541#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6542#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6543
6544
Chen Gangbf0f60a2015-09-27 08:10:18 +08006545static void setup_sigcontext(struct target_sigcontext *sc,
6546 CPUArchState *env, int signo)
6547{
6548 int i;
6549
6550 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6551 __put_user(env->regs[i], &sc->gregs[i]);
6552 }
6553
6554 __put_user(env->pc, &sc->pc);
6555 __put_user(0, &sc->ics);
6556 __put_user(signo, &sc->faultnum);
6557}
6558
6559static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6560{
6561 int i;
6562
6563 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6564 __get_user(env->regs[i], &sc->gregs[i]);
6565 }
6566
6567 __get_user(env->pc, &sc->pc);
6568}
6569
6570static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6571 size_t frame_size)
6572{
6573 unsigned long sp = env->regs[TILEGX_R_SP];
6574
6575 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6576 return -1UL;
6577 }
6578
6579 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6580 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6581 }
6582
6583 sp -= frame_size;
6584 sp &= -16UL;
6585 return sp;
6586}
6587
6588static void setup_rt_frame(int sig, struct target_sigaction *ka,
6589 target_siginfo_t *info,
6590 target_sigset_t *set, CPUArchState *env)
6591{
6592 abi_ulong frame_addr;
6593 struct target_rt_sigframe *frame;
6594 unsigned long restorer;
6595
6596 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006597 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006598 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6599 goto give_sigsegv;
6600 }
6601
6602 /* Always write at least the signal number for the stack backtracer. */
6603 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6604 /* At sigreturn time, restore the callee-save registers too. */
6605 tswap_siginfo(&frame->info, info);
6606 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6607 } else {
6608 __put_user(info->si_signo, &frame->info.si_signo);
6609 }
6610
6611 /* Create the ucontext. */
6612 __put_user(0, &frame->uc.tuc_flags);
6613 __put_user(0, &frame->uc.tuc_link);
6614 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6615 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6616 &frame->uc.tuc_stack.ss_flags);
6617 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6618 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6619
Chen Gangbf0f60a2015-09-27 08:10:18 +08006620 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006621 restorer = (unsigned long) ka->sa_restorer;
6622 } else {
6623 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6624 __put_user(INSN_SWINT1, &frame->retcode[1]);
6625 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006626 }
6627 env->pc = (unsigned long) ka->_sa_handler;
6628 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6629 env->regs[TILEGX_R_LR] = restorer;
6630 env->regs[0] = (unsigned long) sig;
6631 env->regs[1] = (unsigned long) &frame->info;
6632 env->regs[2] = (unsigned long) &frame->uc;
6633 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6634
6635 unlock_user_struct(frame, frame_addr, 1);
6636 return;
6637
6638give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006639 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006640}
6641
6642long do_rt_sigreturn(CPUTLGState *env)
6643{
6644 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6645 struct target_rt_sigframe *frame;
6646 sigset_t set;
6647
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006648 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006649 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6650 goto badframe;
6651 }
6652 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006653 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006654
6655 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6656 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6657 uc.tuc_stack),
6658 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6659 goto badframe;
6660 }
6661
6662 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006663 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006664
6665
6666 badframe:
6667 unlock_user_struct(frame, frame_addr, 0);
6668 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006669 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006670}
6671
Michael Clark47ae93c2018-03-03 01:31:11 +13006672#elif defined(TARGET_RISCV)
6673
6674/* Signal handler invocation must be transparent for the code being
6675 interrupted. Complete CPU (hart) state is saved on entry and restored
6676 before returning from the handler. Process sigmask is also saved to block
6677 signals while the handler is running. The handler gets its own stack,
6678 which also doubles as storage for the CPU state and sigmask.
6679
6680 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6681
6682struct target_sigcontext {
6683 abi_long pc;
6684 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6685 uint64_t fpr[32];
6686 uint32_t fcsr;
6687}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6688
6689struct target_ucontext {
6690 unsigned long uc_flags;
6691 struct target_ucontext *uc_link;
6692 target_stack_t uc_stack;
6693 struct target_sigcontext uc_mcontext;
6694 target_sigset_t uc_sigmask;
6695};
6696
6697struct target_rt_sigframe {
6698 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6699 struct target_siginfo info;
6700 struct target_ucontext uc;
6701};
6702
6703static abi_ulong get_sigframe(struct target_sigaction *ka,
6704 CPURISCVState *regs, size_t framesize)
6705{
6706 abi_ulong sp = regs->gpr[xSP];
6707 int onsigstack = on_sig_stack(sp);
6708
6709 /* redzone */
6710 /* This is the X/Open sanctioned signal stack switching. */
6711 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6712 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6713 }
6714
6715 sp -= framesize;
6716 sp &= ~3UL; /* align sp on 4-byte boundary */
6717
6718 /* If we are on the alternate signal stack and would overflow it, don't.
6719 Return an always-bogus address instead so we will die with SIGSEGV. */
6720 if (onsigstack && !likely(on_sig_stack(sp))) {
6721 return -1L;
6722 }
6723
6724 return sp;
6725}
6726
6727static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6728{
6729 int i;
6730
6731 __put_user(env->pc, &sc->pc);
6732
6733 for (i = 1; i < 32; i++) {
6734 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6735 }
6736 for (i = 0; i < 32; i++) {
6737 __put_user(env->fpr[i], &sc->fpr[i]);
6738 }
6739
6740 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6741 __put_user(fcsr, &sc->fcsr);
6742}
6743
6744static void setup_ucontext(struct target_ucontext *uc,
6745 CPURISCVState *env, target_sigset_t *set)
6746{
6747 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6748 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6749 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6750
6751 __put_user(0, &(uc->uc_flags));
6752 __put_user(0, &(uc->uc_link));
6753
6754 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6755 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6756 __put_user(ss_size, &(uc->uc_stack.ss_size));
6757
6758 int i;
6759 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6760 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6761 }
6762
6763 setup_sigcontext(&uc->uc_mcontext, env);
6764}
6765
6766static inline void install_sigtramp(uint32_t *tramp)
6767{
6768 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6769 __put_user(0x00000073, tramp + 1); /* ecall */
6770}
6771
6772static void setup_rt_frame(int sig, struct target_sigaction *ka,
6773 target_siginfo_t *info,
6774 target_sigset_t *set, CPURISCVState *env)
6775{
6776 abi_ulong frame_addr;
6777 struct target_rt_sigframe *frame;
6778
6779 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6780 trace_user_setup_rt_frame(env, frame_addr);
6781
6782 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6783 goto badframe;
6784 }
6785
6786 setup_ucontext(&frame->uc, env, set);
6787 tswap_siginfo(&frame->info, info);
6788 install_sigtramp(frame->tramp);
6789
6790 env->pc = ka->_sa_handler;
6791 env->gpr[xSP] = frame_addr;
6792 env->gpr[xA0] = sig;
6793 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6794 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6795 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6796
6797 return;
6798
6799badframe:
6800 unlock_user_struct(frame, frame_addr, 1);
6801 if (sig == TARGET_SIGSEGV) {
6802 ka->_sa_handler = TARGET_SIG_DFL;
6803 }
6804 force_sig(TARGET_SIGSEGV);
6805}
6806
6807static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6808{
6809 int i;
6810
6811 __get_user(env->pc, &sc->pc);
6812
6813 for (i = 1; i < 32; ++i) {
6814 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6815 }
6816 for (i = 0; i < 32; ++i) {
6817 __get_user(env->fpr[i], &sc->fpr[i]);
6818 }
6819
6820 uint32_t fcsr;
6821 __get_user(fcsr, &sc->fcsr);
6822 csr_write_helper(env, fcsr, CSR_FCSR);
6823}
6824
6825static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6826{
6827 sigset_t blocked;
6828 target_sigset_t target_set;
6829 int i;
6830
6831 target_sigemptyset(&target_set);
6832 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6833 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6834 }
6835
6836 target_to_host_sigset_internal(&blocked, &target_set);
6837 set_sigmask(&blocked);
6838
6839 restore_sigcontext(env, &uc->uc_mcontext);
6840}
6841
6842long do_rt_sigreturn(CPURISCVState *env)
6843{
6844 struct target_rt_sigframe *frame;
6845 abi_ulong frame_addr;
6846
6847 frame_addr = env->gpr[xSP];
6848 trace_user_do_sigreturn(env, frame_addr);
6849 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6850 goto badframe;
6851 }
6852
6853 restore_ucontext(env, &frame->uc);
6854
6855 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6856 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6857 goto badframe;
6858 }
6859
6860 unlock_user_struct(frame, frame_addr, 0);
6861 return -TARGET_QEMU_ESIGRETURN;
6862
6863badframe:
6864 unlock_user_struct(frame, frame_addr, 0);
6865 force_sig(TARGET_SIGSEGV);
6866 return 0;
6867}
6868
Richard Henderson1659e382016-12-15 09:59:01 -08006869#elif defined(TARGET_HPPA)
6870
6871struct target_sigcontext {
6872 abi_ulong sc_flags;
6873 abi_ulong sc_gr[32];
6874 uint64_t sc_fr[32];
6875 abi_ulong sc_iasq[2];
6876 abi_ulong sc_iaoq[2];
6877 abi_ulong sc_sar;
6878};
6879
6880struct target_ucontext {
6881 abi_uint tuc_flags;
6882 abi_ulong tuc_link;
6883 target_stack_t tuc_stack;
6884 abi_uint pad[1];
6885 struct target_sigcontext tuc_mcontext;
6886 target_sigset_t tuc_sigmask;
6887};
6888
6889struct target_rt_sigframe {
6890 abi_uint tramp[9];
6891 target_siginfo_t info;
6892 struct target_ucontext uc;
6893 /* hidden location of upper halves of pa2.0 64-bit gregs */
6894};
6895
6896static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6897{
6898 int flags = 0;
6899 int i;
6900
6901 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6902
6903 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6904 /* In the gateway page, executing a syscall. */
6905 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6906 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6907 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6908 } else {
6909 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6910 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6911 }
6912 __put_user(0, &sc->sc_iasq[0]);
6913 __put_user(0, &sc->sc_iasq[1]);
6914 __put_user(flags, &sc->sc_flags);
6915
6916 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6917 for (i = 1; i < 32; ++i) {
6918 __put_user(env->gr[i], &sc->sc_gr[i]);
6919 }
6920
6921 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6922 for (i = 1; i < 32; ++i) {
6923 __put_user(env->fr[i], &sc->sc_fr[i]);
6924 }
6925
Richard Henderson35136a72017-10-10 21:19:34 -07006926 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006927}
6928
6929static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6930{
6931 target_ulong psw;
6932 int i;
6933
6934 __get_user(psw, &sc->sc_gr[0]);
6935 cpu_hppa_put_psw(env, psw);
6936
6937 for (i = 1; i < 32; ++i) {
6938 __get_user(env->gr[i], &sc->sc_gr[i]);
6939 }
6940 for (i = 0; i < 32; ++i) {
6941 __get_user(env->fr[i], &sc->sc_fr[i]);
6942 }
6943 cpu_hppa_loaded_fr0(env);
6944
6945 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6946 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006947 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006948}
6949
6950/* No, this doesn't look right, but it's copied straight from the kernel. */
6951#define PARISC_RT_SIGFRAME_SIZE32 \
6952 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6953
6954static void setup_rt_frame(int sig, struct target_sigaction *ka,
6955 target_siginfo_t *info,
6956 target_sigset_t *set, CPUArchState *env)
6957{
6958 abi_ulong frame_addr, sp, haddr;
6959 struct target_rt_sigframe *frame;
6960 int i;
6961
6962 sp = env->gr[30];
6963 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6964 if (sas_ss_flags(sp) == 0) {
6965 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6966 }
6967 }
6968 frame_addr = QEMU_ALIGN_UP(sp, 64);
6969 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6970
6971 trace_user_setup_rt_frame(env, frame_addr);
6972
6973 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6974 goto give_sigsegv;
6975 }
6976
6977 tswap_siginfo(&frame->info, info);
6978 frame->uc.tuc_flags = 0;
6979 frame->uc.tuc_link = 0;
6980
6981 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6982 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6983 &frame->uc.tuc_stack.ss_flags);
6984 __put_user(target_sigaltstack_used.ss_size,
6985 &frame->uc.tuc_stack.ss_size);
6986
6987 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6988 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6989 }
6990
6991 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6992
6993 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6994 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6995 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6996 __put_user(0x08000240, frame->tramp + 3); /* nop */
6997
6998 unlock_user_struct(frame, frame_addr, 1);
6999
7000 env->gr[2] = h2g(frame->tramp);
7001 env->gr[30] = sp;
7002 env->gr[26] = sig;
7003 env->gr[25] = h2g(&frame->info);
7004 env->gr[24] = h2g(&frame->uc);
7005
7006 haddr = ka->_sa_handler;
7007 if (haddr & 2) {
7008 /* Function descriptor. */
7009 target_ulong *fdesc, dest;
7010
7011 haddr &= -4;
7012 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
7013 goto give_sigsegv;
7014 }
7015 __get_user(dest, fdesc);
7016 __get_user(env->gr[19], fdesc + 1);
7017 unlock_user_struct(fdesc, haddr, 1);
7018 haddr = dest;
7019 }
7020 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02007021 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08007022 return;
7023
7024 give_sigsegv:
7025 force_sigsegv(sig);
7026}
7027
7028long do_rt_sigreturn(CPUArchState *env)
7029{
7030 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
7031 struct target_rt_sigframe *frame;
7032 sigset_t set;
7033
7034 trace_user_do_rt_sigreturn(env, frame_addr);
7035 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7036 goto badframe;
7037 }
7038 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7039 set_sigmask(&set);
7040
7041 restore_sigcontext(env, &frame->uc.tuc_mcontext);
7042 unlock_user_struct(frame, frame_addr, 0);
7043
7044 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
7045 uc.tuc_stack),
7046 0, env->gr[30]) == -EFAULT) {
7047 goto badframe;
7048 }
7049
7050 unlock_user_struct(frame, frame_addr, 0);
7051 return -TARGET_QEMU_ESIGRETURN;
7052
7053 badframe:
7054 force_sig(TARGET_SIGSEGV);
7055 return -TARGET_QEMU_ESIGRETURN;
7056}
7057
Max Filippovba7651f2017-01-25 10:54:11 -08007058#elif defined(TARGET_XTENSA)
7059
7060struct target_sigcontext {
7061 abi_ulong sc_pc;
7062 abi_ulong sc_ps;
7063 abi_ulong sc_lbeg;
7064 abi_ulong sc_lend;
7065 abi_ulong sc_lcount;
7066 abi_ulong sc_sar;
7067 abi_ulong sc_acclo;
7068 abi_ulong sc_acchi;
7069 abi_ulong sc_a[16];
7070 abi_ulong sc_xtregs;
7071};
7072
7073struct target_ucontext {
7074 abi_ulong tuc_flags;
7075 abi_ulong tuc_link;
7076 target_stack_t tuc_stack;
7077 struct target_sigcontext tuc_mcontext;
7078 target_sigset_t tuc_sigmask;
7079};
7080
7081struct target_rt_sigframe {
7082 target_siginfo_t info;
7083 struct target_ucontext uc;
7084 /* TODO: xtregs */
7085 uint8_t retcode[6];
7086 abi_ulong window[4];
7087};
7088
7089static abi_ulong get_sigframe(struct target_sigaction *sa,
7090 CPUXtensaState *env,
7091 unsigned long framesize)
7092{
7093 abi_ulong sp = env->regs[1];
7094
7095 /* This is the X/Open sanctioned signal stack switching. */
7096 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
7097 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
7098 }
7099 return (sp - framesize) & -16;
7100}
7101
7102static int flush_window_regs(CPUXtensaState *env)
7103{
Max Filippovba7651f2017-01-25 10:54:11 -08007104 uint32_t wb = env->sregs[WINDOW_BASE];
Max Filippov20ef6672018-03-28 00:25:22 -07007105 uint32_t ws = xtensa_replicate_windowstart(env) >> (wb + 1);
7106 unsigned d = ctz32(ws) + 1;
7107 unsigned i;
7108 int ret = 0;
Max Filippovba7651f2017-01-25 10:54:11 -08007109
Max Filippov20ef6672018-03-28 00:25:22 -07007110 for (i = d; i < env->config->nareg / 4; i += d) {
7111 uint32_t ssp, osp;
7112 unsigned j;
Max Filippovba7651f2017-01-25 10:54:11 -08007113
Max Filippov20ef6672018-03-28 00:25:22 -07007114 ws >>= d;
7115 xtensa_rotate_window(env, d);
Max Filippovba7651f2017-01-25 10:54:11 -08007116
7117 if (ws & 0x1) {
Max Filippov20ef6672018-03-28 00:25:22 -07007118 ssp = env->regs[5];
Max Filippovba7651f2017-01-25 10:54:11 -08007119 d = 1;
7120 } else if (ws & 0x2) {
Max Filippov20ef6672018-03-28 00:25:22 -07007121 ssp = env->regs[9];
7122 ret |= get_user_ual(osp, env->regs[1] - 12);
7123 osp -= 32;
Max Filippovba7651f2017-01-25 10:54:11 -08007124 d = 2;
Max Filippovba7651f2017-01-25 10:54:11 -08007125 } else if (ws & 0x4) {
Max Filippov20ef6672018-03-28 00:25:22 -07007126 ssp = env->regs[13];
7127 ret |= get_user_ual(osp, env->regs[1] - 12);
7128 osp -= 48;
Max Filippovba7651f2017-01-25 10:54:11 -08007129 d = 3;
Max Filippovba7651f2017-01-25 10:54:11 -08007130 } else {
7131 g_assert_not_reached();
7132 }
Max Filippov20ef6672018-03-28 00:25:22 -07007133
7134 for (j = 0; j < 4; ++j) {
7135 ret |= put_user_ual(env->regs[j], ssp - 16 + j * 4);
Max Filippovba7651f2017-01-25 10:54:11 -08007136 }
Max Filippov20ef6672018-03-28 00:25:22 -07007137 for (j = 4; j < d * 4; ++j) {
7138 ret |= put_user_ual(env->regs[j], osp - 16 + j * 4);
7139 }
Max Filippovba7651f2017-01-25 10:54:11 -08007140 }
Max Filippov20ef6672018-03-28 00:25:22 -07007141 xtensa_rotate_window(env, d);
7142 g_assert(env->sregs[WINDOW_BASE] == wb);
Max Filippovba7651f2017-01-25 10:54:11 -08007143 return ret == 0;
7144}
7145
7146static int setup_sigcontext(struct target_rt_sigframe *frame,
7147 CPUXtensaState *env)
7148{
7149 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7150 int i;
7151
7152 __put_user(env->pc, &sc->sc_pc);
7153 __put_user(env->sregs[PS], &sc->sc_ps);
7154 __put_user(env->sregs[LBEG], &sc->sc_lbeg);
7155 __put_user(env->sregs[LEND], &sc->sc_lend);
7156 __put_user(env->sregs[LCOUNT], &sc->sc_lcount);
7157 if (!flush_window_regs(env)) {
7158 return 0;
7159 }
7160 for (i = 0; i < 16; ++i) {
7161 __put_user(env->regs[i], sc->sc_a + i);
7162 }
7163 __put_user(0, &sc->sc_xtregs);
7164 /* TODO: xtregs */
7165 return 1;
7166}
7167
7168static void setup_rt_frame(int sig, struct target_sigaction *ka,
7169 target_siginfo_t *info,
7170 target_sigset_t *set, CPUXtensaState *env)
7171{
7172 abi_ulong frame_addr;
7173 struct target_rt_sigframe *frame;
7174 uint32_t ra;
7175 int i;
7176
7177 frame_addr = get_sigframe(ka, env, sizeof(*frame));
7178 trace_user_setup_rt_frame(env, frame_addr);
7179
7180 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
7181 goto give_sigsegv;
7182 }
7183
7184 if (ka->sa_flags & SA_SIGINFO) {
7185 tswap_siginfo(&frame->info, info);
7186 }
7187
7188 __put_user(0, &frame->uc.tuc_flags);
7189 __put_user(0, &frame->uc.tuc_link);
7190 __put_user(target_sigaltstack_used.ss_sp,
7191 &frame->uc.tuc_stack.ss_sp);
7192 __put_user(sas_ss_flags(env->regs[1]),
7193 &frame->uc.tuc_stack.ss_flags);
7194 __put_user(target_sigaltstack_used.ss_size,
7195 &frame->uc.tuc_stack.ss_size);
7196 if (!setup_sigcontext(frame, env)) {
7197 unlock_user_struct(frame, frame_addr, 0);
7198 goto give_sigsegv;
7199 }
7200 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
7201 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7202 }
7203
7204 if (ka->sa_flags & TARGET_SA_RESTORER) {
7205 ra = ka->sa_restorer;
7206 } else {
7207 ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
7208#ifdef TARGET_WORDS_BIGENDIAN
7209 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7210 __put_user(0x22, &frame->retcode[0]);
7211 __put_user(0x0a, &frame->retcode[1]);
7212 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7213 /* Generate instruction: SYSCALL */
7214 __put_user(0x00, &frame->retcode[3]);
7215 __put_user(0x05, &frame->retcode[4]);
7216 __put_user(0x00, &frame->retcode[5]);
7217#else
7218 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7219 __put_user(0x22, &frame->retcode[0]);
7220 __put_user(0xa0, &frame->retcode[1]);
7221 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7222 /* Generate instruction: SYSCALL */
7223 __put_user(0x00, &frame->retcode[3]);
7224 __put_user(0x50, &frame->retcode[4]);
7225 __put_user(0x00, &frame->retcode[5]);
7226#endif
7227 }
7228 env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
7229 if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
7230 env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
7231 }
7232 memset(env->regs, 0, sizeof(env->regs));
7233 env->pc = ka->_sa_handler;
7234 env->regs[1] = frame_addr;
7235 env->sregs[WINDOW_BASE] = 0;
7236 env->sregs[WINDOW_START] = 1;
7237
7238 env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
7239 env->regs[6] = sig;
7240 env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
7241 env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
7242 unlock_user_struct(frame, frame_addr, 1);
7243 return;
7244
7245give_sigsegv:
7246 force_sigsegv(sig);
7247 return;
7248}
7249
7250static void restore_sigcontext(CPUXtensaState *env,
7251 struct target_rt_sigframe *frame)
7252{
7253 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7254 uint32_t ps;
7255 int i;
7256
7257 __get_user(env->pc, &sc->sc_pc);
7258 __get_user(ps, &sc->sc_ps);
7259 __get_user(env->sregs[LBEG], &sc->sc_lbeg);
7260 __get_user(env->sregs[LEND], &sc->sc_lend);
7261 __get_user(env->sregs[LCOUNT], &sc->sc_lcount);
7262
7263 env->sregs[WINDOW_BASE] = 0;
7264 env->sregs[WINDOW_START] = 1;
7265 env->sregs[PS] = deposit32(env->sregs[PS],
7266 PS_CALLINC_SHIFT,
7267 PS_CALLINC_LEN,
7268 extract32(ps, PS_CALLINC_SHIFT,
7269 PS_CALLINC_LEN));
7270 for (i = 0; i < 16; ++i) {
7271 __get_user(env->regs[i], sc->sc_a + i);
7272 }
7273 /* TODO: xtregs */
7274}
7275
7276long do_rt_sigreturn(CPUXtensaState *env)
7277{
7278 abi_ulong frame_addr = env->regs[1];
7279 struct target_rt_sigframe *frame;
7280 sigset_t set;
7281
7282 trace_user_do_rt_sigreturn(env, frame_addr);
7283 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7284 goto badframe;
7285 }
7286 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7287 set_sigmask(&set);
7288
7289 restore_sigcontext(env, frame);
7290
7291 if (do_sigaltstack(frame_addr +
7292 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7293 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) {
7294 goto badframe;
7295 }
7296 unlock_user_struct(frame, frame_addr, 0);
7297 return -TARGET_QEMU_ESIGRETURN;
7298
7299badframe:
7300 unlock_user_struct(frame, frame_addr, 0);
7301 force_sig(TARGET_SIGSEGV);
7302 return -TARGET_QEMU_ESIGRETURN;
7303}
7304
bellardb346ff42003-06-15 20:05:50 +00007305#else
Peter Maydellf8b985d2018-03-08 14:47:33 +00007306#error Target needs to add support for signal handling
bellard66fb9762003-03-23 01:06:05 +00007307#endif
7308
Peter Maydell31efaef2016-07-06 15:09:29 +01007309static void handle_pending_signal(CPUArchState *cpu_env, int sig,
7310 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01007311{
7312 CPUState *cpu = ENV_GET_CPU(cpu_env);
7313 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007314 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01007315 target_sigset_t target_old_set;
7316 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01007317 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01007318
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01007319 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00007320 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007321 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00007322
Andreas Färberdb6b81d2013-06-27 19:49:31 +02007323 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00007324 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00007325 sa = NULL;
7326 handler = TARGET_SIG_IGN;
7327 } else {
7328 sa = &sigact_table[sig - 1];
7329 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00007330 }
bellard66fb9762003-03-23 01:06:05 +00007331
Peter Maydell0cb581d2016-07-18 18:12:24 +01007332 if (do_strace) {
7333 print_taken_signal(sig, &k->info);
7334 }
7335
bellard66fb9762003-03-23 01:06:05 +00007336 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00007337 /* default handler : ignore some signal. The other are job control or fatal */
7338 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
7339 kill(getpid(),SIGSTOP);
7340 } else if (sig != TARGET_SIGCHLD &&
7341 sig != TARGET_SIGURG &&
7342 sig != TARGET_SIGWINCH &&
7343 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007344 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007345 }
7346 } else if (handler == TARGET_SIG_IGN) {
7347 /* ignore sig */
7348 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007349 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007350 } else {
bellard9de5e442003-03-23 16:49:39 +00007351 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007352 sigset_t *blocked_set;
7353
pbrook624f7972008-05-31 16:11:38 +00007354 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00007355 /* SA_NODEFER indicates that the current signal should not be
7356 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00007357 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00007358 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00007359
bellard9de5e442003-03-23 16:49:39 +00007360 /* save the previous blocked signal state to restore it at the
7361 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007362 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
7363
7364 /* block signals in the handler */
7365 blocked_set = ts->in_sigsuspend ?
7366 &ts->sigsuspend_mask : &ts->signal_mask;
7367 sigorset(&ts->signal_mask, blocked_set, &set);
7368 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00007369
bellardbc8a22c2003-03-30 21:02:40 +00007370 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00007371#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00007372 {
7373 CPUX86State *env = cpu_env;
7374 if (env->eflags & VM_MASK)
7375 save_v86_state(env);
7376 }
7377#endif
bellard9de5e442003-03-23 16:49:39 +00007378 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08007379#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10007380 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01007381 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13007382 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
Max Filippovba7651f2017-01-25 10:54:11 -08007383 || defined(TARGET_RISCV) || defined(TARGET_XTENSA)
Richard Hendersonff970902013-02-10 10:30:42 -08007384 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007385 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007386#else
pbrook624f7972008-05-31 16:11:38 +00007387 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007388 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00007389 else
pbrook624f7972008-05-31 16:11:38 +00007390 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007391#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01007392 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00007393 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01007394 }
bellard31e31b82003-02-18 22:55:36 +00007395 }
bellard31e31b82003-02-18 22:55:36 +00007396}
Peter Maydelle902d582016-05-27 15:51:44 +01007397
7398void process_pending_signals(CPUArchState *cpu_env)
7399{
7400 CPUState *cpu = ENV_GET_CPU(cpu_env);
7401 int sig;
7402 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007403 sigset_t set;
7404 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007405
Peter Maydell3d3efba2016-05-27 15:51:49 +01007406 while (atomic_read(&ts->signal_pending)) {
7407 /* FIXME: This is not threadsafe. */
7408 sigfillset(&set);
7409 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007410
Peter Maydell8bd37732016-07-28 16:44:45 +01007411 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007412 sig = ts->sync_signal.pending;
7413 if (sig) {
7414 /* Synchronous signals are forced,
7415 * see force_sig_info() and callers in Linux
7416 * Note that not all of our queue_signal() calls in QEMU correspond
7417 * to force_sig_info() calls in Linux (some are send_sig_info()).
7418 * However it seems like a kernel bug to me to allow the process
7419 * to block a synchronous signal since it could then just end up
7420 * looping round and round indefinitely.
7421 */
7422 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7423 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7424 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7425 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7426 }
7427
Peter Maydell31efaef2016-07-06 15:09:29 +01007428 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007429 }
7430
Peter Maydell3d3efba2016-05-27 15:51:49 +01007431 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7432 blocked_set = ts->in_sigsuspend ?
7433 &ts->sigsuspend_mask : &ts->signal_mask;
7434
7435 if (ts->sigtab[sig - 1].pending &&
7436 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007437 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007438 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007439 /* Restart scan from the beginning, as handle_pending_signal
7440 * might have resulted in a new synchronous signal (eg SIGSEGV).
7441 */
7442 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007443 }
Peter Maydelle902d582016-05-27 15:51:44 +01007444 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007445
7446 /* if no signal is pending, unblock signals and recheck (the act
7447 * of unblocking might cause us to take another host signal which
7448 * will set signal_pending again).
7449 */
7450 atomic_set(&ts->signal_pending, 0);
7451 ts->in_sigsuspend = 0;
7452 set = ts->signal_mask;
7453 sigdelset(&set, SIGSEGV);
7454 sigdelset(&set, SIGBUS);
7455 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007456 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007457 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007458}