blob: 761d6acbf3048ced6f566ff88ff14ee887069103 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydell9eede5b2016-05-27 15:51:46 +0100256#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
Pranith Kumar1c1df012017-02-26 11:53:44 -0500257 !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100258/* Just set the guest's signal mask to the specified value; the
259 * caller is assumed to have called block_signals() already.
260 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100261static void set_sigmask(const sigset_t *set)
262{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100263 TaskState *ts = (TaskState *)thread_cpu->opaque;
264
265 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100266}
267#endif
268
bellard9de5e442003-03-23 16:49:39 +0000269/* siginfo conversion */
270
Anthony Liguoric227f092009-10-01 16:12:16 -0500271static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000272 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000273{
Richard Hendersona05c6402012-09-15 11:34:20 -0700274 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100275 int si_code = info->si_code;
276 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000279 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700280
Peter Maydell55d72a72016-06-13 11:22:05 +0100281 /* This memset serves two purposes:
282 * (1) ensure we don't leak random junk to the guest later
283 * (2) placate false positives from gcc about fields
284 * being used uninitialized if it chooses to inline both this
285 * function and tswap_siginfo() into host_to_target_siginfo().
286 */
287 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
288
Peter Maydella70dadc2016-05-27 15:51:59 +0100289 /* This is awkward, because we have to use a combination of
290 * the si_code and si_signo to figure out which of the union's
291 * members are valid. (Within the host kernel it is always possible
292 * to tell, but the kernel carefully avoids giving userspace the
293 * high 16 bits of si_code, so we don't have the information to
294 * do this the easy way...) We therefore make our best guess,
295 * bearing in mind that a guest can spoof most of the si_codes
296 * via rt_sigqueueinfo() if it likes.
297 *
298 * Once we have made our guess, we record it in the top 16 bits of
299 * the si_code, so that tswap_siginfo() later can use it.
300 * tswap_siginfo() will strip these top bits out before writing
301 * si_code to the guest (sign-extending the lower bits).
302 */
303
304 switch (si_code) {
305 case SI_USER:
306 case SI_TKILL:
307 case SI_KERNEL:
308 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
309 * These are the only unspoofable si_code values.
310 */
311 tinfo->_sifields._kill._pid = info->si_pid;
312 tinfo->_sifields._kill._uid = info->si_uid;
313 si_type = QEMU_SI_KILL;
314 break;
315 default:
316 /* Everything else is spoofable. Make best guess based on signal */
317 switch (sig) {
318 case TARGET_SIGCHLD:
319 tinfo->_sifields._sigchld._pid = info->si_pid;
320 tinfo->_sifields._sigchld._uid = info->si_uid;
321 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100322 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100323 tinfo->_sifields._sigchld._utime = info->si_utime;
324 tinfo->_sifields._sigchld._stime = info->si_stime;
325 si_type = QEMU_SI_CHLD;
326 break;
327 case TARGET_SIGIO:
328 tinfo->_sifields._sigpoll._band = info->si_band;
329 tinfo->_sifields._sigpoll._fd = info->si_fd;
330 si_type = QEMU_SI_POLL;
331 break;
332 default:
333 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
334 tinfo->_sifields._rt._pid = info->si_pid;
335 tinfo->_sifields._rt._uid = info->si_uid;
336 /* XXX: potential problem if 64 bit */
337 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100338 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100339 si_type = QEMU_SI_RT;
340 break;
341 }
342 break;
bellard9de5e442003-03-23 16:49:39 +0000343 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100344
345 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000346}
347
Anthony Liguoric227f092009-10-01 16:12:16 -0500348static void tswap_siginfo(target_siginfo_t *tinfo,
349 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000350{
Peter Maydella70dadc2016-05-27 15:51:59 +0100351 int si_type = extract32(info->si_code, 16, 16);
352 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700353
Peter Maydella70dadc2016-05-27 15:51:59 +0100354 __put_user(info->si_signo, &tinfo->si_signo);
355 __put_user(info->si_errno, &tinfo->si_errno);
356 __put_user(si_code, &tinfo->si_code);
357
358 /* We can use our internal marker of which fields in the structure
359 * are valid, rather than duplicating the guesswork of
360 * host_to_target_siginfo_noswap() here.
361 */
362 switch (si_type) {
363 case QEMU_SI_KILL:
364 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
365 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
366 break;
367 case QEMU_SI_TIMER:
368 __put_user(info->_sifields._timer._timer1,
369 &tinfo->_sifields._timer._timer1);
370 __put_user(info->_sifields._timer._timer2,
371 &tinfo->_sifields._timer._timer2);
372 break;
373 case QEMU_SI_POLL:
374 __put_user(info->_sifields._sigpoll._band,
375 &tinfo->_sifields._sigpoll._band);
376 __put_user(info->_sifields._sigpoll._fd,
377 &tinfo->_sifields._sigpoll._fd);
378 break;
379 case QEMU_SI_FAULT:
380 __put_user(info->_sifields._sigfault._addr,
381 &tinfo->_sifields._sigfault._addr);
382 break;
383 case QEMU_SI_CHLD:
384 __put_user(info->_sifields._sigchld._pid,
385 &tinfo->_sifields._sigchld._pid);
386 __put_user(info->_sifields._sigchld._uid,
387 &tinfo->_sifields._sigchld._uid);
388 __put_user(info->_sifields._sigchld._status,
389 &tinfo->_sifields._sigchld._status);
390 __put_user(info->_sifields._sigchld._utime,
391 &tinfo->_sifields._sigchld._utime);
392 __put_user(info->_sifields._sigchld._stime,
393 &tinfo->_sifields._sigchld._stime);
394 break;
395 case QEMU_SI_RT:
396 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
397 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
398 __put_user(info->_sifields._rt._sigval.sival_ptr,
399 &tinfo->_sifields._rt._sigval.sival_ptr);
400 break;
401 default:
402 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000403 }
404}
405
Anthony Liguoric227f092009-10-01 16:12:16 -0500406void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000407{
Peter Maydell55d72a72016-06-13 11:22:05 +0100408 target_siginfo_t tgt_tmp;
409 host_to_target_siginfo_noswap(&tgt_tmp, info);
410 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000411}
412
413/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000414/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500415void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000416{
Peter Maydell90c0f082016-05-27 15:52:01 +0100417 /* This conversion is used only for the rt_sigqueueinfo syscall,
418 * and so we know that the _rt fields are the valid ones.
419 */
420 abi_ulong sival_ptr;
421
422 __get_user(info->si_signo, &tinfo->si_signo);
423 __get_user(info->si_errno, &tinfo->si_errno);
424 __get_user(info->si_code, &tinfo->si_code);
425 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
426 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
427 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
428 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000429}
430
aurel32ca587a82008-12-18 22:44:13 +0000431static int fatal_signal (int sig)
432{
433 switch (sig) {
434 case TARGET_SIGCHLD:
435 case TARGET_SIGURG:
436 case TARGET_SIGWINCH:
437 /* Ignored by default. */
438 return 0;
439 case TARGET_SIGCONT:
440 case TARGET_SIGSTOP:
441 case TARGET_SIGTSTP:
442 case TARGET_SIGTTIN:
443 case TARGET_SIGTTOU:
444 /* Job control signals. */
445 return 0;
446 default:
447 return 1;
448 }
449}
450
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451/* returns 1 if given signal should dump core if not handled */
452static int core_dump_signal(int sig)
453{
454 switch (sig) {
455 case TARGET_SIGABRT:
456 case TARGET_SIGFPE:
457 case TARGET_SIGILL:
458 case TARGET_SIGQUIT:
459 case TARGET_SIGSEGV:
460 case TARGET_SIGTRAP:
461 case TARGET_SIGBUS:
462 return (1);
463 default:
464 return (0);
465 }
466}
467
bellard31e31b82003-02-18 22:55:36 +0000468void signal_init(void)
469{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100470 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000471 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000472 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000473 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000474 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000475
bellard9e5f5282003-07-13 17:33:54 +0000476 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200477 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000478 if (host_to_target_signal_table[i] == 0)
479 host_to_target_signal_table[i] = i;
480 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200481 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000482 j = host_to_target_signal_table[i];
483 target_to_host_signal_table[j] = i;
484 }
ths3b46e622007-09-17 08:09:54 +0000485
Peter Maydell3d3efba2016-05-27 15:51:49 +0100486 /* Set the signal mask from the host mask. */
487 sigprocmask(0, 0, &ts->signal_mask);
488
bellard9de5e442003-03-23 16:49:39 +0000489 /* set all host signal handlers. ALL signals are blocked during
490 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000491 memset(sigact_table, 0, sizeof(sigact_table));
492
bellard9de5e442003-03-23 16:49:39 +0000493 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000494 act.sa_flags = SA_SIGINFO;
495 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000496 for(i = 1; i <= TARGET_NSIG; i++) {
497 host_sig = target_to_host_signal(i);
498 sigaction(host_sig, NULL, &oact);
499 if (oact.sa_sigaction == (void *)SIG_IGN) {
500 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
501 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
502 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
503 }
504 /* If there's already a handler installed then something has
505 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000506 /* Install some handlers for our own use. We need at least
507 SIGSEGV and SIGBUS, to detect exceptions. We can not just
508 trap all signals because it affects syscall interrupt
509 behavior. But do trap all default-fatal signals. */
510 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000511 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000512 }
bellard31e31b82003-02-18 22:55:36 +0000513}
514
Pranith Kumar1c1df012017-02-26 11:53:44 -0500515#ifndef TARGET_UNICORE32
Peter Maydellc599d4d2016-07-28 16:44:49 +0100516/* Force a synchronously taken signal. The kernel force_sig() function
517 * also forces the signal to "not blocked, not ignored", but for QEMU
518 * that work is done in process_pending_signals().
519 */
520static void force_sig(int sig)
521{
522 CPUState *cpu = thread_cpu;
523 CPUArchState *env = cpu->env_ptr;
524 target_siginfo_t info;
525
526 info.si_signo = sig;
527 info.si_errno = 0;
528 info.si_code = TARGET_SI_KERNEL;
529 info._sifields._kill._pid = 0;
530 info._sifields._kill._uid = 0;
531 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
532}
Peter Maydell09391662016-07-28 16:44:47 +0100533
534/* Force a SIGSEGV if we couldn't write to memory trying to set
535 * up the signal frame. oldsig is the signal we were trying to handle
536 * at the point of failure.
537 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300538#if !defined(TARGET_RISCV)
Peter Maydell09391662016-07-28 16:44:47 +0100539static void force_sigsegv(int oldsig)
540{
Peter Maydell09391662016-07-28 16:44:47 +0100541 if (oldsig == SIGSEGV) {
542 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100543 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100544 */
545 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
546 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100547 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100548}
549#endif
bellard66fb9762003-03-23 01:06:05 +0000550
Michael Clark47ae93c2018-03-03 01:31:11 +1300551#endif
552
bellard9de5e442003-03-23 16:49:39 +0000553/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100554static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000555{
Andreas Färber0429a972013-08-26 18:14:44 +0200556 CPUState *cpu = thread_cpu;
557 CPUArchState *env = cpu->env_ptr;
558 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300559 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000560 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100561
Riku Voipio66393fb2009-12-04 15:16:32 +0200562 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100563 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200564 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000565
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300566 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200567 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 stop_all_tasks();
569 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200570 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300571 }
572 if (core_dumped) {
573 /* we already dumped the core of target process, we don't want
574 * a coredump of qemu itself */
575 struct rlimit nodump;
576 getrlimit(RLIMIT_CORE, &nodump);
577 nodump.rlim_cur=0;
578 setrlimit(RLIMIT_CORE, &nodump);
579 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200580 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300581 }
582
Stefan Weil0c587512011-04-28 17:20:32 +0200583 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000584 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
585 * a negative value. To get the proper exit code we need to
586 * actually die from an uncaught signal. Here the default signal
587 * handler is installed, we send ourself a signal and we wait for
588 * it to arrive. */
589 sigfillset(&act.sa_mask);
590 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000591 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000592 sigaction(host_sig, &act, NULL);
593
594 /* For some reason raise(host_sig) doesn't send the signal when
595 * statically linked on x86-64. */
596 kill(getpid(), host_sig);
597
598 /* Make sure the signal isn't masked (just reuse the mask inside
599 of act) */
600 sigdelset(&act.sa_mask, host_sig);
601 sigsuspend(&act.sa_mask);
602
603 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000604 abort();
bellard66fb9762003-03-23 01:06:05 +0000605}
606
bellard9de5e442003-03-23 16:49:39 +0000607/* queue a signal so that it will be send to the virtual CPU as soon
608 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100609int queue_signal(CPUArchState *env, int sig, int si_type,
610 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000611{
Andreas Färber0429a972013-08-26 18:14:44 +0200612 CPUState *cpu = ENV_GET_CPU(env);
613 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000614
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100615 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000616
Peter Maydell9d2803f2016-07-28 16:44:46 +0100617 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100618
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100619 ts->sync_signal.info = *info;
620 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100621 /* signal that a new signal is pending */
622 atomic_set(&ts->signal_pending, 1);
623 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000624}
625
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100626#ifndef HAVE_SAFE_SYSCALL
627static inline void rewind_if_in_safe_syscall(void *puc)
628{
629 /* Default version: never rewind */
630}
631#endif
632
ths5fafdf22007-09-16 21:08:06 +0000633static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000634 void *puc)
635{
Andreas Färbera2247f82013-06-09 19:47:04 +0200636 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100637 CPUState *cpu = ENV_GET_CPU(env);
638 TaskState *ts = cpu->opaque;
639
bellard9de5e442003-03-23 16:49:39 +0000640 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500641 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100642 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100643 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000644
645 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000646 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000647 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000648 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000649 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000650 return;
651 }
652
653 /* get target signal number */
654 sig = host_to_target_signal(host_signum);
655 if (sig < 1 || sig > TARGET_NSIG)
656 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100657 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100658
659 rewind_if_in_safe_syscall(puc);
660
bellard9de5e442003-03-23 16:49:39 +0000661 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100662 k = &ts->sigtab[sig - 1];
663 k->info = tinfo;
664 k->pending = sig;
665 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100666
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100667 /* Block host signals until target signal handler entered. We
668 * can't block SIGSEGV or SIGBUS while we're executing guest
669 * code in case the guest code provokes one in the window between
670 * now and it getting out to the main loop. Signals will be
671 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100672 *
673 * WARNING: we cannot use sigfillset() here because the uc_sigmask
674 * field is a kernel sigset_t, which is much smaller than the
675 * libc sigset_t which sigfillset() operates on. Using sigfillset()
676 * would write 0xff bytes off the end of the structure and trash
677 * data on the struct.
678 * We can't use sizeof(uc->uc_sigmask) either, because the libc
679 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100680 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100681 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100682 sigdelset(&uc->uc_sigmask, SIGSEGV);
683 sigdelset(&uc->uc_sigmask, SIGBUS);
684
685 /* interrupt the virtual CPU as soon as possible */
686 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000687}
688
ths0da46a62007-10-20 20:23:07 +0000689/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000690/* compare linux/kernel/signal.c:do_sigaltstack() */
691abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000692{
693 int ret;
694 struct target_sigaltstack oss;
695
696 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000697 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000698 {
699 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
700 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
701 __put_user(sas_ss_flags(sp), &oss.ss_flags);
702 }
703
bellard579a97f2007-11-11 14:26:47 +0000704 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000705 {
bellard579a97f2007-11-11 14:26:47 +0000706 struct target_sigaltstack *uss;
707 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500708 size_t minstacksize = TARGET_MINSIGSTKSZ;
709
710#if defined(TARGET_PPC64)
711 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
712 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
713 if (get_ppc64_abi(image) > 1) {
714 minstacksize = 4096;
715 }
716#endif
thsa04e1342007-09-27 13:57:58 +0000717
ths0da46a62007-10-20 20:23:07 +0000718 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300719 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000720 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300721 }
722 __get_user(ss.ss_sp, &uss->ss_sp);
723 __get_user(ss.ss_size, &uss->ss_size);
724 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000725 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000726
ths0da46a62007-10-20 20:23:07 +0000727 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000728 if (on_sig_stack(sp))
729 goto out;
730
ths0da46a62007-10-20 20:23:07 +0000731 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000732 if (ss.ss_flags != TARGET_SS_DISABLE
733 && ss.ss_flags != TARGET_SS_ONSTACK
734 && ss.ss_flags != 0)
735 goto out;
736
737 if (ss.ss_flags == TARGET_SS_DISABLE) {
738 ss.ss_size = 0;
739 ss.ss_sp = 0;
740 } else {
ths0da46a62007-10-20 20:23:07 +0000741 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500742 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000743 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500744 }
thsa04e1342007-09-27 13:57:58 +0000745 }
746
747 target_sigaltstack_used.ss_sp = ss.ss_sp;
748 target_sigaltstack_used.ss_size = ss.ss_size;
749 }
750
bellard579a97f2007-11-11 14:26:47 +0000751 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000752 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000753 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000754 goto out;
thsa04e1342007-09-27 13:57:58 +0000755 }
756
757 ret = 0;
758out:
759 return ret;
760}
761
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100762/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000763int do_sigaction(int sig, const struct target_sigaction *act,
764 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000765{
pbrook624f7972008-05-31 16:11:38 +0000766 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000767 struct sigaction act1;
768 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000769 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000770
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100771 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
772 return -TARGET_EINVAL;
773 }
774
775 if (block_signals()) {
776 return -TARGET_ERESTARTSYS;
777 }
778
bellard66fb9762003-03-23 01:06:05 +0000779 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000780 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->_sa_handler, &oact->_sa_handler);
782 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100783#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800784 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000785#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800786 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000787 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000788 }
789 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000790 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->_sa_handler, &act->_sa_handler);
792 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100793#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800794 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000795#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800796 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000797 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000798
799 /* we update the host linux signal state */
800 host_sig = target_to_host_signal(sig);
801 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
802 sigfillset(&act1.sa_mask);
803 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000804 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000805 act1.sa_flags |= SA_RESTART;
806 /* NOTE: it is important to update the host kernel signal
807 ignore state to avoid getting unexpected interrupted
808 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000809 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000810 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000811 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000812 if (fatal_signal (sig))
813 act1.sa_sigaction = host_signal_handler;
814 else
815 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000816 } else {
817 act1.sa_sigaction = host_signal_handler;
818 }
ths0da46a62007-10-20 20:23:07 +0000819 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000820 }
bellard66fb9762003-03-23 01:06:05 +0000821 }
ths0da46a62007-10-20 20:23:07 +0000822 return ret;
bellard66fb9762003-03-23 01:06:05 +0000823}
bellard31e31b82003-02-18 22:55:36 +0000824
Pranith Kumar1c1df012017-02-26 11:53:44 -0500825#if defined(TARGET_I386)
826/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000827
828struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100829 uint16_t significand[4];
830 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000831};
832
833struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100834 uint16_t significand[4];
835 uint16_t exponent;
836 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000837};
838
839struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500840 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000841};
842
Pranith Kumar1c1df012017-02-26 11:53:44 -0500843struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100844 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500845 uint32_t cw;
846 uint32_t sw;
847 uint32_t tag;
848 uint32_t ipoff;
849 uint32_t cssel;
850 uint32_t dataoff;
851 uint32_t datasel;
852 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100853 uint16_t status;
854 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000855
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100856 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500857 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
858 uint32_t mxcsr;
859 uint32_t reserved;
860 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
861 struct target_xmmreg xmm[8];
862 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000863};
864
Pranith Kumar1c1df012017-02-26 11:53:44 -0500865struct target_fpstate_64 {
866 /* FXSAVE format */
867 uint16_t cw;
868 uint16_t sw;
869 uint16_t twd;
870 uint16_t fop;
871 uint64_t rip;
872 uint64_t rdp;
873 uint32_t mxcsr;
874 uint32_t mxcsr_mask;
875 uint32_t st_space[32];
876 uint32_t xmm_space[64];
877 uint32_t reserved[24];
878};
bellard66fb9762003-03-23 01:06:05 +0000879
Pranith Kumar1c1df012017-02-26 11:53:44 -0500880#ifndef TARGET_X86_64
881# define target_fpstate target_fpstate_32
882#else
883# define target_fpstate target_fpstate_64
884#endif
885
886struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100887 uint16_t gs, __gsh;
888 uint16_t fs, __fsh;
889 uint16_t es, __esh;
890 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500891 uint32_t edi;
892 uint32_t esi;
893 uint32_t ebp;
894 uint32_t esp;
895 uint32_t ebx;
896 uint32_t edx;
897 uint32_t ecx;
898 uint32_t eax;
899 uint32_t trapno;
900 uint32_t err;
901 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500903 uint32_t eflags;
904 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100905 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500906 uint32_t fpstate; /* pointer */
907 uint32_t oldmask;
908 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000909};
910
Pranith Kumar1c1df012017-02-26 11:53:44 -0500911struct target_sigcontext_64 {
912 uint64_t r8;
913 uint64_t r9;
914 uint64_t r10;
915 uint64_t r11;
916 uint64_t r12;
917 uint64_t r13;
918 uint64_t r14;
919 uint64_t r15;
920
921 uint64_t rdi;
922 uint64_t rsi;
923 uint64_t rbp;
924 uint64_t rbx;
925 uint64_t rdx;
926 uint64_t rax;
927 uint64_t rcx;
928 uint64_t rsp;
929 uint64_t rip;
930
931 uint64_t eflags;
932
933 uint16_t cs;
934 uint16_t gs;
935 uint16_t fs;
936 uint16_t ss;
937
938 uint64_t err;
939 uint64_t trapno;
940 uint64_t oldmask;
941 uint64_t cr2;
942
943 uint64_t fpstate; /* pointer */
944 uint64_t padding[8];
945};
946
947#ifndef TARGET_X86_64
948# define target_sigcontext target_sigcontext_32
949#else
950# define target_sigcontext target_sigcontext_64
951#endif
952
953/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000954struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100955 abi_ulong tuc_flags;
956 abi_ulong tuc_link;
957 target_stack_t tuc_stack;
958 struct target_sigcontext tuc_mcontext;
959 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000960};
961
Pranith Kumar1c1df012017-02-26 11:53:44 -0500962#ifndef TARGET_X86_64
963struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000964 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000965 int sig;
966 struct target_sigcontext sc;
967 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000968 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000969 char retcode[8];
970};
971
Pranith Kumar1c1df012017-02-26 11:53:44 -0500972struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000973 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000974 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000975 abi_ulong pinfo;
976 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000977 struct target_siginfo info;
978 struct target_ucontext uc;
979 struct target_fpstate fpstate;
980 char retcode[8];
981};
982
Pranith Kumar1c1df012017-02-26 11:53:44 -0500983#else
984
985struct rt_sigframe {
986 abi_ulong pretcode;
987 struct target_ucontext uc;
988 struct target_siginfo info;
989 struct target_fpstate fpstate;
990};
991
992#endif
993
bellard66fb9762003-03-23 01:06:05 +0000994/*
995 * Set up a signal frame.
996 */
997
bellard66fb9762003-03-23 01:06:05 +0000998/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300999static void setup_sigcontext(struct target_sigcontext *sc,
1000 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
1001 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +00001002{
Andreas Färber27103422013-08-26 08:31:06 +02001003 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -05001004#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +02001005 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +00001006
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001007 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001008 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
1009 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
1010 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
1011 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
1012 __put_user(env->regs[R_EDI], &sc->edi);
1013 __put_user(env->regs[R_ESI], &sc->esi);
1014 __put_user(env->regs[R_EBP], &sc->ebp);
1015 __put_user(env->regs[R_ESP], &sc->esp);
1016 __put_user(env->regs[R_EBX], &sc->ebx);
1017 __put_user(env->regs[R_EDX], &sc->edx);
1018 __put_user(env->regs[R_ECX], &sc->ecx);
1019 __put_user(env->regs[R_EAX], &sc->eax);
1020 __put_user(cs->exception_index, &sc->trapno);
1021 __put_user(env->error_code, &sc->err);
1022 __put_user(env->eip, &sc->eip);
1023 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1024 __put_user(env->eflags, &sc->eflags);
1025 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1026 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001028 cpu_x86_fsave(env, fpstate_addr, 1);
1029 fpstate->status = fpstate->sw;
1030 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001031 __put_user(magic, &fpstate->magic);
1032 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001033
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001034 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001035 __put_user(mask, &sc->oldmask);
1036 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001037#else
1038 __put_user(env->regs[R_EDI], &sc->rdi);
1039 __put_user(env->regs[R_ESI], &sc->rsi);
1040 __put_user(env->regs[R_EBP], &sc->rbp);
1041 __put_user(env->regs[R_ESP], &sc->rsp);
1042 __put_user(env->regs[R_EBX], &sc->rbx);
1043 __put_user(env->regs[R_EDX], &sc->rdx);
1044 __put_user(env->regs[R_ECX], &sc->rcx);
1045 __put_user(env->regs[R_EAX], &sc->rax);
1046
1047 __put_user(env->regs[8], &sc->r8);
1048 __put_user(env->regs[9], &sc->r9);
1049 __put_user(env->regs[10], &sc->r10);
1050 __put_user(env->regs[11], &sc->r11);
1051 __put_user(env->regs[12], &sc->r12);
1052 __put_user(env->regs[13], &sc->r13);
1053 __put_user(env->regs[14], &sc->r14);
1054 __put_user(env->regs[15], &sc->r15);
1055
1056 __put_user(cs->exception_index, &sc->trapno);
1057 __put_user(env->error_code, &sc->err);
1058 __put_user(env->eip, &sc->rip);
1059
1060 __put_user(env->eflags, &sc->eflags);
1061 __put_user(env->segs[R_CS].selector, &sc->cs);
1062 __put_user((uint16_t)0, &sc->gs);
1063 __put_user((uint16_t)0, &sc->fs);
1064 __put_user(env->segs[R_SS].selector, &sc->ss);
1065
1066 __put_user(mask, &sc->oldmask);
1067 __put_user(env->cr[2], &sc->cr2);
1068
1069 /* fpstate_addr must be 16 byte aligned for fxsave */
1070 assert(!(fpstate_addr & 0xf));
1071
1072 cpu_x86_fxsave(env, fpstate_addr);
1073 __put_user(fpstate_addr, &sc->fpstate);
1074#endif
bellard66fb9762003-03-23 01:06:05 +00001075}
1076
1077/*
1078 * Determine which stack to use..
1079 */
1080
bellard579a97f2007-11-11 14:26:47 +00001081static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001082get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001083{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001084 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001085
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001086 /* Default to using normal stack */
1087 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001088#ifdef TARGET_X86_64
1089 esp -= 128; /* this is the redzone */
1090#endif
1091
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001092 /* This is the X/Open sanctioned signal stack switching. */
1093 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1094 if (sas_ss_flags(esp) == 0) {
1095 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001096 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001097 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001098#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001099 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001100 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1102 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001103 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001104 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001105#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001107
1108#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001109 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001110#else
1111 return ((esp - frame_size) & (~15ul)) - 8;
1112#endif
bellard66fb9762003-03-23 01:06:05 +00001113}
1114
Pranith Kumar1c1df012017-02-26 11:53:44 -05001115#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001116/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001117static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001118 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001119{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001120 abi_ulong frame_addr;
1121 struct sigframe *frame;
1122 int i;
bellard66fb9762003-03-23 01:06:05 +00001123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1125 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001127 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1128 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001129
Peter Maydellb6e2c932015-01-08 12:19:43 +00001130 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001132 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1133 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001134
Riku Voipio7df2fa32014-04-23 10:34:53 +03001135 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1136 __put_user(set->sig[i], &frame->extramask[i - 1]);
1137 }
bellard66fb9762003-03-23 01:06:05 +00001138
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001139 /* Set up to return from userspace. If provided, use a stub
1140 already in userspace. */
1141 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001142 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001143 } else {
1144 uint16_t val16;
1145 abi_ulong retcode_addr;
1146 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001147 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001148 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1149 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001150 __put_user(val16, (uint16_t *)(frame->retcode+0));
1151 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001152 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001153 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001154 }
bellard66fb9762003-03-23 01:06:05 +00001155
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001156 /* Set up registers for signal handler */
1157 env->regs[R_ESP] = frame_addr;
1158 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001159
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001160 cpu_x86_load_seg(env, R_DS, __USER_DS);
1161 cpu_x86_load_seg(env, R_ES, __USER_DS);
1162 cpu_x86_load_seg(env, R_SS, __USER_DS);
1163 cpu_x86_load_seg(env, R_CS, __USER_CS);
1164 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001165
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001166 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001168 return;
bellard66fb9762003-03-23 01:06:05 +00001169
1170give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001171 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001172}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001173#endif
bellard66fb9762003-03-23 01:06:05 +00001174
Pranith Kumar1c1df012017-02-26 11:53:44 -05001175/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001176static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001177 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001178 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001179{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001180 abi_ulong frame_addr;
1181#ifndef TARGET_X86_64
1182 abi_ulong addr;
1183#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001184 struct rt_sigframe *frame;
1185 int i;
bellard66fb9762003-03-23 01:06:05 +00001186
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001187 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1188 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001189
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001190 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1191 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001192
Pranith Kumar1c1df012017-02-26 11:53:44 -05001193 /* These fields are only in rt_sigframe on 32 bit */
1194#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001195 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001196 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001197 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001198 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001199 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001200#endif
1201 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1202 tswap_siginfo(&frame->info, info);
1203 }
bellard66fb9762003-03-23 01:06:05 +00001204
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001205 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001206 __put_user(0, &frame->uc.tuc_flags);
1207 __put_user(0, &frame->uc.tuc_link);
1208 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1209 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1210 &frame->uc.tuc_stack.ss_flags);
1211 __put_user(target_sigaltstack_used.ss_size,
1212 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001213 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1214 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1215
Riku Voipio0188fad2014-04-23 13:34:15 +03001216 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1217 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1218 }
bellard66fb9762003-03-23 01:06:05 +00001219
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001220 /* Set up to return from userspace. If provided, use a stub
1221 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001222#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001223 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001224 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001225 } else {
1226 uint16_t val16;
1227 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001228 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001229 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001230 __put_user(0xb8, (char *)(frame->retcode+0));
1231 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001232 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001233 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001234 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001235#else
1236 /* XXX: Would be slightly better to return -EFAULT here if test fails
1237 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1238 __put_user(ka->sa_restorer, &frame->pretcode);
1239#endif
bellard66fb9762003-03-23 01:06:05 +00001240
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001241 /* Set up registers for signal handler */
1242 env->regs[R_ESP] = frame_addr;
1243 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001244
Pranith Kumar1c1df012017-02-26 11:53:44 -05001245#ifndef TARGET_X86_64
1246 env->regs[R_EAX] = sig;
1247 env->regs[R_EDX] = (unsigned long)&frame->info;
1248 env->regs[R_ECX] = (unsigned long)&frame->uc;
1249#else
1250 env->regs[R_EAX] = 0;
1251 env->regs[R_EDI] = sig;
1252 env->regs[R_ESI] = (unsigned long)&frame->info;
1253 env->regs[R_EDX] = (unsigned long)&frame->uc;
1254#endif
1255
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001256 cpu_x86_load_seg(env, R_DS, __USER_DS);
1257 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001258 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001259 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001260 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001261
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001262 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001263
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001264 return;
bellard66fb9762003-03-23 01:06:05 +00001265
1266give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001267 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001268}
1269
1270static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001271restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001272{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001273 unsigned int err = 0;
1274 abi_ulong fpstate_addr;
1275 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001276
Pranith Kumar1c1df012017-02-26 11:53:44 -05001277#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001278 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1279 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1280 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1281 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001282
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001283 env->regs[R_EDI] = tswapl(sc->edi);
1284 env->regs[R_ESI] = tswapl(sc->esi);
1285 env->regs[R_EBP] = tswapl(sc->ebp);
1286 env->regs[R_ESP] = tswapl(sc->esp);
1287 env->regs[R_EBX] = tswapl(sc->ebx);
1288 env->regs[R_EDX] = tswapl(sc->edx);
1289 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001290 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001292 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001293#else
1294 env->regs[8] = tswapl(sc->r8);
1295 env->regs[9] = tswapl(sc->r9);
1296 env->regs[10] = tswapl(sc->r10);
1297 env->regs[11] = tswapl(sc->r11);
1298 env->regs[12] = tswapl(sc->r12);
1299 env->regs[13] = tswapl(sc->r13);
1300 env->regs[14] = tswapl(sc->r14);
1301 env->regs[15] = tswapl(sc->r15);
1302
1303 env->regs[R_EDI] = tswapl(sc->rdi);
1304 env->regs[R_ESI] = tswapl(sc->rsi);
1305 env->regs[R_EBP] = tswapl(sc->rbp);
1306 env->regs[R_EBX] = tswapl(sc->rbx);
1307 env->regs[R_EDX] = tswapl(sc->rdx);
1308 env->regs[R_EAX] = tswapl(sc->rax);
1309 env->regs[R_ECX] = tswapl(sc->rcx);
1310 env->regs[R_ESP] = tswapl(sc->rsp);
1311
1312 env->eip = tswapl(sc->rip);
1313#endif
bellard66fb9762003-03-23 01:06:05 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1316 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001317
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001318 tmpflags = tswapl(sc->eflags);
1319 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1320 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001322 fpstate_addr = tswapl(sc->fpstate);
1323 if (fpstate_addr != 0) {
1324 if (!access_ok(VERIFY_READ, fpstate_addr,
1325 sizeof(struct target_fpstate)))
1326 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001327#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001328 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001329#else
1330 cpu_x86_fxrstor(env, fpstate_addr);
1331#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001332 }
bellard66fb9762003-03-23 01:06:05 +00001333
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001334 return err;
bellard66fb9762003-03-23 01:06:05 +00001335badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001336 return 1;
bellard66fb9762003-03-23 01:06:05 +00001337}
1338
Pranith Kumar1c1df012017-02-26 11:53:44 -05001339/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1340#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001341long do_sigreturn(CPUX86State *env)
1342{
bellard579a97f2007-11-11 14:26:47 +00001343 struct sigframe *frame;
1344 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001345 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001346 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001347 int i;
bellard66fb9762003-03-23 01:06:05 +00001348
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001349 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001350 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1351 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001352 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001353 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001354 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001355 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001356 }
bellard66fb9762003-03-23 01:06:05 +00001357
bellard92319442004-06-19 16:58:13 +00001358 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001359 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001360
bellard66fb9762003-03-23 01:06:05 +00001361 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001362 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001363 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001364 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001365 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001366
1367badframe:
bellard579a97f2007-11-11 14:26:47 +00001368 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001369 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001370 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001371}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001372#endif
bellard66fb9762003-03-23 01:06:05 +00001373
1374long do_rt_sigreturn(CPUX86State *env)
1375{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001376 abi_ulong frame_addr;
1377 struct rt_sigframe *frame;
1378 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001379
Pranith Kumar1c1df012017-02-26 11:53:44 -05001380 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001381 trace_user_do_rt_sigreturn(env, frame_addr);
1382 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1383 goto badframe;
1384 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001385 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001386
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001387 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001388 goto badframe;
1389 }
bellard66fb9762003-03-23 01:06:05 +00001390
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001391 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1392 get_sp_from_cpustate(env)) == -EFAULT) {
1393 goto badframe;
1394 }
thsa04e1342007-09-27 13:57:58 +00001395
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001396 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001397 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001398
1399badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001400 unlock_user_struct(frame, frame_addr, 0);
1401 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001402 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001403}
1404
Andreas Schwab1744aea2013-09-03 20:12:16 +01001405#elif defined(TARGET_AARCH64)
1406
1407struct target_sigcontext {
1408 uint64_t fault_address;
1409 /* AArch64 registers */
1410 uint64_t regs[31];
1411 uint64_t sp;
1412 uint64_t pc;
1413 uint64_t pstate;
1414 /* 4K reserved for FP/SIMD state and future expansion */
1415 char __reserved[4096] __attribute__((__aligned__(16)));
1416};
1417
1418struct target_ucontext {
1419 abi_ulong tuc_flags;
1420 abi_ulong tuc_link;
1421 target_stack_t tuc_stack;
1422 target_sigset_t tuc_sigmask;
1423 /* glibc uses a 1024-bit sigset_t */
1424 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1425 /* last for future expansion */
1426 struct target_sigcontext tuc_mcontext;
1427};
1428
1429/*
1430 * Header to be used at the beginning of structures extending the user
1431 * context. Such structures must be placed after the rt_sigframe on the stack
1432 * and be 16-byte aligned. The last structure must be a dummy one with the
1433 * magic and size set to 0.
1434 */
1435struct target_aarch64_ctx {
1436 uint32_t magic;
1437 uint32_t size;
1438};
1439
1440#define TARGET_FPSIMD_MAGIC 0x46508001
1441
1442struct target_fpsimd_context {
1443 struct target_aarch64_ctx head;
1444 uint32_t fpsr;
1445 uint32_t fpcr;
1446 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1447};
1448
1449/*
1450 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1451 * user space as it will change with the addition of new context. User space
1452 * should check the magic/size information.
1453 */
1454struct target_aux_context {
1455 struct target_fpsimd_context fpsimd;
1456 /* additional context to be added before "end" */
1457 struct target_aarch64_ctx end;
1458};
1459
1460struct target_rt_sigframe {
1461 struct target_siginfo info;
1462 struct target_ucontext uc;
1463 uint64_t fp;
1464 uint64_t lr;
1465 uint32_t tramp[2];
1466};
1467
Richard Henderson3b505bb2018-03-09 17:09:43 +00001468static void target_setup_general_frame(struct target_rt_sigframe *sf,
1469 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001470{
1471 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001472
Richard Henderson3b505bb2018-03-09 17:09:43 +00001473 __put_user(0, &sf->uc.tuc_flags);
1474 __put_user(0, &sf->uc.tuc_link);
1475
1476 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1477 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1478 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001479
1480 for (i = 0; i < 31; i++) {
1481 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1482 }
1483 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1484 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001485 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001486
Peter Maydell7af03922014-05-01 18:36:17 +01001487 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001488
1489 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1490 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1491 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001492}
1493
1494static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1495 CPUARMState *env)
1496{
1497 int i;
1498
1499 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1500 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1501 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1502 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001503
1504 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001505 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001506#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001507 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1508 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001509#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001510 __put_user(q[0], &fpsimd->vregs[i * 2]);
1511 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001512#endif
1513 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001514}
1515
Richard Henderson3b505bb2018-03-09 17:09:43 +00001516static void target_setup_end_record(struct target_aarch64_ctx *end)
1517{
1518 __put_user(0, &end->magic);
1519 __put_user(0, &end->size);
1520}
1521
1522static void target_restore_general_frame(CPUARMState *env,
1523 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001524{
1525 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001526 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001527 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001528
1529 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001530 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001531
1532 for (i = 0; i < 31; i++) {
1533 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1534 }
1535
1536 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1537 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001538 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1539 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001540}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001541
Richard Henderson3b505bb2018-03-09 17:09:43 +00001542static void target_restore_fpsimd_record(CPUARMState *env,
1543 struct target_fpsimd_context *fpsimd)
1544{
1545 uint32_t fpsr, fpcr;
1546 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001547
Richard Henderson3b505bb2018-03-09 17:09:43 +00001548 __get_user(fpsr, &fpsimd->fpsr);
1549 vfp_set_fpsr(env, fpsr);
1550 __get_user(fpcr, &fpsimd->fpcr);
1551 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001552
Peter Maydell4cf23482014-03-02 19:36:38 +00001553 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001554 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001555#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001556 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1557 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001558#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001559 __get_user(q[0], &fpsimd->vregs[i * 2]);
1560 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001561#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001562 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001563}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001564
Richard Henderson3b505bb2018-03-09 17:09:43 +00001565static int target_restore_sigframe(CPUARMState *env,
1566 struct target_rt_sigframe *sf)
1567{
1568 struct target_aux_context *aux
1569 = (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1570 uint32_t magic, size;
1571
1572 target_restore_general_frame(env, sf);
1573
1574 __get_user(magic, &aux->fpsimd.head.magic);
1575 __get_user(size, &aux->fpsimd.head.size);
1576 if (magic == TARGET_FPSIMD_MAGIC
1577 && size == sizeof(struct target_fpsimd_context)) {
1578 target_restore_fpsimd_record(env, &aux->fpsimd);
1579 } else {
1580 return 1;
1581 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001582 return 0;
1583}
1584
1585static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1586{
1587 abi_ulong sp;
1588
1589 sp = env->xregs[31];
1590
1591 /*
1592 * This is the X/Open sanctioned signal stack switching.
1593 */
Riku Voipiob545f632014-07-15 17:01:55 +03001594 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001595 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1596 }
1597
1598 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1599
1600 return sp;
1601}
1602
1603static void target_setup_frame(int usig, struct target_sigaction *ka,
1604 target_siginfo_t *info, target_sigset_t *set,
1605 CPUARMState *env)
1606{
1607 struct target_rt_sigframe *frame;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001608 struct target_aux_context *aux;
Michael Matz8a3ae912014-03-02 19:36:39 +00001609 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001610
1611 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001612 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001613 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1614 goto give_sigsegv;
1615 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001616 aux = (struct target_aux_context *)frame->uc.tuc_mcontext.__reserved;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001617
Richard Henderson3b505bb2018-03-09 17:09:43 +00001618 target_setup_general_frame(frame, env, set);
1619 target_setup_fpsimd_record(&aux->fpsimd, env);
1620 target_setup_end_record(&aux->end);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001621
Michael Matz8a3ae912014-03-02 19:36:39 +00001622 if (ka->sa_flags & TARGET_SA_RESTORER) {
1623 return_addr = ka->sa_restorer;
1624 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001625 /*
1626 * mov x8,#__NR_rt_sigreturn; svc #0
1627 * Since these are instructions they need to be put as little-endian
1628 * regardless of target default or current CPU endianness.
1629 */
1630 __put_user_e(0xd2801168, &frame->tramp[0], le);
1631 __put_user_e(0xd4000001, &frame->tramp[1], le);
Michael Matz8a3ae912014-03-02 19:36:39 +00001632 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1633 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001634 env->xregs[0] = usig;
1635 env->xregs[31] = frame_addr;
1636 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1637 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001638 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001639 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001640 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001641 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1642 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1643 }
1644
1645 unlock_user_struct(frame, frame_addr, 1);
1646 return;
1647
1648 give_sigsegv:
1649 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001650 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001651}
1652
1653static void setup_rt_frame(int sig, struct target_sigaction *ka,
1654 target_siginfo_t *info, target_sigset_t *set,
1655 CPUARMState *env)
1656{
1657 target_setup_frame(sig, ka, info, set, env);
1658}
1659
1660static void setup_frame(int sig, struct target_sigaction *ka,
1661 target_sigset_t *set, CPUARMState *env)
1662{
1663 target_setup_frame(sig, ka, 0, set, env);
1664}
1665
1666long do_rt_sigreturn(CPUARMState *env)
1667{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001668 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001669 abi_ulong frame_addr = env->xregs[31];
1670
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001671 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001672 if (frame_addr & 15) {
1673 goto badframe;
1674 }
1675
1676 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1677 goto badframe;
1678 }
1679
1680 if (target_restore_sigframe(env, frame)) {
1681 goto badframe;
1682 }
1683
1684 if (do_sigaltstack(frame_addr +
1685 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1686 0, get_sp_from_cpustate(env)) == -EFAULT) {
1687 goto badframe;
1688 }
1689
1690 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001691 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001692
1693 badframe:
1694 unlock_user_struct(frame, frame_addr, 0);
1695 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001696 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001697}
1698
1699long do_sigreturn(CPUARMState *env)
1700{
1701 return do_rt_sigreturn(env);
1702}
1703
bellard43fff232003-07-09 19:31:39 +00001704#elif defined(TARGET_ARM)
1705
1706struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001707 abi_ulong trap_no;
1708 abi_ulong error_code;
1709 abi_ulong oldmask;
1710 abi_ulong arm_r0;
1711 abi_ulong arm_r1;
1712 abi_ulong arm_r2;
1713 abi_ulong arm_r3;
1714 abi_ulong arm_r4;
1715 abi_ulong arm_r5;
1716 abi_ulong arm_r6;
1717 abi_ulong arm_r7;
1718 abi_ulong arm_r8;
1719 abi_ulong arm_r9;
1720 abi_ulong arm_r10;
1721 abi_ulong arm_fp;
1722 abi_ulong arm_ip;
1723 abi_ulong arm_sp;
1724 abi_ulong arm_lr;
1725 abi_ulong arm_pc;
1726 abi_ulong arm_cpsr;
1727 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001728};
1729
pbrooka745ec62008-05-06 15:36:17 +00001730struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001731 abi_ulong tuc_flags;
1732 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001733 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001734 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001735 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001736};
1737
pbrooka745ec62008-05-06 15:36:17 +00001738struct target_ucontext_v2 {
1739 abi_ulong tuc_flags;
1740 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001741 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001742 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001743 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001744 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001745 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1746};
1747
Peter Maydell0d871bd2010-11-24 15:20:05 +00001748struct target_user_vfp {
1749 uint64_t fpregs[32];
1750 abi_ulong fpscr;
1751};
1752
1753struct target_user_vfp_exc {
1754 abi_ulong fpexc;
1755 abi_ulong fpinst;
1756 abi_ulong fpinst2;
1757};
1758
1759struct target_vfp_sigframe {
1760 abi_ulong magic;
1761 abi_ulong size;
1762 struct target_user_vfp ufp;
1763 struct target_user_vfp_exc ufp_exc;
1764} __attribute__((__aligned__(8)));
1765
Peter Maydell08e11252010-11-24 15:20:07 +00001766struct target_iwmmxt_sigframe {
1767 abi_ulong magic;
1768 abi_ulong size;
1769 uint64_t regs[16];
1770 /* Note that not all the coprocessor control registers are stored here */
1771 uint32_t wcssf;
1772 uint32_t wcasf;
1773 uint32_t wcgr0;
1774 uint32_t wcgr1;
1775 uint32_t wcgr2;
1776 uint32_t wcgr3;
1777} __attribute__((__aligned__(8)));
1778
Peter Maydell0d871bd2010-11-24 15:20:05 +00001779#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001780#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001781
pbrooka8c33202008-05-07 23:22:46 +00001782struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001783{
1784 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001785 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1786 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001787};
1788
pbrooka8c33202008-05-07 23:22:46 +00001789struct sigframe_v2
1790{
1791 struct target_ucontext_v2 uc;
1792 abi_ulong retcode;
1793};
1794
pbrooka745ec62008-05-06 15:36:17 +00001795struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001796{
bellardf8b0aa22007-11-11 23:03:42 +00001797 abi_ulong pinfo;
1798 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001799 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001800 struct target_ucontext_v1 uc;
1801 abi_ulong retcode;
1802};
1803
1804struct rt_sigframe_v2
1805{
1806 struct target_siginfo info;
1807 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001808 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001809};
1810
1811#define TARGET_CONFIG_CPU_32 1
1812
1813/*
1814 * For ARM syscalls, we encode the syscall number into the instruction.
1815 */
1816#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1817#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1818
1819/*
1820 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1821 * need two 16-bit instructions.
1822 */
1823#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1824#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1825
blueswir1992f48a2007-10-14 16:27:31 +00001826static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001827 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1828 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1829};
1830
1831
Andreas Färber05390242012-02-25 03:37:53 +01001832static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001833{
1834 return 1;
1835}
1836
pbrooka8c33202008-05-07 23:22:46 +00001837static void
bellard43fff232003-07-09 19:31:39 +00001838setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001839 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001840{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001841 __put_user(env->regs[0], &sc->arm_r0);
1842 __put_user(env->regs[1], &sc->arm_r1);
1843 __put_user(env->regs[2], &sc->arm_r2);
1844 __put_user(env->regs[3], &sc->arm_r3);
1845 __put_user(env->regs[4], &sc->arm_r4);
1846 __put_user(env->regs[5], &sc->arm_r5);
1847 __put_user(env->regs[6], &sc->arm_r6);
1848 __put_user(env->regs[7], &sc->arm_r7);
1849 __put_user(env->regs[8], &sc->arm_r8);
1850 __put_user(env->regs[9], &sc->arm_r9);
1851 __put_user(env->regs[10], &sc->arm_r10);
1852 __put_user(env->regs[11], &sc->arm_fp);
1853 __put_user(env->regs[12], &sc->arm_ip);
1854 __put_user(env->regs[13], &sc->arm_sp);
1855 __put_user(env->regs[14], &sc->arm_lr);
1856 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001857#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001858 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001859#endif
1860
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001861 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1862 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1863 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1864 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001865}
1866
bellard579a97f2007-11-11 14:26:47 +00001867static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001868get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001869{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001870 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001871
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001872 /*
1873 * This is the X/Open sanctioned signal stack switching.
1874 */
1875 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1876 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1877 }
1878 /*
1879 * ATPCS B01 mandates 8-byte alignment
1880 */
1881 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001882}
1883
Riku Voipio0188fad2014-04-23 13:34:15 +03001884static void
Andreas Färber05390242012-02-25 03:37:53 +01001885setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001886 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001887{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001888 abi_ulong handler = ka->_sa_handler;
1889 abi_ulong retcode;
1890 int thumb = handler & 1;
1891 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001892
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001893 cpsr &= ~CPSR_IT;
1894 if (thumb) {
1895 cpsr |= CPSR_T;
1896 } else {
1897 cpsr &= ~CPSR_T;
1898 }
bellard43fff232003-07-09 19:31:39 +00001899
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001900 if (ka->sa_flags & TARGET_SA_RESTORER) {
1901 retcode = ka->sa_restorer;
1902 } else {
1903 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001904
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001905 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1906 idx += 2;
1907 }
bellard43fff232003-07-09 19:31:39 +00001908
Riku Voipio0188fad2014-04-23 13:34:15 +03001909 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001910
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001911 retcode = rc_addr + thumb;
1912 }
bellard43fff232003-07-09 19:31:39 +00001913
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001914 env->regs[0] = usig;
1915 env->regs[13] = frame_addr;
1916 env->regs[14] = retcode;
1917 env->regs[15] = handler & (thumb ? ~1 : ~3);
1918 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001919}
1920
Andreas Färber05390242012-02-25 03:37:53 +01001921static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001922{
1923 int i;
1924 struct target_vfp_sigframe *vfpframe;
1925 vfpframe = (struct target_vfp_sigframe *)regspace;
1926 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1927 __put_user(sizeof(*vfpframe), &vfpframe->size);
1928 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001929 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001930 }
1931 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1932 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1933 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1934 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1935 return (abi_ulong*)(vfpframe+1);
1936}
1937
Andreas Färber05390242012-02-25 03:37:53 +01001938static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1939 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001940{
1941 int i;
1942 struct target_iwmmxt_sigframe *iwmmxtframe;
1943 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1944 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1945 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1946 for (i = 0; i < 16; i++) {
1947 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1948 }
1949 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1950 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1951 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1952 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1953 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1954 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1955 return (abi_ulong*)(iwmmxtframe+1);
1956}
1957
pbrooka8c33202008-05-07 23:22:46 +00001958static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001959 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001960{
pbrooka8c33202008-05-07 23:22:46 +00001961 struct target_sigaltstack stack;
1962 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001963 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001964
1965 /* Clear all the bits of the ucontext we don't use. */
1966 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1967
1968 memset(&stack, 0, sizeof(stack));
1969 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1970 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1971 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1972 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1973
1974 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001975 /* Save coprocessor signal frame. */
1976 regspace = uc->tuc_regspace;
1977 if (arm_feature(env, ARM_FEATURE_VFP)) {
1978 regspace = setup_sigframe_v2_vfp(regspace, env);
1979 }
Peter Maydell08e11252010-11-24 15:20:07 +00001980 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1981 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1982 }
1983
Peter Maydell0d871bd2010-11-24 15:20:05 +00001984 /* Write terminating magic word */
1985 __put_user(0, regspace);
1986
pbrooka8c33202008-05-07 23:22:46 +00001987 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1988 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1989 }
1990}
1991
1992/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001993static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001994 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001995{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001996 struct sigframe_v1 *frame;
1997 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1998 int i;
bellard43fff232003-07-09 19:31:39 +00001999
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002000 trace_user_setup_frame(regs, frame_addr);
2001 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002002 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002003 }
bellard579a97f2007-11-11 14:26:47 +00002004
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002005 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002006
Riku Voipio0188fad2014-04-23 13:34:15 +03002007 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2008 __put_user(set->sig[i], &frame->extramask[i - 1]);
2009 }
bellard43fff232003-07-09 19:31:39 +00002010
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002011 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2012 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002013
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002014 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002015 return;
2016sigsegv:
2017 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002018}
2019
pbrook624f7972008-05-31 16:11:38 +00002020static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002021 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002022{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002023 struct sigframe_v2 *frame;
2024 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002025
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002026 trace_user_setup_frame(regs, frame_addr);
2027 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002028 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002029 }
pbrooka8c33202008-05-07 23:22:46 +00002030
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002031 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002032
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002033 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2034 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002035
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002036 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002037 return;
2038sigsegv:
2039 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002040}
2041
pbrook624f7972008-05-31 16:11:38 +00002042static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002043 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002044{
2045 if (get_osversion() >= 0x020612) {
2046 setup_frame_v2(usig, ka, set, regs);
2047 } else {
2048 setup_frame_v1(usig, ka, set, regs);
2049 }
bellard43fff232003-07-09 19:31:39 +00002050}
2051
bellard579a97f2007-11-11 14:26:47 +00002052/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002053static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002054 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002055 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002056{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002057 struct rt_sigframe_v1 *frame;
2058 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2059 struct target_sigaltstack stack;
2060 int i;
2061 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002062
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002063 trace_user_setup_rt_frame(env, frame_addr);
2064 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002065 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002066 }
bellardedf779f2004-02-22 13:40:13 +00002067
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002068 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2069 __put_user(info_addr, &frame->pinfo);
2070 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2071 __put_user(uc_addr, &frame->puc);
2072 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002073
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002074 /* Clear all the bits of the ucontext we don't use. */
2075 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002076
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002077 memset(&stack, 0, sizeof(stack));
2078 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2079 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2080 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2081 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002082
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002083 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2084 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2085 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2086 }
bellard43fff232003-07-09 19:31:39 +00002087
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002088 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2089 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002090
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002091 env->regs[1] = info_addr;
2092 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002093
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002094 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002095 return;
2096sigsegv:
2097 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002098}
2099
pbrook624f7972008-05-31 16:11:38 +00002100static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002101 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002102 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002103{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002104 struct rt_sigframe_v2 *frame;
2105 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2106 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002107
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002108 trace_user_setup_rt_frame(env, frame_addr);
2109 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002110 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002111 }
pbrooka745ec62008-05-06 15:36:17 +00002112
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002113 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2114 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2115 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002116
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002117 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002118
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002119 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2120 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002121
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002122 env->regs[1] = info_addr;
2123 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002124
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002125 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002126 return;
2127sigsegv:
2128 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002129}
2130
pbrook624f7972008-05-31 16:11:38 +00002131static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002132 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002133 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002134{
2135 if (get_osversion() >= 0x020612) {
2136 setup_rt_frame_v2(usig, ka, info, set, env);
2137 } else {
2138 setup_rt_frame_v1(usig, ka, info, set, env);
2139 }
2140}
2141
bellard43fff232003-07-09 19:31:39 +00002142static int
Andreas Färber05390242012-02-25 03:37:53 +01002143restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002144{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002145 int err = 0;
2146 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002147
Riku Voipio1d8b5122014-04-23 10:26:05 +03002148 __get_user(env->regs[0], &sc->arm_r0);
2149 __get_user(env->regs[1], &sc->arm_r1);
2150 __get_user(env->regs[2], &sc->arm_r2);
2151 __get_user(env->regs[3], &sc->arm_r3);
2152 __get_user(env->regs[4], &sc->arm_r4);
2153 __get_user(env->regs[5], &sc->arm_r5);
2154 __get_user(env->regs[6], &sc->arm_r6);
2155 __get_user(env->regs[7], &sc->arm_r7);
2156 __get_user(env->regs[8], &sc->arm_r8);
2157 __get_user(env->regs[9], &sc->arm_r9);
2158 __get_user(env->regs[10], &sc->arm_r10);
2159 __get_user(env->regs[11], &sc->arm_fp);
2160 __get_user(env->regs[12], &sc->arm_ip);
2161 __get_user(env->regs[13], &sc->arm_sp);
2162 __get_user(env->regs[14], &sc->arm_lr);
2163 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002164#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002165 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002166 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002167#endif
2168
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002169 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002170
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002171 return err;
bellard43fff232003-07-09 19:31:39 +00002172}
2173
Andreas Färber05390242012-02-25 03:37:53 +01002174static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002175{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002176 abi_ulong frame_addr;
2177 struct sigframe_v1 *frame = NULL;
2178 target_sigset_t set;
2179 sigset_t host_set;
2180 int i;
bellard43fff232003-07-09 19:31:39 +00002181
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002182 /*
2183 * Since we stacked the signal on a 64-bit boundary,
2184 * then 'sp' should be word aligned here. If it's
2185 * not, then the user is trying to mess with us.
2186 */
2187 frame_addr = env->regs[13];
2188 trace_user_do_sigreturn(env, frame_addr);
2189 if (frame_addr & 7) {
2190 goto badframe;
2191 }
Peter Maydell978fae92013-07-29 12:00:32 +01002192
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002193 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2194 goto badframe;
2195 }
bellard43fff232003-07-09 19:31:39 +00002196
Riku Voipiof5f601a2014-04-23 13:00:17 +03002197 __get_user(set.sig[0], &frame->sc.oldmask);
2198 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2199 __get_user(set.sig[i], &frame->extramask[i - 1]);
2200 }
bellard43fff232003-07-09 19:31:39 +00002201
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002202 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002203 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002204
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002205 if (restore_sigcontext(env, &frame->sc)) {
2206 goto badframe;
2207 }
bellard43fff232003-07-09 19:31:39 +00002208
2209#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002210 /* Send SIGTRAP if we're single-stepping */
2211 if (ptrace_cancel_bpt(current))
2212 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002213#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002214 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002215 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002216
2217badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002218 force_sig(TARGET_SIGSEGV);
2219 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002220}
2221
Andreas Färber05390242012-02-25 03:37:53 +01002222static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002223{
2224 int i;
2225 abi_ulong magic, sz;
2226 uint32_t fpscr, fpexc;
2227 struct target_vfp_sigframe *vfpframe;
2228 vfpframe = (struct target_vfp_sigframe *)regspace;
2229
2230 __get_user(magic, &vfpframe->magic);
2231 __get_user(sz, &vfpframe->size);
2232 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2233 return 0;
2234 }
2235 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002236 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002237 }
2238 __get_user(fpscr, &vfpframe->ufp.fpscr);
2239 vfp_set_fpscr(env, fpscr);
2240 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2241 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2242 * and the exception flag is cleared
2243 */
2244 fpexc |= (1 << 30);
2245 fpexc &= ~((1 << 31) | (1 << 28));
2246 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2247 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2248 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2249 return (abi_ulong*)(vfpframe + 1);
2250}
2251
Andreas Färber05390242012-02-25 03:37:53 +01002252static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2253 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002254{
2255 int i;
2256 abi_ulong magic, sz;
2257 struct target_iwmmxt_sigframe *iwmmxtframe;
2258 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2259
2260 __get_user(magic, &iwmmxtframe->magic);
2261 __get_user(sz, &iwmmxtframe->size);
2262 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2263 return 0;
2264 }
2265 for (i = 0; i < 16; i++) {
2266 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2267 }
2268 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2269 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2270 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2271 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2272 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2273 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2274 return (abi_ulong*)(iwmmxtframe + 1);
2275}
2276
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002277static int do_sigframe_return_v2(CPUARMState *env,
2278 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002279 struct target_ucontext_v2 *uc)
2280{
2281 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002282 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002283
2284 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002285 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002286
2287 if (restore_sigcontext(env, &uc->tuc_mcontext))
2288 return 1;
2289
Peter Maydell5f9099d2010-11-24 15:20:06 +00002290 /* Restore coprocessor signal frame */
2291 regspace = uc->tuc_regspace;
2292 if (arm_feature(env, ARM_FEATURE_VFP)) {
2293 regspace = restore_sigframe_v2_vfp(env, regspace);
2294 if (!regspace) {
2295 return 1;
2296 }
2297 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002298 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2299 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2300 if (!regspace) {
2301 return 1;
2302 }
2303 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002304
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002305 if (do_sigaltstack(context_addr
2306 + offsetof(struct target_ucontext_v2, tuc_stack),
2307 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002308 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002309 }
pbrooka8c33202008-05-07 23:22:46 +00002310
2311#if 0
2312 /* Send SIGTRAP if we're single-stepping */
2313 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002314 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002315#endif
2316
2317 return 0;
2318}
2319
Andreas Färber05390242012-02-25 03:37:53 +01002320static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002321{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002322 abi_ulong frame_addr;
2323 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002324
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002325 /*
2326 * Since we stacked the signal on a 64-bit boundary,
2327 * then 'sp' should be word aligned here. If it's
2328 * not, then the user is trying to mess with us.
2329 */
2330 frame_addr = env->regs[13];
2331 trace_user_do_sigreturn(env, frame_addr);
2332 if (frame_addr & 7) {
2333 goto badframe;
2334 }
Peter Maydell978fae92013-07-29 12:00:32 +01002335
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002336 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2337 goto badframe;
2338 }
pbrooka8c33202008-05-07 23:22:46 +00002339
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002340 if (do_sigframe_return_v2(env,
2341 frame_addr
2342 + offsetof(struct sigframe_v2, uc),
2343 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002344 goto badframe;
2345 }
pbrooka8c33202008-05-07 23:22:46 +00002346
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002348 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002349
2350badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002351 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002352 force_sig(TARGET_SIGSEGV);
2353 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002354}
2355
Andreas Färber05390242012-02-25 03:37:53 +01002356long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002357{
2358 if (get_osversion() >= 0x020612) {
2359 return do_sigreturn_v2(env);
2360 } else {
2361 return do_sigreturn_v1(env);
2362 }
2363}
2364
Andreas Färber05390242012-02-25 03:37:53 +01002365static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002366{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002367 abi_ulong frame_addr;
2368 struct rt_sigframe_v1 *frame = NULL;
2369 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002370
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002371 /*
2372 * Since we stacked the signal on a 64-bit boundary,
2373 * then 'sp' should be word aligned here. If it's
2374 * not, then the user is trying to mess with us.
2375 */
2376 frame_addr = env->regs[13];
2377 trace_user_do_rt_sigreturn(env, frame_addr);
2378 if (frame_addr & 7) {
2379 goto badframe;
2380 }
Peter Maydell978fae92013-07-29 12:00:32 +01002381
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002382 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2383 goto badframe;
2384 }
bellard43fff232003-07-09 19:31:39 +00002385
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002386 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002387 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002388
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002389 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2390 goto badframe;
2391 }
bellard43fff232003-07-09 19:31:39 +00002392
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002393 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2394 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002395
bellard43fff232003-07-09 19:31:39 +00002396#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002397 /* Send SIGTRAP if we're single-stepping */
2398 if (ptrace_cancel_bpt(current))
2399 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002400#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002401 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002402 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002403
2404badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002405 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002406 force_sig(TARGET_SIGSEGV);
2407 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002408}
2409
Andreas Färber05390242012-02-25 03:37:53 +01002410static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002411{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002412 abi_ulong frame_addr;
2413 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002414
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002415 /*
2416 * Since we stacked the signal on a 64-bit boundary,
2417 * then 'sp' should be word aligned here. If it's
2418 * not, then the user is trying to mess with us.
2419 */
2420 frame_addr = env->regs[13];
2421 trace_user_do_rt_sigreturn(env, frame_addr);
2422 if (frame_addr & 7) {
2423 goto badframe;
2424 }
Peter Maydell978fae92013-07-29 12:00:32 +01002425
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002426 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2427 goto badframe;
2428 }
pbrooka745ec62008-05-06 15:36:17 +00002429
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002430 if (do_sigframe_return_v2(env,
2431 frame_addr
2432 + offsetof(struct rt_sigframe_v2, uc),
2433 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002434 goto badframe;
2435 }
pbrooka745ec62008-05-06 15:36:17 +00002436
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002437 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002438 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002439
2440badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002441 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002442 force_sig(TARGET_SIGSEGV);
2443 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002444}
2445
Andreas Färber05390242012-02-25 03:37:53 +01002446long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002447{
2448 if (get_osversion() >= 0x020612) {
2449 return do_rt_sigreturn_v2(env);
2450 } else {
2451 return do_rt_sigreturn_v1(env);
2452 }
2453}
2454
bellard6d5e2162004-09-30 22:04:13 +00002455#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002456
bellard6d5e2162004-09-30 22:04:13 +00002457#define __SUNOS_MAXWIN 31
2458
2459/* This is what SunOS does, so shall I. */
2460struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002461 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002462
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002463 abi_ulong sigc_mask; /* sigmask to restore */
2464 abi_ulong sigc_sp; /* stack pointer */
2465 abi_ulong sigc_pc; /* program counter */
2466 abi_ulong sigc_npc; /* next program counter */
2467 abi_ulong sigc_psr; /* for condition codes etc */
2468 abi_ulong sigc_g1; /* User uses these two registers */
2469 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002470
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002471 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002472 * at the time of the signal.
2473 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002474 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002475
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002476 /* stack ptrs for each regwin buf */
2477 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002478
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002479 /* Windows to restore after signal */
2480 struct {
2481 abi_ulong locals[8];
2482 abi_ulong ins[8];
2483 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002484};
2485/* A Sparc stack frame */
2486struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002487 abi_ulong locals[8];
2488 abi_ulong ins[8];
2489 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002490 * since we never need to access them ourselves.
2491 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002492 char *structptr;
2493 abi_ulong xargs[6];
2494 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002495};
2496
2497typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002498 struct {
2499 abi_ulong psr;
2500 abi_ulong pc;
2501 abi_ulong npc;
2502 abi_ulong y;
2503 abi_ulong u_regs[16]; /* globals and ins */
2504 } si_regs;
2505 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002506} __siginfo_t;
2507
2508typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002509 abi_ulong si_float_regs[32];
2510 unsigned long si_fsr;
2511 unsigned long si_fpqdepth;
2512 struct {
2513 unsigned long *insn_addr;
2514 unsigned long insn;
2515 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002516} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002517
2518
2519struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002520 struct sparc_stackf ss;
2521 __siginfo_t info;
2522 abi_ulong fpu_save;
2523 abi_ulong insns[2] __attribute__ ((aligned (8)));
2524 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2525 abi_ulong extra_size; /* Should be 0 */
2526 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002527};
2528struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002529 struct sparc_stackf ss;
2530 siginfo_t info;
2531 abi_ulong regs[20];
2532 sigset_t mask;
2533 abi_ulong fpu_save;
2534 unsigned int insns[2];
2535 stack_t stack;
2536 unsigned int extra_size; /* Should be 0 */
2537 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002538};
2539
bellarde80cfcf2004-12-19 23:18:01 +00002540#define UREG_O0 16
2541#define UREG_O6 22
2542#define UREG_I0 0
2543#define UREG_I1 1
2544#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002545#define UREG_I3 3
2546#define UREG_I4 4
2547#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002548#define UREG_I6 6
2549#define UREG_I7 7
2550#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002551#define UREG_FP UREG_I6
2552#define UREG_SP UREG_O6
2553
pbrook624f7972008-05-31 16:11:38 +00002554static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002555 CPUSPARCState *env,
2556 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002557{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002558 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002559
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002560 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002561
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002562 /* This is the X/Open sanctioned signal stack switching. */
2563 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2564 if (!on_sig_stack(sp)
2565 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2566 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2567 }
2568 }
2569 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002570}
2571
2572static int
Andreas Färber05390242012-02-25 03:37:53 +01002573setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002574{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002575 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002576
Riku Voipio1d8b5122014-04-23 10:26:05 +03002577 __put_user(env->psr, &si->si_regs.psr);
2578 __put_user(env->pc, &si->si_regs.pc);
2579 __put_user(env->npc, &si->si_regs.npc);
2580 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002581 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002582 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002583 }
2584 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002585 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002586 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002587 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002588 return err;
bellard6d5e2162004-09-30 22:04:13 +00002589}
bellarde80cfcf2004-12-19 23:18:01 +00002590
bellard80a9d032005-01-03 23:31:27 +00002591#if 0
bellard6d5e2162004-09-30 22:04:13 +00002592static int
2593setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002594 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002595{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002596 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002597
Riku Voipio1d8b5122014-04-23 10:26:05 +03002598 __put_user(mask, &sc->sigc_mask);
2599 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2600 __put_user(env->pc, &sc->sigc_pc);
2601 __put_user(env->npc, &sc->sigc_npc);
2602 __put_user(env->psr, &sc->sigc_psr);
2603 __put_user(env->gregs[1], &sc->sigc_g1);
2604 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002605
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002606 return err;
bellard6d5e2162004-09-30 22:04:13 +00002607}
bellard80a9d032005-01-03 23:31:27 +00002608#endif
bellard6d5e2162004-09-30 22:04:13 +00002609#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2610
pbrook624f7972008-05-31 16:11:38 +00002611static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002612 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002613{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002614 abi_ulong sf_addr;
2615 struct target_signal_frame *sf;
2616 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002617
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002618 /* 1. Make sure everything is clean */
2619 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002620
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002621 sigframe_size = NF_ALIGNEDSZ;
2622 sf_addr = get_sigframe(ka, env, sigframe_size);
2623 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002624
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002625 sf = lock_user(VERIFY_WRITE, sf_addr,
2626 sizeof(struct target_signal_frame), 0);
2627 if (!sf) {
2628 goto sigsegv;
2629 }
bellard6d5e2162004-09-30 22:04:13 +00002630#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002631 if (invalid_frame_pointer(sf, sigframe_size))
2632 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002633#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002634 /* 2. Save the current process state */
2635 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002636 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002637
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002638 //save_fpu_state(regs, &sf->fpu_state);
2639 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002640
Riku Voipio1d8b5122014-04-23 10:26:05 +03002641 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002642 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002643 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002644 }
bellard6d5e2162004-09-30 22:04:13 +00002645
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002646 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002647 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002648 }
2649 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002650 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002651 }
2652 if (err)
2653 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002654
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002655 /* 3. signal handler back-trampoline and parameters */
2656 env->regwptr[UREG_FP] = sf_addr;
2657 env->regwptr[UREG_I0] = sig;
2658 env->regwptr[UREG_I1] = sf_addr +
2659 offsetof(struct target_signal_frame, info);
2660 env->regwptr[UREG_I2] = sf_addr +
2661 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002662
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002663 /* 4. signal handler */
2664 env->pc = ka->_sa_handler;
2665 env->npc = (env->pc + 4);
2666 /* 5. return to kernel instructions */
2667 if (ka->sa_restorer) {
2668 env->regwptr[UREG_I7] = ka->sa_restorer;
2669 } else {
2670 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002671
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002672 env->regwptr[UREG_I7] = sf_addr +
2673 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002674
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002675 /* mov __NR_sigreturn, %g1 */
2676 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002677 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002678
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002679 /* t 0x10 */
2680 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002681 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002682 if (err)
2683 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002684
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002685 /* Flush instruction space. */
2686 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2687 // tb_flush(env);
2688 }
2689 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2690 return;
bellard459a4012007-11-11 19:45:10 +00002691#if 0
2692sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002693 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002694#endif
bellard6d5e2162004-09-30 22:04:13 +00002695sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002696 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002697 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002698}
bellard6d5e2162004-09-30 22:04:13 +00002699
pbrook624f7972008-05-31 16:11:38 +00002700static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002701 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002702 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002703{
2704 fprintf(stderr, "setup_rt_frame: not implemented\n");
2705}
2706
Andreas Färber05390242012-02-25 03:37:53 +01002707long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002708{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002709 abi_ulong sf_addr;
2710 struct target_signal_frame *sf;
2711 uint32_t up_psr, pc, npc;
2712 target_sigset_t set;
2713 sigset_t host_set;
2714 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002715
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002716 sf_addr = env->regwptr[UREG_FP];
2717 trace_user_do_sigreturn(env, sf_addr);
2718 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2719 goto segv_and_exit;
2720 }
bellard6d5e2162004-09-30 22:04:13 +00002721
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002722 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002723
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002724 if (sf_addr & 3)
2725 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002726
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002727 __get_user(pc, &sf->info.si_regs.pc);
2728 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002729
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002730 if ((pc | npc) & 3) {
2731 goto segv_and_exit;
2732 }
bellard6d5e2162004-09-30 22:04:13 +00002733
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002734 /* 2. Restore the state */
2735 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002736
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002737 /* User can only change condition codes and FPU enabling in %psr. */
2738 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2739 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002740
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002741 env->pc = pc;
2742 env->npc = npc;
2743 __get_user(env->y, &sf->info.si_regs.y);
2744 for (i=0; i < 8; i++) {
2745 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2746 }
2747 for (i=0; i < 8; i++) {
2748 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2749 }
bellard6d5e2162004-09-30 22:04:13 +00002750
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002751 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002752 * __get_user(fpu_save, &sf->fpu_save);
2753 * if (fpu_save)
2754 * err |= restore_fpu_state(env, fpu_save);
2755 */
bellard6d5e2162004-09-30 22:04:13 +00002756
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002757 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002758 * the races which exist anyways.
2759 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002760 __get_user(set.sig[0], &sf->info.si_mask);
2761 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2762 __get_user(set.sig[i], &sf->extramask[i - 1]);
2763 }
bellarde80cfcf2004-12-19 23:18:01 +00002764
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002765 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002766 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002767
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002768 if (err) {
2769 goto segv_and_exit;
2770 }
2771 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002772 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002773
2774segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002775 unlock_user_struct(sf, sf_addr, 0);
2776 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002777 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002778}
2779
Andreas Färber05390242012-02-25 03:37:53 +01002780long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002781{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002782 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002783 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002784 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002785}
2786
bellard459a4012007-11-11 19:45:10 +00002787#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00002788#define SPARC_MC_TSTATE 0
2789#define SPARC_MC_PC 1
2790#define SPARC_MC_NPC 2
2791#define SPARC_MC_Y 3
2792#define SPARC_MC_G1 4
2793#define SPARC_MC_G2 5
2794#define SPARC_MC_G3 6
2795#define SPARC_MC_G4 7
2796#define SPARC_MC_G5 8
2797#define SPARC_MC_G6 9
2798#define SPARC_MC_G7 10
2799#define SPARC_MC_O0 11
2800#define SPARC_MC_O1 12
2801#define SPARC_MC_O2 13
2802#define SPARC_MC_O3 14
2803#define SPARC_MC_O4 15
2804#define SPARC_MC_O5 16
2805#define SPARC_MC_O6 17
2806#define SPARC_MC_O7 18
2807#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00002808
Anthony Liguoric227f092009-10-01 16:12:16 -05002809typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002810typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002811
2812struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002813 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002814 uint32_t mcfq_insn;
2815};
2816
2817struct target_mc_fpu {
2818 union {
2819 uint32_t sregs[32];
2820 uint64_t dregs[32];
2821 //uint128_t qregs[16];
2822 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002823 abi_ulong mcfpu_fsr;
2824 abi_ulong mcfpu_fprs;
2825 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002826 struct target_mc_fq *mcfpu_fq;
2827 unsigned char mcfpu_qcnt;
2828 unsigned char mcfpu_qentsz;
2829 unsigned char mcfpu_enab;
2830};
Anthony Liguoric227f092009-10-01 16:12:16 -05002831typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002832
2833typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002834 target_mc_gregset_t mc_gregs;
2835 target_mc_greg_t mc_fp;
2836 target_mc_greg_t mc_i7;
2837 target_mc_fpu_t mc_fpregs;
2838} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002839
2840struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002841 struct target_ucontext *tuc_link;
2842 abi_ulong tuc_flags;
2843 target_sigset_t tuc_sigmask;
2844 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002845};
2846
2847/* A V9 register window */
2848struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002849 abi_ulong locals[8];
2850 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002851};
2852
2853#define TARGET_STACK_BIAS 2047
2854
2855/* {set, get}context() needed for 64-bit SparcLinux userland. */
2856void sparc64_set_context(CPUSPARCState *env)
2857{
bellard459a4012007-11-11 19:45:10 +00002858 abi_ulong ucp_addr;
2859 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002860 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002861 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002862 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002863 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002864
bellard459a4012007-11-11 19:45:10 +00002865 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002866 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002867 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002868 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002869 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002870 __get_user(pc, &((*grp)[SPARC_MC_PC]));
2871 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002872 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002873 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002874 }
blueswir15bfb56b2007-10-05 17:01:51 +00002875 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002876 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002877 sigset_t set;
2878
2879 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002880 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002881 } else {
bellard459a4012007-11-11 19:45:10 +00002882 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002883 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002884 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002885 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002886 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002887 }
blueswir15bfb56b2007-10-05 17:01:51 +00002888 }
2889 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002890 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002891 }
2892 env->pc = pc;
2893 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002894 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
2895 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002896 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002897 cpu_put_ccr(env, tstate >> 32);
2898 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00002899 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
2900 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
2901 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
2902 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
2903 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
2904 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
2905 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
2906 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
2907 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
2908 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
2909 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
2910 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
2911 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
2912 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
2913 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002914
Riku Voipio1d8b5122014-04-23 10:26:05 +03002915 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2916 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002917
bellard459a4012007-11-11 19:45:10 +00002918 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002919 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2920 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002921 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002922 }
2923 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2924 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002925 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002926 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002927 /* FIXME this does not match how the kernel handles the FPU in
2928 * its sparc64_set_context implementation. In particular the FPU
2929 * is only restored if fenab is non-zero in:
2930 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2931 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002932 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002933 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002934 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2935 for (i = 0; i < 64; i++, src++) {
2936 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002937 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002938 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002939 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002940 }
2941 }
bellard459a4012007-11-11 19:45:10 +00002942 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002943 __get_user(env->fsr,
2944 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2945 __get_user(env->gsr,
2946 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002947 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002948 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002949do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002950 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002951 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002952}
2953
2954void sparc64_get_context(CPUSPARCState *env)
2955{
bellard459a4012007-11-11 19:45:10 +00002956 abi_ulong ucp_addr;
2957 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002958 target_mc_gregset_t *grp;
2959 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002960 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002961 int err;
2962 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002963 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002964 sigset_t set;
2965
bellard459a4012007-11-11 19:45:10 +00002966 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002967 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002968 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002969 }
bellard459a4012007-11-11 19:45:10 +00002970
Aurelien Jarno60e99242010-03-29 02:12:51 +02002971 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002972 grp = &mcp->mc_gregs;
2973
2974 /* Skip over the trap instruction, first. */
2975 env->pc = env->npc;
2976 env->npc += 4;
2977
Peter Maydell3d3efba2016-05-27 15:51:49 +01002978 /* If we're only reading the signal mask then do_sigprocmask()
2979 * is guaranteed not to fail, which is important because we don't
2980 * have any way to signal a failure or restart this operation since
2981 * this is not a normal syscall.
2982 */
2983 err = do_sigprocmask(0, NULL, &set);
2984 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002985 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002986 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002987 __put_user(target_set.sig[0],
2988 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002989 } else {
2990 abi_ulong *src, *dst;
2991 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002992 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002993 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002994 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002995 }
blueswir15bfb56b2007-10-05 17:01:51 +00002996 if (err)
2997 goto do_sigsegv;
2998 }
2999
bellard459a4012007-11-11 19:45:10 +00003000 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003001 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3002 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3003 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3004 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3005 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3006 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3007 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3008 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3009 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3010 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3011 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3012 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3013 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3014 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3015 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3016 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3017 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3018 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3019 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003020
bellard459a4012007-11-11 19:45:10 +00003021 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3022 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003023 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3024 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003025 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003026 }
3027 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3028 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003029 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003030 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003031 __put_user(fp, &(mcp->mc_fp));
3032 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003033
bellard459a4012007-11-11 19:45:10 +00003034 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003035 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3036 for (i = 0; i < 64; i++, dst++) {
3037 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003038 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003039 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003040 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003041 }
3042 }
bellard459a4012007-11-11 19:45:10 +00003043 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003044 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3045 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3046 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003047
3048 if (err)
3049 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003050 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003051 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003052do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003053 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003054 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003055}
3056#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003057#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003058
Richard Hendersonff970902013-02-10 10:30:42 -08003059# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003060struct target_sigcontext {
3061 uint32_t sc_regmask; /* Unused */
3062 uint32_t sc_status;
3063 uint64_t sc_pc;
3064 uint64_t sc_regs[32];
3065 uint64_t sc_fpregs[32];
3066 uint32_t sc_ownedfp; /* Unused */
3067 uint32_t sc_fpc_csr;
3068 uint32_t sc_fpc_eir; /* Unused */
3069 uint32_t sc_used_math;
3070 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003071 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003072 uint64_t sc_mdhi;
3073 uint64_t sc_mdlo;
3074 target_ulong sc_hi1; /* Was sc_cause */
3075 target_ulong sc_lo1; /* Was sc_badvaddr */
3076 target_ulong sc_hi2; /* Was sc_sigset[4] */
3077 target_ulong sc_lo2;
3078 target_ulong sc_hi3;
3079 target_ulong sc_lo3;
3080};
Richard Hendersonff970902013-02-10 10:30:42 -08003081# else /* N32 || N64 */
3082struct target_sigcontext {
3083 uint64_t sc_regs[32];
3084 uint64_t sc_fpregs[32];
3085 uint64_t sc_mdhi;
3086 uint64_t sc_hi1;
3087 uint64_t sc_hi2;
3088 uint64_t sc_hi3;
3089 uint64_t sc_mdlo;
3090 uint64_t sc_lo1;
3091 uint64_t sc_lo2;
3092 uint64_t sc_lo3;
3093 uint64_t sc_pc;
3094 uint32_t sc_fpc_csr;
3095 uint32_t sc_used_math;
3096 uint32_t sc_dsp;
3097 uint32_t sc_reserved;
3098};
3099# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003100
3101struct sigframe {
3102 uint32_t sf_ass[4]; /* argument save space for o32 */
3103 uint32_t sf_code[2]; /* signal trampoline */
3104 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003105 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003106};
3107
pbrook0b1bcb02009-04-21 01:41:10 +00003108struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003109 target_ulong tuc_flags;
3110 target_ulong tuc_link;
3111 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003112 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003113 struct target_sigcontext tuc_mcontext;
3114 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003115};
3116
3117struct target_rt_sigframe {
3118 uint32_t rs_ass[4]; /* argument save space for o32 */
3119 uint32_t rs_code[2]; /* signal trampoline */
3120 struct target_siginfo rs_info;
3121 struct target_ucontext rs_uc;
3122};
3123
bellard106ec872006-06-27 21:08:10 +00003124/* Install trampoline to jump back from signal handler */
3125static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3126{
Richard Henderson084d0492013-02-10 10:30:44 -08003127 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003128
3129 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003130 * Set up the return code ...
3131 *
3132 * li v0, __NR__foo_sigreturn
3133 * syscall
3134 */
bellard106ec872006-06-27 21:08:10 +00003135
Riku Voipio1d8b5122014-04-23 10:26:05 +03003136 __put_user(0x24020000 + syscall, tramp + 0);
3137 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003138 return err;
3139}
3140
Riku Voipio41ecc722014-04-23 11:01:00 +03003141static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003142 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003143{
Richard Henderson084d0492013-02-10 10:30:44 -08003144 int i;
bellard106ec872006-06-27 21:08:10 +00003145
Riku Voipio1d8b5122014-04-23 10:26:05 +03003146 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003147 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003148
Richard Henderson084d0492013-02-10 10:30:44 -08003149 __put_user(0, &sc->sc_regs[0]);
3150 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003151 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003152 }
bellard106ec872006-06-27 21:08:10 +00003153
Riku Voipio1d8b5122014-04-23 10:26:05 +03003154 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3155 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003156
Richard Henderson084d0492013-02-10 10:30:44 -08003157 /* Rather than checking for dsp existence, always copy. The storage
3158 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003159 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3160 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3161 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3162 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3163 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3164 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003165 {
3166 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003167 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003168 }
Richard Henderson084d0492013-02-10 10:30:44 -08003169
Riku Voipio1d8b5122014-04-23 10:26:05 +03003170 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003171
3172 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003173 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003174 }
bellard106ec872006-06-27 21:08:10 +00003175}
3176
Riku Voipio016d2e12014-04-23 11:19:48 +03003177static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003178restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003179{
Richard Henderson084d0492013-02-10 10:30:44 -08003180 int i;
bellard106ec872006-06-27 21:08:10 +00003181
Riku Voipio1d8b5122014-04-23 10:26:05 +03003182 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003183
Riku Voipio1d8b5122014-04-23 10:26:05 +03003184 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3185 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003186
Richard Henderson084d0492013-02-10 10:30:44 -08003187 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003188 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003189 }
3190
Riku Voipio1d8b5122014-04-23 10:26:05 +03003191 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3192 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3193 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3194 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3195 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3196 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003197 {
3198 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003199 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003200 cpu_wrdsp(dsp, 0x3ff, regs);
3201 }
3202
3203 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003204 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003205 }
bellard106ec872006-06-27 21:08:10 +00003206}
Richard Hendersonff970902013-02-10 10:30:42 -08003207
bellard106ec872006-06-27 21:08:10 +00003208/*
3209 * Determine which stack to use..
3210 */
bellard579a97f2007-11-11 14:26:47 +00003211static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003212get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003213{
3214 unsigned long sp;
3215
3216 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003217 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003218
3219 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003220 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003221 * above the user stack, 16-bytes before the next lowest
3222 * 16 byte boundary. Try to avoid trashing it.
3223 */
3224 sp -= 32;
3225
bellard106ec872006-06-27 21:08:10 +00003226 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003227 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003228 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3229 }
bellard106ec872006-06-27 21:08:10 +00003230
bellard579a97f2007-11-11 14:26:47 +00003231 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003232}
3233
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003234static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3235{
3236 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3237 env->hflags &= ~MIPS_HFLAG_M16;
3238 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3239 env->active_tc.PC &= ~(target_ulong) 1;
3240 }
3241}
3242
Richard Hendersonff970902013-02-10 10:30:42 -08003243# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003244/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003245static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003246 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003247{
3248 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003249 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003250 int i;
3251
bellard579a97f2007-11-11 14:26:47 +00003252 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003253 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003254 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3255 goto give_sigsegv;
3256 }
bellard106ec872006-06-27 21:08:10 +00003257
3258 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3259
Riku Voipio41ecc722014-04-23 11:01:00 +03003260 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003261
3262 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003263 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003264 }
3265
3266 /*
3267 * Arguments to signal handler:
3268 *
3269 * a0 = signal number
3270 * a1 = 0 (should be cause)
3271 * a2 = pointer to struct sigcontext
3272 *
3273 * $25 and PC point to the signal handler, $29 points to the
3274 * struct sigframe.
3275 */
thsb5dc7732008-06-27 10:02:35 +00003276 regs->active_tc.gpr[ 4] = sig;
3277 regs->active_tc.gpr[ 5] = 0;
3278 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3279 regs->active_tc.gpr[29] = frame_addr;
3280 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003281 /* The original kernel code sets CP0_EPC to the handler
3282 * since it returns to userland using eret
3283 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003284 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003285 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003286 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003287 return;
3288
3289give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003290 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003291}
3292
Andreas Färber05390242012-02-25 03:37:53 +01003293long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003294{
ths388bb212007-05-13 13:58:00 +00003295 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003296 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003297 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003298 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003299 int i;
bellard106ec872006-06-27 21:08:10 +00003300
thsb5dc7732008-06-27 10:02:35 +00003301 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003302 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003303 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003304 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003305
ths388bb212007-05-13 13:58:00 +00003306 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003307 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003308 }
bellard106ec872006-06-27 21:08:10 +00003309
ths388bb212007-05-13 13:58:00 +00003310 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003311 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003312
Riku Voipio016d2e12014-04-23 11:19:48 +03003313 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003314
3315#if 0
ths388bb212007-05-13 13:58:00 +00003316 /*
3317 * Don't let your children do this ...
3318 */
3319 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003320 "move\t$29, %0\n\t"
3321 "j\tsyscall_exit"
3322 :/* no outputs */
3323 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003324 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003325#endif
ths3b46e622007-09-17 08:09:54 +00003326
thsb5dc7732008-06-27 10:02:35 +00003327 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003328 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003329 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003330 * maybe a problem with nested signals ? */
3331 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003332 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003333
3334badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003335 force_sig(TARGET_SIGSEGV);
3336 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003337}
Richard Hendersonff970902013-02-10 10:30:42 -08003338# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003339
pbrook624f7972008-05-31 16:11:38 +00003340static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003341 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003342 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003343{
pbrook0b1bcb02009-04-21 01:41:10 +00003344 struct target_rt_sigframe *frame;
3345 abi_ulong frame_addr;
3346 int i;
3347
3348 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003349 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003350 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3351 goto give_sigsegv;
3352 }
pbrook0b1bcb02009-04-21 01:41:10 +00003353
3354 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3355
Peter Maydellf6c7a052015-01-08 12:19:48 +00003356 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003357
Aurelien Jarno60e99242010-03-29 02:12:51 +02003358 __put_user(0, &frame->rs_uc.tuc_flags);
3359 __put_user(0, &frame->rs_uc.tuc_link);
3360 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3361 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003362 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003363 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003364
Aurelien Jarno60e99242010-03-29 02:12:51 +02003365 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003366
3367 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003368 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003369 }
3370
3371 /*
3372 * Arguments to signal handler:
3373 *
3374 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003375 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003376 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003377 *
3378 * $25 and PC point to the signal handler, $29 points to the
3379 * struct sigframe.
3380 */
3381 env->active_tc.gpr[ 4] = sig;
3382 env->active_tc.gpr[ 5] = frame_addr
3383 + offsetof(struct target_rt_sigframe, rs_info);
3384 env->active_tc.gpr[ 6] = frame_addr
3385 + offsetof(struct target_rt_sigframe, rs_uc);
3386 env->active_tc.gpr[29] = frame_addr;
3387 env->active_tc.gpr[31] = frame_addr
3388 + offsetof(struct target_rt_sigframe, rs_code);
3389 /* The original kernel code sets CP0_EPC to the handler
3390 * since it returns to userland using eret
3391 * we cannot do this here, and we must set PC directly */
3392 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003393 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003394 unlock_user_struct(frame, frame_addr, 1);
3395 return;
3396
3397give_sigsegv:
3398 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003399 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003400}
3401
Andreas Färber05390242012-02-25 03:37:53 +01003402long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003403{
pbrook0b1bcb02009-04-21 01:41:10 +00003404 struct target_rt_sigframe *frame;
3405 abi_ulong frame_addr;
3406 sigset_t blocked;
3407
pbrook0b1bcb02009-04-21 01:41:10 +00003408 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003409 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003410 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3411 goto badframe;
3412 }
pbrook0b1bcb02009-04-21 01:41:10 +00003413
Aurelien Jarno60e99242010-03-29 02:12:51 +02003414 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003415 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003416
Riku Voipio016d2e12014-04-23 11:19:48 +03003417 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003418
3419 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003420 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3421 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003422 goto badframe;
3423
3424 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003425 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003426 /* I am not sure this is right, but it seems to work
3427 * maybe a problem with nested signals ? */
3428 env->CP0_EPC = 0;
3429 return -TARGET_QEMU_ESIGRETURN;
3430
3431badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003432 force_sig(TARGET_SIGSEGV);
3433 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003434}
bellard6d5e2162004-09-30 22:04:13 +00003435
thsc3b5bc82007-12-02 06:31:25 +00003436#elif defined(TARGET_SH4)
3437
3438/*
3439 * code and data structures from linux kernel:
3440 * include/asm-sh/sigcontext.h
3441 * arch/sh/kernel/signal.c
3442 */
3443
3444struct target_sigcontext {
3445 target_ulong oldmask;
3446
3447 /* CPU registers */
3448 target_ulong sc_gregs[16];
3449 target_ulong sc_pc;
3450 target_ulong sc_pr;
3451 target_ulong sc_sr;
3452 target_ulong sc_gbr;
3453 target_ulong sc_mach;
3454 target_ulong sc_macl;
3455
3456 /* FPU registers */
3457 target_ulong sc_fpregs[16];
3458 target_ulong sc_xfpregs[16];
3459 unsigned int sc_fpscr;
3460 unsigned int sc_fpul;
3461 unsigned int sc_ownedfp;
3462};
3463
3464struct target_sigframe
3465{
3466 struct target_sigcontext sc;
3467 target_ulong extramask[TARGET_NSIG_WORDS-1];
3468 uint16_t retcode[3];
3469};
3470
3471
3472struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003473 target_ulong tuc_flags;
3474 struct target_ucontext *tuc_link;
3475 target_stack_t tuc_stack;
3476 struct target_sigcontext tuc_mcontext;
3477 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003478};
3479
3480struct target_rt_sigframe
3481{
3482 struct target_siginfo info;
3483 struct target_ucontext uc;
3484 uint16_t retcode[3];
3485};
3486
3487
3488#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3489#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3490
pbrook624f7972008-05-31 16:11:38 +00003491static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003492 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003493{
pbrook624f7972008-05-31 16:11:38 +00003494 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003495 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3496 }
3497
3498 return (sp - frame_size) & -8ul;
3499}
3500
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003501/* Notice when we're in the middle of a gUSA region and reset.
3502 Note that this will only occur for !parallel_cpus, as we will
3503 translate such sequences differently in a parallel context. */
3504static void unwind_gusa(CPUSH4State *regs)
3505{
3506 /* If the stack pointer is sufficiently negative, and we haven't
3507 completed the sequence, then reset to the entry to the region. */
3508 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3509 However, the page mappings in qemu linux-user aren't as restricted
3510 and we wind up with the normal stack mapped above 0xF0000000.
3511 That said, there is no reason why the kernel should be allowing
3512 a gUSA region that spans 1GB. Use a tighter check here, for what
3513 can actually be enabled by the immediate move. */
3514 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3515 /* Reset the PC to before the gUSA region, as computed from
3516 R0 = region end, SP = -(region size), plus one more for the
3517 insn that actually initializes SP to the region size. */
3518 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3519
3520 /* Reset the SP to the saved version in R1. */
3521 regs->gregs[15] = regs->gregs[1];
3522 }
3523}
3524
Riku Voipio41ecc722014-04-23 11:01:00 +03003525static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003526 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003527{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003528 int i;
thsc3b5bc82007-12-02 06:31:25 +00003529
Riku Voipio1d8b5122014-04-23 10:26:05 +03003530#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003531 COPY(gregs[0]); COPY(gregs[1]);
3532 COPY(gregs[2]); COPY(gregs[3]);
3533 COPY(gregs[4]); COPY(gregs[5]);
3534 COPY(gregs[6]); COPY(gregs[7]);
3535 COPY(gregs[8]); COPY(gregs[9]);
3536 COPY(gregs[10]); COPY(gregs[11]);
3537 COPY(gregs[12]); COPY(gregs[13]);
3538 COPY(gregs[14]); COPY(gregs[15]);
3539 COPY(gbr); COPY(mach);
3540 COPY(macl); COPY(pr);
3541 COPY(sr); COPY(pc);
3542#undef COPY
3543
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003544 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003545 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003546 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003547 __put_user(regs->fpscr, &sc->sc_fpscr);
3548 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003549
3550 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003551 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003552}
3553
Timothy E Baldwinba412492016-05-12 18:47:35 +01003554static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003555{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003556 int i;
thsc3b5bc82007-12-02 06:31:25 +00003557
Riku Voipio1d8b5122014-04-23 10:26:05 +03003558#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003559 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003560 COPY(gregs[2]); COPY(gregs[3]);
3561 COPY(gregs[4]); COPY(gregs[5]);
3562 COPY(gregs[6]); COPY(gregs[7]);
3563 COPY(gregs[8]); COPY(gregs[9]);
3564 COPY(gregs[10]); COPY(gregs[11]);
3565 COPY(gregs[12]); COPY(gregs[13]);
3566 COPY(gregs[14]); COPY(gregs[15]);
3567 COPY(gbr); COPY(mach);
3568 COPY(macl); COPY(pr);
3569 COPY(sr); COPY(pc);
3570#undef COPY
3571
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003572 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003573 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003574 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003575 __get_user(regs->fpscr, &sc->sc_fpscr);
3576 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003577
3578 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003579 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003580}
3581
pbrook624f7972008-05-31 16:11:38 +00003582static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003583 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003584{
3585 struct target_sigframe *frame;
3586 abi_ulong frame_addr;
3587 int i;
thsc3b5bc82007-12-02 06:31:25 +00003588
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003589 unwind_gusa(regs);
3590
thsc3b5bc82007-12-02 06:31:25 +00003591 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003592 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003593 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3594 goto give_sigsegv;
3595 }
thsc3b5bc82007-12-02 06:31:25 +00003596
Riku Voipio41ecc722014-04-23 11:01:00 +03003597 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003598
3599 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003600 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003601 }
3602
3603 /* Set up to return from userspace. If provided, use a stub
3604 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003605 if (ka->sa_flags & TARGET_SA_RESTORER) {
3606 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003607 } else {
3608 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003609 abi_ulong retcode_addr = frame_addr +
3610 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003611 __put_user(MOVW(2), &frame->retcode[0]);
3612 __put_user(TRAP_NOARG, &frame->retcode[1]);
3613 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003614 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003615 }
3616
thsc3b5bc82007-12-02 06:31:25 +00003617 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003618 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003619 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003620 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003621 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003622 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003623 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003624
3625 unlock_user_struct(frame, frame_addr, 1);
3626 return;
3627
3628give_sigsegv:
3629 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003630 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003631}
3632
pbrook624f7972008-05-31 16:11:38 +00003633static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003634 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003635 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003636{
3637 struct target_rt_sigframe *frame;
3638 abi_ulong frame_addr;
3639 int i;
thsc3b5bc82007-12-02 06:31:25 +00003640
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003641 unwind_gusa(regs);
3642
thsc3b5bc82007-12-02 06:31:25 +00003643 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003644 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003645 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3646 goto give_sigsegv;
3647 }
thsc3b5bc82007-12-02 06:31:25 +00003648
Peter Maydellf6c7a052015-01-08 12:19:48 +00003649 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003650
3651 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003652 __put_user(0, &frame->uc.tuc_flags);
3653 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3654 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3655 &frame->uc.tuc_stack.ss_sp);
3656 __put_user(sas_ss_flags(regs->gregs[15]),
3657 &frame->uc.tuc_stack.ss_flags);
3658 __put_user(target_sigaltstack_used.ss_size,
3659 &frame->uc.tuc_stack.ss_size);
3660 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003661 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003662 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003663 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003664 }
3665
3666 /* Set up to return from userspace. If provided, use a stub
3667 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003668 if (ka->sa_flags & TARGET_SA_RESTORER) {
3669 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003670 } else {
3671 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003672 abi_ulong retcode_addr = frame_addr +
3673 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003674 __put_user(MOVW(2), &frame->retcode[0]);
3675 __put_user(TRAP_NOARG, &frame->retcode[1]);
3676 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003677 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003678 }
3679
thsc3b5bc82007-12-02 06:31:25 +00003680 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003681 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003682 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003683 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3684 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003685 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003686 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003687
3688 unlock_user_struct(frame, frame_addr, 1);
3689 return;
3690
3691give_sigsegv:
3692 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003693 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003694}
3695
Andreas Färber05390242012-02-25 03:37:53 +01003696long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003697{
3698 struct target_sigframe *frame;
3699 abi_ulong frame_addr;
3700 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003701 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003702 int i;
3703 int err = 0;
3704
thsc3b5bc82007-12-02 06:31:25 +00003705 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003706 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003707 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3708 goto badframe;
3709 }
thsc3b5bc82007-12-02 06:31:25 +00003710
Riku Voipio1d8b5122014-04-23 10:26:05 +03003711 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003712 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003713 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003714 }
3715
3716 if (err)
3717 goto badframe;
3718
3719 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003720 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003721
Timothy E Baldwinba412492016-05-12 18:47:35 +01003722 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003723
3724 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003725 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003726
3727badframe:
3728 unlock_user_struct(frame, frame_addr, 0);
3729 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003730 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003731}
3732
Andreas Färber05390242012-02-25 03:37:53 +01003733long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003734{
3735 struct target_rt_sigframe *frame;
3736 abi_ulong frame_addr;
3737 sigset_t blocked;
3738
thsc3b5bc82007-12-02 06:31:25 +00003739 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003740 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003741 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3742 goto badframe;
3743 }
thsc3b5bc82007-12-02 06:31:25 +00003744
Aurelien Jarno60e99242010-03-29 02:12:51 +02003745 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003746 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003747
Timothy E Baldwinba412492016-05-12 18:47:35 +01003748 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003749
3750 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003751 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3752 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003753 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003754 }
thsc3b5bc82007-12-02 06:31:25 +00003755
3756 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003757 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003758
3759badframe:
3760 unlock_user_struct(frame, frame_addr, 0);
3761 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003762 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003763}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003764#elif defined(TARGET_MICROBLAZE)
3765
3766struct target_sigcontext {
3767 struct target_pt_regs regs; /* needs to be first */
3768 uint32_t oldmask;
3769};
3770
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003771struct target_stack_t {
3772 abi_ulong ss_sp;
3773 int ss_flags;
3774 unsigned int ss_size;
3775};
3776
3777struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003778 abi_ulong tuc_flags;
3779 abi_ulong tuc_link;
3780 struct target_stack_t tuc_stack;
3781 struct target_sigcontext tuc_mcontext;
3782 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003783};
3784
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003785/* Signal frames. */
3786struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003787 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003788 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3789 uint32_t tramp[2];
3790};
3791
3792struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003793 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07003794 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003795 uint32_t tramp[2];
3796};
3797
Andreas Färber05390242012-02-25 03:37:53 +01003798static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003799{
3800 __put_user(env->regs[0], &sc->regs.r0);
3801 __put_user(env->regs[1], &sc->regs.r1);
3802 __put_user(env->regs[2], &sc->regs.r2);
3803 __put_user(env->regs[3], &sc->regs.r3);
3804 __put_user(env->regs[4], &sc->regs.r4);
3805 __put_user(env->regs[5], &sc->regs.r5);
3806 __put_user(env->regs[6], &sc->regs.r6);
3807 __put_user(env->regs[7], &sc->regs.r7);
3808 __put_user(env->regs[8], &sc->regs.r8);
3809 __put_user(env->regs[9], &sc->regs.r9);
3810 __put_user(env->regs[10], &sc->regs.r10);
3811 __put_user(env->regs[11], &sc->regs.r11);
3812 __put_user(env->regs[12], &sc->regs.r12);
3813 __put_user(env->regs[13], &sc->regs.r13);
3814 __put_user(env->regs[14], &sc->regs.r14);
3815 __put_user(env->regs[15], &sc->regs.r15);
3816 __put_user(env->regs[16], &sc->regs.r16);
3817 __put_user(env->regs[17], &sc->regs.r17);
3818 __put_user(env->regs[18], &sc->regs.r18);
3819 __put_user(env->regs[19], &sc->regs.r19);
3820 __put_user(env->regs[20], &sc->regs.r20);
3821 __put_user(env->regs[21], &sc->regs.r21);
3822 __put_user(env->regs[22], &sc->regs.r22);
3823 __put_user(env->regs[23], &sc->regs.r23);
3824 __put_user(env->regs[24], &sc->regs.r24);
3825 __put_user(env->regs[25], &sc->regs.r25);
3826 __put_user(env->regs[26], &sc->regs.r26);
3827 __put_user(env->regs[27], &sc->regs.r27);
3828 __put_user(env->regs[28], &sc->regs.r28);
3829 __put_user(env->regs[29], &sc->regs.r29);
3830 __put_user(env->regs[30], &sc->regs.r30);
3831 __put_user(env->regs[31], &sc->regs.r31);
3832 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3833}
3834
Andreas Färber05390242012-02-25 03:37:53 +01003835static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003836{
3837 __get_user(env->regs[0], &sc->regs.r0);
3838 __get_user(env->regs[1], &sc->regs.r1);
3839 __get_user(env->regs[2], &sc->regs.r2);
3840 __get_user(env->regs[3], &sc->regs.r3);
3841 __get_user(env->regs[4], &sc->regs.r4);
3842 __get_user(env->regs[5], &sc->regs.r5);
3843 __get_user(env->regs[6], &sc->regs.r6);
3844 __get_user(env->regs[7], &sc->regs.r7);
3845 __get_user(env->regs[8], &sc->regs.r8);
3846 __get_user(env->regs[9], &sc->regs.r9);
3847 __get_user(env->regs[10], &sc->regs.r10);
3848 __get_user(env->regs[11], &sc->regs.r11);
3849 __get_user(env->regs[12], &sc->regs.r12);
3850 __get_user(env->regs[13], &sc->regs.r13);
3851 __get_user(env->regs[14], &sc->regs.r14);
3852 __get_user(env->regs[15], &sc->regs.r15);
3853 __get_user(env->regs[16], &sc->regs.r16);
3854 __get_user(env->regs[17], &sc->regs.r17);
3855 __get_user(env->regs[18], &sc->regs.r18);
3856 __get_user(env->regs[19], &sc->regs.r19);
3857 __get_user(env->regs[20], &sc->regs.r20);
3858 __get_user(env->regs[21], &sc->regs.r21);
3859 __get_user(env->regs[22], &sc->regs.r22);
3860 __get_user(env->regs[23], &sc->regs.r23);
3861 __get_user(env->regs[24], &sc->regs.r24);
3862 __get_user(env->regs[25], &sc->regs.r25);
3863 __get_user(env->regs[26], &sc->regs.r26);
3864 __get_user(env->regs[27], &sc->regs.r27);
3865 __get_user(env->regs[28], &sc->regs.r28);
3866 __get_user(env->regs[29], &sc->regs.r29);
3867 __get_user(env->regs[30], &sc->regs.r30);
3868 __get_user(env->regs[31], &sc->regs.r31);
3869 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3870}
3871
3872static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003873 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003874{
3875 abi_ulong sp = env->regs[1];
3876
Riku Voipiob545f632014-07-15 17:01:55 +03003877 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003878 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003879 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003880
3881 return ((sp - frame_size) & -8UL);
3882}
3883
3884static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003885 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003886{
3887 struct target_signal_frame *frame;
3888 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003889 int i;
3890
3891 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003892 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003893 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3894 goto badframe;
3895
3896 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003897 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003898
3899 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003900 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003901 }
3902
Richard Hendersonf711df62010-11-22 14:57:52 -08003903 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003904
3905 /* Set up to return from userspace. If provided, use a stub
3906 already in userspace. */
3907 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3908 if (ka->sa_flags & TARGET_SA_RESTORER) {
3909 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3910 } else {
3911 uint32_t t;
3912 /* Note, these encodings are _big endian_! */
3913 /* addi r12, r0, __NR_sigreturn */
3914 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003915 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003916 /* brki r14, 0x8 */
3917 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003918 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003919
3920 /* Return from sighandler will jump to the tramp.
3921 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003922 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3923 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003924 }
3925
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003926 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003927 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003928 /* Signal handler args: */
3929 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003930 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003931 /* arg 1: sigcontext */
3932 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003933
3934 /* Offset of 4 to handle microblaze rtid r14, 0 */
3935 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3936
3937 unlock_user_struct(frame, frame_addr, 1);
3938 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003939badframe:
Peter Maydell09391662016-07-28 16:44:47 +01003940 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003941}
3942
3943static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003944 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003945 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003946{
3947 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3948}
3949
Andreas Färber05390242012-02-25 03:37:53 +01003950long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003951{
3952 struct target_signal_frame *frame;
3953 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003954 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003955 sigset_t set;
3956 int i;
3957
3958 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003959 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003960 /* Make sure the guest isn't playing games. */
3961 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3962 goto badframe;
3963
3964 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003965 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003966 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003967 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003968 }
3969 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003970 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003971
Richard Hendersonf711df62010-11-22 14:57:52 -08003972 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003973 /* We got here through a sigreturn syscall, our path back is via an
3974 rtb insn so setup r14 for that. */
3975 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003976
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003977 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003978 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003979badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003980 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003981 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003982}
3983
Andreas Färber05390242012-02-25 03:37:53 +01003984long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003985{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003986 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003987 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3988 return -TARGET_ENOSYS;
3989}
3990
edgar_iglb6d3abd2008-02-28 11:29:27 +00003991#elif defined(TARGET_CRIS)
3992
3993struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003994 struct target_pt_regs regs; /* needs to be first */
3995 uint32_t oldmask;
3996 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003997};
3998
3999/* Signal frames. */
4000struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004001 struct target_sigcontext sc;
4002 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4003 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004004};
4005
4006struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004007 siginfo_t *pinfo;
4008 void *puc;
4009 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004010 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004011 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004012};
4013
Andreas Färber05390242012-02-25 03:37:53 +01004014static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004015{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004016 __put_user(env->regs[0], &sc->regs.r0);
4017 __put_user(env->regs[1], &sc->regs.r1);
4018 __put_user(env->regs[2], &sc->regs.r2);
4019 __put_user(env->regs[3], &sc->regs.r3);
4020 __put_user(env->regs[4], &sc->regs.r4);
4021 __put_user(env->regs[5], &sc->regs.r5);
4022 __put_user(env->regs[6], &sc->regs.r6);
4023 __put_user(env->regs[7], &sc->regs.r7);
4024 __put_user(env->regs[8], &sc->regs.r8);
4025 __put_user(env->regs[9], &sc->regs.r9);
4026 __put_user(env->regs[10], &sc->regs.r10);
4027 __put_user(env->regs[11], &sc->regs.r11);
4028 __put_user(env->regs[12], &sc->regs.r12);
4029 __put_user(env->regs[13], &sc->regs.r13);
4030 __put_user(env->regs[14], &sc->usp);
4031 __put_user(env->regs[15], &sc->regs.acr);
4032 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4033 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4034 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004035}
edgar_igl9664d922008-03-03 22:23:53 +00004036
Andreas Färber05390242012-02-25 03:37:53 +01004037static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004038{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004039 __get_user(env->regs[0], &sc->regs.r0);
4040 __get_user(env->regs[1], &sc->regs.r1);
4041 __get_user(env->regs[2], &sc->regs.r2);
4042 __get_user(env->regs[3], &sc->regs.r3);
4043 __get_user(env->regs[4], &sc->regs.r4);
4044 __get_user(env->regs[5], &sc->regs.r5);
4045 __get_user(env->regs[6], &sc->regs.r6);
4046 __get_user(env->regs[7], &sc->regs.r7);
4047 __get_user(env->regs[8], &sc->regs.r8);
4048 __get_user(env->regs[9], &sc->regs.r9);
4049 __get_user(env->regs[10], &sc->regs.r10);
4050 __get_user(env->regs[11], &sc->regs.r11);
4051 __get_user(env->regs[12], &sc->regs.r12);
4052 __get_user(env->regs[13], &sc->regs.r13);
4053 __get_user(env->regs[14], &sc->usp);
4054 __get_user(env->regs[15], &sc->regs.acr);
4055 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4056 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4057 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004058}
4059
Andreas Färber05390242012-02-25 03:37:53 +01004060static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004061{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004062 abi_ulong sp;
4063 /* Align the stack downwards to 4. */
4064 sp = (env->regs[R_SP] & ~3);
4065 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004066}
4067
pbrook624f7972008-05-31 16:11:38 +00004068static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004069 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004070{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004071 struct target_signal_frame *frame;
4072 abi_ulong frame_addr;
4073 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004074
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004075 frame_addr = get_sigframe(env, sizeof *frame);
4076 trace_user_setup_frame(env, frame_addr);
4077 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4078 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004079
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004080 /*
4081 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4082 * use this trampoline anymore but it sets it up for GDB.
4083 * In QEMU, using the trampoline simplifies things a bit so we use it.
4084 *
4085 * This is movu.w __NR_sigreturn, r9; break 13;
4086 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004087 __put_user(0x9c5f, frame->retcode+0);
4088 __put_user(TARGET_NR_sigreturn,
4089 frame->retcode + 1);
4090 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004091
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004092 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004093 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004094
Riku Voipio0188fad2014-04-23 13:34:15 +03004095 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4096 __put_user(set->sig[i], &frame->extramask[i - 1]);
4097 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004098
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004099 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004100
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004101 /* Move the stack and setup the arguments for the handler. */
4102 env->regs[R_SP] = frame_addr;
4103 env->regs[10] = sig;
4104 env->pc = (unsigned long) ka->_sa_handler;
4105 /* Link SRP so the guest returns through the trampoline. */
4106 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004107
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004108 unlock_user_struct(frame, frame_addr, 1);
4109 return;
4110badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004111 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004112}
4113
pbrook624f7972008-05-31 16:11:38 +00004114static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004115 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004116 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004117{
4118 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4119}
4120
Andreas Färber05390242012-02-25 03:37:53 +01004121long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004122{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004123 struct target_signal_frame *frame;
4124 abi_ulong frame_addr;
4125 target_sigset_t target_set;
4126 sigset_t set;
4127 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004128
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004129 frame_addr = env->regs[R_SP];
4130 trace_user_do_sigreturn(env, frame_addr);
4131 /* Make sure the guest isn't playing games. */
4132 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4133 goto badframe;
4134 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004135
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004136 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004137 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004138 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004139 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004140 }
4141 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004142 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004143
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004144 restore_sigcontext(&frame->sc, env);
4145 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004146 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004147badframe:
4148 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004149 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004150}
4151
Andreas Färber05390242012-02-25 03:37:53 +01004152long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004153{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004154 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004155 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4156 return -TARGET_ENOSYS;
4157}
thsc3b5bc82007-12-02 06:31:25 +00004158
Marek Vasuta0a839b2017-01-18 23:01:42 +01004159#elif defined(TARGET_NIOS2)
4160
4161#define MCONTEXT_VERSION 2
4162
4163struct target_sigcontext {
4164 int version;
4165 unsigned long gregs[32];
4166};
4167
4168struct target_ucontext {
4169 abi_ulong tuc_flags;
4170 abi_ulong tuc_link;
4171 target_stack_t tuc_stack;
4172 struct target_sigcontext tuc_mcontext;
4173 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4174};
4175
4176struct target_rt_sigframe {
4177 struct target_siginfo info;
4178 struct target_ucontext uc;
4179};
4180
4181static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4182{
4183 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4184#ifdef CONFIG_STACK_GROWSUP
4185 return target_sigaltstack_used.ss_sp;
4186#else
4187 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4188#endif
4189 }
4190 return sp;
4191}
4192
4193static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4194{
4195 unsigned long *gregs = uc->tuc_mcontext.gregs;
4196
4197 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4198 __put_user(env->regs[1], &gregs[0]);
4199 __put_user(env->regs[2], &gregs[1]);
4200 __put_user(env->regs[3], &gregs[2]);
4201 __put_user(env->regs[4], &gregs[3]);
4202 __put_user(env->regs[5], &gregs[4]);
4203 __put_user(env->regs[6], &gregs[5]);
4204 __put_user(env->regs[7], &gregs[6]);
4205 __put_user(env->regs[8], &gregs[7]);
4206 __put_user(env->regs[9], &gregs[8]);
4207 __put_user(env->regs[10], &gregs[9]);
4208 __put_user(env->regs[11], &gregs[10]);
4209 __put_user(env->regs[12], &gregs[11]);
4210 __put_user(env->regs[13], &gregs[12]);
4211 __put_user(env->regs[14], &gregs[13]);
4212 __put_user(env->regs[15], &gregs[14]);
4213 __put_user(env->regs[16], &gregs[15]);
4214 __put_user(env->regs[17], &gregs[16]);
4215 __put_user(env->regs[18], &gregs[17]);
4216 __put_user(env->regs[19], &gregs[18]);
4217 __put_user(env->regs[20], &gregs[19]);
4218 __put_user(env->regs[21], &gregs[20]);
4219 __put_user(env->regs[22], &gregs[21]);
4220 __put_user(env->regs[23], &gregs[22]);
4221 __put_user(env->regs[R_RA], &gregs[23]);
4222 __put_user(env->regs[R_FP], &gregs[24]);
4223 __put_user(env->regs[R_GP], &gregs[25]);
4224 __put_user(env->regs[R_EA], &gregs[27]);
4225 __put_user(env->regs[R_SP], &gregs[28]);
4226
4227 return 0;
4228}
4229
4230static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4231 int *pr2)
4232{
4233 int temp;
4234 abi_ulong off, frame_addr = env->regs[R_SP];
4235 unsigned long *gregs = uc->tuc_mcontext.gregs;
4236 int err;
4237
4238 /* Always make any pending restarted system calls return -EINTR */
4239 /* current->restart_block.fn = do_no_restart_syscall; */
4240
4241 __get_user(temp, &uc->tuc_mcontext.version);
4242 if (temp != MCONTEXT_VERSION) {
4243 return 1;
4244 }
4245
4246 /* restore passed registers */
4247 __get_user(env->regs[1], &gregs[0]);
4248 __get_user(env->regs[2], &gregs[1]);
4249 __get_user(env->regs[3], &gregs[2]);
4250 __get_user(env->regs[4], &gregs[3]);
4251 __get_user(env->regs[5], &gregs[4]);
4252 __get_user(env->regs[6], &gregs[5]);
4253 __get_user(env->regs[7], &gregs[6]);
4254 __get_user(env->regs[8], &gregs[7]);
4255 __get_user(env->regs[9], &gregs[8]);
4256 __get_user(env->regs[10], &gregs[9]);
4257 __get_user(env->regs[11], &gregs[10]);
4258 __get_user(env->regs[12], &gregs[11]);
4259 __get_user(env->regs[13], &gregs[12]);
4260 __get_user(env->regs[14], &gregs[13]);
4261 __get_user(env->regs[15], &gregs[14]);
4262 __get_user(env->regs[16], &gregs[15]);
4263 __get_user(env->regs[17], &gregs[16]);
4264 __get_user(env->regs[18], &gregs[17]);
4265 __get_user(env->regs[19], &gregs[18]);
4266 __get_user(env->regs[20], &gregs[19]);
4267 __get_user(env->regs[21], &gregs[20]);
4268 __get_user(env->regs[22], &gregs[21]);
4269 __get_user(env->regs[23], &gregs[22]);
4270 /* gregs[23] is handled below */
4271 /* Verify, should this be settable */
4272 __get_user(env->regs[R_FP], &gregs[24]);
4273 /* Verify, should this be settable */
4274 __get_user(env->regs[R_GP], &gregs[25]);
4275 /* Not really necessary no user settable bits */
4276 __get_user(temp, &gregs[26]);
4277 __get_user(env->regs[R_EA], &gregs[27]);
4278
4279 __get_user(env->regs[R_RA], &gregs[23]);
4280 __get_user(env->regs[R_SP], &gregs[28]);
4281
4282 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4283 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4284 if (err == -EFAULT) {
4285 return 1;
4286 }
4287
4288 *pr2 = env->regs[2];
4289 return 0;
4290}
4291
4292static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4293 size_t frame_size)
4294{
4295 unsigned long usp;
4296
4297 /* Default to using normal stack. */
4298 usp = env->regs[R_SP];
4299
4300 /* This is the X/Open sanctioned signal stack switching. */
4301 usp = sigsp(usp, ka);
4302
4303 /* Verify, is it 32 or 64 bit aligned */
4304 return (void *)((usp - frame_size) & -8UL);
4305}
4306
4307static void setup_rt_frame(int sig, struct target_sigaction *ka,
4308 target_siginfo_t *info,
4309 target_sigset_t *set,
4310 CPUNios2State *env)
4311{
4312 struct target_rt_sigframe *frame;
4313 int i, err = 0;
4314
4315 frame = get_sigframe(ka, env, sizeof(*frame));
4316
4317 if (ka->sa_flags & SA_SIGINFO) {
4318 tswap_siginfo(&frame->info, info);
4319 }
4320
4321 /* Create the ucontext. */
4322 __put_user(0, &frame->uc.tuc_flags);
4323 __put_user(0, &frame->uc.tuc_link);
4324 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4325 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4326 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4327 err |= rt_setup_ucontext(&frame->uc, env);
4328 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4329 __put_user((abi_ulong)set->sig[i],
4330 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4331 }
4332
4333 if (err) {
4334 goto give_sigsegv;
4335 }
4336
4337 /* Set up to return from userspace; jump to fixed address sigreturn
4338 trampoline on kuser page. */
4339 env->regs[R_RA] = (unsigned long) (0x1044);
4340
4341 /* Set up registers for signal handler */
4342 env->regs[R_SP] = (unsigned long) frame;
4343 env->regs[4] = (unsigned long) sig;
4344 env->regs[5] = (unsigned long) &frame->info;
4345 env->regs[6] = (unsigned long) &frame->uc;
4346 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4347 return;
4348
4349give_sigsegv:
4350 if (sig == TARGET_SIGSEGV) {
4351 ka->_sa_handler = TARGET_SIG_DFL;
4352 }
4353 force_sigsegv(sig);
4354 return;
4355}
4356
4357long do_sigreturn(CPUNios2State *env)
4358{
4359 trace_user_do_sigreturn(env, 0);
4360 fprintf(stderr, "do_sigreturn: not implemented\n");
4361 return -TARGET_ENOSYS;
4362}
4363
4364long do_rt_sigreturn(CPUNios2State *env)
4365{
4366 /* Verify, can we follow the stack back */
4367 abi_ulong frame_addr = env->regs[R_SP];
4368 struct target_rt_sigframe *frame;
4369 sigset_t set;
4370 int rval;
4371
4372 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4373 goto badframe;
4374 }
4375
4376 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4377 do_sigprocmask(SIG_SETMASK, &set, NULL);
4378
4379 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4380 goto badframe;
4381 }
4382
4383 unlock_user_struct(frame, frame_addr, 0);
4384 return rval;
4385
4386badframe:
4387 unlock_user_struct(frame, frame_addr, 0);
4388 force_sig(TARGET_SIGSEGV);
4389 return 0;
4390}
4391/* TARGET_NIOS2 */
4392
Jia Liud9627832012-07-20 15:50:52 +08004393#elif defined(TARGET_OPENRISC)
4394
4395struct target_sigcontext {
4396 struct target_pt_regs regs;
4397 abi_ulong oldmask;
4398 abi_ulong usp;
4399};
4400
4401struct target_ucontext {
4402 abi_ulong tuc_flags;
4403 abi_ulong tuc_link;
4404 target_stack_t tuc_stack;
4405 struct target_sigcontext tuc_mcontext;
4406 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4407};
4408
4409struct target_rt_sigframe {
4410 abi_ulong pinfo;
4411 uint64_t puc;
4412 struct target_siginfo info;
4413 struct target_sigcontext sc;
4414 struct target_ucontext uc;
4415 unsigned char retcode[16]; /* trampoline code */
4416};
4417
4418/* This is the asm-generic/ucontext.h version */
4419#if 0
4420static int restore_sigcontext(CPUOpenRISCState *regs,
4421 struct target_sigcontext *sc)
4422{
4423 unsigned int err = 0;
4424 unsigned long old_usp;
4425
4426 /* Alwys make any pending restarted system call return -EINTR */
4427 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4428
4429 /* restore the regs from &sc->regs (same as sc, since regs is first)
4430 * (sc is already checked for VERIFY_READ since the sigframe was
4431 * checked in sys_sigreturn previously)
4432 */
4433
4434 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4435 goto badframe;
4436 }
4437
4438 /* make sure the U-flag is set so user-mode cannot fool us */
4439
4440 regs->sr &= ~SR_SM;
4441
4442 /* restore the old USP as it was before we stacked the sc etc.
4443 * (we cannot just pop the sigcontext since we aligned the sp and
4444 * stuff after pushing it)
4445 */
4446
Riku Voipio1d8b5122014-04-23 10:26:05 +03004447 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004448 phx_signal("old_usp 0x%lx", old_usp);
4449
4450 __PHX__ REALLY /* ??? */
4451 wrusp(old_usp);
4452 regs->gpr[1] = old_usp;
4453
4454 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4455 * after this completes, but we don't use that mechanism. maybe we can
4456 * use it now ?
4457 */
4458
4459 return err;
4460
4461badframe:
4462 return 1;
4463}
4464#endif
4465
4466/* Set up a signal frame. */
4467
Riku Voipio41ecc722014-04-23 11:01:00 +03004468static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004469 CPUOpenRISCState *regs,
4470 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004471{
Stafford Horned89e71e2017-04-06 06:44:56 +09004472 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004473
4474 /* copy the regs. they are first in sc so we can use sc directly */
4475
Riku Voipio1d8b5122014-04-23 10:26:05 +03004476 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004477
4478 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4479 the signal handler. The frametype will be restored to its previous
4480 value in restore_sigcontext. */
4481 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4482
4483 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004484 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004485 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004486}
4487
4488static inline unsigned long align_sigframe(unsigned long sp)
4489{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004490 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004491}
4492
4493static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4494 CPUOpenRISCState *regs,
4495 size_t frame_size)
4496{
Stafford Horned89e71e2017-04-06 06:44:56 +09004497 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004498 int onsigstack = on_sig_stack(sp);
4499
4500 /* redzone */
4501 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004502 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004503 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4504 }
4505
4506 sp = align_sigframe(sp - frame_size);
4507
4508 /*
4509 * If we are on the alternate signal stack and would overflow it, don't.
4510 * Return an always-bogus address instead so we will die with SIGSEGV.
4511 */
4512
4513 if (onsigstack && !likely(on_sig_stack(sp))) {
4514 return -1L;
4515 }
4516
4517 return sp;
4518}
4519
Jia Liud9627832012-07-20 15:50:52 +08004520static void setup_rt_frame(int sig, struct target_sigaction *ka,
4521 target_siginfo_t *info,
4522 target_sigset_t *set, CPUOpenRISCState *env)
4523{
4524 int err = 0;
4525 abi_ulong frame_addr;
4526 unsigned long return_ip;
4527 struct target_rt_sigframe *frame;
4528 abi_ulong info_addr, uc_addr;
4529
Jia Liud9627832012-07-20 15:50:52 +08004530 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004531 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004532 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4533 goto give_sigsegv;
4534 }
4535
4536 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004537 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004538 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004539 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004540
4541 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004542 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004543 }
4544
Khem Raj04b33e22017-06-28 13:44:52 -07004545 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004546 __put_user(0, &frame->uc.tuc_flags);
4547 __put_user(0, &frame->uc.tuc_link);
4548 __put_user(target_sigaltstack_used.ss_sp,
4549 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004550 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4551 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004552 __put_user(target_sigaltstack_used.ss_size,
4553 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004554 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004555
4556 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4557
Jia Liud9627832012-07-20 15:50:52 +08004558 /* trampoline - the desired return ip is the retcode itself */
4559 return_ip = (unsigned long)&frame->retcode;
4560 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004561 __put_user(0xa960, (short *)(frame->retcode + 0));
4562 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4563 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4564 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004565
4566 if (err) {
4567 goto give_sigsegv;
4568 }
4569
4570 /* TODO what is the current->exec_domain stuff and invmap ? */
4571
4572 /* Set up registers for signal handler */
4573 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004574 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4575 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4576 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4577 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004578
4579 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004580 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004581
4582 return;
4583
4584give_sigsegv:
4585 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004586 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004587}
4588
4589long do_sigreturn(CPUOpenRISCState *env)
4590{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004591 trace_user_do_sigreturn(env, 0);
4592 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004593 return -TARGET_ENOSYS;
4594}
4595
4596long do_rt_sigreturn(CPUOpenRISCState *env)
4597{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004598 trace_user_do_rt_sigreturn(env, 0);
4599 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004600 return -TARGET_ENOSYS;
4601}
4602/* TARGET_OPENRISC */
4603
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004604#elif defined(TARGET_S390X)
4605
4606#define __NUM_GPRS 16
4607#define __NUM_FPRS 16
4608#define __NUM_ACRS 16
4609
4610#define S390_SYSCALL_SIZE 2
4611#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4612
4613#define _SIGCONTEXT_NSIG 64
4614#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4615#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4616#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4617#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4618#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4619
4620typedef struct {
4621 target_psw_t psw;
4622 target_ulong gprs[__NUM_GPRS];
4623 unsigned int acrs[__NUM_ACRS];
4624} target_s390_regs_common;
4625
4626typedef struct {
4627 unsigned int fpc;
4628 double fprs[__NUM_FPRS];
4629} target_s390_fp_regs;
4630
4631typedef struct {
4632 target_s390_regs_common regs;
4633 target_s390_fp_regs fpregs;
4634} target_sigregs;
4635
4636struct target_sigcontext {
4637 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4638 target_sigregs *sregs;
4639};
4640
4641typedef struct {
4642 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4643 struct target_sigcontext sc;
4644 target_sigregs sregs;
4645 int signo;
4646 uint8_t retcode[S390_SYSCALL_SIZE];
4647} sigframe;
4648
4649struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004650 target_ulong tuc_flags;
4651 struct target_ucontext *tuc_link;
4652 target_stack_t tuc_stack;
4653 target_sigregs tuc_mcontext;
4654 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004655};
4656
4657typedef struct {
4658 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4659 uint8_t retcode[S390_SYSCALL_SIZE];
4660 struct target_siginfo info;
4661 struct target_ucontext uc;
4662} rt_sigframe;
4663
4664static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004665get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004666{
4667 abi_ulong sp;
4668
4669 /* Default to using normal stack */
4670 sp = env->regs[15];
4671
4672 /* This is the X/Open sanctioned signal stack switching. */
4673 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4674 if (!sas_ss_flags(sp)) {
4675 sp = target_sigaltstack_used.ss_sp +
4676 target_sigaltstack_used.ss_size;
4677 }
4678 }
4679
4680 /* This is the legacy signal stack switching. */
4681 else if (/* FIXME !user_mode(regs) */ 0 &&
4682 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4683 ka->sa_restorer) {
4684 sp = (abi_ulong) ka->sa_restorer;
4685 }
4686
4687 return (sp - frame_size) & -8ul;
4688}
4689
Andreas Färber05390242012-02-25 03:37:53 +01004690static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004691{
4692 int i;
4693 //save_access_regs(current->thread.acrs); FIXME
4694
4695 /* Copy a 'clean' PSW mask to the user to avoid leaking
4696 information about whether PER is currently on. */
4697 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4698 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4699 for (i = 0; i < 16; i++) {
4700 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4701 }
4702 for (i = 0; i < 16; i++) {
4703 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4704 }
4705 /*
4706 * We have to store the fp registers to current->thread.fp_regs
4707 * to merge them with the emulated registers.
4708 */
4709 //save_fp_regs(&current->thread.fp_regs); FIXME
4710 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004711 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004712 }
4713}
4714
4715static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004716 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004717{
4718 sigframe *frame;
4719 abi_ulong frame_addr;
4720
4721 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004722 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004723 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004724 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004725 }
4726
Riku Voipio0188fad2014-04-23 13:34:15 +03004727 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004728
4729 save_sigregs(env, &frame->sregs);
4730
4731 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4732 (abi_ulong *)&frame->sc.sregs);
4733
4734 /* Set up to return from userspace. If provided, use a stub
4735 already in userspace. */
4736 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004737 env->regs[14] = (unsigned long)
4738 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004739 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004740 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4741 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004742 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4743 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004744 }
4745
4746 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004747 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004748
4749 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004750 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004751 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4752
4753 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004754 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004755
4756 /* We forgot to include these in the sigcontext.
4757 To avoid breaking binary compatibility, they are passed as args. */
4758 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4759 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4760
4761 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02004762 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004763 unlock_user_struct(frame, frame_addr, 1);
4764 return;
4765
4766give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004767 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004768}
4769
4770static void setup_rt_frame(int sig, struct target_sigaction *ka,
4771 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004772 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004773{
4774 int i;
4775 rt_sigframe *frame;
4776 abi_ulong frame_addr;
4777
4778 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004779 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004780 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4781 goto give_sigsegv;
4782 }
4783
Peter Maydellf6c7a052015-01-08 12:19:48 +00004784 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004785
4786 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004787 __put_user(0, &frame->uc.tuc_flags);
4788 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4789 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004790 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004791 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004792 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4793 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004794 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4795 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004796 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004797 }
4798
4799 /* Set up to return from userspace. If provided, use a stub
4800 already in userspace. */
4801 if (ka->sa_flags & TARGET_SA_RESTORER) {
4802 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4803 } else {
4804 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004805 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4806 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004807 }
4808
4809 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004810 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004811
4812 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004813 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004814 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4815
4816 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004817 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4818 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004819 return;
4820
4821give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004822 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004823}
4824
4825static int
Andreas Färber05390242012-02-25 03:37:53 +01004826restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004827{
4828 int err = 0;
4829 int i;
4830
4831 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004832 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004833 }
4834
Riku Voipio1d8b5122014-04-23 10:26:05 +03004835 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004836 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4837 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004838 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004839 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4840
4841 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004842 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004843 }
4844 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004845 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004846 }
4847
4848 return err;
4849}
4850
Andreas Färber05390242012-02-25 03:37:53 +01004851long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004852{
4853 sigframe *frame;
4854 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004855 target_sigset_t target_set;
4856 sigset_t set;
4857
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004858 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004859 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4860 goto badframe;
4861 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004862 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004863
4864 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004865 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004866
4867 if (restore_sigregs(env, &frame->sregs)) {
4868 goto badframe;
4869 }
4870
4871 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004872 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004873
4874badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004875 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004876 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004877}
4878
Andreas Färber05390242012-02-25 03:37:53 +01004879long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004880{
4881 rt_sigframe *frame;
4882 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004883 sigset_t set;
4884
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004885 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004886 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4887 goto badframe;
4888 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004889 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004890
Peter Maydell9eede5b2016-05-27 15:51:46 +01004891 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004892
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004893 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004894 goto badframe;
4895 }
4896
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004897 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004898 get_sp_from_cpustate(env)) == -EFAULT) {
4899 goto badframe;
4900 }
4901 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004902 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004903
4904badframe:
4905 unlock_user_struct(frame, frame_addr, 0);
4906 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004907 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004908}
4909
Tom Musta61e75fe2014-06-30 08:13:38 -05004910#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004911
4912/* Size of dummy stack frame allocated when calling signal handler.
4913 See arch/powerpc/include/asm/ptrace.h. */
4914#if defined(TARGET_PPC64)
4915#define SIGNAL_FRAMESIZE 128
4916#else
4917#define SIGNAL_FRAMESIZE 64
4918#endif
4919
Tom Musta61e75fe2014-06-30 08:13:38 -05004920/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4921 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4922struct target_mcontext {
4923 target_ulong mc_gregs[48];
4924 /* Includes fpscr. */
4925 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004926#if defined(TARGET_PPC64)
4927 /* Pointer to the vector regs */
4928 target_ulong v_regs;
4929#else
Tom Musta61e75fe2014-06-30 08:13:38 -05004930 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004931#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05004932 /* We need to handle Altivec and SPE at the same time, which no
4933 kernel needs to do. Fortunately, the kernel defines this bit to
4934 be Altivec-register-large all the time, rather than trying to
4935 twiddle it based on the specific platform. */
4936 union {
4937 /* SPE vector registers. One extra for SPEFSCR. */
4938 uint32_t spe[33];
4939 /* Altivec vector registers. The packing of VSCR and VRSAVE
4940 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004941 them apart; PPC32 stuffs them together.
4942 We also need to account for the VSX registers on PPC64
4943 */
Tom Musta61e75fe2014-06-30 08:13:38 -05004944#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004945#define QEMU_NVRREG (34 + 16)
4946 /* On ppc64, this mcontext structure is naturally *unaligned*,
4947 * or rather it is aligned on a 8 bytes boundary but not on
4948 * a 16 bytes one. This pad fixes it up. This is also why the
4949 * vector regs are referenced by the v_regs pointer above so
4950 * any amount of padding can be added here
4951 */
4952 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05004953#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004954 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05004955#define QEMU_NVRREG 33
4956#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004957 /* We cannot use ppc_avr_t here as we do *not* want the implied
4958 * 16-bytes alignment that would result from it. This would have
4959 * the effect of making the whole struct target_mcontext aligned
4960 * which breaks the layout of struct target_ucontext on ppc64.
4961 */
4962 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05004963#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004964 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05004965};
4966
Nathan Froydbcd49332009-05-12 19:13:18 -07004967/* See arch/powerpc/include/asm/sigcontext.h. */
4968struct target_sigcontext {
4969 target_ulong _unused[4];
4970 int32_t signal;
4971#if defined(TARGET_PPC64)
4972 int32_t pad0;
4973#endif
4974 target_ulong handler;
4975 target_ulong oldmask;
4976 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004977#if defined(TARGET_PPC64)
4978 struct target_mcontext mcontext;
4979#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004980};
4981
4982/* Indices for target_mcontext.mc_gregs, below.
4983 See arch/powerpc/include/asm/ptrace.h for details. */
4984enum {
4985 TARGET_PT_R0 = 0,
4986 TARGET_PT_R1 = 1,
4987 TARGET_PT_R2 = 2,
4988 TARGET_PT_R3 = 3,
4989 TARGET_PT_R4 = 4,
4990 TARGET_PT_R5 = 5,
4991 TARGET_PT_R6 = 6,
4992 TARGET_PT_R7 = 7,
4993 TARGET_PT_R8 = 8,
4994 TARGET_PT_R9 = 9,
4995 TARGET_PT_R10 = 10,
4996 TARGET_PT_R11 = 11,
4997 TARGET_PT_R12 = 12,
4998 TARGET_PT_R13 = 13,
4999 TARGET_PT_R14 = 14,
5000 TARGET_PT_R15 = 15,
5001 TARGET_PT_R16 = 16,
5002 TARGET_PT_R17 = 17,
5003 TARGET_PT_R18 = 18,
5004 TARGET_PT_R19 = 19,
5005 TARGET_PT_R20 = 20,
5006 TARGET_PT_R21 = 21,
5007 TARGET_PT_R22 = 22,
5008 TARGET_PT_R23 = 23,
5009 TARGET_PT_R24 = 24,
5010 TARGET_PT_R25 = 25,
5011 TARGET_PT_R26 = 26,
5012 TARGET_PT_R27 = 27,
5013 TARGET_PT_R28 = 28,
5014 TARGET_PT_R29 = 29,
5015 TARGET_PT_R30 = 30,
5016 TARGET_PT_R31 = 31,
5017 TARGET_PT_NIP = 32,
5018 TARGET_PT_MSR = 33,
5019 TARGET_PT_ORIG_R3 = 34,
5020 TARGET_PT_CTR = 35,
5021 TARGET_PT_LNK = 36,
5022 TARGET_PT_XER = 37,
5023 TARGET_PT_CCR = 38,
5024 /* Yes, there are two registers with #39. One is 64-bit only. */
5025 TARGET_PT_MQ = 39,
5026 TARGET_PT_SOFTE = 39,
5027 TARGET_PT_TRAP = 40,
5028 TARGET_PT_DAR = 41,
5029 TARGET_PT_DSISR = 42,
5030 TARGET_PT_RESULT = 43,
5031 TARGET_PT_REGS_COUNT = 44
5032};
5033
Nathan Froydbcd49332009-05-12 19:13:18 -07005034
5035struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005036 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005037 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005038 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005039#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005040 int32_t tuc_pad[7];
5041 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005042 points to uc_mcontext field */
5043#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005044 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005045#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005046 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005047 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005048#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005049 int32_t tuc_maskext[30];
5050 int32_t tuc_pad2[3];
5051 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005052#endif
5053};
5054
5055/* See arch/powerpc/kernel/signal_32.c. */
5056struct target_sigframe {
5057 struct target_sigcontext sctx;
5058 struct target_mcontext mctx;
5059 int32_t abigap[56];
5060};
5061
Tom Musta61e75fe2014-06-30 08:13:38 -05005062#if defined(TARGET_PPC64)
5063
5064#define TARGET_TRAMP_SIZE 6
5065
5066struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005067 /* sys_rt_sigreturn requires the ucontext be the first field */
5068 struct target_ucontext uc;
5069 target_ulong _unused[2];
5070 uint32_t trampoline[TARGET_TRAMP_SIZE];
5071 target_ulong pinfo; /* struct siginfo __user * */
5072 target_ulong puc; /* void __user * */
5073 struct target_siginfo info;
5074 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5075 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005076} __attribute__((aligned(16)));
5077
5078#else
5079
Nathan Froydbcd49332009-05-12 19:13:18 -07005080struct target_rt_sigframe {
5081 struct target_siginfo info;
5082 struct target_ucontext uc;
5083 int32_t abigap[56];
5084};
5085
Tom Musta61e75fe2014-06-30 08:13:38 -05005086#endif
5087
Tom Musta8d6ab332014-06-30 08:13:39 -05005088#if defined(TARGET_PPC64)
5089
5090struct target_func_ptr {
5091 target_ulong entry;
5092 target_ulong toc;
5093};
5094
5095#endif
5096
Nathan Froydbcd49332009-05-12 19:13:18 -07005097/* We use the mc_pad field for the signal return trampoline. */
5098#define tramp mc_pad
5099
5100/* See arch/powerpc/kernel/signal.c. */
5101static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005102 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005103 int frame_size)
5104{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005105 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005106
5107 oldsp = env->gpr[1];
5108
5109 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005110 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005111 oldsp = (target_sigaltstack_used.ss_sp
5112 + target_sigaltstack_used.ss_size);
5113 }
5114
Eduardo Habkost9be38592016-06-13 18:57:58 -03005115 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005116}
5117
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005118#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5119 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5120#define PPC_VEC_HI 0
5121#define PPC_VEC_LO 1
5122#else
5123#define PPC_VEC_HI 1
5124#define PPC_VEC_LO 0
5125#endif
5126
5127
Tom Musta76781082014-06-30 08:13:37 -05005128static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005129{
5130 target_ulong msr = env->msr;
5131 int i;
5132 target_ulong ccr = 0;
5133
5134 /* In general, the kernel attempts to be intelligent about what it
5135 needs to save for Altivec/FP/SPE registers. We don't care that
5136 much, so we just go ahead and save everything. */
5137
5138 /* Save general registers. */
5139 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005140 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005141 }
Riku Voipioc650c002014-04-23 13:53:45 +03005142 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5143 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5144 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5145 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005146
5147 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5148 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5149 }
Riku Voipioc650c002014-04-23 13:53:45 +03005150 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005151
5152 /* Save Altivec registers if necessary. */
5153 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005154 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005155 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005156 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005157 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005158
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005159 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5160 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005161 }
5162 /* Set MSR_VR in the saved MSR value to indicate that
5163 frame->mc_vregs contains valid data. */
5164 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005165#if defined(TARGET_PPC64)
5166 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5167 /* 64-bit needs to put a pointer to the vectors in the frame */
5168 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5169#else
5170 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5171#endif
5172 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5173 }
5174
5175 /* Save VSX second halves */
5176 if (env->insns_flags2 & PPC2_VSX) {
5177 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5178 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5179 __put_user(env->vsr[i], &vsregs[i]);
5180 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005181 }
5182
5183 /* Save floating point registers. */
5184 if (env->insns_flags & PPC_FLOAT) {
5185 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005186 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005187 }
Riku Voipioc650c002014-04-23 13:53:45 +03005188 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005189 }
5190
5191 /* Save SPE registers. The kernel only saves the high half. */
5192 if (env->insns_flags & PPC_SPE) {
5193#if defined(TARGET_PPC64)
5194 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005195 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005196 }
5197#else
5198 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005199 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005200 }
5201#endif
5202 /* Set MSR_SPE in the saved MSR value to indicate that
5203 frame->mc_vregs contains valid data. */
5204 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005205 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005206 }
5207
5208 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005209 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005210}
Nathan Froydbcd49332009-05-12 19:13:18 -07005211
Tom Musta76781082014-06-30 08:13:37 -05005212static void encode_trampoline(int sigret, uint32_t *tramp)
5213{
Nathan Froydbcd49332009-05-12 19:13:18 -07005214 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5215 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005216 __put_user(0x38000000 | sigret, &tramp[0]);
5217 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005218 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005219}
5220
Riku Voipioc650c002014-04-23 13:53:45 +03005221static void restore_user_regs(CPUPPCState *env,
5222 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005223{
5224 target_ulong save_r2 = 0;
5225 target_ulong msr;
5226 target_ulong ccr;
5227
5228 int i;
5229
5230 if (!sig) {
5231 save_r2 = env->gpr[2];
5232 }
5233
5234 /* Restore general registers. */
5235 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005236 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005237 }
Riku Voipioc650c002014-04-23 13:53:45 +03005238 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5239 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5240 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5241 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5242 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005243
5244 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5245 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5246 }
5247
5248 if (!sig) {
5249 env->gpr[2] = save_r2;
5250 }
5251 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005252 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005253
5254 /* If doing signal return, restore the previous little-endian mode. */
5255 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005256 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005257
5258 /* Restore Altivec registers if necessary. */
5259 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005260 ppc_avr_t *v_regs;
5261 uint32_t *vrsave;
5262#if defined(TARGET_PPC64)
5263 uint64_t v_addr;
5264 /* 64-bit needs to recover the pointer to the vectors from the frame */
5265 __get_user(v_addr, &frame->v_regs);
5266 v_regs = g2h(v_addr);
5267#else
5268 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5269#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005270 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005271 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005272 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005273
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005274 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5275 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005276 }
5277 /* Set MSR_VEC in the saved MSR value to indicate that
5278 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005279#if defined(TARGET_PPC64)
5280 vrsave = (uint32_t *)&v_regs[33];
5281#else
5282 vrsave = (uint32_t *)&v_regs[32];
5283#endif
5284 __get_user(env->spr[SPR_VRSAVE], vrsave);
5285 }
5286
5287 /* Restore VSX second halves */
5288 if (env->insns_flags2 & PPC2_VSX) {
5289 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5290 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5291 __get_user(env->vsr[i], &vsregs[i]);
5292 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005293 }
5294
5295 /* Restore floating point registers. */
5296 if (env->insns_flags & PPC_FLOAT) {
5297 uint64_t fpscr;
5298 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005299 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005300 }
Riku Voipioc650c002014-04-23 13:53:45 +03005301 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005302 env->fpscr = (uint32_t) fpscr;
5303 }
5304
5305 /* Save SPE registers. The kernel only saves the high half. */
5306 if (env->insns_flags & PPC_SPE) {
5307#if defined(TARGET_PPC64)
5308 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5309 uint32_t hi;
5310
Riku Voipioc650c002014-04-23 13:53:45 +03005311 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005312 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5313 }
5314#else
5315 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005316 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005317 }
5318#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005319 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005320 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005321}
5322
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005323#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005324static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005325 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005326{
5327 struct target_sigframe *frame;
5328 struct target_sigcontext *sc;
5329 target_ulong frame_addr, newsp;
5330 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005331
5332 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005333 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005334 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5335 goto sigsegv;
5336 sc = &frame->sctx;
5337
Riku Voipio1d8b5122014-04-23 10:26:05 +03005338 __put_user(ka->_sa_handler, &sc->handler);
5339 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005340 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005341 __put_user(h2g(&frame->mctx), &sc->regs);
5342 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005343
5344 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005345 save_user_regs(env, &frame->mctx);
5346
5347 /* Construct the trampoline code on the stack. */
5348 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005349
5350 /* The kernel checks for the presence of a VDSO here. We don't
5351 emulate a vdso, so use a sigreturn system call. */
5352 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5353
5354 /* Turn off all fp exceptions. */
5355 env->fpscr = 0;
5356
5357 /* Create a stack frame for the caller of the handler. */
5358 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005359 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005360
5361 if (err)
5362 goto sigsegv;
5363
5364 /* Set up registers for signal handler. */
5365 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005366 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005367 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005368
Nathan Froydbcd49332009-05-12 19:13:18 -07005369 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005370
Nathan Froydbcd49332009-05-12 19:13:18 -07005371 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005372 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005373
5374 unlock_user_struct(frame, frame_addr, 1);
5375 return;
5376
5377sigsegv:
5378 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005379 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005380}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005381#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005382
5383static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005384 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005385 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005386{
5387 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005388 uint32_t *trampptr = 0;
5389 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005390 target_ulong rt_sf_addr, newsp = 0;
5391 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005392#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005393 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005394 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5395#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005396
5397 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5398 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5399 goto sigsegv;
5400
Peter Maydellf6c7a052015-01-08 12:19:48 +00005401 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005402
Riku Voipio1d8b5122014-04-23 10:26:05 +03005403 __put_user(0, &rt_sf->uc.tuc_flags);
5404 __put_user(0, &rt_sf->uc.tuc_link);
5405 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5406 &rt_sf->uc.tuc_stack.ss_sp);
5407 __put_user(sas_ss_flags(env->gpr[1]),
5408 &rt_sf->uc.tuc_stack.ss_flags);
5409 __put_user(target_sigaltstack_used.ss_size,
5410 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005411#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005412 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5413 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005414#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005415 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005416 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005417 }
5418
Tom Musta61e75fe2014-06-30 08:13:38 -05005419#if defined(TARGET_PPC64)
5420 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5421 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005422
5423 sc = &rt_sf->uc.tuc_sigcontext;
5424 __put_user(h2g(mctx), &sc->regs);
5425 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005426#else
5427 mctx = &rt_sf->uc.tuc_mcontext;
5428 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5429#endif
5430
5431 save_user_regs(env, mctx);
5432 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005433
5434 /* The kernel checks for the presence of a VDSO here. We don't
5435 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005436 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005437
5438 /* Turn off all fp exceptions. */
5439 env->fpscr = 0;
5440
5441 /* Create a stack frame for the caller of the handler. */
5442 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005443 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005444
5445 if (err)
5446 goto sigsegv;
5447
5448 /* Set up registers for signal handler. */
5449 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005450 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005451 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5452 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5453 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005454
5455#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005456 if (get_ppc64_abi(image) < 2) {
5457 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5458 struct target_func_ptr *handler =
5459 (struct target_func_ptr *)g2h(ka->_sa_handler);
5460 env->nip = tswapl(handler->entry);
5461 env->gpr[2] = tswapl(handler->toc);
5462 } else {
5463 /* ELFv2 PPC64 function pointers are entry points, but R12
5464 * must also be set */
5465 env->nip = tswapl((target_ulong) ka->_sa_handler);
5466 env->gpr[12] = env->nip;
5467 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005468#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005469 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005470#endif
5471
Nathan Froydbcd49332009-05-12 19:13:18 -07005472 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005473 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005474
5475 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5476 return;
5477
5478sigsegv:
5479 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005480 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005481
5482}
5483
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005484#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005485long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005486{
5487 struct target_sigcontext *sc = NULL;
5488 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005489 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005490 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005491 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005492
5493 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5494 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5495 goto sigsegv;
5496
5497#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005498 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005499#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005500 __get_user(set.sig[0], &sc->oldmask);
5501 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005502#endif
5503 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005504 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005505
Riku Voipiof5f601a2014-04-23 13:00:17 +03005506 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005507 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5508 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005509 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005510
5511 unlock_user_struct(sr, sr_addr, 1);
5512 unlock_user_struct(sc, sc_addr, 1);
5513 return -TARGET_QEMU_ESIGRETURN;
5514
5515sigsegv:
5516 unlock_user_struct(sr, sr_addr, 1);
5517 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005518 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005519 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005520}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005521#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005522
5523/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005524static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005525{
5526 struct target_mcontext *mcp;
5527 target_ulong mcp_addr;
5528 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005529 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005530
Aurelien Jarno60e99242010-03-29 02:12:51 +02005531 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005532 sizeof (set)))
5533 return 1;
5534
Tom Musta19774ec2014-06-30 08:13:40 -05005535#if defined(TARGET_PPC64)
5536 mcp_addr = h2g(ucp) +
5537 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5538#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005539 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005540#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005541
5542 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5543 return 1;
5544
5545 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005546 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005547 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005548
5549 unlock_user_struct(mcp, mcp_addr, 1);
5550 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005551}
5552
Andreas Färber05390242012-02-25 03:37:53 +01005553long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005554{
5555 struct target_rt_sigframe *rt_sf = NULL;
5556 target_ulong rt_sf_addr;
5557
5558 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5559 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5560 goto sigsegv;
5561
5562 if (do_setcontext(&rt_sf->uc, env, 1))
5563 goto sigsegv;
5564
5565 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005566 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005567 0, env->gpr[1]);
5568
5569 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5570 return -TARGET_QEMU_ESIGRETURN;
5571
5572sigsegv:
5573 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005574 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005575 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005576}
5577
Laurent Vivier492a8742009-08-03 16:12:17 +02005578#elif defined(TARGET_M68K)
5579
5580struct target_sigcontext {
5581 abi_ulong sc_mask;
5582 abi_ulong sc_usp;
5583 abi_ulong sc_d0;
5584 abi_ulong sc_d1;
5585 abi_ulong sc_a0;
5586 abi_ulong sc_a1;
5587 unsigned short sc_sr;
5588 abi_ulong sc_pc;
5589};
5590
5591struct target_sigframe
5592{
5593 abi_ulong pretcode;
5594 int sig;
5595 int code;
5596 abi_ulong psc;
5597 char retcode[8];
5598 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5599 struct target_sigcontext sc;
5600};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005601
Anthony Liguoric227f092009-10-01 16:12:16 -05005602typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005603#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005604typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005605
5606typedef struct target_fpregset {
5607 int f_fpcntl[3];
5608 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005609} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005610
5611struct target_mcontext {
5612 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005613 target_gregset_t gregs;
5614 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005615};
5616
5617#define TARGET_MCONTEXT_VERSION 2
5618
5619struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005620 abi_ulong tuc_flags;
5621 abi_ulong tuc_link;
5622 target_stack_t tuc_stack;
5623 struct target_mcontext tuc_mcontext;
5624 abi_long tuc_filler[80];
5625 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005626};
5627
5628struct target_rt_sigframe
5629{
5630 abi_ulong pretcode;
5631 int sig;
5632 abi_ulong pinfo;
5633 abi_ulong puc;
5634 char retcode[8];
5635 struct target_siginfo info;
5636 struct target_ucontext uc;
5637};
Laurent Vivier492a8742009-08-03 16:12:17 +02005638
Riku Voipio41ecc722014-04-23 11:01:00 +03005639static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005640 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005641{
Laurent Vivieref597602018-01-04 02:28:59 +01005642 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005643 __put_user(mask, &sc->sc_mask);
5644 __put_user(env->aregs[7], &sc->sc_usp);
5645 __put_user(env->dregs[0], &sc->sc_d0);
5646 __put_user(env->dregs[1], &sc->sc_d1);
5647 __put_user(env->aregs[0], &sc->sc_a0);
5648 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005649 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005650 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005651}
5652
Riku Voipio016d2e12014-04-23 11:19:48 +03005653static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005654restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005655{
Laurent Vivier492a8742009-08-03 16:12:17 +02005656 int temp;
5657
Riku Voipio1d8b5122014-04-23 10:26:05 +03005658 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005659 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005660 __get_user(env->dregs[1], &sc->sc_d1);
5661 __get_user(env->aregs[0], &sc->sc_a0);
5662 __get_user(env->aregs[1], &sc->sc_a1);
5663 __get_user(env->pc, &sc->sc_pc);
5664 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005665 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005666}
5667
5668/*
5669 * Determine which stack to use..
5670 */
5671static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005672get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5673 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005674{
5675 unsigned long sp;
5676
5677 sp = regs->aregs[7];
5678
5679 /* This is the X/Open sanctioned signal stack switching. */
5680 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5681 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5682 }
5683
5684 return ((sp - frame_size) & -8UL);
5685}
5686
5687static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005688 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005689{
5690 struct target_sigframe *frame;
5691 abi_ulong frame_addr;
5692 abi_ulong retcode_addr;
5693 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005694 int i;
5695
5696 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005697 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005698 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5699 goto give_sigsegv;
5700 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005701
Riku Voipio1d8b5122014-04-23 10:26:05 +03005702 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005703
5704 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005705 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005706
Riku Voipio41ecc722014-04-23 11:01:00 +03005707 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005708
5709 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005710 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005711 }
5712
5713 /* Set up to return from userspace. */
5714
5715 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005716 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005717
5718 /* moveq #,d0; trap #0 */
5719
Riku Voipio1d8b5122014-04-23 10:26:05 +03005720 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005721 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005722
Laurent Vivier492a8742009-08-03 16:12:17 +02005723 /* Set up to return from userspace */
5724
5725 env->aregs[7] = frame_addr;
5726 env->pc = ka->_sa_handler;
5727
5728 unlock_user_struct(frame, frame_addr, 1);
5729 return;
5730
5731give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005732 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005733}
5734
Laurent Vivieree46a462017-09-14 18:35:05 +02005735static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5736 CPUM68KState *env)
5737{
5738 int i;
5739 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5740
5741 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
5742 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
5743 /* fpiar is not emulated */
5744
5745 for (i = 0; i < 8; i++) {
5746 uint32_t high = env->fregs[i].d.high << 16;
5747 __put_user(high, &fpregs->f_fpregs[i * 3]);
5748 __put_user(env->fregs[i].d.low,
5749 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5750 }
5751}
5752
Laurent Vivier71811552009-08-03 16:12:18 +02005753static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005754 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005755{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005756 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01005757 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02005758
Riku Voipio1d8b5122014-04-23 10:26:05 +03005759 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5760 __put_user(env->dregs[0], &gregs[0]);
5761 __put_user(env->dregs[1], &gregs[1]);
5762 __put_user(env->dregs[2], &gregs[2]);
5763 __put_user(env->dregs[3], &gregs[3]);
5764 __put_user(env->dregs[4], &gregs[4]);
5765 __put_user(env->dregs[5], &gregs[5]);
5766 __put_user(env->dregs[6], &gregs[6]);
5767 __put_user(env->dregs[7], &gregs[7]);
5768 __put_user(env->aregs[0], &gregs[8]);
5769 __put_user(env->aregs[1], &gregs[9]);
5770 __put_user(env->aregs[2], &gregs[10]);
5771 __put_user(env->aregs[3], &gregs[11]);
5772 __put_user(env->aregs[4], &gregs[12]);
5773 __put_user(env->aregs[5], &gregs[13]);
5774 __put_user(env->aregs[6], &gregs[14]);
5775 __put_user(env->aregs[7], &gregs[15]);
5776 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005777 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005778
Laurent Vivieree46a462017-09-14 18:35:05 +02005779 target_rt_save_fpu_state(uc, env);
5780
Riku Voipio1d8b5122014-04-23 10:26:05 +03005781 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005782}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005783
Laurent Vivieree46a462017-09-14 18:35:05 +02005784static inline void target_rt_restore_fpu_state(CPUM68KState *env,
5785 struct target_ucontext *uc)
5786{
5787 int i;
5788 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5789 uint32_t fpcr;
5790
5791 __get_user(fpcr, &fpregs->f_fpcntl[0]);
5792 cpu_m68k_set_fpcr(env, fpcr);
5793 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
5794 /* fpiar is not emulated */
5795
5796 for (i = 0; i < 8; i++) {
5797 uint32_t high;
5798 __get_user(high, &fpregs->f_fpregs[i * 3]);
5799 env->fregs[i].d.high = high >> 16;
5800 __get_user(env->fregs[i].d.low,
5801 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5802 }
5803}
5804
Andreas Färber05390242012-02-25 03:37:53 +01005805static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005806 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005807{
5808 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005809 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005810
Riku Voipio1d8b5122014-04-23 10:26:05 +03005811 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005812 if (temp != TARGET_MCONTEXT_VERSION)
5813 goto badframe;
5814
5815 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005816 __get_user(env->dregs[0], &gregs[0]);
5817 __get_user(env->dregs[1], &gregs[1]);
5818 __get_user(env->dregs[2], &gregs[2]);
5819 __get_user(env->dregs[3], &gregs[3]);
5820 __get_user(env->dregs[4], &gregs[4]);
5821 __get_user(env->dregs[5], &gregs[5]);
5822 __get_user(env->dregs[6], &gregs[6]);
5823 __get_user(env->dregs[7], &gregs[7]);
5824 __get_user(env->aregs[0], &gregs[8]);
5825 __get_user(env->aregs[1], &gregs[9]);
5826 __get_user(env->aregs[2], &gregs[10]);
5827 __get_user(env->aregs[3], &gregs[11]);
5828 __get_user(env->aregs[4], &gregs[12]);
5829 __get_user(env->aregs[5], &gregs[13]);
5830 __get_user(env->aregs[6], &gregs[14]);
5831 __get_user(env->aregs[7], &gregs[15]);
5832 __get_user(env->pc, &gregs[16]);
5833 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005834 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02005835
Laurent Vivieree46a462017-09-14 18:35:05 +02005836 target_rt_restore_fpu_state(env, uc);
5837
Riku Voipio1d8b5122014-04-23 10:26:05 +03005838 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005839
5840badframe:
5841 return 1;
5842}
5843
Laurent Vivier492a8742009-08-03 16:12:17 +02005844static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005845 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005846 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005847{
Laurent Vivier71811552009-08-03 16:12:18 +02005848 struct target_rt_sigframe *frame;
5849 abi_ulong frame_addr;
5850 abi_ulong retcode_addr;
5851 abi_ulong info_addr;
5852 abi_ulong uc_addr;
5853 int err = 0;
5854 int i;
5855
5856 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005857 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005858 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5859 goto give_sigsegv;
5860 }
Laurent Vivier71811552009-08-03 16:12:18 +02005861
Riku Voipio1d8b5122014-04-23 10:26:05 +03005862 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005863
5864 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005865 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005866
5867 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005868 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005869
Peter Maydellf6c7a052015-01-08 12:19:48 +00005870 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005871
5872 /* Create the ucontext */
5873
Riku Voipio1d8b5122014-04-23 10:26:05 +03005874 __put_user(0, &frame->uc.tuc_flags);
5875 __put_user(0, &frame->uc.tuc_link);
5876 __put_user(target_sigaltstack_used.ss_sp,
5877 &frame->uc.tuc_stack.ss_sp);
5878 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005879 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005880 __put_user(target_sigaltstack_used.ss_size,
5881 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005882 err |= target_rt_setup_ucontext(&frame->uc, env);
5883
5884 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005885 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005886
5887 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005888 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005889 }
5890
5891 /* Set up to return from userspace. */
5892
5893 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005894 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005895
5896 /* moveq #,d0; notb d0; trap #0 */
5897
Riku Voipio1d8b5122014-04-23 10:26:05 +03005898 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005899 (uint32_t *)(frame->retcode + 0));
5900 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005901
5902 if (err)
5903 goto give_sigsegv;
5904
5905 /* Set up to return from userspace */
5906
5907 env->aregs[7] = frame_addr;
5908 env->pc = ka->_sa_handler;
5909
5910 unlock_user_struct(frame, frame_addr, 1);
5911 return;
5912
5913give_sigsegv:
5914 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005915 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005916}
5917
Andreas Färber05390242012-02-25 03:37:53 +01005918long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005919{
5920 struct target_sigframe *frame;
5921 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005922 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005923 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005924 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005925
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005926 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005927 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5928 goto badframe;
5929
5930 /* set blocked signals */
5931
Riku Voipiof5f601a2014-04-23 13:00:17 +03005932 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005933
5934 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005935 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005936 }
5937
5938 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005939 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005940
5941 /* restore registers */
5942
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005943 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005944
5945 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005946 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005947
5948badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005949 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005950 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005951}
5952
Andreas Färber05390242012-02-25 03:37:53 +01005953long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005954{
Laurent Vivier71811552009-08-03 16:12:18 +02005955 struct target_rt_sigframe *frame;
5956 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02005957 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005958
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005959 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005960 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5961 goto badframe;
5962
Michael Karcher59ebb6e2017-02-25 12:05:17 +01005963 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005964 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005965
5966 /* restore registers */
5967
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005968 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005969 goto badframe;
5970
5971 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005972 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005973 0, get_sp_from_cpustate(env)) == -EFAULT)
5974 goto badframe;
5975
5976 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005977 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005978
5979badframe:
5980 unlock_user_struct(frame, frame_addr, 0);
5981 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005982 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005983}
5984
Richard Henderson6049f4f2009-12-27 18:30:03 -08005985#elif defined(TARGET_ALPHA)
5986
5987struct target_sigcontext {
5988 abi_long sc_onstack;
5989 abi_long sc_mask;
5990 abi_long sc_pc;
5991 abi_long sc_ps;
5992 abi_long sc_regs[32];
5993 abi_long sc_ownedfp;
5994 abi_long sc_fpregs[32];
5995 abi_ulong sc_fpcr;
5996 abi_ulong sc_fp_control;
5997 abi_ulong sc_reserved1;
5998 abi_ulong sc_reserved2;
5999 abi_ulong sc_ssize;
6000 abi_ulong sc_sbase;
6001 abi_ulong sc_traparg_a0;
6002 abi_ulong sc_traparg_a1;
6003 abi_ulong sc_traparg_a2;
6004 abi_ulong sc_fp_trap_pc;
6005 abi_ulong sc_fp_trigger_sum;
6006 abi_ulong sc_fp_trigger_inst;
6007};
6008
6009struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006010 abi_ulong tuc_flags;
6011 abi_ulong tuc_link;
6012 abi_ulong tuc_osf_sigmask;
6013 target_stack_t tuc_stack;
6014 struct target_sigcontext tuc_mcontext;
6015 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006016};
6017
6018struct target_sigframe {
6019 struct target_sigcontext sc;
6020 unsigned int retcode[3];
6021};
6022
6023struct target_rt_sigframe {
6024 target_siginfo_t info;
6025 struct target_ucontext uc;
6026 unsigned int retcode[3];
6027};
6028
6029#define INSN_MOV_R30_R16 0x47fe0410
6030#define INSN_LDI_R0 0x201f0000
6031#define INSN_CALLSYS 0x00000083
6032
Riku Voipio41ecc722014-04-23 11:01:00 +03006033static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006034 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006035{
Riku Voipio41ecc722014-04-23 11:01:00 +03006036 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006037
Riku Voipio1d8b5122014-04-23 10:26:05 +03006038 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6039 __put_user(set->sig[0], &sc->sc_mask);
6040 __put_user(env->pc, &sc->sc_pc);
6041 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006042
6043 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006044 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006045 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006046 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006047
6048 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006049 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006050 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006051 __put_user(0, &sc->sc_fpregs[31]);
6052 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006053
Riku Voipio1d8b5122014-04-23 10:26:05 +03006054 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6055 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6056 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006057}
6058
Riku Voipio016d2e12014-04-23 11:19:48 +03006059static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006060 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006061{
6062 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006063 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006064
Riku Voipio1d8b5122014-04-23 10:26:05 +03006065 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006066
6067 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006068 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006069 }
6070 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006071 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006072 }
6073
Riku Voipio1d8b5122014-04-23 10:26:05 +03006074 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006075 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006076}
6077
6078static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006079 CPUAlphaState *env,
6080 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006081{
6082 abi_ulong sp = env->ir[IR_SP];
6083
6084 /* This is the X/Open sanctioned signal stack switching. */
6085 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6086 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6087 }
6088 return (sp - framesize) & -32;
6089}
6090
6091static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006092 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006093{
6094 abi_ulong frame_addr, r26;
6095 struct target_sigframe *frame;
6096 int err = 0;
6097
6098 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006099 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006100 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6101 goto give_sigsegv;
6102 }
6103
Riku Voipio41ecc722014-04-23 11:01:00 +03006104 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006105
6106 if (ka->sa_restorer) {
6107 r26 = ka->sa_restorer;
6108 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006109 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6110 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6111 &frame->retcode[1]);
6112 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006113 /* imb() */
6114 r26 = frame_addr;
6115 }
6116
6117 unlock_user_struct(frame, frame_addr, 1);
6118
6119 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006120give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006121 force_sigsegv(sig);
6122 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006123 }
6124
6125 env->ir[IR_RA] = r26;
6126 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6127 env->ir[IR_A0] = sig;
6128 env->ir[IR_A1] = 0;
6129 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6130 env->ir[IR_SP] = frame_addr;
6131}
6132
6133static void setup_rt_frame(int sig, struct target_sigaction *ka,
6134 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006135 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006136{
6137 abi_ulong frame_addr, r26;
6138 struct target_rt_sigframe *frame;
6139 int i, err = 0;
6140
6141 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006142 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006143 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6144 goto give_sigsegv;
6145 }
6146
Peter Maydellf6c7a052015-01-08 12:19:48 +00006147 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006148
Riku Voipio1d8b5122014-04-23 10:26:05 +03006149 __put_user(0, &frame->uc.tuc_flags);
6150 __put_user(0, &frame->uc.tuc_link);
6151 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6152 __put_user(target_sigaltstack_used.ss_sp,
6153 &frame->uc.tuc_stack.ss_sp);
6154 __put_user(sas_ss_flags(env->ir[IR_SP]),
6155 &frame->uc.tuc_stack.ss_flags);
6156 __put_user(target_sigaltstack_used.ss_size,
6157 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006158 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006159 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006160 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006161 }
6162
6163 if (ka->sa_restorer) {
6164 r26 = ka->sa_restorer;
6165 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006166 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6167 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6168 &frame->retcode[1]);
6169 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006170 /* imb(); */
6171 r26 = frame_addr;
6172 }
6173
6174 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006175give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006176 force_sigsegv(sig);
6177 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006178 }
6179
6180 env->ir[IR_RA] = r26;
6181 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6182 env->ir[IR_A0] = sig;
6183 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6184 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6185 env->ir[IR_SP] = frame_addr;
6186}
6187
Andreas Färber05390242012-02-25 03:37:53 +01006188long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006189{
6190 struct target_sigcontext *sc;
6191 abi_ulong sc_addr = env->ir[IR_A0];
6192 target_sigset_t target_set;
6193 sigset_t set;
6194
6195 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6196 goto badframe;
6197 }
6198
6199 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006200 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006201
6202 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006203 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006204
Riku Voipio016d2e12014-04-23 11:19:48 +03006205 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006206 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006207 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006208
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006209badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006210 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006211 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006212}
6213
Andreas Färber05390242012-02-25 03:37:53 +01006214long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006215{
6216 abi_ulong frame_addr = env->ir[IR_A0];
6217 struct target_rt_sigframe *frame;
6218 sigset_t set;
6219
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006220 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006221 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6222 goto badframe;
6223 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006224 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006225 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006226
Riku Voipio016d2e12014-04-23 11:19:48 +03006227 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006228 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006229 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006230 0, env->ir[IR_SP]) == -EFAULT) {
6231 goto badframe;
6232 }
6233
6234 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006235 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006236
6237
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006238badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006239 unlock_user_struct(frame, frame_addr, 0);
6240 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006241 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006242}
6243
Chen Gangbf0f60a2015-09-27 08:10:18 +08006244#elif defined(TARGET_TILEGX)
6245
6246struct target_sigcontext {
6247 union {
6248 /* General-purpose registers. */
6249 abi_ulong gregs[56];
6250 struct {
6251 abi_ulong __gregs[53];
6252 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6253 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6254 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6255 };
6256 };
6257 abi_ulong pc; /* Program counter. */
6258 abi_ulong ics; /* In Interrupt Critical Section? */
6259 abi_ulong faultnum; /* Fault number. */
6260 abi_ulong pad[5];
6261};
6262
6263struct target_ucontext {
6264 abi_ulong tuc_flags;
6265 abi_ulong tuc_link;
6266 target_stack_t tuc_stack;
6267 struct target_sigcontext tuc_mcontext;
6268 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6269};
6270
6271struct target_rt_sigframe {
6272 unsigned char save_area[16]; /* caller save area */
6273 struct target_siginfo info;
6274 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006275 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006276};
6277
Chen Gangf1d9d102016-03-29 21:53:49 +08006278#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6279#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6280
6281
Chen Gangbf0f60a2015-09-27 08:10:18 +08006282static void setup_sigcontext(struct target_sigcontext *sc,
6283 CPUArchState *env, int signo)
6284{
6285 int i;
6286
6287 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6288 __put_user(env->regs[i], &sc->gregs[i]);
6289 }
6290
6291 __put_user(env->pc, &sc->pc);
6292 __put_user(0, &sc->ics);
6293 __put_user(signo, &sc->faultnum);
6294}
6295
6296static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6297{
6298 int i;
6299
6300 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6301 __get_user(env->regs[i], &sc->gregs[i]);
6302 }
6303
6304 __get_user(env->pc, &sc->pc);
6305}
6306
6307static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6308 size_t frame_size)
6309{
6310 unsigned long sp = env->regs[TILEGX_R_SP];
6311
6312 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6313 return -1UL;
6314 }
6315
6316 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6317 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6318 }
6319
6320 sp -= frame_size;
6321 sp &= -16UL;
6322 return sp;
6323}
6324
6325static void setup_rt_frame(int sig, struct target_sigaction *ka,
6326 target_siginfo_t *info,
6327 target_sigset_t *set, CPUArchState *env)
6328{
6329 abi_ulong frame_addr;
6330 struct target_rt_sigframe *frame;
6331 unsigned long restorer;
6332
6333 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006334 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006335 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6336 goto give_sigsegv;
6337 }
6338
6339 /* Always write at least the signal number for the stack backtracer. */
6340 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6341 /* At sigreturn time, restore the callee-save registers too. */
6342 tswap_siginfo(&frame->info, info);
6343 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6344 } else {
6345 __put_user(info->si_signo, &frame->info.si_signo);
6346 }
6347
6348 /* Create the ucontext. */
6349 __put_user(0, &frame->uc.tuc_flags);
6350 __put_user(0, &frame->uc.tuc_link);
6351 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6352 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6353 &frame->uc.tuc_stack.ss_flags);
6354 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6355 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6356
Chen Gangbf0f60a2015-09-27 08:10:18 +08006357 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006358 restorer = (unsigned long) ka->sa_restorer;
6359 } else {
6360 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6361 __put_user(INSN_SWINT1, &frame->retcode[1]);
6362 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006363 }
6364 env->pc = (unsigned long) ka->_sa_handler;
6365 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6366 env->regs[TILEGX_R_LR] = restorer;
6367 env->regs[0] = (unsigned long) sig;
6368 env->regs[1] = (unsigned long) &frame->info;
6369 env->regs[2] = (unsigned long) &frame->uc;
6370 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6371
6372 unlock_user_struct(frame, frame_addr, 1);
6373 return;
6374
6375give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006376 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006377}
6378
6379long do_rt_sigreturn(CPUTLGState *env)
6380{
6381 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6382 struct target_rt_sigframe *frame;
6383 sigset_t set;
6384
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006385 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006386 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6387 goto badframe;
6388 }
6389 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006390 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006391
6392 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6393 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6394 uc.tuc_stack),
6395 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6396 goto badframe;
6397 }
6398
6399 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006400 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006401
6402
6403 badframe:
6404 unlock_user_struct(frame, frame_addr, 0);
6405 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006406 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006407}
6408
Michael Clark47ae93c2018-03-03 01:31:11 +13006409#elif defined(TARGET_RISCV)
6410
6411/* Signal handler invocation must be transparent for the code being
6412 interrupted. Complete CPU (hart) state is saved on entry and restored
6413 before returning from the handler. Process sigmask is also saved to block
6414 signals while the handler is running. The handler gets its own stack,
6415 which also doubles as storage for the CPU state and sigmask.
6416
6417 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6418
6419struct target_sigcontext {
6420 abi_long pc;
6421 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6422 uint64_t fpr[32];
6423 uint32_t fcsr;
6424}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6425
6426struct target_ucontext {
6427 unsigned long uc_flags;
6428 struct target_ucontext *uc_link;
6429 target_stack_t uc_stack;
6430 struct target_sigcontext uc_mcontext;
6431 target_sigset_t uc_sigmask;
6432};
6433
6434struct target_rt_sigframe {
6435 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6436 struct target_siginfo info;
6437 struct target_ucontext uc;
6438};
6439
6440static abi_ulong get_sigframe(struct target_sigaction *ka,
6441 CPURISCVState *regs, size_t framesize)
6442{
6443 abi_ulong sp = regs->gpr[xSP];
6444 int onsigstack = on_sig_stack(sp);
6445
6446 /* redzone */
6447 /* This is the X/Open sanctioned signal stack switching. */
6448 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6449 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6450 }
6451
6452 sp -= framesize;
6453 sp &= ~3UL; /* align sp on 4-byte boundary */
6454
6455 /* If we are on the alternate signal stack and would overflow it, don't.
6456 Return an always-bogus address instead so we will die with SIGSEGV. */
6457 if (onsigstack && !likely(on_sig_stack(sp))) {
6458 return -1L;
6459 }
6460
6461 return sp;
6462}
6463
6464static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6465{
6466 int i;
6467
6468 __put_user(env->pc, &sc->pc);
6469
6470 for (i = 1; i < 32; i++) {
6471 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6472 }
6473 for (i = 0; i < 32; i++) {
6474 __put_user(env->fpr[i], &sc->fpr[i]);
6475 }
6476
6477 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6478 __put_user(fcsr, &sc->fcsr);
6479}
6480
6481static void setup_ucontext(struct target_ucontext *uc,
6482 CPURISCVState *env, target_sigset_t *set)
6483{
6484 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6485 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6486 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6487
6488 __put_user(0, &(uc->uc_flags));
6489 __put_user(0, &(uc->uc_link));
6490
6491 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6492 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6493 __put_user(ss_size, &(uc->uc_stack.ss_size));
6494
6495 int i;
6496 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6497 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6498 }
6499
6500 setup_sigcontext(&uc->uc_mcontext, env);
6501}
6502
6503static inline void install_sigtramp(uint32_t *tramp)
6504{
6505 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6506 __put_user(0x00000073, tramp + 1); /* ecall */
6507}
6508
6509static void setup_rt_frame(int sig, struct target_sigaction *ka,
6510 target_siginfo_t *info,
6511 target_sigset_t *set, CPURISCVState *env)
6512{
6513 abi_ulong frame_addr;
6514 struct target_rt_sigframe *frame;
6515
6516 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6517 trace_user_setup_rt_frame(env, frame_addr);
6518
6519 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6520 goto badframe;
6521 }
6522
6523 setup_ucontext(&frame->uc, env, set);
6524 tswap_siginfo(&frame->info, info);
6525 install_sigtramp(frame->tramp);
6526
6527 env->pc = ka->_sa_handler;
6528 env->gpr[xSP] = frame_addr;
6529 env->gpr[xA0] = sig;
6530 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6531 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6532 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6533
6534 return;
6535
6536badframe:
6537 unlock_user_struct(frame, frame_addr, 1);
6538 if (sig == TARGET_SIGSEGV) {
6539 ka->_sa_handler = TARGET_SIG_DFL;
6540 }
6541 force_sig(TARGET_SIGSEGV);
6542}
6543
6544static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6545{
6546 int i;
6547
6548 __get_user(env->pc, &sc->pc);
6549
6550 for (i = 1; i < 32; ++i) {
6551 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6552 }
6553 for (i = 0; i < 32; ++i) {
6554 __get_user(env->fpr[i], &sc->fpr[i]);
6555 }
6556
6557 uint32_t fcsr;
6558 __get_user(fcsr, &sc->fcsr);
6559 csr_write_helper(env, fcsr, CSR_FCSR);
6560}
6561
6562static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6563{
6564 sigset_t blocked;
6565 target_sigset_t target_set;
6566 int i;
6567
6568 target_sigemptyset(&target_set);
6569 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6570 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6571 }
6572
6573 target_to_host_sigset_internal(&blocked, &target_set);
6574 set_sigmask(&blocked);
6575
6576 restore_sigcontext(env, &uc->uc_mcontext);
6577}
6578
6579long do_rt_sigreturn(CPURISCVState *env)
6580{
6581 struct target_rt_sigframe *frame;
6582 abi_ulong frame_addr;
6583
6584 frame_addr = env->gpr[xSP];
6585 trace_user_do_sigreturn(env, frame_addr);
6586 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6587 goto badframe;
6588 }
6589
6590 restore_ucontext(env, &frame->uc);
6591
6592 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6593 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6594 goto badframe;
6595 }
6596
6597 unlock_user_struct(frame, frame_addr, 0);
6598 return -TARGET_QEMU_ESIGRETURN;
6599
6600badframe:
6601 unlock_user_struct(frame, frame_addr, 0);
6602 force_sig(TARGET_SIGSEGV);
6603 return 0;
6604}
6605
Richard Henderson1659e382016-12-15 09:59:01 -08006606#elif defined(TARGET_HPPA)
6607
6608struct target_sigcontext {
6609 abi_ulong sc_flags;
6610 abi_ulong sc_gr[32];
6611 uint64_t sc_fr[32];
6612 abi_ulong sc_iasq[2];
6613 abi_ulong sc_iaoq[2];
6614 abi_ulong sc_sar;
6615};
6616
6617struct target_ucontext {
6618 abi_uint tuc_flags;
6619 abi_ulong tuc_link;
6620 target_stack_t tuc_stack;
6621 abi_uint pad[1];
6622 struct target_sigcontext tuc_mcontext;
6623 target_sigset_t tuc_sigmask;
6624};
6625
6626struct target_rt_sigframe {
6627 abi_uint tramp[9];
6628 target_siginfo_t info;
6629 struct target_ucontext uc;
6630 /* hidden location of upper halves of pa2.0 64-bit gregs */
6631};
6632
6633static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6634{
6635 int flags = 0;
6636 int i;
6637
6638 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6639
6640 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6641 /* In the gateway page, executing a syscall. */
6642 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6643 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6644 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6645 } else {
6646 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6647 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6648 }
6649 __put_user(0, &sc->sc_iasq[0]);
6650 __put_user(0, &sc->sc_iasq[1]);
6651 __put_user(flags, &sc->sc_flags);
6652
6653 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6654 for (i = 1; i < 32; ++i) {
6655 __put_user(env->gr[i], &sc->sc_gr[i]);
6656 }
6657
6658 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6659 for (i = 1; i < 32; ++i) {
6660 __put_user(env->fr[i], &sc->sc_fr[i]);
6661 }
6662
Richard Henderson35136a72017-10-10 21:19:34 -07006663 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006664}
6665
6666static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6667{
6668 target_ulong psw;
6669 int i;
6670
6671 __get_user(psw, &sc->sc_gr[0]);
6672 cpu_hppa_put_psw(env, psw);
6673
6674 for (i = 1; i < 32; ++i) {
6675 __get_user(env->gr[i], &sc->sc_gr[i]);
6676 }
6677 for (i = 0; i < 32; ++i) {
6678 __get_user(env->fr[i], &sc->sc_fr[i]);
6679 }
6680 cpu_hppa_loaded_fr0(env);
6681
6682 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6683 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006684 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006685}
6686
6687/* No, this doesn't look right, but it's copied straight from the kernel. */
6688#define PARISC_RT_SIGFRAME_SIZE32 \
6689 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6690
6691static void setup_rt_frame(int sig, struct target_sigaction *ka,
6692 target_siginfo_t *info,
6693 target_sigset_t *set, CPUArchState *env)
6694{
6695 abi_ulong frame_addr, sp, haddr;
6696 struct target_rt_sigframe *frame;
6697 int i;
6698
6699 sp = env->gr[30];
6700 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6701 if (sas_ss_flags(sp) == 0) {
6702 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6703 }
6704 }
6705 frame_addr = QEMU_ALIGN_UP(sp, 64);
6706 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6707
6708 trace_user_setup_rt_frame(env, frame_addr);
6709
6710 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6711 goto give_sigsegv;
6712 }
6713
6714 tswap_siginfo(&frame->info, info);
6715 frame->uc.tuc_flags = 0;
6716 frame->uc.tuc_link = 0;
6717
6718 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6719 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6720 &frame->uc.tuc_stack.ss_flags);
6721 __put_user(target_sigaltstack_used.ss_size,
6722 &frame->uc.tuc_stack.ss_size);
6723
6724 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6725 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6726 }
6727
6728 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6729
6730 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6731 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6732 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6733 __put_user(0x08000240, frame->tramp + 3); /* nop */
6734
6735 unlock_user_struct(frame, frame_addr, 1);
6736
6737 env->gr[2] = h2g(frame->tramp);
6738 env->gr[30] = sp;
6739 env->gr[26] = sig;
6740 env->gr[25] = h2g(&frame->info);
6741 env->gr[24] = h2g(&frame->uc);
6742
6743 haddr = ka->_sa_handler;
6744 if (haddr & 2) {
6745 /* Function descriptor. */
6746 target_ulong *fdesc, dest;
6747
6748 haddr &= -4;
6749 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
6750 goto give_sigsegv;
6751 }
6752 __get_user(dest, fdesc);
6753 __get_user(env->gr[19], fdesc + 1);
6754 unlock_user_struct(fdesc, haddr, 1);
6755 haddr = dest;
6756 }
6757 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02006758 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08006759 return;
6760
6761 give_sigsegv:
6762 force_sigsegv(sig);
6763}
6764
6765long do_rt_sigreturn(CPUArchState *env)
6766{
6767 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
6768 struct target_rt_sigframe *frame;
6769 sigset_t set;
6770
6771 trace_user_do_rt_sigreturn(env, frame_addr);
6772 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6773 goto badframe;
6774 }
6775 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
6776 set_sigmask(&set);
6777
6778 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6779 unlock_user_struct(frame, frame_addr, 0);
6780
6781 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6782 uc.tuc_stack),
6783 0, env->gr[30]) == -EFAULT) {
6784 goto badframe;
6785 }
6786
6787 unlock_user_struct(frame, frame_addr, 0);
6788 return -TARGET_QEMU_ESIGRETURN;
6789
6790 badframe:
6791 force_sig(TARGET_SIGSEGV);
6792 return -TARGET_QEMU_ESIGRETURN;
6793}
6794
bellardb346ff42003-06-15 20:05:50 +00006795#else
6796
pbrook624f7972008-05-31 16:11:38 +00006797static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006798 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006799{
6800 fprintf(stderr, "setup_frame: not implemented\n");
6801}
6802
pbrook624f7972008-05-31 16:11:38 +00006803static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006804 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006805 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006806{
6807 fprintf(stderr, "setup_rt_frame: not implemented\n");
6808}
6809
Andreas Färber9349b4f2012-03-14 01:38:32 +01006810long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006811{
6812 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006813 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006814}
6815
Andreas Färber9349b4f2012-03-14 01:38:32 +01006816long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006817{
6818 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006819 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006820}
6821
bellard66fb9762003-03-23 01:06:05 +00006822#endif
6823
Peter Maydell31efaef2016-07-06 15:09:29 +01006824static void handle_pending_signal(CPUArchState *cpu_env, int sig,
6825 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01006826{
6827 CPUState *cpu = ENV_GET_CPU(cpu_env);
6828 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006829 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01006830 target_sigset_t target_old_set;
6831 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01006832 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01006833
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006834 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00006835 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006836 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00006837
Andreas Färberdb6b81d2013-06-27 19:49:31 +02006838 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00006839 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00006840 sa = NULL;
6841 handler = TARGET_SIG_IGN;
6842 } else {
6843 sa = &sigact_table[sig - 1];
6844 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00006845 }
bellard66fb9762003-03-23 01:06:05 +00006846
Peter Maydell0cb581d2016-07-18 18:12:24 +01006847 if (do_strace) {
6848 print_taken_signal(sig, &k->info);
6849 }
6850
bellard66fb9762003-03-23 01:06:05 +00006851 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00006852 /* default handler : ignore some signal. The other are job control or fatal */
6853 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
6854 kill(getpid(),SIGSTOP);
6855 } else if (sig != TARGET_SIGCHLD &&
6856 sig != TARGET_SIGURG &&
6857 sig != TARGET_SIGWINCH &&
6858 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006859 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006860 }
6861 } else if (handler == TARGET_SIG_IGN) {
6862 /* ignore sig */
6863 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006864 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006865 } else {
bellard9de5e442003-03-23 16:49:39 +00006866 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006867 sigset_t *blocked_set;
6868
pbrook624f7972008-05-31 16:11:38 +00006869 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00006870 /* SA_NODEFER indicates that the current signal should not be
6871 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00006872 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00006873 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00006874
bellard9de5e442003-03-23 16:49:39 +00006875 /* save the previous blocked signal state to restore it at the
6876 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006877 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
6878
6879 /* block signals in the handler */
6880 blocked_set = ts->in_sigsuspend ?
6881 &ts->sigsuspend_mask : &ts->signal_mask;
6882 sigorset(&ts->signal_mask, blocked_set, &set);
6883 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00006884
bellardbc8a22c2003-03-30 21:02:40 +00006885 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00006886#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00006887 {
6888 CPUX86State *env = cpu_env;
6889 if (env->eflags & VM_MASK)
6890 save_v86_state(env);
6891 }
6892#endif
bellard9de5e442003-03-23 16:49:39 +00006893 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08006894#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10006895 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01006896 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13006897 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
6898 || defined(TARGET_RISCV)
Richard Hendersonff970902013-02-10 10:30:42 -08006899 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006900 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006901#else
pbrook624f7972008-05-31 16:11:38 +00006902 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006903 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00006904 else
pbrook624f7972008-05-31 16:11:38 +00006905 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006906#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01006907 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00006908 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01006909 }
bellard31e31b82003-02-18 22:55:36 +00006910 }
bellard31e31b82003-02-18 22:55:36 +00006911}
Peter Maydelle902d582016-05-27 15:51:44 +01006912
6913void process_pending_signals(CPUArchState *cpu_env)
6914{
6915 CPUState *cpu = ENV_GET_CPU(cpu_env);
6916 int sig;
6917 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006918 sigset_t set;
6919 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01006920
Peter Maydell3d3efba2016-05-27 15:51:49 +01006921 while (atomic_read(&ts->signal_pending)) {
6922 /* FIXME: This is not threadsafe. */
6923 sigfillset(&set);
6924 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01006925
Peter Maydell8bd37732016-07-28 16:44:45 +01006926 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006927 sig = ts->sync_signal.pending;
6928 if (sig) {
6929 /* Synchronous signals are forced,
6930 * see force_sig_info() and callers in Linux
6931 * Note that not all of our queue_signal() calls in QEMU correspond
6932 * to force_sig_info() calls in Linux (some are send_sig_info()).
6933 * However it seems like a kernel bug to me to allow the process
6934 * to block a synchronous signal since it could then just end up
6935 * looping round and round indefinitely.
6936 */
6937 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
6938 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
6939 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
6940 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
6941 }
6942
Peter Maydell31efaef2016-07-06 15:09:29 +01006943 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006944 }
6945
Peter Maydell3d3efba2016-05-27 15:51:49 +01006946 for (sig = 1; sig <= TARGET_NSIG; sig++) {
6947 blocked_set = ts->in_sigsuspend ?
6948 &ts->sigsuspend_mask : &ts->signal_mask;
6949
6950 if (ts->sigtab[sig - 1].pending &&
6951 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006952 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01006953 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01006954 /* Restart scan from the beginning, as handle_pending_signal
6955 * might have resulted in a new synchronous signal (eg SIGSEGV).
6956 */
6957 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006958 }
Peter Maydelle902d582016-05-27 15:51:44 +01006959 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01006960
6961 /* if no signal is pending, unblock signals and recheck (the act
6962 * of unblocking might cause us to take another host signal which
6963 * will set signal_pending again).
6964 */
6965 atomic_set(&ts->signal_pending, 0);
6966 ts->in_sigsuspend = 0;
6967 set = ts->signal_mask;
6968 sigdelset(&set, SIGSEGV);
6969 sigdelset(&set, SIGBUS);
6970 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01006971 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01006972 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01006973}