blob: 9399f0ec470fc5b34458eb03796b10737be44dfc [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydelldaa43742018-03-08 14:47:32 +0000256#if !defined(TARGET_OPENRISC) && !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100257/* Just set the guest's signal mask to the specified value; the
258 * caller is assumed to have called block_signals() already.
259 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100260static void set_sigmask(const sigset_t *set)
261{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100262 TaskState *ts = (TaskState *)thread_cpu->opaque;
263
264 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100265}
266#endif
267
bellard9de5e442003-03-23 16:49:39 +0000268/* siginfo conversion */
269
Anthony Liguoric227f092009-10-01 16:12:16 -0500270static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000271 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000272{
Richard Hendersona05c6402012-09-15 11:34:20 -0700273 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100274 int si_code = info->si_code;
275 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000276 tinfo->si_signo = sig;
277 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000278 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700279
Peter Maydell55d72a72016-06-13 11:22:05 +0100280 /* This memset serves two purposes:
281 * (1) ensure we don't leak random junk to the guest later
282 * (2) placate false positives from gcc about fields
283 * being used uninitialized if it chooses to inline both this
284 * function and tswap_siginfo() into host_to_target_siginfo().
285 */
286 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
287
Peter Maydella70dadc2016-05-27 15:51:59 +0100288 /* This is awkward, because we have to use a combination of
289 * the si_code and si_signo to figure out which of the union's
290 * members are valid. (Within the host kernel it is always possible
291 * to tell, but the kernel carefully avoids giving userspace the
292 * high 16 bits of si_code, so we don't have the information to
293 * do this the easy way...) We therefore make our best guess,
294 * bearing in mind that a guest can spoof most of the si_codes
295 * via rt_sigqueueinfo() if it likes.
296 *
297 * Once we have made our guess, we record it in the top 16 bits of
298 * the si_code, so that tswap_siginfo() later can use it.
299 * tswap_siginfo() will strip these top bits out before writing
300 * si_code to the guest (sign-extending the lower bits).
301 */
302
303 switch (si_code) {
304 case SI_USER:
305 case SI_TKILL:
306 case SI_KERNEL:
307 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
308 * These are the only unspoofable si_code values.
309 */
310 tinfo->_sifields._kill._pid = info->si_pid;
311 tinfo->_sifields._kill._uid = info->si_uid;
312 si_type = QEMU_SI_KILL;
313 break;
314 default:
315 /* Everything else is spoofable. Make best guess based on signal */
316 switch (sig) {
317 case TARGET_SIGCHLD:
318 tinfo->_sifields._sigchld._pid = info->si_pid;
319 tinfo->_sifields._sigchld._uid = info->si_uid;
320 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100321 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100322 tinfo->_sifields._sigchld._utime = info->si_utime;
323 tinfo->_sifields._sigchld._stime = info->si_stime;
324 si_type = QEMU_SI_CHLD;
325 break;
326 case TARGET_SIGIO:
327 tinfo->_sifields._sigpoll._band = info->si_band;
328 tinfo->_sifields._sigpoll._fd = info->si_fd;
329 si_type = QEMU_SI_POLL;
330 break;
331 default:
332 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
333 tinfo->_sifields._rt._pid = info->si_pid;
334 tinfo->_sifields._rt._uid = info->si_uid;
335 /* XXX: potential problem if 64 bit */
336 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100337 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100338 si_type = QEMU_SI_RT;
339 break;
340 }
341 break;
bellard9de5e442003-03-23 16:49:39 +0000342 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100343
344 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000345}
346
Anthony Liguoric227f092009-10-01 16:12:16 -0500347static void tswap_siginfo(target_siginfo_t *tinfo,
348 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000349{
Peter Maydella70dadc2016-05-27 15:51:59 +0100350 int si_type = extract32(info->si_code, 16, 16);
351 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700352
Peter Maydella70dadc2016-05-27 15:51:59 +0100353 __put_user(info->si_signo, &tinfo->si_signo);
354 __put_user(info->si_errno, &tinfo->si_errno);
355 __put_user(si_code, &tinfo->si_code);
356
357 /* We can use our internal marker of which fields in the structure
358 * are valid, rather than duplicating the guesswork of
359 * host_to_target_siginfo_noswap() here.
360 */
361 switch (si_type) {
362 case QEMU_SI_KILL:
363 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
364 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
365 break;
366 case QEMU_SI_TIMER:
367 __put_user(info->_sifields._timer._timer1,
368 &tinfo->_sifields._timer._timer1);
369 __put_user(info->_sifields._timer._timer2,
370 &tinfo->_sifields._timer._timer2);
371 break;
372 case QEMU_SI_POLL:
373 __put_user(info->_sifields._sigpoll._band,
374 &tinfo->_sifields._sigpoll._band);
375 __put_user(info->_sifields._sigpoll._fd,
376 &tinfo->_sifields._sigpoll._fd);
377 break;
378 case QEMU_SI_FAULT:
379 __put_user(info->_sifields._sigfault._addr,
380 &tinfo->_sifields._sigfault._addr);
381 break;
382 case QEMU_SI_CHLD:
383 __put_user(info->_sifields._sigchld._pid,
384 &tinfo->_sifields._sigchld._pid);
385 __put_user(info->_sifields._sigchld._uid,
386 &tinfo->_sifields._sigchld._uid);
387 __put_user(info->_sifields._sigchld._status,
388 &tinfo->_sifields._sigchld._status);
389 __put_user(info->_sifields._sigchld._utime,
390 &tinfo->_sifields._sigchld._utime);
391 __put_user(info->_sifields._sigchld._stime,
392 &tinfo->_sifields._sigchld._stime);
393 break;
394 case QEMU_SI_RT:
395 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
396 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
397 __put_user(info->_sifields._rt._sigval.sival_ptr,
398 &tinfo->_sifields._rt._sigval.sival_ptr);
399 break;
400 default:
401 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000402 }
403}
404
Anthony Liguoric227f092009-10-01 16:12:16 -0500405void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000406{
Peter Maydell55d72a72016-06-13 11:22:05 +0100407 target_siginfo_t tgt_tmp;
408 host_to_target_siginfo_noswap(&tgt_tmp, info);
409 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000410}
411
412/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000413/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500414void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000415{
Peter Maydell90c0f082016-05-27 15:52:01 +0100416 /* This conversion is used only for the rt_sigqueueinfo syscall,
417 * and so we know that the _rt fields are the valid ones.
418 */
419 abi_ulong sival_ptr;
420
421 __get_user(info->si_signo, &tinfo->si_signo);
422 __get_user(info->si_errno, &tinfo->si_errno);
423 __get_user(info->si_code, &tinfo->si_code);
424 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
425 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
426 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
427 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000428}
429
aurel32ca587a82008-12-18 22:44:13 +0000430static int fatal_signal (int sig)
431{
432 switch (sig) {
433 case TARGET_SIGCHLD:
434 case TARGET_SIGURG:
435 case TARGET_SIGWINCH:
436 /* Ignored by default. */
437 return 0;
438 case TARGET_SIGCONT:
439 case TARGET_SIGSTOP:
440 case TARGET_SIGTSTP:
441 case TARGET_SIGTTIN:
442 case TARGET_SIGTTOU:
443 /* Job control signals. */
444 return 0;
445 default:
446 return 1;
447 }
448}
449
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300450/* returns 1 if given signal should dump core if not handled */
451static int core_dump_signal(int sig)
452{
453 switch (sig) {
454 case TARGET_SIGABRT:
455 case TARGET_SIGFPE:
456 case TARGET_SIGILL:
457 case TARGET_SIGQUIT:
458 case TARGET_SIGSEGV:
459 case TARGET_SIGTRAP:
460 case TARGET_SIGBUS:
461 return (1);
462 default:
463 return (0);
464 }
465}
466
bellard31e31b82003-02-18 22:55:36 +0000467void signal_init(void)
468{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100469 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000470 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000471 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000472 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000473 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000474
bellard9e5f5282003-07-13 17:33:54 +0000475 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200476 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000477 if (host_to_target_signal_table[i] == 0)
478 host_to_target_signal_table[i] = i;
479 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200480 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000481 j = host_to_target_signal_table[i];
482 target_to_host_signal_table[j] = i;
483 }
ths3b46e622007-09-17 08:09:54 +0000484
Peter Maydell3d3efba2016-05-27 15:51:49 +0100485 /* Set the signal mask from the host mask. */
486 sigprocmask(0, 0, &ts->signal_mask);
487
bellard9de5e442003-03-23 16:49:39 +0000488 /* set all host signal handlers. ALL signals are blocked during
489 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000490 memset(sigact_table, 0, sizeof(sigact_table));
491
bellard9de5e442003-03-23 16:49:39 +0000492 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000493 act.sa_flags = SA_SIGINFO;
494 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000495 for(i = 1; i <= TARGET_NSIG; i++) {
496 host_sig = target_to_host_signal(i);
497 sigaction(host_sig, NULL, &oact);
498 if (oact.sa_sigaction == (void *)SIG_IGN) {
499 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
500 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
501 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
502 }
503 /* If there's already a handler installed then something has
504 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000505 /* Install some handlers for our own use. We need at least
506 SIGSEGV and SIGBUS, to detect exceptions. We can not just
507 trap all signals because it affects syscall interrupt
508 behavior. But do trap all default-fatal signals. */
509 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000510 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000511 }
bellard31e31b82003-02-18 22:55:36 +0000512}
513
Peter Maydellc599d4d2016-07-28 16:44:49 +0100514/* Force a synchronously taken signal. The kernel force_sig() function
515 * also forces the signal to "not blocked, not ignored", but for QEMU
516 * that work is done in process_pending_signals().
517 */
518static void force_sig(int sig)
519{
520 CPUState *cpu = thread_cpu;
521 CPUArchState *env = cpu->env_ptr;
522 target_siginfo_t info;
523
524 info.si_signo = sig;
525 info.si_errno = 0;
526 info.si_code = TARGET_SI_KERNEL;
527 info._sifields._kill._pid = 0;
528 info._sifields._kill._uid = 0;
529 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
530}
Peter Maydell09391662016-07-28 16:44:47 +0100531
532/* Force a SIGSEGV if we couldn't write to memory trying to set
533 * up the signal frame. oldsig is the signal we were trying to handle
534 * at the point of failure.
535 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300536#if !defined(TARGET_RISCV)
Peter Maydell09391662016-07-28 16:44:47 +0100537static void force_sigsegv(int oldsig)
538{
Peter Maydell09391662016-07-28 16:44:47 +0100539 if (oldsig == SIGSEGV) {
540 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100541 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100542 */
543 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
544 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100545 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100546}
bellard66fb9762003-03-23 01:06:05 +0000547
Michael Clark47ae93c2018-03-03 01:31:11 +1300548#endif
549
bellard9de5e442003-03-23 16:49:39 +0000550/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100551static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000552{
Andreas Färber0429a972013-08-26 18:14:44 +0200553 CPUState *cpu = thread_cpu;
554 CPUArchState *env = cpu->env_ptr;
555 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300556 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000557 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100558
Riku Voipio66393fb2009-12-04 15:16:32 +0200559 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100560 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200561 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000562
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300563 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200564 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300565 stop_all_tasks();
566 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200567 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 }
569 if (core_dumped) {
570 /* we already dumped the core of target process, we don't want
571 * a coredump of qemu itself */
572 struct rlimit nodump;
573 getrlimit(RLIMIT_CORE, &nodump);
574 nodump.rlim_cur=0;
575 setrlimit(RLIMIT_CORE, &nodump);
576 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200577 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300578 }
579
Stefan Weil0c587512011-04-28 17:20:32 +0200580 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000581 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
582 * a negative value. To get the proper exit code we need to
583 * actually die from an uncaught signal. Here the default signal
584 * handler is installed, we send ourself a signal and we wait for
585 * it to arrive. */
586 sigfillset(&act.sa_mask);
587 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000588 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000589 sigaction(host_sig, &act, NULL);
590
591 /* For some reason raise(host_sig) doesn't send the signal when
592 * statically linked on x86-64. */
593 kill(getpid(), host_sig);
594
595 /* Make sure the signal isn't masked (just reuse the mask inside
596 of act) */
597 sigdelset(&act.sa_mask, host_sig);
598 sigsuspend(&act.sa_mask);
599
600 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000601 abort();
bellard66fb9762003-03-23 01:06:05 +0000602}
603
bellard9de5e442003-03-23 16:49:39 +0000604/* queue a signal so that it will be send to the virtual CPU as soon
605 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100606int queue_signal(CPUArchState *env, int sig, int si_type,
607 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000608{
Andreas Färber0429a972013-08-26 18:14:44 +0200609 CPUState *cpu = ENV_GET_CPU(env);
610 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000611
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100612 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000613
Peter Maydell9d2803f2016-07-28 16:44:46 +0100614 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100615
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100616 ts->sync_signal.info = *info;
617 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100618 /* signal that a new signal is pending */
619 atomic_set(&ts->signal_pending, 1);
620 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000621}
622
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100623#ifndef HAVE_SAFE_SYSCALL
624static inline void rewind_if_in_safe_syscall(void *puc)
625{
626 /* Default version: never rewind */
627}
628#endif
629
ths5fafdf22007-09-16 21:08:06 +0000630static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000631 void *puc)
632{
Andreas Färbera2247f82013-06-09 19:47:04 +0200633 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100634 CPUState *cpu = ENV_GET_CPU(env);
635 TaskState *ts = cpu->opaque;
636
bellard9de5e442003-03-23 16:49:39 +0000637 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500638 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100639 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100640 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000641
642 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000643 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000644 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000645 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000646 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000647 return;
648 }
649
650 /* get target signal number */
651 sig = host_to_target_signal(host_signum);
652 if (sig < 1 || sig > TARGET_NSIG)
653 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100654 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100655
656 rewind_if_in_safe_syscall(puc);
657
bellard9de5e442003-03-23 16:49:39 +0000658 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100659 k = &ts->sigtab[sig - 1];
660 k->info = tinfo;
661 k->pending = sig;
662 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100663
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100664 /* Block host signals until target signal handler entered. We
665 * can't block SIGSEGV or SIGBUS while we're executing guest
666 * code in case the guest code provokes one in the window between
667 * now and it getting out to the main loop. Signals will be
668 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100669 *
670 * WARNING: we cannot use sigfillset() here because the uc_sigmask
671 * field is a kernel sigset_t, which is much smaller than the
672 * libc sigset_t which sigfillset() operates on. Using sigfillset()
673 * would write 0xff bytes off the end of the structure and trash
674 * data on the struct.
675 * We can't use sizeof(uc->uc_sigmask) either, because the libc
676 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100677 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100678 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100679 sigdelset(&uc->uc_sigmask, SIGSEGV);
680 sigdelset(&uc->uc_sigmask, SIGBUS);
681
682 /* interrupt the virtual CPU as soon as possible */
683 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000684}
685
ths0da46a62007-10-20 20:23:07 +0000686/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000687/* compare linux/kernel/signal.c:do_sigaltstack() */
688abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000689{
690 int ret;
691 struct target_sigaltstack oss;
692
693 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000694 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000695 {
696 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
697 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
698 __put_user(sas_ss_flags(sp), &oss.ss_flags);
699 }
700
bellard579a97f2007-11-11 14:26:47 +0000701 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000702 {
bellard579a97f2007-11-11 14:26:47 +0000703 struct target_sigaltstack *uss;
704 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500705 size_t minstacksize = TARGET_MINSIGSTKSZ;
706
707#if defined(TARGET_PPC64)
708 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
709 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
710 if (get_ppc64_abi(image) > 1) {
711 minstacksize = 4096;
712 }
713#endif
thsa04e1342007-09-27 13:57:58 +0000714
ths0da46a62007-10-20 20:23:07 +0000715 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300716 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000717 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300718 }
719 __get_user(ss.ss_sp, &uss->ss_sp);
720 __get_user(ss.ss_size, &uss->ss_size);
721 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000722 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000723
ths0da46a62007-10-20 20:23:07 +0000724 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000725 if (on_sig_stack(sp))
726 goto out;
727
ths0da46a62007-10-20 20:23:07 +0000728 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000729 if (ss.ss_flags != TARGET_SS_DISABLE
730 && ss.ss_flags != TARGET_SS_ONSTACK
731 && ss.ss_flags != 0)
732 goto out;
733
734 if (ss.ss_flags == TARGET_SS_DISABLE) {
735 ss.ss_size = 0;
736 ss.ss_sp = 0;
737 } else {
ths0da46a62007-10-20 20:23:07 +0000738 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500739 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000740 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500741 }
thsa04e1342007-09-27 13:57:58 +0000742 }
743
744 target_sigaltstack_used.ss_sp = ss.ss_sp;
745 target_sigaltstack_used.ss_size = ss.ss_size;
746 }
747
bellard579a97f2007-11-11 14:26:47 +0000748 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000749 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000750 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000751 goto out;
thsa04e1342007-09-27 13:57:58 +0000752 }
753
754 ret = 0;
755out:
756 return ret;
757}
758
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100759/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000760int do_sigaction(int sig, const struct target_sigaction *act,
761 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000762{
pbrook624f7972008-05-31 16:11:38 +0000763 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000764 struct sigaction act1;
765 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000766 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000767
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100768 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
769 return -TARGET_EINVAL;
770 }
771
772 if (block_signals()) {
773 return -TARGET_ERESTARTSYS;
774 }
775
bellard66fb9762003-03-23 01:06:05 +0000776 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000777 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800778 __put_user(k->_sa_handler, &oact->_sa_handler);
779 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100780#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000782#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800783 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000784 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000785 }
786 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000787 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800788 __get_user(k->_sa_handler, &act->_sa_handler);
789 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100790#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000792#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800793 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000794 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000795
796 /* we update the host linux signal state */
797 host_sig = target_to_host_signal(sig);
798 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
799 sigfillset(&act1.sa_mask);
800 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000801 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000802 act1.sa_flags |= SA_RESTART;
803 /* NOTE: it is important to update the host kernel signal
804 ignore state to avoid getting unexpected interrupted
805 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000806 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000807 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000808 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000809 if (fatal_signal (sig))
810 act1.sa_sigaction = host_signal_handler;
811 else
812 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000813 } else {
814 act1.sa_sigaction = host_signal_handler;
815 }
ths0da46a62007-10-20 20:23:07 +0000816 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000817 }
bellard66fb9762003-03-23 01:06:05 +0000818 }
ths0da46a62007-10-20 20:23:07 +0000819 return ret;
bellard66fb9762003-03-23 01:06:05 +0000820}
bellard31e31b82003-02-18 22:55:36 +0000821
Pranith Kumar1c1df012017-02-26 11:53:44 -0500822#if defined(TARGET_I386)
823/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000824
825struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100826 uint16_t significand[4];
827 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000828};
829
830struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100831 uint16_t significand[4];
832 uint16_t exponent;
833 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000834};
835
836struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500837 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000838};
839
Pranith Kumar1c1df012017-02-26 11:53:44 -0500840struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100841 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500842 uint32_t cw;
843 uint32_t sw;
844 uint32_t tag;
845 uint32_t ipoff;
846 uint32_t cssel;
847 uint32_t dataoff;
848 uint32_t datasel;
849 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100850 uint16_t status;
851 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000852
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100853 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500854 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
855 uint32_t mxcsr;
856 uint32_t reserved;
857 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
858 struct target_xmmreg xmm[8];
859 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000860};
861
Pranith Kumar1c1df012017-02-26 11:53:44 -0500862struct target_fpstate_64 {
863 /* FXSAVE format */
864 uint16_t cw;
865 uint16_t sw;
866 uint16_t twd;
867 uint16_t fop;
868 uint64_t rip;
869 uint64_t rdp;
870 uint32_t mxcsr;
871 uint32_t mxcsr_mask;
872 uint32_t st_space[32];
873 uint32_t xmm_space[64];
874 uint32_t reserved[24];
875};
bellard66fb9762003-03-23 01:06:05 +0000876
Pranith Kumar1c1df012017-02-26 11:53:44 -0500877#ifndef TARGET_X86_64
878# define target_fpstate target_fpstate_32
879#else
880# define target_fpstate target_fpstate_64
881#endif
882
883struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100884 uint16_t gs, __gsh;
885 uint16_t fs, __fsh;
886 uint16_t es, __esh;
887 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500888 uint32_t edi;
889 uint32_t esi;
890 uint32_t ebp;
891 uint32_t esp;
892 uint32_t ebx;
893 uint32_t edx;
894 uint32_t ecx;
895 uint32_t eax;
896 uint32_t trapno;
897 uint32_t err;
898 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100899 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500900 uint32_t eflags;
901 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500903 uint32_t fpstate; /* pointer */
904 uint32_t oldmask;
905 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000906};
907
Pranith Kumar1c1df012017-02-26 11:53:44 -0500908struct target_sigcontext_64 {
909 uint64_t r8;
910 uint64_t r9;
911 uint64_t r10;
912 uint64_t r11;
913 uint64_t r12;
914 uint64_t r13;
915 uint64_t r14;
916 uint64_t r15;
917
918 uint64_t rdi;
919 uint64_t rsi;
920 uint64_t rbp;
921 uint64_t rbx;
922 uint64_t rdx;
923 uint64_t rax;
924 uint64_t rcx;
925 uint64_t rsp;
926 uint64_t rip;
927
928 uint64_t eflags;
929
930 uint16_t cs;
931 uint16_t gs;
932 uint16_t fs;
933 uint16_t ss;
934
935 uint64_t err;
936 uint64_t trapno;
937 uint64_t oldmask;
938 uint64_t cr2;
939
940 uint64_t fpstate; /* pointer */
941 uint64_t padding[8];
942};
943
944#ifndef TARGET_X86_64
945# define target_sigcontext target_sigcontext_32
946#else
947# define target_sigcontext target_sigcontext_64
948#endif
949
950/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000951struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100952 abi_ulong tuc_flags;
953 abi_ulong tuc_link;
954 target_stack_t tuc_stack;
955 struct target_sigcontext tuc_mcontext;
956 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000957};
958
Pranith Kumar1c1df012017-02-26 11:53:44 -0500959#ifndef TARGET_X86_64
960struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000961 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000962 int sig;
963 struct target_sigcontext sc;
964 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000965 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000966 char retcode[8];
967};
968
Pranith Kumar1c1df012017-02-26 11:53:44 -0500969struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000970 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000971 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000972 abi_ulong pinfo;
973 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000974 struct target_siginfo info;
975 struct target_ucontext uc;
976 struct target_fpstate fpstate;
977 char retcode[8];
978};
979
Pranith Kumar1c1df012017-02-26 11:53:44 -0500980#else
981
982struct rt_sigframe {
983 abi_ulong pretcode;
984 struct target_ucontext uc;
985 struct target_siginfo info;
986 struct target_fpstate fpstate;
987};
988
989#endif
990
bellard66fb9762003-03-23 01:06:05 +0000991/*
992 * Set up a signal frame.
993 */
994
bellard66fb9762003-03-23 01:06:05 +0000995/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300996static void setup_sigcontext(struct target_sigcontext *sc,
997 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
998 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000999{
Andreas Färber27103422013-08-26 08:31:06 +02001000 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -05001001#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +02001002 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +00001003
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001004 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001005 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
1006 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
1007 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
1008 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
1009 __put_user(env->regs[R_EDI], &sc->edi);
1010 __put_user(env->regs[R_ESI], &sc->esi);
1011 __put_user(env->regs[R_EBP], &sc->ebp);
1012 __put_user(env->regs[R_ESP], &sc->esp);
1013 __put_user(env->regs[R_EBX], &sc->ebx);
1014 __put_user(env->regs[R_EDX], &sc->edx);
1015 __put_user(env->regs[R_ECX], &sc->ecx);
1016 __put_user(env->regs[R_EAX], &sc->eax);
1017 __put_user(cs->exception_index, &sc->trapno);
1018 __put_user(env->error_code, &sc->err);
1019 __put_user(env->eip, &sc->eip);
1020 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1021 __put_user(env->eflags, &sc->eflags);
1022 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1023 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001024
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001025 cpu_x86_fsave(env, fpstate_addr, 1);
1026 fpstate->status = fpstate->sw;
1027 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001028 __put_user(magic, &fpstate->magic);
1029 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001030
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001031 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001032 __put_user(mask, &sc->oldmask);
1033 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001034#else
1035 __put_user(env->regs[R_EDI], &sc->rdi);
1036 __put_user(env->regs[R_ESI], &sc->rsi);
1037 __put_user(env->regs[R_EBP], &sc->rbp);
1038 __put_user(env->regs[R_ESP], &sc->rsp);
1039 __put_user(env->regs[R_EBX], &sc->rbx);
1040 __put_user(env->regs[R_EDX], &sc->rdx);
1041 __put_user(env->regs[R_ECX], &sc->rcx);
1042 __put_user(env->regs[R_EAX], &sc->rax);
1043
1044 __put_user(env->regs[8], &sc->r8);
1045 __put_user(env->regs[9], &sc->r9);
1046 __put_user(env->regs[10], &sc->r10);
1047 __put_user(env->regs[11], &sc->r11);
1048 __put_user(env->regs[12], &sc->r12);
1049 __put_user(env->regs[13], &sc->r13);
1050 __put_user(env->regs[14], &sc->r14);
1051 __put_user(env->regs[15], &sc->r15);
1052
1053 __put_user(cs->exception_index, &sc->trapno);
1054 __put_user(env->error_code, &sc->err);
1055 __put_user(env->eip, &sc->rip);
1056
1057 __put_user(env->eflags, &sc->eflags);
1058 __put_user(env->segs[R_CS].selector, &sc->cs);
1059 __put_user((uint16_t)0, &sc->gs);
1060 __put_user((uint16_t)0, &sc->fs);
1061 __put_user(env->segs[R_SS].selector, &sc->ss);
1062
1063 __put_user(mask, &sc->oldmask);
1064 __put_user(env->cr[2], &sc->cr2);
1065
1066 /* fpstate_addr must be 16 byte aligned for fxsave */
1067 assert(!(fpstate_addr & 0xf));
1068
1069 cpu_x86_fxsave(env, fpstate_addr);
1070 __put_user(fpstate_addr, &sc->fpstate);
1071#endif
bellard66fb9762003-03-23 01:06:05 +00001072}
1073
1074/*
1075 * Determine which stack to use..
1076 */
1077
bellard579a97f2007-11-11 14:26:47 +00001078static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001079get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001080{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001081 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001082
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001083 /* Default to using normal stack */
1084 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001085#ifdef TARGET_X86_64
1086 esp -= 128; /* this is the redzone */
1087#endif
1088
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001089 /* This is the X/Open sanctioned signal stack switching. */
1090 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1091 if (sas_ss_flags(esp) == 0) {
1092 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001093 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001094 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001095#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001096 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001097 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001098 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1099 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001100 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001102#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001103 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001104
1105#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001107#else
1108 return ((esp - frame_size) & (~15ul)) - 8;
1109#endif
bellard66fb9762003-03-23 01:06:05 +00001110}
1111
Pranith Kumar1c1df012017-02-26 11:53:44 -05001112#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001113/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001114static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001115 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001116{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001117 abi_ulong frame_addr;
1118 struct sigframe *frame;
1119 int i;
bellard66fb9762003-03-23 01:06:05 +00001120
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001121 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1122 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1125 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001126
Peter Maydellb6e2c932015-01-08 12:19:43 +00001127 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001128
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001129 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1130 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001131
Riku Voipio7df2fa32014-04-23 10:34:53 +03001132 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1133 __put_user(set->sig[i], &frame->extramask[i - 1]);
1134 }
bellard66fb9762003-03-23 01:06:05 +00001135
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001136 /* Set up to return from userspace. If provided, use a stub
1137 already in userspace. */
1138 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001139 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001140 } else {
1141 uint16_t val16;
1142 abi_ulong retcode_addr;
1143 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001144 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001145 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1146 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001147 __put_user(val16, (uint16_t *)(frame->retcode+0));
1148 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001149 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001150 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001151 }
bellard66fb9762003-03-23 01:06:05 +00001152
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001153 /* Set up registers for signal handler */
1154 env->regs[R_ESP] = frame_addr;
1155 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001156
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001157 cpu_x86_load_seg(env, R_DS, __USER_DS);
1158 cpu_x86_load_seg(env, R_ES, __USER_DS);
1159 cpu_x86_load_seg(env, R_SS, __USER_DS);
1160 cpu_x86_load_seg(env, R_CS, __USER_CS);
1161 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001162
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001163 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001164
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001165 return;
bellard66fb9762003-03-23 01:06:05 +00001166
1167give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001168 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001169}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001170#endif
bellard66fb9762003-03-23 01:06:05 +00001171
Pranith Kumar1c1df012017-02-26 11:53:44 -05001172/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001173static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001174 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001175 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001176{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001177 abi_ulong frame_addr;
1178#ifndef TARGET_X86_64
1179 abi_ulong addr;
1180#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001181 struct rt_sigframe *frame;
1182 int i;
bellard66fb9762003-03-23 01:06:05 +00001183
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001184 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1185 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001186
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001187 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1188 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001189
Pranith Kumar1c1df012017-02-26 11:53:44 -05001190 /* These fields are only in rt_sigframe on 32 bit */
1191#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001192 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001193 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001194 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001195 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001196 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001197#endif
1198 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1199 tswap_siginfo(&frame->info, info);
1200 }
bellard66fb9762003-03-23 01:06:05 +00001201
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001202 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001203 __put_user(0, &frame->uc.tuc_flags);
1204 __put_user(0, &frame->uc.tuc_link);
1205 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1206 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1207 &frame->uc.tuc_stack.ss_flags);
1208 __put_user(target_sigaltstack_used.ss_size,
1209 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001210 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1211 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1212
Riku Voipio0188fad2014-04-23 13:34:15 +03001213 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1214 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1215 }
bellard66fb9762003-03-23 01:06:05 +00001216
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001217 /* Set up to return from userspace. If provided, use a stub
1218 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001219#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001220 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001221 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001222 } else {
1223 uint16_t val16;
1224 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001225 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001226 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001227 __put_user(0xb8, (char *)(frame->retcode+0));
1228 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001229 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001230 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001231 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001232#else
1233 /* XXX: Would be slightly better to return -EFAULT here if test fails
1234 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1235 __put_user(ka->sa_restorer, &frame->pretcode);
1236#endif
bellard66fb9762003-03-23 01:06:05 +00001237
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001238 /* Set up registers for signal handler */
1239 env->regs[R_ESP] = frame_addr;
1240 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001241
Pranith Kumar1c1df012017-02-26 11:53:44 -05001242#ifndef TARGET_X86_64
1243 env->regs[R_EAX] = sig;
1244 env->regs[R_EDX] = (unsigned long)&frame->info;
1245 env->regs[R_ECX] = (unsigned long)&frame->uc;
1246#else
1247 env->regs[R_EAX] = 0;
1248 env->regs[R_EDI] = sig;
1249 env->regs[R_ESI] = (unsigned long)&frame->info;
1250 env->regs[R_EDX] = (unsigned long)&frame->uc;
1251#endif
1252
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001253 cpu_x86_load_seg(env, R_DS, __USER_DS);
1254 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001255 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001256 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001257 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001258
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001259 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001260
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001261 return;
bellard66fb9762003-03-23 01:06:05 +00001262
1263give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001264 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001265}
1266
1267static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001268restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001269{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001270 unsigned int err = 0;
1271 abi_ulong fpstate_addr;
1272 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001273
Pranith Kumar1c1df012017-02-26 11:53:44 -05001274#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001275 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1276 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1277 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1278 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001279
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001280 env->regs[R_EDI] = tswapl(sc->edi);
1281 env->regs[R_ESI] = tswapl(sc->esi);
1282 env->regs[R_EBP] = tswapl(sc->ebp);
1283 env->regs[R_ESP] = tswapl(sc->esp);
1284 env->regs[R_EBX] = tswapl(sc->ebx);
1285 env->regs[R_EDX] = tswapl(sc->edx);
1286 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001287 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001288
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001289 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001290#else
1291 env->regs[8] = tswapl(sc->r8);
1292 env->regs[9] = tswapl(sc->r9);
1293 env->regs[10] = tswapl(sc->r10);
1294 env->regs[11] = tswapl(sc->r11);
1295 env->regs[12] = tswapl(sc->r12);
1296 env->regs[13] = tswapl(sc->r13);
1297 env->regs[14] = tswapl(sc->r14);
1298 env->regs[15] = tswapl(sc->r15);
1299
1300 env->regs[R_EDI] = tswapl(sc->rdi);
1301 env->regs[R_ESI] = tswapl(sc->rsi);
1302 env->regs[R_EBP] = tswapl(sc->rbp);
1303 env->regs[R_EBX] = tswapl(sc->rbx);
1304 env->regs[R_EDX] = tswapl(sc->rdx);
1305 env->regs[R_EAX] = tswapl(sc->rax);
1306 env->regs[R_ECX] = tswapl(sc->rcx);
1307 env->regs[R_ESP] = tswapl(sc->rsp);
1308
1309 env->eip = tswapl(sc->rip);
1310#endif
bellard66fb9762003-03-23 01:06:05 +00001311
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001312 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1313 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 tmpflags = tswapl(sc->eflags);
1316 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1317 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001318
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001319 fpstate_addr = tswapl(sc->fpstate);
1320 if (fpstate_addr != 0) {
1321 if (!access_ok(VERIFY_READ, fpstate_addr,
1322 sizeof(struct target_fpstate)))
1323 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001324#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001325 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001326#else
1327 cpu_x86_fxrstor(env, fpstate_addr);
1328#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001329 }
bellard66fb9762003-03-23 01:06:05 +00001330
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001331 return err;
bellard66fb9762003-03-23 01:06:05 +00001332badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001333 return 1;
bellard66fb9762003-03-23 01:06:05 +00001334}
1335
Pranith Kumar1c1df012017-02-26 11:53:44 -05001336/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1337#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001338long do_sigreturn(CPUX86State *env)
1339{
bellard579a97f2007-11-11 14:26:47 +00001340 struct sigframe *frame;
1341 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001342 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001343 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001344 int i;
bellard66fb9762003-03-23 01:06:05 +00001345
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001346 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001347 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1348 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001349 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001350 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001351 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001352 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001353 }
bellard66fb9762003-03-23 01:06:05 +00001354
bellard92319442004-06-19 16:58:13 +00001355 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001356 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001357
bellard66fb9762003-03-23 01:06:05 +00001358 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001359 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001360 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001361 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001362 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001363
1364badframe:
bellard579a97f2007-11-11 14:26:47 +00001365 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001366 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001367 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001368}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001369#endif
bellard66fb9762003-03-23 01:06:05 +00001370
1371long do_rt_sigreturn(CPUX86State *env)
1372{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001373 abi_ulong frame_addr;
1374 struct rt_sigframe *frame;
1375 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001376
Pranith Kumar1c1df012017-02-26 11:53:44 -05001377 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001378 trace_user_do_rt_sigreturn(env, frame_addr);
1379 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1380 goto badframe;
1381 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001382 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001383
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001384 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001385 goto badframe;
1386 }
bellard66fb9762003-03-23 01:06:05 +00001387
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001388 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1389 get_sp_from_cpustate(env)) == -EFAULT) {
1390 goto badframe;
1391 }
thsa04e1342007-09-27 13:57:58 +00001392
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001393 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001394 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001395
1396badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001397 unlock_user_struct(frame, frame_addr, 0);
1398 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001399 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001400}
1401
Andreas Schwab1744aea2013-09-03 20:12:16 +01001402#elif defined(TARGET_AARCH64)
1403
1404struct target_sigcontext {
1405 uint64_t fault_address;
1406 /* AArch64 registers */
1407 uint64_t regs[31];
1408 uint64_t sp;
1409 uint64_t pc;
1410 uint64_t pstate;
1411 /* 4K reserved for FP/SIMD state and future expansion */
1412 char __reserved[4096] __attribute__((__aligned__(16)));
1413};
1414
1415struct target_ucontext {
1416 abi_ulong tuc_flags;
1417 abi_ulong tuc_link;
1418 target_stack_t tuc_stack;
1419 target_sigset_t tuc_sigmask;
1420 /* glibc uses a 1024-bit sigset_t */
1421 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1422 /* last for future expansion */
1423 struct target_sigcontext tuc_mcontext;
1424};
1425
1426/*
1427 * Header to be used at the beginning of structures extending the user
1428 * context. Such structures must be placed after the rt_sigframe on the stack
1429 * and be 16-byte aligned. The last structure must be a dummy one with the
1430 * magic and size set to 0.
1431 */
1432struct target_aarch64_ctx {
1433 uint32_t magic;
1434 uint32_t size;
1435};
1436
1437#define TARGET_FPSIMD_MAGIC 0x46508001
1438
1439struct target_fpsimd_context {
1440 struct target_aarch64_ctx head;
1441 uint32_t fpsr;
1442 uint32_t fpcr;
1443 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1444};
1445
Richard Henderson7a53fb92018-03-09 17:09:43 +00001446#define TARGET_EXTRA_MAGIC 0x45585401
1447
1448struct target_extra_context {
1449 struct target_aarch64_ctx head;
1450 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
1451 uint32_t size; /* size in bytes of the extra space */
1452 uint32_t reserved[3];
1453};
1454
Richard Henderson8c5931d2018-03-09 17:09:44 +00001455#define TARGET_SVE_MAGIC 0x53564501
1456
1457struct target_sve_context {
1458 struct target_aarch64_ctx head;
1459 uint16_t vl;
1460 uint16_t reserved[3];
1461 /* The actual SVE data immediately follows. It is layed out
1462 * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
1463 * the original struct pointer.
1464 */
1465};
1466
1467#define TARGET_SVE_VQ_BYTES 16
1468
1469#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
1470#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
1471
1472#define TARGET_SVE_SIG_REGS_OFFSET \
1473 QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
1474#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
1475 (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
1476#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
1477 (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
1478#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
1479 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
1480#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
1481 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
1482
Andreas Schwab1744aea2013-09-03 20:12:16 +01001483struct target_rt_sigframe {
1484 struct target_siginfo info;
1485 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001486};
1487
1488struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001489 uint64_t fp;
1490 uint64_t lr;
1491 uint32_t tramp[2];
1492};
1493
Richard Henderson3b505bb2018-03-09 17:09:43 +00001494static void target_setup_general_frame(struct target_rt_sigframe *sf,
1495 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001496{
1497 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001498
Richard Henderson3b505bb2018-03-09 17:09:43 +00001499 __put_user(0, &sf->uc.tuc_flags);
1500 __put_user(0, &sf->uc.tuc_link);
1501
1502 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1503 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1504 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001505
1506 for (i = 0; i < 31; i++) {
1507 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1508 }
1509 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1510 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001511 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001512
Peter Maydell7af03922014-05-01 18:36:17 +01001513 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001514
1515 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1516 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1517 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001518}
1519
1520static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1521 CPUARMState *env)
1522{
1523 int i;
1524
1525 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1526 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1527 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1528 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001529
1530 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001531 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001532#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001533 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1534 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001535#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001536 __put_user(q[0], &fpsimd->vregs[i * 2]);
1537 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001538#endif
1539 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001540}
1541
Richard Henderson7a53fb92018-03-09 17:09:43 +00001542static void target_setup_extra_record(struct target_extra_context *extra,
1543 uint64_t datap, uint32_t extra_size)
1544{
1545 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
1546 __put_user(sizeof(struct target_extra_context), &extra->head.size);
1547 __put_user(datap, &extra->datap);
1548 __put_user(extra_size, &extra->size);
1549}
1550
Richard Henderson3b505bb2018-03-09 17:09:43 +00001551static void target_setup_end_record(struct target_aarch64_ctx *end)
1552{
1553 __put_user(0, &end->magic);
1554 __put_user(0, &end->size);
1555}
1556
Richard Henderson8c5931d2018-03-09 17:09:44 +00001557static void target_setup_sve_record(struct target_sve_context *sve,
1558 CPUARMState *env, int vq, int size)
1559{
1560 int i, j;
1561
1562 __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
1563 __put_user(size, &sve->head.size);
1564 __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
1565
1566 /* Note that SVE regs are stored as a byte stream, with each byte element
1567 * at a subsequent address. This corresponds to a little-endian store
1568 * of our 64-bit hunks.
1569 */
1570 for (i = 0; i < 32; ++i) {
1571 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1572 for (j = 0; j < vq * 2; ++j) {
1573 __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
1574 }
1575 }
1576 for (i = 0; i <= 16; ++i) {
1577 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1578 for (j = 0; j < vq; ++j) {
1579 uint64_t r = env->vfp.pregs[i].p[j >> 2];
1580 __put_user_e(r >> ((j & 3) * 16), p + j, le);
1581 }
1582 }
1583}
1584
Richard Henderson3b505bb2018-03-09 17:09:43 +00001585static void target_restore_general_frame(CPUARMState *env,
1586 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001587{
1588 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001589 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001590 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001591
1592 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001593 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001594
1595 for (i = 0; i < 31; i++) {
1596 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1597 }
1598
1599 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1600 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001601 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1602 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001603}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001604
Richard Henderson3b505bb2018-03-09 17:09:43 +00001605static void target_restore_fpsimd_record(CPUARMState *env,
1606 struct target_fpsimd_context *fpsimd)
1607{
1608 uint32_t fpsr, fpcr;
1609 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001610
Richard Henderson3b505bb2018-03-09 17:09:43 +00001611 __get_user(fpsr, &fpsimd->fpsr);
1612 vfp_set_fpsr(env, fpsr);
1613 __get_user(fpcr, &fpsimd->fpcr);
1614 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001615
Peter Maydell4cf23482014-03-02 19:36:38 +00001616 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001617 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001618#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001619 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1620 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001621#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001622 __get_user(q[0], &fpsimd->vregs[i * 2]);
1623 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001624#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001625 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001626}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001627
Richard Henderson8c5931d2018-03-09 17:09:44 +00001628static void target_restore_sve_record(CPUARMState *env,
1629 struct target_sve_context *sve, int vq)
1630{
1631 int i, j;
1632
1633 /* Note that SVE regs are stored as a byte stream, with each byte element
1634 * at a subsequent address. This corresponds to a little-endian load
1635 * of our 64-bit hunks.
1636 */
1637 for (i = 0; i < 32; ++i) {
1638 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1639 for (j = 0; j < vq * 2; ++j) {
1640 __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
1641 }
1642 }
1643 for (i = 0; i <= 16; ++i) {
1644 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1645 for (j = 0; j < vq; ++j) {
1646 uint16_t r;
1647 __get_user_e(r, p + j, le);
1648 if (j & 3) {
1649 env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
1650 } else {
1651 env->vfp.pregs[i].p[j >> 2] = r;
1652 }
1653 }
1654 }
1655}
1656
Richard Henderson3b505bb2018-03-09 17:09:43 +00001657static int target_restore_sigframe(CPUARMState *env,
1658 struct target_rt_sigframe *sf)
1659{
Richard Henderson7a53fb92018-03-09 17:09:43 +00001660 struct target_aarch64_ctx *ctx, *extra = NULL;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001661 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001662 struct target_sve_context *sve = NULL;
Richard Henderson7a53fb92018-03-09 17:09:43 +00001663 uint64_t extra_datap = 0;
1664 bool used_extra = false;
1665 bool err = false;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001666 int vq = 0, sve_size = 0;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001667
1668 target_restore_general_frame(env, sf);
1669
Richard Hendersone1eecd12018-03-09 17:09:43 +00001670 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1671 while (ctx) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001672 uint32_t magic, size, extra_size;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001673
1674 __get_user(magic, &ctx->magic);
1675 __get_user(size, &ctx->size);
1676 switch (magic) {
1677 case 0:
1678 if (size != 0) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001679 err = true;
1680 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001681 }
Richard Henderson7a53fb92018-03-09 17:09:43 +00001682 if (used_extra) {
1683 ctx = NULL;
1684 } else {
1685 ctx = extra;
1686 used_extra = true;
1687 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001688 continue;
1689
1690 case TARGET_FPSIMD_MAGIC:
1691 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001692 err = true;
1693 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001694 }
1695 fpsimd = (struct target_fpsimd_context *)ctx;
1696 break;
1697
Richard Henderson8c5931d2018-03-09 17:09:44 +00001698 case TARGET_SVE_MAGIC:
1699 if (arm_feature(env, ARM_FEATURE_SVE)) {
1700 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1701 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1702 if (!sve && size == sve_size) {
1703 sve = (struct target_sve_context *)ctx;
1704 break;
1705 }
1706 }
1707 err = true;
1708 goto exit;
1709
Richard Henderson7a53fb92018-03-09 17:09:43 +00001710 case TARGET_EXTRA_MAGIC:
1711 if (extra || size != sizeof(struct target_extra_context)) {
1712 err = true;
1713 goto exit;
1714 }
1715 __get_user(extra_datap,
1716 &((struct target_extra_context *)ctx)->datap);
1717 __get_user(extra_size,
1718 &((struct target_extra_context *)ctx)->size);
1719 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
1720 break;
1721
Richard Hendersone1eecd12018-03-09 17:09:43 +00001722 default:
1723 /* Unknown record -- we certainly didn't generate it.
1724 * Did we in fact get out of sync?
1725 */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001726 err = true;
1727 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001728 }
1729 ctx = (void *)ctx + size;
1730 }
1731
1732 /* Require FPSIMD always. */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001733 if (fpsimd) {
1734 target_restore_fpsimd_record(env, fpsimd);
1735 } else {
1736 err = true;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001737 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001738
Richard Henderson8c5931d2018-03-09 17:09:44 +00001739 /* SVE data, if present, overwrites FPSIMD data. */
1740 if (sve) {
1741 target_restore_sve_record(env, sve, vq);
1742 }
1743
Richard Henderson7a53fb92018-03-09 17:09:43 +00001744 exit:
1745 unlock_user(extra, extra_datap, 0);
1746 return err;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001747}
1748
Richard Henderson8c5931d2018-03-09 17:09:44 +00001749static abi_ulong get_sigframe(struct target_sigaction *ka,
1750 CPUARMState *env, int size)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001751{
1752 abi_ulong sp;
1753
1754 sp = env->xregs[31];
1755
1756 /*
1757 * This is the X/Open sanctioned signal stack switching.
1758 */
Riku Voipiob545f632014-07-15 17:01:55 +03001759 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001760 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1761 }
1762
Richard Henderson8c5931d2018-03-09 17:09:44 +00001763 sp = (sp - size) & ~15;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001764
1765 return sp;
1766}
1767
Richard Henderson8c5931d2018-03-09 17:09:44 +00001768typedef struct {
1769 int total_size;
1770 int extra_base;
1771 int extra_size;
1772 int std_end_ofs;
1773 int extra_ofs;
1774 int extra_end_ofs;
1775} target_sigframe_layout;
1776
1777static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
1778{
1779 /* Make sure there will always be space for the end marker. */
1780 const int std_size = sizeof(struct target_rt_sigframe)
1781 - sizeof(struct target_aarch64_ctx);
1782 int this_loc = l->total_size;
1783
1784 if (l->extra_base) {
1785 /* Once we have begun an extra space, all allocations go there. */
1786 l->extra_size += this_size;
1787 } else if (this_size + this_loc > std_size) {
1788 /* This allocation does not fit in the standard space. */
1789 /* Allocate the extra record. */
1790 l->extra_ofs = this_loc;
1791 l->total_size += sizeof(struct target_extra_context);
1792
1793 /* Allocate the standard end record. */
1794 l->std_end_ofs = l->total_size;
1795 l->total_size += sizeof(struct target_aarch64_ctx);
1796
1797 /* Allocate the requested record. */
1798 l->extra_base = this_loc = l->total_size;
1799 l->extra_size = this_size;
1800 }
1801 l->total_size += this_size;
1802
1803 return this_loc;
1804}
1805
Andreas Schwab1744aea2013-09-03 20:12:16 +01001806static void target_setup_frame(int usig, struct target_sigaction *ka,
1807 target_siginfo_t *info, target_sigset_t *set,
1808 CPUARMState *env)
1809{
Richard Henderson8c5931d2018-03-09 17:09:44 +00001810 target_sigframe_layout layout = {
1811 /* Begin with the size pointing to the reserved space. */
1812 .total_size = offsetof(struct target_rt_sigframe,
1813 uc.tuc_mcontext.__reserved),
1814 };
1815 int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001816 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001817 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001818 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001819
Richard Henderson8c5931d2018-03-09 17:09:44 +00001820 /* FPSIMD record is always in the standard space. */
1821 fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
1822 &layout);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001823
Richard Henderson8c5931d2018-03-09 17:09:44 +00001824 /* SVE state needs saving only if it exists. */
1825 if (arm_feature(env, ARM_FEATURE_SVE)) {
1826 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1827 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1828 sve_ofs = alloc_sigframe_space(sve_size, &layout);
1829 }
1830
1831 if (layout.extra_ofs) {
1832 /* Reserve space for the extra end marker. The standard end marker
1833 * will have been allocated when we allocated the extra record.
1834 */
1835 layout.extra_end_ofs
1836 = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
1837 } else {
1838 /* Reserve space for the standard end marker.
1839 * Do not use alloc_sigframe_space because we cheat
1840 * std_size therein to reserve space for this.
1841 */
1842 layout.std_end_ofs = layout.total_size;
1843 layout.total_size += sizeof(struct target_aarch64_ctx);
1844 }
1845
1846 /* Reserve space for the return code. On a real system this would
1847 * be within the VDSO. So, despite the name this is not a "real"
1848 * record within the frame.
1849 */
1850 fr_ofs = layout.total_size;
1851 layout.total_size += sizeof(struct target_rt_frame_record);
1852
1853 frame_addr = get_sigframe(ka, env, layout.total_size);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001854 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001855 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1856 goto give_sigsegv;
1857 }
1858
Richard Henderson3b505bb2018-03-09 17:09:43 +00001859 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001860 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson8c5931d2018-03-09 17:09:44 +00001861 target_setup_end_record((void *)frame + layout.std_end_ofs);
1862 if (layout.extra_ofs) {
1863 target_setup_extra_record((void *)frame + layout.extra_ofs,
1864 frame_addr + layout.extra_base,
1865 layout.extra_size);
1866 target_setup_end_record((void *)frame + layout.extra_end_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001867 }
Richard Henderson8c5931d2018-03-09 17:09:44 +00001868 if (sve_ofs) {
1869 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001870 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001871
1872 /* Set up the stack frame for unwinding. */
1873 fr = (void *)frame + fr_ofs;
1874 __put_user(env->xregs[29], &fr->fp);
1875 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001876
Michael Matz8a3ae912014-03-02 19:36:39 +00001877 if (ka->sa_flags & TARGET_SA_RESTORER) {
1878 return_addr = ka->sa_restorer;
1879 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001880 /*
1881 * mov x8,#__NR_rt_sigreturn; svc #0
1882 * Since these are instructions they need to be put as little-endian
1883 * regardless of target default or current CPU endianness.
1884 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001885 __put_user_e(0xd2801168, &fr->tramp[0], le);
1886 __put_user_e(0xd4000001, &fr->tramp[1], le);
1887 return_addr = frame_addr + fr_ofs
1888 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001889 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001890 env->xregs[0] = usig;
1891 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001892 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001893 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001894 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001895 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001896 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001897 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1898 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1899 }
1900
1901 unlock_user_struct(frame, frame_addr, 1);
1902 return;
1903
1904 give_sigsegv:
1905 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001906 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001907}
1908
1909static void setup_rt_frame(int sig, struct target_sigaction *ka,
1910 target_siginfo_t *info, target_sigset_t *set,
1911 CPUARMState *env)
1912{
1913 target_setup_frame(sig, ka, info, set, env);
1914}
1915
1916static void setup_frame(int sig, struct target_sigaction *ka,
1917 target_sigset_t *set, CPUARMState *env)
1918{
1919 target_setup_frame(sig, ka, 0, set, env);
1920}
1921
1922long do_rt_sigreturn(CPUARMState *env)
1923{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001924 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001925 abi_ulong frame_addr = env->xregs[31];
1926
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001927 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001928 if (frame_addr & 15) {
1929 goto badframe;
1930 }
1931
1932 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1933 goto badframe;
1934 }
1935
1936 if (target_restore_sigframe(env, frame)) {
1937 goto badframe;
1938 }
1939
1940 if (do_sigaltstack(frame_addr +
1941 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1942 0, get_sp_from_cpustate(env)) == -EFAULT) {
1943 goto badframe;
1944 }
1945
1946 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001947 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001948
1949 badframe:
1950 unlock_user_struct(frame, frame_addr, 0);
1951 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001952 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001953}
1954
1955long do_sigreturn(CPUARMState *env)
1956{
1957 return do_rt_sigreturn(env);
1958}
1959
bellard43fff232003-07-09 19:31:39 +00001960#elif defined(TARGET_ARM)
1961
1962struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001963 abi_ulong trap_no;
1964 abi_ulong error_code;
1965 abi_ulong oldmask;
1966 abi_ulong arm_r0;
1967 abi_ulong arm_r1;
1968 abi_ulong arm_r2;
1969 abi_ulong arm_r3;
1970 abi_ulong arm_r4;
1971 abi_ulong arm_r5;
1972 abi_ulong arm_r6;
1973 abi_ulong arm_r7;
1974 abi_ulong arm_r8;
1975 abi_ulong arm_r9;
1976 abi_ulong arm_r10;
1977 abi_ulong arm_fp;
1978 abi_ulong arm_ip;
1979 abi_ulong arm_sp;
1980 abi_ulong arm_lr;
1981 abi_ulong arm_pc;
1982 abi_ulong arm_cpsr;
1983 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001984};
1985
pbrooka745ec62008-05-06 15:36:17 +00001986struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001987 abi_ulong tuc_flags;
1988 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001989 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001990 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001991 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001992};
1993
pbrooka745ec62008-05-06 15:36:17 +00001994struct target_ucontext_v2 {
1995 abi_ulong tuc_flags;
1996 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001997 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001998 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001999 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00002000 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00002001 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
2002};
2003
Peter Maydell0d871bd2010-11-24 15:20:05 +00002004struct target_user_vfp {
2005 uint64_t fpregs[32];
2006 abi_ulong fpscr;
2007};
2008
2009struct target_user_vfp_exc {
2010 abi_ulong fpexc;
2011 abi_ulong fpinst;
2012 abi_ulong fpinst2;
2013};
2014
2015struct target_vfp_sigframe {
2016 abi_ulong magic;
2017 abi_ulong size;
2018 struct target_user_vfp ufp;
2019 struct target_user_vfp_exc ufp_exc;
2020} __attribute__((__aligned__(8)));
2021
Peter Maydell08e11252010-11-24 15:20:07 +00002022struct target_iwmmxt_sigframe {
2023 abi_ulong magic;
2024 abi_ulong size;
2025 uint64_t regs[16];
2026 /* Note that not all the coprocessor control registers are stored here */
2027 uint32_t wcssf;
2028 uint32_t wcasf;
2029 uint32_t wcgr0;
2030 uint32_t wcgr1;
2031 uint32_t wcgr2;
2032 uint32_t wcgr3;
2033} __attribute__((__aligned__(8)));
2034
Peter Maydell0d871bd2010-11-24 15:20:05 +00002035#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00002036#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00002037
pbrooka8c33202008-05-07 23:22:46 +00002038struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002039{
2040 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00002041 abi_ulong extramask[TARGET_NSIG_WORDS-1];
2042 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002043};
2044
pbrooka8c33202008-05-07 23:22:46 +00002045struct sigframe_v2
2046{
2047 struct target_ucontext_v2 uc;
2048 abi_ulong retcode;
2049};
2050
pbrooka745ec62008-05-06 15:36:17 +00002051struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002052{
bellardf8b0aa22007-11-11 23:03:42 +00002053 abi_ulong pinfo;
2054 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00002055 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00002056 struct target_ucontext_v1 uc;
2057 abi_ulong retcode;
2058};
2059
2060struct rt_sigframe_v2
2061{
2062 struct target_siginfo info;
2063 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00002064 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002065};
2066
2067#define TARGET_CONFIG_CPU_32 1
2068
2069/*
2070 * For ARM syscalls, we encode the syscall number into the instruction.
2071 */
2072#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
2073#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
2074
2075/*
2076 * For Thumb syscalls, we pass the syscall number via r7. We therefore
2077 * need two 16-bit instructions.
2078 */
2079#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
2080#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
2081
blueswir1992f48a2007-10-14 16:27:31 +00002082static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00002083 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
2084 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
2085};
2086
2087
Andreas Färber05390242012-02-25 03:37:53 +01002088static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00002089{
2090 return 1;
2091}
2092
pbrooka8c33202008-05-07 23:22:46 +00002093static void
bellard43fff232003-07-09 19:31:39 +00002094setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002095 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00002096{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002097 __put_user(env->regs[0], &sc->arm_r0);
2098 __put_user(env->regs[1], &sc->arm_r1);
2099 __put_user(env->regs[2], &sc->arm_r2);
2100 __put_user(env->regs[3], &sc->arm_r3);
2101 __put_user(env->regs[4], &sc->arm_r4);
2102 __put_user(env->regs[5], &sc->arm_r5);
2103 __put_user(env->regs[6], &sc->arm_r6);
2104 __put_user(env->regs[7], &sc->arm_r7);
2105 __put_user(env->regs[8], &sc->arm_r8);
2106 __put_user(env->regs[9], &sc->arm_r9);
2107 __put_user(env->regs[10], &sc->arm_r10);
2108 __put_user(env->regs[11], &sc->arm_fp);
2109 __put_user(env->regs[12], &sc->arm_ip);
2110 __put_user(env->regs[13], &sc->arm_sp);
2111 __put_user(env->regs[14], &sc->arm_lr);
2112 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002113#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002114 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00002115#endif
2116
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002117 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
2118 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
2119 __put_user(/* current->thread.address */ 0, &sc->fault_address);
2120 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00002121}
2122
bellard579a97f2007-11-11 14:26:47 +00002123static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002124get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00002125{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002126 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00002127
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002128 /*
2129 * This is the X/Open sanctioned signal stack switching.
2130 */
2131 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
2132 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2133 }
2134 /*
2135 * ATPCS B01 mandates 8-byte alignment
2136 */
2137 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00002138}
2139
Riku Voipio0188fad2014-04-23 13:34:15 +03002140static void
Andreas Färber05390242012-02-25 03:37:53 +01002141setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002142 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00002143{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002144 abi_ulong handler = ka->_sa_handler;
2145 abi_ulong retcode;
2146 int thumb = handler & 1;
2147 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01002148
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002149 cpsr &= ~CPSR_IT;
2150 if (thumb) {
2151 cpsr |= CPSR_T;
2152 } else {
2153 cpsr &= ~CPSR_T;
2154 }
bellard43fff232003-07-09 19:31:39 +00002155
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002156 if (ka->sa_flags & TARGET_SA_RESTORER) {
2157 retcode = ka->sa_restorer;
2158 } else {
2159 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00002160
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002161 if (ka->sa_flags & TARGET_SA_SIGINFO) {
2162 idx += 2;
2163 }
bellard43fff232003-07-09 19:31:39 +00002164
Riku Voipio0188fad2014-04-23 13:34:15 +03002165 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02002166
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002167 retcode = rc_addr + thumb;
2168 }
bellard43fff232003-07-09 19:31:39 +00002169
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002170 env->regs[0] = usig;
2171 env->regs[13] = frame_addr;
2172 env->regs[14] = retcode;
2173 env->regs[15] = handler & (thumb ? ~1 : ~3);
2174 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002175}
2176
Andreas Färber05390242012-02-25 03:37:53 +01002177static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002178{
2179 int i;
2180 struct target_vfp_sigframe *vfpframe;
2181 vfpframe = (struct target_vfp_sigframe *)regspace;
2182 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2183 __put_user(sizeof(*vfpframe), &vfpframe->size);
2184 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002185 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002186 }
2187 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2188 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2189 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2190 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2191 return (abi_ulong*)(vfpframe+1);
2192}
2193
Andreas Färber05390242012-02-25 03:37:53 +01002194static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2195 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002196{
2197 int i;
2198 struct target_iwmmxt_sigframe *iwmmxtframe;
2199 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2200 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2201 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2202 for (i = 0; i < 16; i++) {
2203 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2204 }
2205 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2206 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2207 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2208 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2209 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2210 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2211 return (abi_ulong*)(iwmmxtframe+1);
2212}
2213
pbrooka8c33202008-05-07 23:22:46 +00002214static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002215 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002216{
pbrooka8c33202008-05-07 23:22:46 +00002217 struct target_sigaltstack stack;
2218 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002219 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002220
2221 /* Clear all the bits of the ucontext we don't use. */
2222 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2223
2224 memset(&stack, 0, sizeof(stack));
2225 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2226 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2227 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2228 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2229
2230 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002231 /* Save coprocessor signal frame. */
2232 regspace = uc->tuc_regspace;
2233 if (arm_feature(env, ARM_FEATURE_VFP)) {
2234 regspace = setup_sigframe_v2_vfp(regspace, env);
2235 }
Peter Maydell08e11252010-11-24 15:20:07 +00002236 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2237 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2238 }
2239
Peter Maydell0d871bd2010-11-24 15:20:05 +00002240 /* Write terminating magic word */
2241 __put_user(0, regspace);
2242
pbrooka8c33202008-05-07 23:22:46 +00002243 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2244 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2245 }
2246}
2247
2248/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002249static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002250 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002251{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002252 struct sigframe_v1 *frame;
2253 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2254 int i;
bellard43fff232003-07-09 19:31:39 +00002255
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002256 trace_user_setup_frame(regs, frame_addr);
2257 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002258 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002259 }
bellard579a97f2007-11-11 14:26:47 +00002260
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002262
Riku Voipio0188fad2014-04-23 13:34:15 +03002263 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2264 __put_user(set->sig[i], &frame->extramask[i - 1]);
2265 }
bellard43fff232003-07-09 19:31:39 +00002266
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002267 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2268 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002269
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002270 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002271 return;
2272sigsegv:
2273 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002274}
2275
pbrook624f7972008-05-31 16:11:38 +00002276static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002277 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002278{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002279 struct sigframe_v2 *frame;
2280 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002281
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002282 trace_user_setup_frame(regs, frame_addr);
2283 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002284 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 }
pbrooka8c33202008-05-07 23:22:46 +00002286
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002287 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002288
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002289 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2290 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002292 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002293 return;
2294sigsegv:
2295 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002296}
2297
pbrook624f7972008-05-31 16:11:38 +00002298static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002299 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002300{
2301 if (get_osversion() >= 0x020612) {
2302 setup_frame_v2(usig, ka, set, regs);
2303 } else {
2304 setup_frame_v1(usig, ka, set, regs);
2305 }
bellard43fff232003-07-09 19:31:39 +00002306}
2307
bellard579a97f2007-11-11 14:26:47 +00002308/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002309static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002310 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002311 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002312{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002313 struct rt_sigframe_v1 *frame;
2314 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2315 struct target_sigaltstack stack;
2316 int i;
2317 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002318
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002319 trace_user_setup_rt_frame(env, frame_addr);
2320 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002321 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002322 }
bellardedf779f2004-02-22 13:40:13 +00002323
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002324 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2325 __put_user(info_addr, &frame->pinfo);
2326 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2327 __put_user(uc_addr, &frame->puc);
2328 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002329
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002330 /* Clear all the bits of the ucontext we don't use. */
2331 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002332
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002333 memset(&stack, 0, sizeof(stack));
2334 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2335 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2336 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2337 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002338
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002339 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2340 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2341 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2342 }
bellard43fff232003-07-09 19:31:39 +00002343
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002344 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2345 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002346
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 env->regs[1] = info_addr;
2348 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002349
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002350 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002351 return;
2352sigsegv:
2353 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002354}
2355
pbrook624f7972008-05-31 16:11:38 +00002356static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002357 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002358 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002359{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002360 struct rt_sigframe_v2 *frame;
2361 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2362 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002363
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002364 trace_user_setup_rt_frame(env, frame_addr);
2365 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002366 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002367 }
pbrooka745ec62008-05-06 15:36:17 +00002368
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002369 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2370 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2371 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002372
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002373 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002374
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002375 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2376 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002377
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002378 env->regs[1] = info_addr;
2379 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002380
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002381 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002382 return;
2383sigsegv:
2384 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002385}
2386
pbrook624f7972008-05-31 16:11:38 +00002387static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002388 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002389 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002390{
2391 if (get_osversion() >= 0x020612) {
2392 setup_rt_frame_v2(usig, ka, info, set, env);
2393 } else {
2394 setup_rt_frame_v1(usig, ka, info, set, env);
2395 }
2396}
2397
bellard43fff232003-07-09 19:31:39 +00002398static int
Andreas Färber05390242012-02-25 03:37:53 +01002399restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002400{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002401 int err = 0;
2402 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002403
Riku Voipio1d8b5122014-04-23 10:26:05 +03002404 __get_user(env->regs[0], &sc->arm_r0);
2405 __get_user(env->regs[1], &sc->arm_r1);
2406 __get_user(env->regs[2], &sc->arm_r2);
2407 __get_user(env->regs[3], &sc->arm_r3);
2408 __get_user(env->regs[4], &sc->arm_r4);
2409 __get_user(env->regs[5], &sc->arm_r5);
2410 __get_user(env->regs[6], &sc->arm_r6);
2411 __get_user(env->regs[7], &sc->arm_r7);
2412 __get_user(env->regs[8], &sc->arm_r8);
2413 __get_user(env->regs[9], &sc->arm_r9);
2414 __get_user(env->regs[10], &sc->arm_r10);
2415 __get_user(env->regs[11], &sc->arm_fp);
2416 __get_user(env->regs[12], &sc->arm_ip);
2417 __get_user(env->regs[13], &sc->arm_sp);
2418 __get_user(env->regs[14], &sc->arm_lr);
2419 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002420#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002421 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002422 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002423#endif
2424
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002425 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002426
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002427 return err;
bellard43fff232003-07-09 19:31:39 +00002428}
2429
Andreas Färber05390242012-02-25 03:37:53 +01002430static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002431{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002432 abi_ulong frame_addr;
2433 struct sigframe_v1 *frame = NULL;
2434 target_sigset_t set;
2435 sigset_t host_set;
2436 int i;
bellard43fff232003-07-09 19:31:39 +00002437
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002438 /*
2439 * Since we stacked the signal on a 64-bit boundary,
2440 * then 'sp' should be word aligned here. If it's
2441 * not, then the user is trying to mess with us.
2442 */
2443 frame_addr = env->regs[13];
2444 trace_user_do_sigreturn(env, frame_addr);
2445 if (frame_addr & 7) {
2446 goto badframe;
2447 }
Peter Maydell978fae92013-07-29 12:00:32 +01002448
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002449 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2450 goto badframe;
2451 }
bellard43fff232003-07-09 19:31:39 +00002452
Riku Voipiof5f601a2014-04-23 13:00:17 +03002453 __get_user(set.sig[0], &frame->sc.oldmask);
2454 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2455 __get_user(set.sig[i], &frame->extramask[i - 1]);
2456 }
bellard43fff232003-07-09 19:31:39 +00002457
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002458 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002459 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002460
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002461 if (restore_sigcontext(env, &frame->sc)) {
2462 goto badframe;
2463 }
bellard43fff232003-07-09 19:31:39 +00002464
2465#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002466 /* Send SIGTRAP if we're single-stepping */
2467 if (ptrace_cancel_bpt(current))
2468 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002469#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002470 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002471 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002472
2473badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002474 force_sig(TARGET_SIGSEGV);
2475 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002476}
2477
Andreas Färber05390242012-02-25 03:37:53 +01002478static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002479{
2480 int i;
2481 abi_ulong magic, sz;
2482 uint32_t fpscr, fpexc;
2483 struct target_vfp_sigframe *vfpframe;
2484 vfpframe = (struct target_vfp_sigframe *)regspace;
2485
2486 __get_user(magic, &vfpframe->magic);
2487 __get_user(sz, &vfpframe->size);
2488 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2489 return 0;
2490 }
2491 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002492 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002493 }
2494 __get_user(fpscr, &vfpframe->ufp.fpscr);
2495 vfp_set_fpscr(env, fpscr);
2496 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2497 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2498 * and the exception flag is cleared
2499 */
2500 fpexc |= (1 << 30);
2501 fpexc &= ~((1 << 31) | (1 << 28));
2502 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2503 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2504 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2505 return (abi_ulong*)(vfpframe + 1);
2506}
2507
Andreas Färber05390242012-02-25 03:37:53 +01002508static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2509 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002510{
2511 int i;
2512 abi_ulong magic, sz;
2513 struct target_iwmmxt_sigframe *iwmmxtframe;
2514 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2515
2516 __get_user(magic, &iwmmxtframe->magic);
2517 __get_user(sz, &iwmmxtframe->size);
2518 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2519 return 0;
2520 }
2521 for (i = 0; i < 16; i++) {
2522 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2523 }
2524 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2525 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2526 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2527 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2528 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2529 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2530 return (abi_ulong*)(iwmmxtframe + 1);
2531}
2532
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002533static int do_sigframe_return_v2(CPUARMState *env,
2534 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002535 struct target_ucontext_v2 *uc)
2536{
2537 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002538 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002539
2540 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002541 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002542
2543 if (restore_sigcontext(env, &uc->tuc_mcontext))
2544 return 1;
2545
Peter Maydell5f9099d2010-11-24 15:20:06 +00002546 /* Restore coprocessor signal frame */
2547 regspace = uc->tuc_regspace;
2548 if (arm_feature(env, ARM_FEATURE_VFP)) {
2549 regspace = restore_sigframe_v2_vfp(env, regspace);
2550 if (!regspace) {
2551 return 1;
2552 }
2553 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002554 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2555 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2556 if (!regspace) {
2557 return 1;
2558 }
2559 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002560
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002561 if (do_sigaltstack(context_addr
2562 + offsetof(struct target_ucontext_v2, tuc_stack),
2563 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002564 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002565 }
pbrooka8c33202008-05-07 23:22:46 +00002566
2567#if 0
2568 /* Send SIGTRAP if we're single-stepping */
2569 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002570 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002571#endif
2572
2573 return 0;
2574}
2575
Andreas Färber05390242012-02-25 03:37:53 +01002576static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002577{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002578 abi_ulong frame_addr;
2579 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002580
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002581 /*
2582 * Since we stacked the signal on a 64-bit boundary,
2583 * then 'sp' should be word aligned here. If it's
2584 * not, then the user is trying to mess with us.
2585 */
2586 frame_addr = env->regs[13];
2587 trace_user_do_sigreturn(env, frame_addr);
2588 if (frame_addr & 7) {
2589 goto badframe;
2590 }
Peter Maydell978fae92013-07-29 12:00:32 +01002591
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002592 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2593 goto badframe;
2594 }
pbrooka8c33202008-05-07 23:22:46 +00002595
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002596 if (do_sigframe_return_v2(env,
2597 frame_addr
2598 + offsetof(struct sigframe_v2, uc),
2599 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002600 goto badframe;
2601 }
pbrooka8c33202008-05-07 23:22:46 +00002602
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002603 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002604 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002605
2606badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002607 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002608 force_sig(TARGET_SIGSEGV);
2609 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002610}
2611
Andreas Färber05390242012-02-25 03:37:53 +01002612long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002613{
2614 if (get_osversion() >= 0x020612) {
2615 return do_sigreturn_v2(env);
2616 } else {
2617 return do_sigreturn_v1(env);
2618 }
2619}
2620
Andreas Färber05390242012-02-25 03:37:53 +01002621static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002622{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002623 abi_ulong frame_addr;
2624 struct rt_sigframe_v1 *frame = NULL;
2625 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002626
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002627 /*
2628 * Since we stacked the signal on a 64-bit boundary,
2629 * then 'sp' should be word aligned here. If it's
2630 * not, then the user is trying to mess with us.
2631 */
2632 frame_addr = env->regs[13];
2633 trace_user_do_rt_sigreturn(env, frame_addr);
2634 if (frame_addr & 7) {
2635 goto badframe;
2636 }
Peter Maydell978fae92013-07-29 12:00:32 +01002637
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002638 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2639 goto badframe;
2640 }
bellard43fff232003-07-09 19:31:39 +00002641
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002642 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002643 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002644
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002645 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2646 goto badframe;
2647 }
bellard43fff232003-07-09 19:31:39 +00002648
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002649 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2650 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002651
bellard43fff232003-07-09 19:31:39 +00002652#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002653 /* Send SIGTRAP if we're single-stepping */
2654 if (ptrace_cancel_bpt(current))
2655 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002656#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002657 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002658 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002659
2660badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002661 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002662 force_sig(TARGET_SIGSEGV);
2663 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002664}
2665
Andreas Färber05390242012-02-25 03:37:53 +01002666static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002667{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002668 abi_ulong frame_addr;
2669 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002670
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002671 /*
2672 * Since we stacked the signal on a 64-bit boundary,
2673 * then 'sp' should be word aligned here. If it's
2674 * not, then the user is trying to mess with us.
2675 */
2676 frame_addr = env->regs[13];
2677 trace_user_do_rt_sigreturn(env, frame_addr);
2678 if (frame_addr & 7) {
2679 goto badframe;
2680 }
Peter Maydell978fae92013-07-29 12:00:32 +01002681
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002682 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2683 goto badframe;
2684 }
pbrooka745ec62008-05-06 15:36:17 +00002685
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002686 if (do_sigframe_return_v2(env,
2687 frame_addr
2688 + offsetof(struct rt_sigframe_v2, uc),
2689 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002690 goto badframe;
2691 }
pbrooka745ec62008-05-06 15:36:17 +00002692
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002693 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002694 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002695
2696badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002697 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002698 force_sig(TARGET_SIGSEGV);
2699 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002700}
2701
Andreas Färber05390242012-02-25 03:37:53 +01002702long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002703{
2704 if (get_osversion() >= 0x020612) {
2705 return do_rt_sigreturn_v2(env);
2706 } else {
2707 return do_rt_sigreturn_v1(env);
2708 }
2709}
2710
bellard6d5e2162004-09-30 22:04:13 +00002711#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002712
bellard6d5e2162004-09-30 22:04:13 +00002713#define __SUNOS_MAXWIN 31
2714
2715/* This is what SunOS does, so shall I. */
2716struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002717 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002718
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002719 abi_ulong sigc_mask; /* sigmask to restore */
2720 abi_ulong sigc_sp; /* stack pointer */
2721 abi_ulong sigc_pc; /* program counter */
2722 abi_ulong sigc_npc; /* next program counter */
2723 abi_ulong sigc_psr; /* for condition codes etc */
2724 abi_ulong sigc_g1; /* User uses these two registers */
2725 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002726
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002727 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002728 * at the time of the signal.
2729 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002730 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002731
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002732 /* stack ptrs for each regwin buf */
2733 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002734
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002735 /* Windows to restore after signal */
2736 struct {
2737 abi_ulong locals[8];
2738 abi_ulong ins[8];
2739 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002740};
2741/* A Sparc stack frame */
2742struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002743 abi_ulong locals[8];
2744 abi_ulong ins[8];
2745 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002746 * since we never need to access them ourselves.
2747 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002748 char *structptr;
2749 abi_ulong xargs[6];
2750 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002751};
2752
2753typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002754 struct {
2755 abi_ulong psr;
2756 abi_ulong pc;
2757 abi_ulong npc;
2758 abi_ulong y;
2759 abi_ulong u_regs[16]; /* globals and ins */
2760 } si_regs;
2761 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002762} __siginfo_t;
2763
2764typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002765 abi_ulong si_float_regs[32];
2766 unsigned long si_fsr;
2767 unsigned long si_fpqdepth;
2768 struct {
2769 unsigned long *insn_addr;
2770 unsigned long insn;
2771 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002772} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002773
2774
2775struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002776 struct sparc_stackf ss;
2777 __siginfo_t info;
2778 abi_ulong fpu_save;
2779 abi_ulong insns[2] __attribute__ ((aligned (8)));
2780 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2781 abi_ulong extra_size; /* Should be 0 */
2782 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002783};
2784struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002785 struct sparc_stackf ss;
2786 siginfo_t info;
2787 abi_ulong regs[20];
2788 sigset_t mask;
2789 abi_ulong fpu_save;
2790 unsigned int insns[2];
2791 stack_t stack;
2792 unsigned int extra_size; /* Should be 0 */
2793 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002794};
2795
bellarde80cfcf2004-12-19 23:18:01 +00002796#define UREG_O0 16
2797#define UREG_O6 22
2798#define UREG_I0 0
2799#define UREG_I1 1
2800#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002801#define UREG_I3 3
2802#define UREG_I4 4
2803#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002804#define UREG_I6 6
2805#define UREG_I7 7
2806#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002807#define UREG_FP UREG_I6
2808#define UREG_SP UREG_O6
2809
pbrook624f7972008-05-31 16:11:38 +00002810static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002811 CPUSPARCState *env,
2812 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002813{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002814 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002815
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002816 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002817
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002818 /* This is the X/Open sanctioned signal stack switching. */
2819 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2820 if (!on_sig_stack(sp)
2821 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2822 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2823 }
2824 }
2825 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002826}
2827
2828static int
Andreas Färber05390242012-02-25 03:37:53 +01002829setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002830{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002831 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002832
Riku Voipio1d8b5122014-04-23 10:26:05 +03002833 __put_user(env->psr, &si->si_regs.psr);
2834 __put_user(env->pc, &si->si_regs.pc);
2835 __put_user(env->npc, &si->si_regs.npc);
2836 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002837 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002838 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002839 }
2840 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002841 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002842 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002843 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002844 return err;
bellard6d5e2162004-09-30 22:04:13 +00002845}
bellarde80cfcf2004-12-19 23:18:01 +00002846
bellard80a9d032005-01-03 23:31:27 +00002847#if 0
bellard6d5e2162004-09-30 22:04:13 +00002848static int
2849setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002850 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002851{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002852 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002853
Riku Voipio1d8b5122014-04-23 10:26:05 +03002854 __put_user(mask, &sc->sigc_mask);
2855 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2856 __put_user(env->pc, &sc->sigc_pc);
2857 __put_user(env->npc, &sc->sigc_npc);
2858 __put_user(env->psr, &sc->sigc_psr);
2859 __put_user(env->gregs[1], &sc->sigc_g1);
2860 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002861
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002862 return err;
bellard6d5e2162004-09-30 22:04:13 +00002863}
bellard80a9d032005-01-03 23:31:27 +00002864#endif
bellard6d5e2162004-09-30 22:04:13 +00002865#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2866
pbrook624f7972008-05-31 16:11:38 +00002867static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002868 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002869{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002870 abi_ulong sf_addr;
2871 struct target_signal_frame *sf;
2872 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002873
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002874 /* 1. Make sure everything is clean */
2875 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002876
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002877 sigframe_size = NF_ALIGNEDSZ;
2878 sf_addr = get_sigframe(ka, env, sigframe_size);
2879 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002880
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002881 sf = lock_user(VERIFY_WRITE, sf_addr,
2882 sizeof(struct target_signal_frame), 0);
2883 if (!sf) {
2884 goto sigsegv;
2885 }
bellard6d5e2162004-09-30 22:04:13 +00002886#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002887 if (invalid_frame_pointer(sf, sigframe_size))
2888 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002889#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002890 /* 2. Save the current process state */
2891 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002892 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002893
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002894 //save_fpu_state(regs, &sf->fpu_state);
2895 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002896
Riku Voipio1d8b5122014-04-23 10:26:05 +03002897 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002898 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002899 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002900 }
bellard6d5e2162004-09-30 22:04:13 +00002901
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002902 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002903 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002904 }
2905 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002906 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002907 }
2908 if (err)
2909 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002910
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002911 /* 3. signal handler back-trampoline and parameters */
2912 env->regwptr[UREG_FP] = sf_addr;
2913 env->regwptr[UREG_I0] = sig;
2914 env->regwptr[UREG_I1] = sf_addr +
2915 offsetof(struct target_signal_frame, info);
2916 env->regwptr[UREG_I2] = sf_addr +
2917 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002918
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002919 /* 4. signal handler */
2920 env->pc = ka->_sa_handler;
2921 env->npc = (env->pc + 4);
2922 /* 5. return to kernel instructions */
2923 if (ka->sa_restorer) {
2924 env->regwptr[UREG_I7] = ka->sa_restorer;
2925 } else {
2926 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002927
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002928 env->regwptr[UREG_I7] = sf_addr +
2929 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002930
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002931 /* mov __NR_sigreturn, %g1 */
2932 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002933 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002934
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002935 /* t 0x10 */
2936 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002937 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002938 if (err)
2939 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002940
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002941 /* Flush instruction space. */
2942 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2943 // tb_flush(env);
2944 }
2945 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2946 return;
bellard459a4012007-11-11 19:45:10 +00002947#if 0
2948sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002949 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002950#endif
bellard6d5e2162004-09-30 22:04:13 +00002951sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002952 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002953 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002954}
bellard6d5e2162004-09-30 22:04:13 +00002955
pbrook624f7972008-05-31 16:11:38 +00002956static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002957 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002958 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002959{
2960 fprintf(stderr, "setup_rt_frame: not implemented\n");
2961}
2962
Andreas Färber05390242012-02-25 03:37:53 +01002963long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002964{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002965 abi_ulong sf_addr;
2966 struct target_signal_frame *sf;
2967 uint32_t up_psr, pc, npc;
2968 target_sigset_t set;
2969 sigset_t host_set;
2970 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002971
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002972 sf_addr = env->regwptr[UREG_FP];
2973 trace_user_do_sigreturn(env, sf_addr);
2974 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2975 goto segv_and_exit;
2976 }
bellard6d5e2162004-09-30 22:04:13 +00002977
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002978 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002979
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002980 if (sf_addr & 3)
2981 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002982
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002983 __get_user(pc, &sf->info.si_regs.pc);
2984 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002985
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002986 if ((pc | npc) & 3) {
2987 goto segv_and_exit;
2988 }
bellard6d5e2162004-09-30 22:04:13 +00002989
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002990 /* 2. Restore the state */
2991 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002992
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002993 /* User can only change condition codes and FPU enabling in %psr. */
2994 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2995 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002996
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002997 env->pc = pc;
2998 env->npc = npc;
2999 __get_user(env->y, &sf->info.si_regs.y);
3000 for (i=0; i < 8; i++) {
3001 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
3002 }
3003 for (i=0; i < 8; i++) {
3004 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
3005 }
bellard6d5e2162004-09-30 22:04:13 +00003006
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003007 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01003008 * __get_user(fpu_save, &sf->fpu_save);
3009 * if (fpu_save)
3010 * err |= restore_fpu_state(env, fpu_save);
3011 */
bellard6d5e2162004-09-30 22:04:13 +00003012
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003013 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00003014 * the races which exist anyways.
3015 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003016 __get_user(set.sig[0], &sf->info.si_mask);
3017 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3018 __get_user(set.sig[i], &sf->extramask[i - 1]);
3019 }
bellarde80cfcf2004-12-19 23:18:01 +00003020
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003021 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003022 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00003023
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003024 if (err) {
3025 goto segv_and_exit;
3026 }
3027 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01003028 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003029
3030segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003031 unlock_user_struct(sf, sf_addr, 0);
3032 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003033 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003034}
3035
Andreas Färber05390242012-02-25 03:37:53 +01003036long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00003037{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003038 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00003039 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00003040 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00003041}
3042
bellard459a4012007-11-11 19:45:10 +00003043#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00003044#define SPARC_MC_TSTATE 0
3045#define SPARC_MC_PC 1
3046#define SPARC_MC_NPC 2
3047#define SPARC_MC_Y 3
3048#define SPARC_MC_G1 4
3049#define SPARC_MC_G2 5
3050#define SPARC_MC_G3 6
3051#define SPARC_MC_G4 7
3052#define SPARC_MC_G5 8
3053#define SPARC_MC_G6 9
3054#define SPARC_MC_G7 10
3055#define SPARC_MC_O0 11
3056#define SPARC_MC_O1 12
3057#define SPARC_MC_O2 13
3058#define SPARC_MC_O3 14
3059#define SPARC_MC_O4 15
3060#define SPARC_MC_O5 16
3061#define SPARC_MC_O6 17
3062#define SPARC_MC_O7 18
3063#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00003064
Anthony Liguoric227f092009-10-01 16:12:16 -05003065typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003066typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00003067
3068struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00003069 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003070 uint32_t mcfq_insn;
3071};
3072
3073struct target_mc_fpu {
3074 union {
3075 uint32_t sregs[32];
3076 uint64_t dregs[32];
3077 //uint128_t qregs[16];
3078 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00003079 abi_ulong mcfpu_fsr;
3080 abi_ulong mcfpu_fprs;
3081 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00003082 struct target_mc_fq *mcfpu_fq;
3083 unsigned char mcfpu_qcnt;
3084 unsigned char mcfpu_qentsz;
3085 unsigned char mcfpu_enab;
3086};
Anthony Liguoric227f092009-10-01 16:12:16 -05003087typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003088
3089typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05003090 target_mc_gregset_t mc_gregs;
3091 target_mc_greg_t mc_fp;
3092 target_mc_greg_t mc_i7;
3093 target_mc_fpu_t mc_fpregs;
3094} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003095
3096struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003097 struct target_ucontext *tuc_link;
3098 abi_ulong tuc_flags;
3099 target_sigset_t tuc_sigmask;
3100 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003101};
3102
3103/* A V9 register window */
3104struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00003105 abi_ulong locals[8];
3106 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00003107};
3108
3109#define TARGET_STACK_BIAS 2047
3110
3111/* {set, get}context() needed for 64-bit SparcLinux userland. */
3112void sparc64_set_context(CPUSPARCState *env)
3113{
bellard459a4012007-11-11 19:45:10 +00003114 abi_ulong ucp_addr;
3115 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003116 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00003117 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00003118 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003119 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00003120
bellard459a4012007-11-11 19:45:10 +00003121 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003122 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00003123 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003124 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02003125 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003126 __get_user(pc, &((*grp)[SPARC_MC_PC]));
3127 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003128 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00003129 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003130 }
blueswir15bfb56b2007-10-05 17:01:51 +00003131 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05003132 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003133 sigset_t set;
3134
3135 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003136 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00003137 } else {
bellard459a4012007-11-11 19:45:10 +00003138 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003139 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00003140 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003141 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003142 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003143 }
blueswir15bfb56b2007-10-05 17:01:51 +00003144 }
3145 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003146 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00003147 }
3148 env->pc = pc;
3149 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003150 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
3151 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00003152 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00003153 cpu_put_ccr(env, tstate >> 32);
3154 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00003155 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
3156 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
3157 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
3158 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
3159 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
3160 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
3161 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
3162 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
3163 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
3164 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
3165 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
3166 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
3167 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
3168 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
3169 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003170
Riku Voipio1d8b5122014-04-23 10:26:05 +03003171 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3172 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003173
bellard459a4012007-11-11 19:45:10 +00003174 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003175 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3176 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003177 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003178 }
3179 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3180 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003181 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003182 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003183 /* FIXME this does not match how the kernel handles the FPU in
3184 * its sparc64_set_context implementation. In particular the FPU
3185 * is only restored if fenab is non-zero in:
3186 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3187 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003188 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003189 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003190 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3191 for (i = 0; i < 64; i++, src++) {
3192 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003193 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003194 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003195 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003196 }
3197 }
bellard459a4012007-11-11 19:45:10 +00003198 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003199 __get_user(env->fsr,
3200 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3201 __get_user(env->gsr,
3202 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003203 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003204 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003205do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003206 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003207 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003208}
3209
3210void sparc64_get_context(CPUSPARCState *env)
3211{
bellard459a4012007-11-11 19:45:10 +00003212 abi_ulong ucp_addr;
3213 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003214 target_mc_gregset_t *grp;
3215 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003216 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003217 int err;
3218 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003219 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003220 sigset_t set;
3221
bellard459a4012007-11-11 19:45:10 +00003222 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003223 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003224 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003225 }
bellard459a4012007-11-11 19:45:10 +00003226
Aurelien Jarno60e99242010-03-29 02:12:51 +02003227 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003228 grp = &mcp->mc_gregs;
3229
3230 /* Skip over the trap instruction, first. */
3231 env->pc = env->npc;
3232 env->npc += 4;
3233
Peter Maydell3d3efba2016-05-27 15:51:49 +01003234 /* If we're only reading the signal mask then do_sigprocmask()
3235 * is guaranteed not to fail, which is important because we don't
3236 * have any way to signal a failure or restart this operation since
3237 * this is not a normal syscall.
3238 */
3239 err = do_sigprocmask(0, NULL, &set);
3240 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003241 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003242 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003243 __put_user(target_set.sig[0],
3244 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003245 } else {
3246 abi_ulong *src, *dst;
3247 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003248 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003249 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003250 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003251 }
blueswir15bfb56b2007-10-05 17:01:51 +00003252 if (err)
3253 goto do_sigsegv;
3254 }
3255
bellard459a4012007-11-11 19:45:10 +00003256 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003257 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3258 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3259 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3260 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3261 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3262 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3263 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3264 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3265 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3266 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3267 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3268 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3269 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3270 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3271 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3272 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3273 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3274 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3275 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003276
bellard459a4012007-11-11 19:45:10 +00003277 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3278 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003279 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3280 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003281 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003282 }
3283 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3284 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003285 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003286 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003287 __put_user(fp, &(mcp->mc_fp));
3288 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003289
bellard459a4012007-11-11 19:45:10 +00003290 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003291 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3292 for (i = 0; i < 64; i++, dst++) {
3293 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003294 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003295 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003296 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003297 }
3298 }
bellard459a4012007-11-11 19:45:10 +00003299 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003300 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3301 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3302 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003303
3304 if (err)
3305 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003306 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003307 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003308do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003309 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003310 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003311}
3312#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003313#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003314
Richard Hendersonff970902013-02-10 10:30:42 -08003315# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003316struct target_sigcontext {
3317 uint32_t sc_regmask; /* Unused */
3318 uint32_t sc_status;
3319 uint64_t sc_pc;
3320 uint64_t sc_regs[32];
3321 uint64_t sc_fpregs[32];
3322 uint32_t sc_ownedfp; /* Unused */
3323 uint32_t sc_fpc_csr;
3324 uint32_t sc_fpc_eir; /* Unused */
3325 uint32_t sc_used_math;
3326 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003327 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003328 uint64_t sc_mdhi;
3329 uint64_t sc_mdlo;
3330 target_ulong sc_hi1; /* Was sc_cause */
3331 target_ulong sc_lo1; /* Was sc_badvaddr */
3332 target_ulong sc_hi2; /* Was sc_sigset[4] */
3333 target_ulong sc_lo2;
3334 target_ulong sc_hi3;
3335 target_ulong sc_lo3;
3336};
Richard Hendersonff970902013-02-10 10:30:42 -08003337# else /* N32 || N64 */
3338struct target_sigcontext {
3339 uint64_t sc_regs[32];
3340 uint64_t sc_fpregs[32];
3341 uint64_t sc_mdhi;
3342 uint64_t sc_hi1;
3343 uint64_t sc_hi2;
3344 uint64_t sc_hi3;
3345 uint64_t sc_mdlo;
3346 uint64_t sc_lo1;
3347 uint64_t sc_lo2;
3348 uint64_t sc_lo3;
3349 uint64_t sc_pc;
3350 uint32_t sc_fpc_csr;
3351 uint32_t sc_used_math;
3352 uint32_t sc_dsp;
3353 uint32_t sc_reserved;
3354};
3355# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003356
3357struct sigframe {
3358 uint32_t sf_ass[4]; /* argument save space for o32 */
3359 uint32_t sf_code[2]; /* signal trampoline */
3360 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003361 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003362};
3363
pbrook0b1bcb02009-04-21 01:41:10 +00003364struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003365 target_ulong tuc_flags;
3366 target_ulong tuc_link;
3367 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003368 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003369 struct target_sigcontext tuc_mcontext;
3370 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003371};
3372
3373struct target_rt_sigframe {
3374 uint32_t rs_ass[4]; /* argument save space for o32 */
3375 uint32_t rs_code[2]; /* signal trampoline */
3376 struct target_siginfo rs_info;
3377 struct target_ucontext rs_uc;
3378};
3379
bellard106ec872006-06-27 21:08:10 +00003380/* Install trampoline to jump back from signal handler */
3381static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3382{
Richard Henderson084d0492013-02-10 10:30:44 -08003383 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003384
3385 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003386 * Set up the return code ...
3387 *
3388 * li v0, __NR__foo_sigreturn
3389 * syscall
3390 */
bellard106ec872006-06-27 21:08:10 +00003391
Riku Voipio1d8b5122014-04-23 10:26:05 +03003392 __put_user(0x24020000 + syscall, tramp + 0);
3393 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003394 return err;
3395}
3396
Riku Voipio41ecc722014-04-23 11:01:00 +03003397static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003398 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003399{
Richard Henderson084d0492013-02-10 10:30:44 -08003400 int i;
bellard106ec872006-06-27 21:08:10 +00003401
Riku Voipio1d8b5122014-04-23 10:26:05 +03003402 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003403 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003404
Richard Henderson084d0492013-02-10 10:30:44 -08003405 __put_user(0, &sc->sc_regs[0]);
3406 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003407 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003408 }
bellard106ec872006-06-27 21:08:10 +00003409
Riku Voipio1d8b5122014-04-23 10:26:05 +03003410 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3411 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003412
Richard Henderson084d0492013-02-10 10:30:44 -08003413 /* Rather than checking for dsp existence, always copy. The storage
3414 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003415 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3416 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3417 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3418 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3419 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3420 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003421 {
3422 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003423 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003424 }
Richard Henderson084d0492013-02-10 10:30:44 -08003425
Riku Voipio1d8b5122014-04-23 10:26:05 +03003426 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003427
3428 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003429 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003430 }
bellard106ec872006-06-27 21:08:10 +00003431}
3432
Riku Voipio016d2e12014-04-23 11:19:48 +03003433static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003434restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003435{
Richard Henderson084d0492013-02-10 10:30:44 -08003436 int i;
bellard106ec872006-06-27 21:08:10 +00003437
Riku Voipio1d8b5122014-04-23 10:26:05 +03003438 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003439
Riku Voipio1d8b5122014-04-23 10:26:05 +03003440 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3441 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003442
Richard Henderson084d0492013-02-10 10:30:44 -08003443 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003444 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003445 }
3446
Riku Voipio1d8b5122014-04-23 10:26:05 +03003447 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3448 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3449 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3450 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3451 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3452 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003453 {
3454 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003455 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003456 cpu_wrdsp(dsp, 0x3ff, regs);
3457 }
3458
3459 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003460 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003461 }
bellard106ec872006-06-27 21:08:10 +00003462}
Richard Hendersonff970902013-02-10 10:30:42 -08003463
bellard106ec872006-06-27 21:08:10 +00003464/*
3465 * Determine which stack to use..
3466 */
bellard579a97f2007-11-11 14:26:47 +00003467static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003468get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003469{
3470 unsigned long sp;
3471
3472 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003473 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003474
3475 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003476 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003477 * above the user stack, 16-bytes before the next lowest
3478 * 16 byte boundary. Try to avoid trashing it.
3479 */
3480 sp -= 32;
3481
bellard106ec872006-06-27 21:08:10 +00003482 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003483 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003484 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3485 }
bellard106ec872006-06-27 21:08:10 +00003486
bellard579a97f2007-11-11 14:26:47 +00003487 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003488}
3489
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003490static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3491{
3492 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3493 env->hflags &= ~MIPS_HFLAG_M16;
3494 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3495 env->active_tc.PC &= ~(target_ulong) 1;
3496 }
3497}
3498
Richard Hendersonff970902013-02-10 10:30:42 -08003499# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003500/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003501static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003502 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003503{
3504 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003505 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003506 int i;
3507
bellard579a97f2007-11-11 14:26:47 +00003508 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003509 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003510 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3511 goto give_sigsegv;
3512 }
bellard106ec872006-06-27 21:08:10 +00003513
3514 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3515
Riku Voipio41ecc722014-04-23 11:01:00 +03003516 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003517
3518 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003519 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003520 }
3521
3522 /*
3523 * Arguments to signal handler:
3524 *
3525 * a0 = signal number
3526 * a1 = 0 (should be cause)
3527 * a2 = pointer to struct sigcontext
3528 *
3529 * $25 and PC point to the signal handler, $29 points to the
3530 * struct sigframe.
3531 */
thsb5dc7732008-06-27 10:02:35 +00003532 regs->active_tc.gpr[ 4] = sig;
3533 regs->active_tc.gpr[ 5] = 0;
3534 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3535 regs->active_tc.gpr[29] = frame_addr;
3536 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003537 /* The original kernel code sets CP0_EPC to the handler
3538 * since it returns to userland using eret
3539 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003540 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003541 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003542 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003543 return;
3544
3545give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003546 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003547}
3548
Andreas Färber05390242012-02-25 03:37:53 +01003549long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003550{
ths388bb212007-05-13 13:58:00 +00003551 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003552 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003553 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003554 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003555 int i;
bellard106ec872006-06-27 21:08:10 +00003556
thsb5dc7732008-06-27 10:02:35 +00003557 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003558 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003559 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003560 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003561
ths388bb212007-05-13 13:58:00 +00003562 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003563 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003564 }
bellard106ec872006-06-27 21:08:10 +00003565
ths388bb212007-05-13 13:58:00 +00003566 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003567 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003568
Riku Voipio016d2e12014-04-23 11:19:48 +03003569 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003570
3571#if 0
ths388bb212007-05-13 13:58:00 +00003572 /*
3573 * Don't let your children do this ...
3574 */
3575 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003576 "move\t$29, %0\n\t"
3577 "j\tsyscall_exit"
3578 :/* no outputs */
3579 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003580 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003581#endif
ths3b46e622007-09-17 08:09:54 +00003582
thsb5dc7732008-06-27 10:02:35 +00003583 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003584 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003585 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003586 * maybe a problem with nested signals ? */
3587 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003588 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003589
3590badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003591 force_sig(TARGET_SIGSEGV);
3592 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003593}
Richard Hendersonff970902013-02-10 10:30:42 -08003594# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003595
pbrook624f7972008-05-31 16:11:38 +00003596static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003597 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003598 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003599{
pbrook0b1bcb02009-04-21 01:41:10 +00003600 struct target_rt_sigframe *frame;
3601 abi_ulong frame_addr;
3602 int i;
3603
3604 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003605 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003606 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3607 goto give_sigsegv;
3608 }
pbrook0b1bcb02009-04-21 01:41:10 +00003609
3610 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3611
Peter Maydellf6c7a052015-01-08 12:19:48 +00003612 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003613
Aurelien Jarno60e99242010-03-29 02:12:51 +02003614 __put_user(0, &frame->rs_uc.tuc_flags);
3615 __put_user(0, &frame->rs_uc.tuc_link);
3616 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3617 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003618 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003619 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003620
Aurelien Jarno60e99242010-03-29 02:12:51 +02003621 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003622
3623 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003624 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003625 }
3626
3627 /*
3628 * Arguments to signal handler:
3629 *
3630 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003631 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003632 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003633 *
3634 * $25 and PC point to the signal handler, $29 points to the
3635 * struct sigframe.
3636 */
3637 env->active_tc.gpr[ 4] = sig;
3638 env->active_tc.gpr[ 5] = frame_addr
3639 + offsetof(struct target_rt_sigframe, rs_info);
3640 env->active_tc.gpr[ 6] = frame_addr
3641 + offsetof(struct target_rt_sigframe, rs_uc);
3642 env->active_tc.gpr[29] = frame_addr;
3643 env->active_tc.gpr[31] = frame_addr
3644 + offsetof(struct target_rt_sigframe, rs_code);
3645 /* The original kernel code sets CP0_EPC to the handler
3646 * since it returns to userland using eret
3647 * we cannot do this here, and we must set PC directly */
3648 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003649 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003650 unlock_user_struct(frame, frame_addr, 1);
3651 return;
3652
3653give_sigsegv:
3654 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003655 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003656}
3657
Andreas Färber05390242012-02-25 03:37:53 +01003658long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003659{
pbrook0b1bcb02009-04-21 01:41:10 +00003660 struct target_rt_sigframe *frame;
3661 abi_ulong frame_addr;
3662 sigset_t blocked;
3663
pbrook0b1bcb02009-04-21 01:41:10 +00003664 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003665 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003666 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3667 goto badframe;
3668 }
pbrook0b1bcb02009-04-21 01:41:10 +00003669
Aurelien Jarno60e99242010-03-29 02:12:51 +02003670 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003671 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003672
Riku Voipio016d2e12014-04-23 11:19:48 +03003673 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003674
3675 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003676 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3677 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003678 goto badframe;
3679
3680 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003681 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003682 /* I am not sure this is right, but it seems to work
3683 * maybe a problem with nested signals ? */
3684 env->CP0_EPC = 0;
3685 return -TARGET_QEMU_ESIGRETURN;
3686
3687badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003688 force_sig(TARGET_SIGSEGV);
3689 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003690}
bellard6d5e2162004-09-30 22:04:13 +00003691
thsc3b5bc82007-12-02 06:31:25 +00003692#elif defined(TARGET_SH4)
3693
3694/*
3695 * code and data structures from linux kernel:
3696 * include/asm-sh/sigcontext.h
3697 * arch/sh/kernel/signal.c
3698 */
3699
3700struct target_sigcontext {
3701 target_ulong oldmask;
3702
3703 /* CPU registers */
3704 target_ulong sc_gregs[16];
3705 target_ulong sc_pc;
3706 target_ulong sc_pr;
3707 target_ulong sc_sr;
3708 target_ulong sc_gbr;
3709 target_ulong sc_mach;
3710 target_ulong sc_macl;
3711
3712 /* FPU registers */
3713 target_ulong sc_fpregs[16];
3714 target_ulong sc_xfpregs[16];
3715 unsigned int sc_fpscr;
3716 unsigned int sc_fpul;
3717 unsigned int sc_ownedfp;
3718};
3719
3720struct target_sigframe
3721{
3722 struct target_sigcontext sc;
3723 target_ulong extramask[TARGET_NSIG_WORDS-1];
3724 uint16_t retcode[3];
3725};
3726
3727
3728struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003729 target_ulong tuc_flags;
3730 struct target_ucontext *tuc_link;
3731 target_stack_t tuc_stack;
3732 struct target_sigcontext tuc_mcontext;
3733 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003734};
3735
3736struct target_rt_sigframe
3737{
3738 struct target_siginfo info;
3739 struct target_ucontext uc;
3740 uint16_t retcode[3];
3741};
3742
3743
3744#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3745#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3746
pbrook624f7972008-05-31 16:11:38 +00003747static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003748 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003749{
pbrook624f7972008-05-31 16:11:38 +00003750 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003751 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3752 }
3753
3754 return (sp - frame_size) & -8ul;
3755}
3756
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003757/* Notice when we're in the middle of a gUSA region and reset.
3758 Note that this will only occur for !parallel_cpus, as we will
3759 translate such sequences differently in a parallel context. */
3760static void unwind_gusa(CPUSH4State *regs)
3761{
3762 /* If the stack pointer is sufficiently negative, and we haven't
3763 completed the sequence, then reset to the entry to the region. */
3764 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3765 However, the page mappings in qemu linux-user aren't as restricted
3766 and we wind up with the normal stack mapped above 0xF0000000.
3767 That said, there is no reason why the kernel should be allowing
3768 a gUSA region that spans 1GB. Use a tighter check here, for what
3769 can actually be enabled by the immediate move. */
3770 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3771 /* Reset the PC to before the gUSA region, as computed from
3772 R0 = region end, SP = -(region size), plus one more for the
3773 insn that actually initializes SP to the region size. */
3774 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3775
3776 /* Reset the SP to the saved version in R1. */
3777 regs->gregs[15] = regs->gregs[1];
3778 }
3779}
3780
Riku Voipio41ecc722014-04-23 11:01:00 +03003781static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003782 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003783{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003784 int i;
thsc3b5bc82007-12-02 06:31:25 +00003785
Riku Voipio1d8b5122014-04-23 10:26:05 +03003786#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003787 COPY(gregs[0]); COPY(gregs[1]);
3788 COPY(gregs[2]); COPY(gregs[3]);
3789 COPY(gregs[4]); COPY(gregs[5]);
3790 COPY(gregs[6]); COPY(gregs[7]);
3791 COPY(gregs[8]); COPY(gregs[9]);
3792 COPY(gregs[10]); COPY(gregs[11]);
3793 COPY(gregs[12]); COPY(gregs[13]);
3794 COPY(gregs[14]); COPY(gregs[15]);
3795 COPY(gbr); COPY(mach);
3796 COPY(macl); COPY(pr);
3797 COPY(sr); COPY(pc);
3798#undef COPY
3799
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003800 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003801 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003802 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003803 __put_user(regs->fpscr, &sc->sc_fpscr);
3804 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003805
3806 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003807 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003808}
3809
Timothy E Baldwinba412492016-05-12 18:47:35 +01003810static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003811{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003812 int i;
thsc3b5bc82007-12-02 06:31:25 +00003813
Riku Voipio1d8b5122014-04-23 10:26:05 +03003814#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003815 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003816 COPY(gregs[2]); COPY(gregs[3]);
3817 COPY(gregs[4]); COPY(gregs[5]);
3818 COPY(gregs[6]); COPY(gregs[7]);
3819 COPY(gregs[8]); COPY(gregs[9]);
3820 COPY(gregs[10]); COPY(gregs[11]);
3821 COPY(gregs[12]); COPY(gregs[13]);
3822 COPY(gregs[14]); COPY(gregs[15]);
3823 COPY(gbr); COPY(mach);
3824 COPY(macl); COPY(pr);
3825 COPY(sr); COPY(pc);
3826#undef COPY
3827
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003828 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003829 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003830 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003831 __get_user(regs->fpscr, &sc->sc_fpscr);
3832 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003833
3834 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003835 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003836}
3837
pbrook624f7972008-05-31 16:11:38 +00003838static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003839 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003840{
3841 struct target_sigframe *frame;
3842 abi_ulong frame_addr;
3843 int i;
thsc3b5bc82007-12-02 06:31:25 +00003844
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003845 unwind_gusa(regs);
3846
thsc3b5bc82007-12-02 06:31:25 +00003847 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003848 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003849 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3850 goto give_sigsegv;
3851 }
thsc3b5bc82007-12-02 06:31:25 +00003852
Riku Voipio41ecc722014-04-23 11:01:00 +03003853 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003854
3855 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003856 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003857 }
3858
3859 /* Set up to return from userspace. If provided, use a stub
3860 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003861 if (ka->sa_flags & TARGET_SA_RESTORER) {
3862 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003863 } else {
3864 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003865 abi_ulong retcode_addr = frame_addr +
3866 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003867 __put_user(MOVW(2), &frame->retcode[0]);
3868 __put_user(TRAP_NOARG, &frame->retcode[1]);
3869 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003870 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003871 }
3872
thsc3b5bc82007-12-02 06:31:25 +00003873 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003874 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003875 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003876 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003877 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003878 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003879 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003880
3881 unlock_user_struct(frame, frame_addr, 1);
3882 return;
3883
3884give_sigsegv:
3885 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003886 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003887}
3888
pbrook624f7972008-05-31 16:11:38 +00003889static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003890 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003891 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003892{
3893 struct target_rt_sigframe *frame;
3894 abi_ulong frame_addr;
3895 int i;
thsc3b5bc82007-12-02 06:31:25 +00003896
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003897 unwind_gusa(regs);
3898
thsc3b5bc82007-12-02 06:31:25 +00003899 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003900 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003901 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3902 goto give_sigsegv;
3903 }
thsc3b5bc82007-12-02 06:31:25 +00003904
Peter Maydellf6c7a052015-01-08 12:19:48 +00003905 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003906
3907 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003908 __put_user(0, &frame->uc.tuc_flags);
3909 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3910 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3911 &frame->uc.tuc_stack.ss_sp);
3912 __put_user(sas_ss_flags(regs->gregs[15]),
3913 &frame->uc.tuc_stack.ss_flags);
3914 __put_user(target_sigaltstack_used.ss_size,
3915 &frame->uc.tuc_stack.ss_size);
3916 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003917 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003918 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003919 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003920 }
3921
3922 /* Set up to return from userspace. If provided, use a stub
3923 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003924 if (ka->sa_flags & TARGET_SA_RESTORER) {
3925 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003926 } else {
3927 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003928 abi_ulong retcode_addr = frame_addr +
3929 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003930 __put_user(MOVW(2), &frame->retcode[0]);
3931 __put_user(TRAP_NOARG, &frame->retcode[1]);
3932 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003933 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003934 }
3935
thsc3b5bc82007-12-02 06:31:25 +00003936 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003937 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003938 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003939 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3940 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003941 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003942 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003943
3944 unlock_user_struct(frame, frame_addr, 1);
3945 return;
3946
3947give_sigsegv:
3948 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003949 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003950}
3951
Andreas Färber05390242012-02-25 03:37:53 +01003952long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003953{
3954 struct target_sigframe *frame;
3955 abi_ulong frame_addr;
3956 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003957 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003958 int i;
3959 int err = 0;
3960
thsc3b5bc82007-12-02 06:31:25 +00003961 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003962 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003963 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3964 goto badframe;
3965 }
thsc3b5bc82007-12-02 06:31:25 +00003966
Riku Voipio1d8b5122014-04-23 10:26:05 +03003967 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003968 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003969 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003970 }
3971
3972 if (err)
3973 goto badframe;
3974
3975 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003976 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003977
Timothy E Baldwinba412492016-05-12 18:47:35 +01003978 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003979
3980 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003981 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003982
3983badframe:
3984 unlock_user_struct(frame, frame_addr, 0);
3985 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003986 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003987}
3988
Andreas Färber05390242012-02-25 03:37:53 +01003989long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003990{
3991 struct target_rt_sigframe *frame;
3992 abi_ulong frame_addr;
3993 sigset_t blocked;
3994
thsc3b5bc82007-12-02 06:31:25 +00003995 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003996 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003997 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3998 goto badframe;
3999 }
thsc3b5bc82007-12-02 06:31:25 +00004000
Aurelien Jarno60e99242010-03-29 02:12:51 +02004001 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004002 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00004003
Timothy E Baldwinba412492016-05-12 18:47:35 +01004004 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00004005
4006 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004007 offsetof(struct target_rt_sigframe, uc.tuc_stack),
4008 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00004009 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004010 }
thsc3b5bc82007-12-02 06:31:25 +00004011
4012 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01004013 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004014
4015badframe:
4016 unlock_user_struct(frame, frame_addr, 0);
4017 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004018 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004019}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004020#elif defined(TARGET_MICROBLAZE)
4021
4022struct target_sigcontext {
4023 struct target_pt_regs regs; /* needs to be first */
4024 uint32_t oldmask;
4025};
4026
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004027struct target_stack_t {
4028 abi_ulong ss_sp;
4029 int ss_flags;
4030 unsigned int ss_size;
4031};
4032
4033struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08004034 abi_ulong tuc_flags;
4035 abi_ulong tuc_link;
4036 struct target_stack_t tuc_stack;
4037 struct target_sigcontext tuc_mcontext;
4038 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004039};
4040
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004041/* Signal frames. */
4042struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004043 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004044 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4045 uint32_t tramp[2];
4046};
4047
4048struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00004049 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004050 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004051 uint32_t tramp[2];
4052};
4053
Andreas Färber05390242012-02-25 03:37:53 +01004054static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004055{
4056 __put_user(env->regs[0], &sc->regs.r0);
4057 __put_user(env->regs[1], &sc->regs.r1);
4058 __put_user(env->regs[2], &sc->regs.r2);
4059 __put_user(env->regs[3], &sc->regs.r3);
4060 __put_user(env->regs[4], &sc->regs.r4);
4061 __put_user(env->regs[5], &sc->regs.r5);
4062 __put_user(env->regs[6], &sc->regs.r6);
4063 __put_user(env->regs[7], &sc->regs.r7);
4064 __put_user(env->regs[8], &sc->regs.r8);
4065 __put_user(env->regs[9], &sc->regs.r9);
4066 __put_user(env->regs[10], &sc->regs.r10);
4067 __put_user(env->regs[11], &sc->regs.r11);
4068 __put_user(env->regs[12], &sc->regs.r12);
4069 __put_user(env->regs[13], &sc->regs.r13);
4070 __put_user(env->regs[14], &sc->regs.r14);
4071 __put_user(env->regs[15], &sc->regs.r15);
4072 __put_user(env->regs[16], &sc->regs.r16);
4073 __put_user(env->regs[17], &sc->regs.r17);
4074 __put_user(env->regs[18], &sc->regs.r18);
4075 __put_user(env->regs[19], &sc->regs.r19);
4076 __put_user(env->regs[20], &sc->regs.r20);
4077 __put_user(env->regs[21], &sc->regs.r21);
4078 __put_user(env->regs[22], &sc->regs.r22);
4079 __put_user(env->regs[23], &sc->regs.r23);
4080 __put_user(env->regs[24], &sc->regs.r24);
4081 __put_user(env->regs[25], &sc->regs.r25);
4082 __put_user(env->regs[26], &sc->regs.r26);
4083 __put_user(env->regs[27], &sc->regs.r27);
4084 __put_user(env->regs[28], &sc->regs.r28);
4085 __put_user(env->regs[29], &sc->regs.r29);
4086 __put_user(env->regs[30], &sc->regs.r30);
4087 __put_user(env->regs[31], &sc->regs.r31);
4088 __put_user(env->sregs[SR_PC], &sc->regs.pc);
4089}
4090
Andreas Färber05390242012-02-25 03:37:53 +01004091static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004092{
4093 __get_user(env->regs[0], &sc->regs.r0);
4094 __get_user(env->regs[1], &sc->regs.r1);
4095 __get_user(env->regs[2], &sc->regs.r2);
4096 __get_user(env->regs[3], &sc->regs.r3);
4097 __get_user(env->regs[4], &sc->regs.r4);
4098 __get_user(env->regs[5], &sc->regs.r5);
4099 __get_user(env->regs[6], &sc->regs.r6);
4100 __get_user(env->regs[7], &sc->regs.r7);
4101 __get_user(env->regs[8], &sc->regs.r8);
4102 __get_user(env->regs[9], &sc->regs.r9);
4103 __get_user(env->regs[10], &sc->regs.r10);
4104 __get_user(env->regs[11], &sc->regs.r11);
4105 __get_user(env->regs[12], &sc->regs.r12);
4106 __get_user(env->regs[13], &sc->regs.r13);
4107 __get_user(env->regs[14], &sc->regs.r14);
4108 __get_user(env->regs[15], &sc->regs.r15);
4109 __get_user(env->regs[16], &sc->regs.r16);
4110 __get_user(env->regs[17], &sc->regs.r17);
4111 __get_user(env->regs[18], &sc->regs.r18);
4112 __get_user(env->regs[19], &sc->regs.r19);
4113 __get_user(env->regs[20], &sc->regs.r20);
4114 __get_user(env->regs[21], &sc->regs.r21);
4115 __get_user(env->regs[22], &sc->regs.r22);
4116 __get_user(env->regs[23], &sc->regs.r23);
4117 __get_user(env->regs[24], &sc->regs.r24);
4118 __get_user(env->regs[25], &sc->regs.r25);
4119 __get_user(env->regs[26], &sc->regs.r26);
4120 __get_user(env->regs[27], &sc->regs.r27);
4121 __get_user(env->regs[28], &sc->regs.r28);
4122 __get_user(env->regs[29], &sc->regs.r29);
4123 __get_user(env->regs[30], &sc->regs.r30);
4124 __get_user(env->regs[31], &sc->regs.r31);
4125 __get_user(env->sregs[SR_PC], &sc->regs.pc);
4126}
4127
4128static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004129 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004130{
4131 abi_ulong sp = env->regs[1];
4132
Riku Voipiob545f632014-07-15 17:01:55 +03004133 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004134 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03004135 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004136
4137 return ((sp - frame_size) & -8UL);
4138}
4139
4140static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004141 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004142{
4143 struct target_signal_frame *frame;
4144 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004145 int i;
4146
4147 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004148 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004149 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4150 goto badframe;
4151
4152 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004153 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004154
4155 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03004156 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004157 }
4158
Richard Hendersonf711df62010-11-22 14:57:52 -08004159 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004160
4161 /* Set up to return from userspace. If provided, use a stub
4162 already in userspace. */
4163 /* minus 8 is offset to cater for "rtsd r15,8" offset */
4164 if (ka->sa_flags & TARGET_SA_RESTORER) {
4165 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
4166 } else {
4167 uint32_t t;
4168 /* Note, these encodings are _big endian_! */
4169 /* addi r12, r0, __NR_sigreturn */
4170 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004171 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004172 /* brki r14, 0x8 */
4173 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004174 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004175
4176 /* Return from sighandler will jump to the tramp.
4177 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004178 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4179 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004180 }
4181
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004182 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004183 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004184 /* Signal handler args: */
4185 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004186 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004187 /* arg 1: sigcontext */
4188 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004189
4190 /* Offset of 4 to handle microblaze rtid r14, 0 */
4191 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4192
4193 unlock_user_struct(frame, frame_addr, 1);
4194 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004195badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004196 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004197}
4198
4199static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004200 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004201 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004202{
4203 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4204}
4205
Andreas Färber05390242012-02-25 03:37:53 +01004206long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004207{
4208 struct target_signal_frame *frame;
4209 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004210 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004211 sigset_t set;
4212 int i;
4213
4214 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004215 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004216 /* Make sure the guest isn't playing games. */
4217 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4218 goto badframe;
4219
4220 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004221 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004222 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004223 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004224 }
4225 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004226 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004227
Richard Hendersonf711df62010-11-22 14:57:52 -08004228 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004229 /* We got here through a sigreturn syscall, our path back is via an
4230 rtb insn so setup r14 for that. */
4231 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004232
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004233 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004234 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004235badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004236 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004237 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004238}
4239
Andreas Färber05390242012-02-25 03:37:53 +01004240long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004241{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004242 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004243 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4244 return -TARGET_ENOSYS;
4245}
4246
edgar_iglb6d3abd2008-02-28 11:29:27 +00004247#elif defined(TARGET_CRIS)
4248
4249struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004250 struct target_pt_regs regs; /* needs to be first */
4251 uint32_t oldmask;
4252 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004253};
4254
4255/* Signal frames. */
4256struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004257 struct target_sigcontext sc;
4258 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4259 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004260};
4261
4262struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004263 siginfo_t *pinfo;
4264 void *puc;
4265 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004266 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004267 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004268};
4269
Andreas Färber05390242012-02-25 03:37:53 +01004270static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004271{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004272 __put_user(env->regs[0], &sc->regs.r0);
4273 __put_user(env->regs[1], &sc->regs.r1);
4274 __put_user(env->regs[2], &sc->regs.r2);
4275 __put_user(env->regs[3], &sc->regs.r3);
4276 __put_user(env->regs[4], &sc->regs.r4);
4277 __put_user(env->regs[5], &sc->regs.r5);
4278 __put_user(env->regs[6], &sc->regs.r6);
4279 __put_user(env->regs[7], &sc->regs.r7);
4280 __put_user(env->regs[8], &sc->regs.r8);
4281 __put_user(env->regs[9], &sc->regs.r9);
4282 __put_user(env->regs[10], &sc->regs.r10);
4283 __put_user(env->regs[11], &sc->regs.r11);
4284 __put_user(env->regs[12], &sc->regs.r12);
4285 __put_user(env->regs[13], &sc->regs.r13);
4286 __put_user(env->regs[14], &sc->usp);
4287 __put_user(env->regs[15], &sc->regs.acr);
4288 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4289 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4290 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004291}
edgar_igl9664d922008-03-03 22:23:53 +00004292
Andreas Färber05390242012-02-25 03:37:53 +01004293static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004294{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004295 __get_user(env->regs[0], &sc->regs.r0);
4296 __get_user(env->regs[1], &sc->regs.r1);
4297 __get_user(env->regs[2], &sc->regs.r2);
4298 __get_user(env->regs[3], &sc->regs.r3);
4299 __get_user(env->regs[4], &sc->regs.r4);
4300 __get_user(env->regs[5], &sc->regs.r5);
4301 __get_user(env->regs[6], &sc->regs.r6);
4302 __get_user(env->regs[7], &sc->regs.r7);
4303 __get_user(env->regs[8], &sc->regs.r8);
4304 __get_user(env->regs[9], &sc->regs.r9);
4305 __get_user(env->regs[10], &sc->regs.r10);
4306 __get_user(env->regs[11], &sc->regs.r11);
4307 __get_user(env->regs[12], &sc->regs.r12);
4308 __get_user(env->regs[13], &sc->regs.r13);
4309 __get_user(env->regs[14], &sc->usp);
4310 __get_user(env->regs[15], &sc->regs.acr);
4311 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4312 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4313 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004314}
4315
Andreas Färber05390242012-02-25 03:37:53 +01004316static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004317{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004318 abi_ulong sp;
4319 /* Align the stack downwards to 4. */
4320 sp = (env->regs[R_SP] & ~3);
4321 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004322}
4323
pbrook624f7972008-05-31 16:11:38 +00004324static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004325 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004326{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004327 struct target_signal_frame *frame;
4328 abi_ulong frame_addr;
4329 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004330
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004331 frame_addr = get_sigframe(env, sizeof *frame);
4332 trace_user_setup_frame(env, frame_addr);
4333 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4334 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004335
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004336 /*
4337 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4338 * use this trampoline anymore but it sets it up for GDB.
4339 * In QEMU, using the trampoline simplifies things a bit so we use it.
4340 *
4341 * This is movu.w __NR_sigreturn, r9; break 13;
4342 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004343 __put_user(0x9c5f, frame->retcode+0);
4344 __put_user(TARGET_NR_sigreturn,
4345 frame->retcode + 1);
4346 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004347
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004348 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004349 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004350
Riku Voipio0188fad2014-04-23 13:34:15 +03004351 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4352 __put_user(set->sig[i], &frame->extramask[i - 1]);
4353 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004354
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004355 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004356
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004357 /* Move the stack and setup the arguments for the handler. */
4358 env->regs[R_SP] = frame_addr;
4359 env->regs[10] = sig;
4360 env->pc = (unsigned long) ka->_sa_handler;
4361 /* Link SRP so the guest returns through the trampoline. */
4362 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004363
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004364 unlock_user_struct(frame, frame_addr, 1);
4365 return;
4366badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004367 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004368}
4369
pbrook624f7972008-05-31 16:11:38 +00004370static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004371 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004372 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004373{
4374 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4375}
4376
Andreas Färber05390242012-02-25 03:37:53 +01004377long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004378{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004379 struct target_signal_frame *frame;
4380 abi_ulong frame_addr;
4381 target_sigset_t target_set;
4382 sigset_t set;
4383 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004384
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004385 frame_addr = env->regs[R_SP];
4386 trace_user_do_sigreturn(env, frame_addr);
4387 /* Make sure the guest isn't playing games. */
4388 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4389 goto badframe;
4390 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004391
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004392 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004393 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004394 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004395 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004396 }
4397 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004398 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004399
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004400 restore_sigcontext(&frame->sc, env);
4401 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004402 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004403badframe:
4404 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004405 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004406}
4407
Andreas Färber05390242012-02-25 03:37:53 +01004408long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004409{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004410 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004411 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4412 return -TARGET_ENOSYS;
4413}
thsc3b5bc82007-12-02 06:31:25 +00004414
Marek Vasuta0a839b2017-01-18 23:01:42 +01004415#elif defined(TARGET_NIOS2)
4416
4417#define MCONTEXT_VERSION 2
4418
4419struct target_sigcontext {
4420 int version;
4421 unsigned long gregs[32];
4422};
4423
4424struct target_ucontext {
4425 abi_ulong tuc_flags;
4426 abi_ulong tuc_link;
4427 target_stack_t tuc_stack;
4428 struct target_sigcontext tuc_mcontext;
4429 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4430};
4431
4432struct target_rt_sigframe {
4433 struct target_siginfo info;
4434 struct target_ucontext uc;
4435};
4436
4437static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4438{
4439 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4440#ifdef CONFIG_STACK_GROWSUP
4441 return target_sigaltstack_used.ss_sp;
4442#else
4443 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4444#endif
4445 }
4446 return sp;
4447}
4448
4449static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4450{
4451 unsigned long *gregs = uc->tuc_mcontext.gregs;
4452
4453 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4454 __put_user(env->regs[1], &gregs[0]);
4455 __put_user(env->regs[2], &gregs[1]);
4456 __put_user(env->regs[3], &gregs[2]);
4457 __put_user(env->regs[4], &gregs[3]);
4458 __put_user(env->regs[5], &gregs[4]);
4459 __put_user(env->regs[6], &gregs[5]);
4460 __put_user(env->regs[7], &gregs[6]);
4461 __put_user(env->regs[8], &gregs[7]);
4462 __put_user(env->regs[9], &gregs[8]);
4463 __put_user(env->regs[10], &gregs[9]);
4464 __put_user(env->regs[11], &gregs[10]);
4465 __put_user(env->regs[12], &gregs[11]);
4466 __put_user(env->regs[13], &gregs[12]);
4467 __put_user(env->regs[14], &gregs[13]);
4468 __put_user(env->regs[15], &gregs[14]);
4469 __put_user(env->regs[16], &gregs[15]);
4470 __put_user(env->regs[17], &gregs[16]);
4471 __put_user(env->regs[18], &gregs[17]);
4472 __put_user(env->regs[19], &gregs[18]);
4473 __put_user(env->regs[20], &gregs[19]);
4474 __put_user(env->regs[21], &gregs[20]);
4475 __put_user(env->regs[22], &gregs[21]);
4476 __put_user(env->regs[23], &gregs[22]);
4477 __put_user(env->regs[R_RA], &gregs[23]);
4478 __put_user(env->regs[R_FP], &gregs[24]);
4479 __put_user(env->regs[R_GP], &gregs[25]);
4480 __put_user(env->regs[R_EA], &gregs[27]);
4481 __put_user(env->regs[R_SP], &gregs[28]);
4482
4483 return 0;
4484}
4485
4486static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4487 int *pr2)
4488{
4489 int temp;
4490 abi_ulong off, frame_addr = env->regs[R_SP];
4491 unsigned long *gregs = uc->tuc_mcontext.gregs;
4492 int err;
4493
4494 /* Always make any pending restarted system calls return -EINTR */
4495 /* current->restart_block.fn = do_no_restart_syscall; */
4496
4497 __get_user(temp, &uc->tuc_mcontext.version);
4498 if (temp != MCONTEXT_VERSION) {
4499 return 1;
4500 }
4501
4502 /* restore passed registers */
4503 __get_user(env->regs[1], &gregs[0]);
4504 __get_user(env->regs[2], &gregs[1]);
4505 __get_user(env->regs[3], &gregs[2]);
4506 __get_user(env->regs[4], &gregs[3]);
4507 __get_user(env->regs[5], &gregs[4]);
4508 __get_user(env->regs[6], &gregs[5]);
4509 __get_user(env->regs[7], &gregs[6]);
4510 __get_user(env->regs[8], &gregs[7]);
4511 __get_user(env->regs[9], &gregs[8]);
4512 __get_user(env->regs[10], &gregs[9]);
4513 __get_user(env->regs[11], &gregs[10]);
4514 __get_user(env->regs[12], &gregs[11]);
4515 __get_user(env->regs[13], &gregs[12]);
4516 __get_user(env->regs[14], &gregs[13]);
4517 __get_user(env->regs[15], &gregs[14]);
4518 __get_user(env->regs[16], &gregs[15]);
4519 __get_user(env->regs[17], &gregs[16]);
4520 __get_user(env->regs[18], &gregs[17]);
4521 __get_user(env->regs[19], &gregs[18]);
4522 __get_user(env->regs[20], &gregs[19]);
4523 __get_user(env->regs[21], &gregs[20]);
4524 __get_user(env->regs[22], &gregs[21]);
4525 __get_user(env->regs[23], &gregs[22]);
4526 /* gregs[23] is handled below */
4527 /* Verify, should this be settable */
4528 __get_user(env->regs[R_FP], &gregs[24]);
4529 /* Verify, should this be settable */
4530 __get_user(env->regs[R_GP], &gregs[25]);
4531 /* Not really necessary no user settable bits */
4532 __get_user(temp, &gregs[26]);
4533 __get_user(env->regs[R_EA], &gregs[27]);
4534
4535 __get_user(env->regs[R_RA], &gregs[23]);
4536 __get_user(env->regs[R_SP], &gregs[28]);
4537
4538 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4539 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4540 if (err == -EFAULT) {
4541 return 1;
4542 }
4543
4544 *pr2 = env->regs[2];
4545 return 0;
4546}
4547
4548static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4549 size_t frame_size)
4550{
4551 unsigned long usp;
4552
4553 /* Default to using normal stack. */
4554 usp = env->regs[R_SP];
4555
4556 /* This is the X/Open sanctioned signal stack switching. */
4557 usp = sigsp(usp, ka);
4558
4559 /* Verify, is it 32 or 64 bit aligned */
4560 return (void *)((usp - frame_size) & -8UL);
4561}
4562
4563static void setup_rt_frame(int sig, struct target_sigaction *ka,
4564 target_siginfo_t *info,
4565 target_sigset_t *set,
4566 CPUNios2State *env)
4567{
4568 struct target_rt_sigframe *frame;
4569 int i, err = 0;
4570
4571 frame = get_sigframe(ka, env, sizeof(*frame));
4572
4573 if (ka->sa_flags & SA_SIGINFO) {
4574 tswap_siginfo(&frame->info, info);
4575 }
4576
4577 /* Create the ucontext. */
4578 __put_user(0, &frame->uc.tuc_flags);
4579 __put_user(0, &frame->uc.tuc_link);
4580 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4581 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4582 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4583 err |= rt_setup_ucontext(&frame->uc, env);
4584 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4585 __put_user((abi_ulong)set->sig[i],
4586 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4587 }
4588
4589 if (err) {
4590 goto give_sigsegv;
4591 }
4592
4593 /* Set up to return from userspace; jump to fixed address sigreturn
4594 trampoline on kuser page. */
4595 env->regs[R_RA] = (unsigned long) (0x1044);
4596
4597 /* Set up registers for signal handler */
4598 env->regs[R_SP] = (unsigned long) frame;
4599 env->regs[4] = (unsigned long) sig;
4600 env->regs[5] = (unsigned long) &frame->info;
4601 env->regs[6] = (unsigned long) &frame->uc;
4602 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4603 return;
4604
4605give_sigsegv:
4606 if (sig == TARGET_SIGSEGV) {
4607 ka->_sa_handler = TARGET_SIG_DFL;
4608 }
4609 force_sigsegv(sig);
4610 return;
4611}
4612
4613long do_sigreturn(CPUNios2State *env)
4614{
4615 trace_user_do_sigreturn(env, 0);
4616 fprintf(stderr, "do_sigreturn: not implemented\n");
4617 return -TARGET_ENOSYS;
4618}
4619
4620long do_rt_sigreturn(CPUNios2State *env)
4621{
4622 /* Verify, can we follow the stack back */
4623 abi_ulong frame_addr = env->regs[R_SP];
4624 struct target_rt_sigframe *frame;
4625 sigset_t set;
4626 int rval;
4627
4628 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4629 goto badframe;
4630 }
4631
4632 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4633 do_sigprocmask(SIG_SETMASK, &set, NULL);
4634
4635 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4636 goto badframe;
4637 }
4638
4639 unlock_user_struct(frame, frame_addr, 0);
4640 return rval;
4641
4642badframe:
4643 unlock_user_struct(frame, frame_addr, 0);
4644 force_sig(TARGET_SIGSEGV);
4645 return 0;
4646}
4647/* TARGET_NIOS2 */
4648
Jia Liud9627832012-07-20 15:50:52 +08004649#elif defined(TARGET_OPENRISC)
4650
4651struct target_sigcontext {
4652 struct target_pt_regs regs;
4653 abi_ulong oldmask;
4654 abi_ulong usp;
4655};
4656
4657struct target_ucontext {
4658 abi_ulong tuc_flags;
4659 abi_ulong tuc_link;
4660 target_stack_t tuc_stack;
4661 struct target_sigcontext tuc_mcontext;
4662 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4663};
4664
4665struct target_rt_sigframe {
4666 abi_ulong pinfo;
4667 uint64_t puc;
4668 struct target_siginfo info;
4669 struct target_sigcontext sc;
4670 struct target_ucontext uc;
4671 unsigned char retcode[16]; /* trampoline code */
4672};
4673
4674/* This is the asm-generic/ucontext.h version */
4675#if 0
4676static int restore_sigcontext(CPUOpenRISCState *regs,
4677 struct target_sigcontext *sc)
4678{
4679 unsigned int err = 0;
4680 unsigned long old_usp;
4681
4682 /* Alwys make any pending restarted system call return -EINTR */
4683 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4684
4685 /* restore the regs from &sc->regs (same as sc, since regs is first)
4686 * (sc is already checked for VERIFY_READ since the sigframe was
4687 * checked in sys_sigreturn previously)
4688 */
4689
4690 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4691 goto badframe;
4692 }
4693
4694 /* make sure the U-flag is set so user-mode cannot fool us */
4695
4696 regs->sr &= ~SR_SM;
4697
4698 /* restore the old USP as it was before we stacked the sc etc.
4699 * (we cannot just pop the sigcontext since we aligned the sp and
4700 * stuff after pushing it)
4701 */
4702
Riku Voipio1d8b5122014-04-23 10:26:05 +03004703 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004704 phx_signal("old_usp 0x%lx", old_usp);
4705
4706 __PHX__ REALLY /* ??? */
4707 wrusp(old_usp);
4708 regs->gpr[1] = old_usp;
4709
4710 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4711 * after this completes, but we don't use that mechanism. maybe we can
4712 * use it now ?
4713 */
4714
4715 return err;
4716
4717badframe:
4718 return 1;
4719}
4720#endif
4721
4722/* Set up a signal frame. */
4723
Riku Voipio41ecc722014-04-23 11:01:00 +03004724static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004725 CPUOpenRISCState *regs,
4726 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004727{
Stafford Horned89e71e2017-04-06 06:44:56 +09004728 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004729
4730 /* copy the regs. they are first in sc so we can use sc directly */
4731
Riku Voipio1d8b5122014-04-23 10:26:05 +03004732 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004733
4734 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4735 the signal handler. The frametype will be restored to its previous
4736 value in restore_sigcontext. */
4737 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4738
4739 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004740 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004741 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004742}
4743
4744static inline unsigned long align_sigframe(unsigned long sp)
4745{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004746 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004747}
4748
4749static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4750 CPUOpenRISCState *regs,
4751 size_t frame_size)
4752{
Stafford Horned89e71e2017-04-06 06:44:56 +09004753 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004754 int onsigstack = on_sig_stack(sp);
4755
4756 /* redzone */
4757 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004758 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004759 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4760 }
4761
4762 sp = align_sigframe(sp - frame_size);
4763
4764 /*
4765 * If we are on the alternate signal stack and would overflow it, don't.
4766 * Return an always-bogus address instead so we will die with SIGSEGV.
4767 */
4768
4769 if (onsigstack && !likely(on_sig_stack(sp))) {
4770 return -1L;
4771 }
4772
4773 return sp;
4774}
4775
Jia Liud9627832012-07-20 15:50:52 +08004776static void setup_rt_frame(int sig, struct target_sigaction *ka,
4777 target_siginfo_t *info,
4778 target_sigset_t *set, CPUOpenRISCState *env)
4779{
4780 int err = 0;
4781 abi_ulong frame_addr;
4782 unsigned long return_ip;
4783 struct target_rt_sigframe *frame;
4784 abi_ulong info_addr, uc_addr;
4785
Jia Liud9627832012-07-20 15:50:52 +08004786 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004787 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004788 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4789 goto give_sigsegv;
4790 }
4791
4792 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004793 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004794 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004795 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004796
4797 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004798 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004799 }
4800
Khem Raj04b33e22017-06-28 13:44:52 -07004801 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004802 __put_user(0, &frame->uc.tuc_flags);
4803 __put_user(0, &frame->uc.tuc_link);
4804 __put_user(target_sigaltstack_used.ss_sp,
4805 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004806 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4807 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004808 __put_user(target_sigaltstack_used.ss_size,
4809 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004810 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004811
4812 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4813
Jia Liud9627832012-07-20 15:50:52 +08004814 /* trampoline - the desired return ip is the retcode itself */
4815 return_ip = (unsigned long)&frame->retcode;
4816 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004817 __put_user(0xa960, (short *)(frame->retcode + 0));
4818 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4819 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4820 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004821
4822 if (err) {
4823 goto give_sigsegv;
4824 }
4825
4826 /* TODO what is the current->exec_domain stuff and invmap ? */
4827
4828 /* Set up registers for signal handler */
4829 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004830 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4831 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4832 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4833 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004834
4835 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004836 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004837
4838 return;
4839
4840give_sigsegv:
4841 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004842 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004843}
4844
4845long do_sigreturn(CPUOpenRISCState *env)
4846{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004847 trace_user_do_sigreturn(env, 0);
4848 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004849 return -TARGET_ENOSYS;
4850}
4851
4852long do_rt_sigreturn(CPUOpenRISCState *env)
4853{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004854 trace_user_do_rt_sigreturn(env, 0);
4855 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004856 return -TARGET_ENOSYS;
4857}
4858/* TARGET_OPENRISC */
4859
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004860#elif defined(TARGET_S390X)
4861
4862#define __NUM_GPRS 16
4863#define __NUM_FPRS 16
4864#define __NUM_ACRS 16
4865
4866#define S390_SYSCALL_SIZE 2
4867#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4868
4869#define _SIGCONTEXT_NSIG 64
4870#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4871#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4872#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4873#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4874#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4875
4876typedef struct {
4877 target_psw_t psw;
4878 target_ulong gprs[__NUM_GPRS];
4879 unsigned int acrs[__NUM_ACRS];
4880} target_s390_regs_common;
4881
4882typedef struct {
4883 unsigned int fpc;
4884 double fprs[__NUM_FPRS];
4885} target_s390_fp_regs;
4886
4887typedef struct {
4888 target_s390_regs_common regs;
4889 target_s390_fp_regs fpregs;
4890} target_sigregs;
4891
4892struct target_sigcontext {
4893 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4894 target_sigregs *sregs;
4895};
4896
4897typedef struct {
4898 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4899 struct target_sigcontext sc;
4900 target_sigregs sregs;
4901 int signo;
4902 uint8_t retcode[S390_SYSCALL_SIZE];
4903} sigframe;
4904
4905struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004906 target_ulong tuc_flags;
4907 struct target_ucontext *tuc_link;
4908 target_stack_t tuc_stack;
4909 target_sigregs tuc_mcontext;
4910 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004911};
4912
4913typedef struct {
4914 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4915 uint8_t retcode[S390_SYSCALL_SIZE];
4916 struct target_siginfo info;
4917 struct target_ucontext uc;
4918} rt_sigframe;
4919
4920static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004921get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004922{
4923 abi_ulong sp;
4924
4925 /* Default to using normal stack */
4926 sp = env->regs[15];
4927
4928 /* This is the X/Open sanctioned signal stack switching. */
4929 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4930 if (!sas_ss_flags(sp)) {
4931 sp = target_sigaltstack_used.ss_sp +
4932 target_sigaltstack_used.ss_size;
4933 }
4934 }
4935
4936 /* This is the legacy signal stack switching. */
4937 else if (/* FIXME !user_mode(regs) */ 0 &&
4938 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4939 ka->sa_restorer) {
4940 sp = (abi_ulong) ka->sa_restorer;
4941 }
4942
4943 return (sp - frame_size) & -8ul;
4944}
4945
Andreas Färber05390242012-02-25 03:37:53 +01004946static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004947{
4948 int i;
4949 //save_access_regs(current->thread.acrs); FIXME
4950
4951 /* Copy a 'clean' PSW mask to the user to avoid leaking
4952 information about whether PER is currently on. */
4953 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4954 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4955 for (i = 0; i < 16; i++) {
4956 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4957 }
4958 for (i = 0; i < 16; i++) {
4959 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4960 }
4961 /*
4962 * We have to store the fp registers to current->thread.fp_regs
4963 * to merge them with the emulated registers.
4964 */
4965 //save_fp_regs(&current->thread.fp_regs); FIXME
4966 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004967 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004968 }
4969}
4970
4971static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004972 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004973{
4974 sigframe *frame;
4975 abi_ulong frame_addr;
4976
4977 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004978 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004979 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004980 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004981 }
4982
Riku Voipio0188fad2014-04-23 13:34:15 +03004983 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004984
4985 save_sigregs(env, &frame->sregs);
4986
4987 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4988 (abi_ulong *)&frame->sc.sregs);
4989
4990 /* Set up to return from userspace. If provided, use a stub
4991 already in userspace. */
4992 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004993 env->regs[14] = (unsigned long)
4994 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004995 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004996 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4997 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004998 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4999 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005000 }
5001
5002 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005003 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005004
5005 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005006 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005007 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5008
5009 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005010 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005011
5012 /* We forgot to include these in the sigcontext.
5013 To avoid breaking binary compatibility, they are passed as args. */
5014 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
5015 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
5016
5017 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02005018 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005019 unlock_user_struct(frame, frame_addr, 1);
5020 return;
5021
5022give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005023 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005024}
5025
5026static void setup_rt_frame(int sig, struct target_sigaction *ka,
5027 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005028 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005029{
5030 int i;
5031 rt_sigframe *frame;
5032 abi_ulong frame_addr;
5033
5034 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005035 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005036 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5037 goto give_sigsegv;
5038 }
5039
Peter Maydellf6c7a052015-01-08 12:19:48 +00005040 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005041
5042 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005043 __put_user(0, &frame->uc.tuc_flags);
5044 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
5045 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005046 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005047 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005048 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5049 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005050 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
5051 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005052 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005053 }
5054
5055 /* Set up to return from userspace. If provided, use a stub
5056 already in userspace. */
5057 if (ka->sa_flags & TARGET_SA_RESTORER) {
5058 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
5059 } else {
5060 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03005061 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
5062 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005063 }
5064
5065 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005066 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005067
5068 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005069 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005070 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5071
5072 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005073 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
5074 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005075 return;
5076
5077give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005078 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005079}
5080
5081static int
Andreas Färber05390242012-02-25 03:37:53 +01005082restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005083{
5084 int err = 0;
5085 int i;
5086
5087 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005088 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005089 }
5090
Riku Voipio1d8b5122014-04-23 10:26:05 +03005091 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005092 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
5093 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005094 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005095 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
5096
5097 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005098 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005099 }
5100 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04005101 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005102 }
5103
5104 return err;
5105}
5106
Andreas Färber05390242012-02-25 03:37:53 +01005107long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005108{
5109 sigframe *frame;
5110 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005111 target_sigset_t target_set;
5112 sigset_t set;
5113
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005114 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005115 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5116 goto badframe;
5117 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03005118 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005119
5120 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005121 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005122
5123 if (restore_sigregs(env, &frame->sregs)) {
5124 goto badframe;
5125 }
5126
5127 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005128 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005129
5130badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005131 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005132 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005133}
5134
Andreas Färber05390242012-02-25 03:37:53 +01005135long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005136{
5137 rt_sigframe *frame;
5138 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005139 sigset_t set;
5140
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005141 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005142 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5143 goto badframe;
5144 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005145 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005146
Peter Maydell9eede5b2016-05-27 15:51:46 +01005147 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005148
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005149 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005150 goto badframe;
5151 }
5152
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005153 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005154 get_sp_from_cpustate(env)) == -EFAULT) {
5155 goto badframe;
5156 }
5157 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005158 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005159
5160badframe:
5161 unlock_user_struct(frame, frame_addr, 0);
5162 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005163 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005164}
5165
Tom Musta61e75fe2014-06-30 08:13:38 -05005166#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07005167
5168/* Size of dummy stack frame allocated when calling signal handler.
5169 See arch/powerpc/include/asm/ptrace.h. */
5170#if defined(TARGET_PPC64)
5171#define SIGNAL_FRAMESIZE 128
5172#else
5173#define SIGNAL_FRAMESIZE 64
5174#endif
5175
Tom Musta61e75fe2014-06-30 08:13:38 -05005176/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5177 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5178struct target_mcontext {
5179 target_ulong mc_gregs[48];
5180 /* Includes fpscr. */
5181 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005182#if defined(TARGET_PPC64)
5183 /* Pointer to the vector regs */
5184 target_ulong v_regs;
5185#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005186 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005187#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005188 /* We need to handle Altivec and SPE at the same time, which no
5189 kernel needs to do. Fortunately, the kernel defines this bit to
5190 be Altivec-register-large all the time, rather than trying to
5191 twiddle it based on the specific platform. */
5192 union {
5193 /* SPE vector registers. One extra for SPEFSCR. */
5194 uint32_t spe[33];
5195 /* Altivec vector registers. The packing of VSCR and VRSAVE
5196 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005197 them apart; PPC32 stuffs them together.
5198 We also need to account for the VSX registers on PPC64
5199 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005200#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005201#define QEMU_NVRREG (34 + 16)
5202 /* On ppc64, this mcontext structure is naturally *unaligned*,
5203 * or rather it is aligned on a 8 bytes boundary but not on
5204 * a 16 bytes one. This pad fixes it up. This is also why the
5205 * vector regs are referenced by the v_regs pointer above so
5206 * any amount of padding can be added here
5207 */
5208 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005209#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005210 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005211#define QEMU_NVRREG 33
5212#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005213 /* We cannot use ppc_avr_t here as we do *not* want the implied
5214 * 16-bytes alignment that would result from it. This would have
5215 * the effect of making the whole struct target_mcontext aligned
5216 * which breaks the layout of struct target_ucontext on ppc64.
5217 */
5218 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005219#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005220 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005221};
5222
Nathan Froydbcd49332009-05-12 19:13:18 -07005223/* See arch/powerpc/include/asm/sigcontext.h. */
5224struct target_sigcontext {
5225 target_ulong _unused[4];
5226 int32_t signal;
5227#if defined(TARGET_PPC64)
5228 int32_t pad0;
5229#endif
5230 target_ulong handler;
5231 target_ulong oldmask;
5232 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005233#if defined(TARGET_PPC64)
5234 struct target_mcontext mcontext;
5235#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005236};
5237
5238/* Indices for target_mcontext.mc_gregs, below.
5239 See arch/powerpc/include/asm/ptrace.h for details. */
5240enum {
5241 TARGET_PT_R0 = 0,
5242 TARGET_PT_R1 = 1,
5243 TARGET_PT_R2 = 2,
5244 TARGET_PT_R3 = 3,
5245 TARGET_PT_R4 = 4,
5246 TARGET_PT_R5 = 5,
5247 TARGET_PT_R6 = 6,
5248 TARGET_PT_R7 = 7,
5249 TARGET_PT_R8 = 8,
5250 TARGET_PT_R9 = 9,
5251 TARGET_PT_R10 = 10,
5252 TARGET_PT_R11 = 11,
5253 TARGET_PT_R12 = 12,
5254 TARGET_PT_R13 = 13,
5255 TARGET_PT_R14 = 14,
5256 TARGET_PT_R15 = 15,
5257 TARGET_PT_R16 = 16,
5258 TARGET_PT_R17 = 17,
5259 TARGET_PT_R18 = 18,
5260 TARGET_PT_R19 = 19,
5261 TARGET_PT_R20 = 20,
5262 TARGET_PT_R21 = 21,
5263 TARGET_PT_R22 = 22,
5264 TARGET_PT_R23 = 23,
5265 TARGET_PT_R24 = 24,
5266 TARGET_PT_R25 = 25,
5267 TARGET_PT_R26 = 26,
5268 TARGET_PT_R27 = 27,
5269 TARGET_PT_R28 = 28,
5270 TARGET_PT_R29 = 29,
5271 TARGET_PT_R30 = 30,
5272 TARGET_PT_R31 = 31,
5273 TARGET_PT_NIP = 32,
5274 TARGET_PT_MSR = 33,
5275 TARGET_PT_ORIG_R3 = 34,
5276 TARGET_PT_CTR = 35,
5277 TARGET_PT_LNK = 36,
5278 TARGET_PT_XER = 37,
5279 TARGET_PT_CCR = 38,
5280 /* Yes, there are two registers with #39. One is 64-bit only. */
5281 TARGET_PT_MQ = 39,
5282 TARGET_PT_SOFTE = 39,
5283 TARGET_PT_TRAP = 40,
5284 TARGET_PT_DAR = 41,
5285 TARGET_PT_DSISR = 42,
5286 TARGET_PT_RESULT = 43,
5287 TARGET_PT_REGS_COUNT = 44
5288};
5289
Nathan Froydbcd49332009-05-12 19:13:18 -07005290
5291struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005292 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005293 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005294 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005295#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005296 int32_t tuc_pad[7];
5297 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005298 points to uc_mcontext field */
5299#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005300 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005301#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005302 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005303 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005304#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005305 int32_t tuc_maskext[30];
5306 int32_t tuc_pad2[3];
5307 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005308#endif
5309};
5310
5311/* See arch/powerpc/kernel/signal_32.c. */
5312struct target_sigframe {
5313 struct target_sigcontext sctx;
5314 struct target_mcontext mctx;
5315 int32_t abigap[56];
5316};
5317
Tom Musta61e75fe2014-06-30 08:13:38 -05005318#if defined(TARGET_PPC64)
5319
5320#define TARGET_TRAMP_SIZE 6
5321
5322struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005323 /* sys_rt_sigreturn requires the ucontext be the first field */
5324 struct target_ucontext uc;
5325 target_ulong _unused[2];
5326 uint32_t trampoline[TARGET_TRAMP_SIZE];
5327 target_ulong pinfo; /* struct siginfo __user * */
5328 target_ulong puc; /* void __user * */
5329 struct target_siginfo info;
5330 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5331 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005332} __attribute__((aligned(16)));
5333
5334#else
5335
Nathan Froydbcd49332009-05-12 19:13:18 -07005336struct target_rt_sigframe {
5337 struct target_siginfo info;
5338 struct target_ucontext uc;
5339 int32_t abigap[56];
5340};
5341
Tom Musta61e75fe2014-06-30 08:13:38 -05005342#endif
5343
Tom Musta8d6ab332014-06-30 08:13:39 -05005344#if defined(TARGET_PPC64)
5345
5346struct target_func_ptr {
5347 target_ulong entry;
5348 target_ulong toc;
5349};
5350
5351#endif
5352
Nathan Froydbcd49332009-05-12 19:13:18 -07005353/* We use the mc_pad field for the signal return trampoline. */
5354#define tramp mc_pad
5355
5356/* See arch/powerpc/kernel/signal.c. */
5357static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005358 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005359 int frame_size)
5360{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005361 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005362
5363 oldsp = env->gpr[1];
5364
5365 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005366 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005367 oldsp = (target_sigaltstack_used.ss_sp
5368 + target_sigaltstack_used.ss_size);
5369 }
5370
Eduardo Habkost9be38592016-06-13 18:57:58 -03005371 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005372}
5373
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005374#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5375 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5376#define PPC_VEC_HI 0
5377#define PPC_VEC_LO 1
5378#else
5379#define PPC_VEC_HI 1
5380#define PPC_VEC_LO 0
5381#endif
5382
5383
Tom Musta76781082014-06-30 08:13:37 -05005384static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005385{
5386 target_ulong msr = env->msr;
5387 int i;
5388 target_ulong ccr = 0;
5389
5390 /* In general, the kernel attempts to be intelligent about what it
5391 needs to save for Altivec/FP/SPE registers. We don't care that
5392 much, so we just go ahead and save everything. */
5393
5394 /* Save general registers. */
5395 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005396 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005397 }
Riku Voipioc650c002014-04-23 13:53:45 +03005398 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5399 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5400 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5401 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005402
5403 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5404 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5405 }
Riku Voipioc650c002014-04-23 13:53:45 +03005406 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005407
5408 /* Save Altivec registers if necessary. */
5409 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005410 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005411 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005412 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005413 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005414
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005415 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5416 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005417 }
5418 /* Set MSR_VR in the saved MSR value to indicate that
5419 frame->mc_vregs contains valid data. */
5420 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005421#if defined(TARGET_PPC64)
5422 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5423 /* 64-bit needs to put a pointer to the vectors in the frame */
5424 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5425#else
5426 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5427#endif
5428 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5429 }
5430
5431 /* Save VSX second halves */
5432 if (env->insns_flags2 & PPC2_VSX) {
5433 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5434 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5435 __put_user(env->vsr[i], &vsregs[i]);
5436 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005437 }
5438
5439 /* Save floating point registers. */
5440 if (env->insns_flags & PPC_FLOAT) {
5441 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005442 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005443 }
Riku Voipioc650c002014-04-23 13:53:45 +03005444 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005445 }
5446
5447 /* Save SPE registers. The kernel only saves the high half. */
5448 if (env->insns_flags & PPC_SPE) {
5449#if defined(TARGET_PPC64)
5450 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005451 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005452 }
5453#else
5454 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005455 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005456 }
5457#endif
5458 /* Set MSR_SPE in the saved MSR value to indicate that
5459 frame->mc_vregs contains valid data. */
5460 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005461 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005462 }
5463
5464 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005465 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005466}
Nathan Froydbcd49332009-05-12 19:13:18 -07005467
Tom Musta76781082014-06-30 08:13:37 -05005468static void encode_trampoline(int sigret, uint32_t *tramp)
5469{
Nathan Froydbcd49332009-05-12 19:13:18 -07005470 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5471 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005472 __put_user(0x38000000 | sigret, &tramp[0]);
5473 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005474 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005475}
5476
Riku Voipioc650c002014-04-23 13:53:45 +03005477static void restore_user_regs(CPUPPCState *env,
5478 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005479{
5480 target_ulong save_r2 = 0;
5481 target_ulong msr;
5482 target_ulong ccr;
5483
5484 int i;
5485
5486 if (!sig) {
5487 save_r2 = env->gpr[2];
5488 }
5489
5490 /* Restore general registers. */
5491 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005492 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005493 }
Riku Voipioc650c002014-04-23 13:53:45 +03005494 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5495 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5496 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5497 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5498 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005499
5500 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5501 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5502 }
5503
5504 if (!sig) {
5505 env->gpr[2] = save_r2;
5506 }
5507 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005508 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005509
5510 /* If doing signal return, restore the previous little-endian mode. */
5511 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005512 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005513
5514 /* Restore Altivec registers if necessary. */
5515 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005516 ppc_avr_t *v_regs;
5517 uint32_t *vrsave;
5518#if defined(TARGET_PPC64)
5519 uint64_t v_addr;
5520 /* 64-bit needs to recover the pointer to the vectors from the frame */
5521 __get_user(v_addr, &frame->v_regs);
5522 v_regs = g2h(v_addr);
5523#else
5524 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5525#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005526 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005527 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005528 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005529
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005530 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5531 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005532 }
5533 /* Set MSR_VEC in the saved MSR value to indicate that
5534 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005535#if defined(TARGET_PPC64)
5536 vrsave = (uint32_t *)&v_regs[33];
5537#else
5538 vrsave = (uint32_t *)&v_regs[32];
5539#endif
5540 __get_user(env->spr[SPR_VRSAVE], vrsave);
5541 }
5542
5543 /* Restore VSX second halves */
5544 if (env->insns_flags2 & PPC2_VSX) {
5545 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5546 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5547 __get_user(env->vsr[i], &vsregs[i]);
5548 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005549 }
5550
5551 /* Restore floating point registers. */
5552 if (env->insns_flags & PPC_FLOAT) {
5553 uint64_t fpscr;
5554 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005555 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005556 }
Riku Voipioc650c002014-04-23 13:53:45 +03005557 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005558 env->fpscr = (uint32_t) fpscr;
5559 }
5560
5561 /* Save SPE registers. The kernel only saves the high half. */
5562 if (env->insns_flags & PPC_SPE) {
5563#if defined(TARGET_PPC64)
5564 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5565 uint32_t hi;
5566
Riku Voipioc650c002014-04-23 13:53:45 +03005567 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005568 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5569 }
5570#else
5571 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005572 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005573 }
5574#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005575 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005576 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005577}
5578
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005579#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005580static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005581 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005582{
5583 struct target_sigframe *frame;
5584 struct target_sigcontext *sc;
5585 target_ulong frame_addr, newsp;
5586 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005587
5588 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005589 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005590 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5591 goto sigsegv;
5592 sc = &frame->sctx;
5593
Riku Voipio1d8b5122014-04-23 10:26:05 +03005594 __put_user(ka->_sa_handler, &sc->handler);
5595 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005596 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005597 __put_user(h2g(&frame->mctx), &sc->regs);
5598 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005599
5600 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005601 save_user_regs(env, &frame->mctx);
5602
5603 /* Construct the trampoline code on the stack. */
5604 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005605
5606 /* The kernel checks for the presence of a VDSO here. We don't
5607 emulate a vdso, so use a sigreturn system call. */
5608 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5609
5610 /* Turn off all fp exceptions. */
5611 env->fpscr = 0;
5612
5613 /* Create a stack frame for the caller of the handler. */
5614 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005615 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005616
5617 if (err)
5618 goto sigsegv;
5619
5620 /* Set up registers for signal handler. */
5621 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005622 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005623 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005624
Nathan Froydbcd49332009-05-12 19:13:18 -07005625 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005626
Nathan Froydbcd49332009-05-12 19:13:18 -07005627 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005628 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005629
5630 unlock_user_struct(frame, frame_addr, 1);
5631 return;
5632
5633sigsegv:
5634 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005635 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005636}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005637#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005638
5639static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005640 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005641 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005642{
5643 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005644 uint32_t *trampptr = 0;
5645 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005646 target_ulong rt_sf_addr, newsp = 0;
5647 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005648#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005649 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005650 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5651#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005652
5653 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5654 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5655 goto sigsegv;
5656
Peter Maydellf6c7a052015-01-08 12:19:48 +00005657 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005658
Riku Voipio1d8b5122014-04-23 10:26:05 +03005659 __put_user(0, &rt_sf->uc.tuc_flags);
5660 __put_user(0, &rt_sf->uc.tuc_link);
5661 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5662 &rt_sf->uc.tuc_stack.ss_sp);
5663 __put_user(sas_ss_flags(env->gpr[1]),
5664 &rt_sf->uc.tuc_stack.ss_flags);
5665 __put_user(target_sigaltstack_used.ss_size,
5666 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005667#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005668 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5669 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005670#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005671 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005672 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005673 }
5674
Tom Musta61e75fe2014-06-30 08:13:38 -05005675#if defined(TARGET_PPC64)
5676 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5677 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005678
5679 sc = &rt_sf->uc.tuc_sigcontext;
5680 __put_user(h2g(mctx), &sc->regs);
5681 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005682#else
5683 mctx = &rt_sf->uc.tuc_mcontext;
5684 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5685#endif
5686
5687 save_user_regs(env, mctx);
5688 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005689
5690 /* The kernel checks for the presence of a VDSO here. We don't
5691 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005692 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005693
5694 /* Turn off all fp exceptions. */
5695 env->fpscr = 0;
5696
5697 /* Create a stack frame for the caller of the handler. */
5698 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005699 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005700
5701 if (err)
5702 goto sigsegv;
5703
5704 /* Set up registers for signal handler. */
5705 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005706 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005707 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5708 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5709 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005710
5711#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005712 if (get_ppc64_abi(image) < 2) {
5713 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5714 struct target_func_ptr *handler =
5715 (struct target_func_ptr *)g2h(ka->_sa_handler);
5716 env->nip = tswapl(handler->entry);
5717 env->gpr[2] = tswapl(handler->toc);
5718 } else {
5719 /* ELFv2 PPC64 function pointers are entry points, but R12
5720 * must also be set */
5721 env->nip = tswapl((target_ulong) ka->_sa_handler);
5722 env->gpr[12] = env->nip;
5723 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005724#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005725 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005726#endif
5727
Nathan Froydbcd49332009-05-12 19:13:18 -07005728 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005729 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005730
5731 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5732 return;
5733
5734sigsegv:
5735 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005736 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005737
5738}
5739
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005740#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005741long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005742{
5743 struct target_sigcontext *sc = NULL;
5744 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005745 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005746 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005747 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005748
5749 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5750 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5751 goto sigsegv;
5752
5753#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005754 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005755#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005756 __get_user(set.sig[0], &sc->oldmask);
5757 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005758#endif
5759 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005760 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005761
Riku Voipiof5f601a2014-04-23 13:00:17 +03005762 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005763 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5764 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005765 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005766
5767 unlock_user_struct(sr, sr_addr, 1);
5768 unlock_user_struct(sc, sc_addr, 1);
5769 return -TARGET_QEMU_ESIGRETURN;
5770
5771sigsegv:
5772 unlock_user_struct(sr, sr_addr, 1);
5773 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005774 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005775 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005776}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005777#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005778
5779/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005780static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005781{
5782 struct target_mcontext *mcp;
5783 target_ulong mcp_addr;
5784 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005785 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005786
Aurelien Jarno60e99242010-03-29 02:12:51 +02005787 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005788 sizeof (set)))
5789 return 1;
5790
Tom Musta19774ec2014-06-30 08:13:40 -05005791#if defined(TARGET_PPC64)
5792 mcp_addr = h2g(ucp) +
5793 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5794#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005795 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005796#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005797
5798 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5799 return 1;
5800
5801 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005802 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005803 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005804
5805 unlock_user_struct(mcp, mcp_addr, 1);
5806 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005807}
5808
Andreas Färber05390242012-02-25 03:37:53 +01005809long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005810{
5811 struct target_rt_sigframe *rt_sf = NULL;
5812 target_ulong rt_sf_addr;
5813
5814 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5815 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5816 goto sigsegv;
5817
5818 if (do_setcontext(&rt_sf->uc, env, 1))
5819 goto sigsegv;
5820
5821 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005822 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005823 0, env->gpr[1]);
5824
5825 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5826 return -TARGET_QEMU_ESIGRETURN;
5827
5828sigsegv:
5829 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005830 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005831 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005832}
5833
Laurent Vivier492a8742009-08-03 16:12:17 +02005834#elif defined(TARGET_M68K)
5835
5836struct target_sigcontext {
5837 abi_ulong sc_mask;
5838 abi_ulong sc_usp;
5839 abi_ulong sc_d0;
5840 abi_ulong sc_d1;
5841 abi_ulong sc_a0;
5842 abi_ulong sc_a1;
5843 unsigned short sc_sr;
5844 abi_ulong sc_pc;
5845};
5846
5847struct target_sigframe
5848{
5849 abi_ulong pretcode;
5850 int sig;
5851 int code;
5852 abi_ulong psc;
5853 char retcode[8];
5854 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5855 struct target_sigcontext sc;
5856};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005857
Anthony Liguoric227f092009-10-01 16:12:16 -05005858typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005859#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005860typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005861
5862typedef struct target_fpregset {
5863 int f_fpcntl[3];
5864 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005865} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005866
5867struct target_mcontext {
5868 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005869 target_gregset_t gregs;
5870 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005871};
5872
5873#define TARGET_MCONTEXT_VERSION 2
5874
5875struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005876 abi_ulong tuc_flags;
5877 abi_ulong tuc_link;
5878 target_stack_t tuc_stack;
5879 struct target_mcontext tuc_mcontext;
5880 abi_long tuc_filler[80];
5881 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005882};
5883
5884struct target_rt_sigframe
5885{
5886 abi_ulong pretcode;
5887 int sig;
5888 abi_ulong pinfo;
5889 abi_ulong puc;
5890 char retcode[8];
5891 struct target_siginfo info;
5892 struct target_ucontext uc;
5893};
Laurent Vivier492a8742009-08-03 16:12:17 +02005894
Riku Voipio41ecc722014-04-23 11:01:00 +03005895static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005896 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005897{
Laurent Vivieref597602018-01-04 02:28:59 +01005898 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005899 __put_user(mask, &sc->sc_mask);
5900 __put_user(env->aregs[7], &sc->sc_usp);
5901 __put_user(env->dregs[0], &sc->sc_d0);
5902 __put_user(env->dregs[1], &sc->sc_d1);
5903 __put_user(env->aregs[0], &sc->sc_a0);
5904 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005905 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005906 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005907}
5908
Riku Voipio016d2e12014-04-23 11:19:48 +03005909static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005910restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005911{
Laurent Vivier492a8742009-08-03 16:12:17 +02005912 int temp;
5913
Riku Voipio1d8b5122014-04-23 10:26:05 +03005914 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005915 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005916 __get_user(env->dregs[1], &sc->sc_d1);
5917 __get_user(env->aregs[0], &sc->sc_a0);
5918 __get_user(env->aregs[1], &sc->sc_a1);
5919 __get_user(env->pc, &sc->sc_pc);
5920 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005921 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005922}
5923
5924/*
5925 * Determine which stack to use..
5926 */
5927static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005928get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5929 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005930{
5931 unsigned long sp;
5932
5933 sp = regs->aregs[7];
5934
5935 /* This is the X/Open sanctioned signal stack switching. */
5936 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5937 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5938 }
5939
5940 return ((sp - frame_size) & -8UL);
5941}
5942
5943static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005944 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005945{
5946 struct target_sigframe *frame;
5947 abi_ulong frame_addr;
5948 abi_ulong retcode_addr;
5949 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005950 int i;
5951
5952 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005953 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005954 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5955 goto give_sigsegv;
5956 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005957
Riku Voipio1d8b5122014-04-23 10:26:05 +03005958 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005959
5960 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005961 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005962
Riku Voipio41ecc722014-04-23 11:01:00 +03005963 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005964
5965 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005966 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005967 }
5968
5969 /* Set up to return from userspace. */
5970
5971 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005972 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005973
5974 /* moveq #,d0; trap #0 */
5975
Riku Voipio1d8b5122014-04-23 10:26:05 +03005976 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005977 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005978
Laurent Vivier492a8742009-08-03 16:12:17 +02005979 /* Set up to return from userspace */
5980
5981 env->aregs[7] = frame_addr;
5982 env->pc = ka->_sa_handler;
5983
5984 unlock_user_struct(frame, frame_addr, 1);
5985 return;
5986
5987give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005988 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005989}
5990
Laurent Vivieree46a462017-09-14 18:35:05 +02005991static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5992 CPUM68KState *env)
5993{
5994 int i;
5995 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5996
5997 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
5998 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
5999 /* fpiar is not emulated */
6000
6001 for (i = 0; i < 8; i++) {
6002 uint32_t high = env->fregs[i].d.high << 16;
6003 __put_user(high, &fpregs->f_fpregs[i * 3]);
6004 __put_user(env->fregs[i].d.low,
6005 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6006 }
6007}
6008
Laurent Vivier71811552009-08-03 16:12:18 +02006009static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01006010 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02006011{
Aurelien Jarno60e99242010-03-29 02:12:51 +02006012 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01006013 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02006014
Riku Voipio1d8b5122014-04-23 10:26:05 +03006015 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
6016 __put_user(env->dregs[0], &gregs[0]);
6017 __put_user(env->dregs[1], &gregs[1]);
6018 __put_user(env->dregs[2], &gregs[2]);
6019 __put_user(env->dregs[3], &gregs[3]);
6020 __put_user(env->dregs[4], &gregs[4]);
6021 __put_user(env->dregs[5], &gregs[5]);
6022 __put_user(env->dregs[6], &gregs[6]);
6023 __put_user(env->dregs[7], &gregs[7]);
6024 __put_user(env->aregs[0], &gregs[8]);
6025 __put_user(env->aregs[1], &gregs[9]);
6026 __put_user(env->aregs[2], &gregs[10]);
6027 __put_user(env->aregs[3], &gregs[11]);
6028 __put_user(env->aregs[4], &gregs[12]);
6029 __put_user(env->aregs[5], &gregs[13]);
6030 __put_user(env->aregs[6], &gregs[14]);
6031 __put_user(env->aregs[7], &gregs[15]);
6032 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006033 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02006034
Laurent Vivieree46a462017-09-14 18:35:05 +02006035 target_rt_save_fpu_state(uc, env);
6036
Riku Voipio1d8b5122014-04-23 10:26:05 +03006037 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006038}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006039
Laurent Vivieree46a462017-09-14 18:35:05 +02006040static inline void target_rt_restore_fpu_state(CPUM68KState *env,
6041 struct target_ucontext *uc)
6042{
6043 int i;
6044 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6045 uint32_t fpcr;
6046
6047 __get_user(fpcr, &fpregs->f_fpcntl[0]);
6048 cpu_m68k_set_fpcr(env, fpcr);
6049 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
6050 /* fpiar is not emulated */
6051
6052 for (i = 0; i < 8; i++) {
6053 uint32_t high;
6054 __get_user(high, &fpregs->f_fpregs[i * 3]);
6055 env->fregs[i].d.high = high >> 16;
6056 __get_user(env->fregs[i].d.low,
6057 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6058 }
6059}
6060
Andreas Färber05390242012-02-25 03:37:53 +01006061static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006062 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02006063{
6064 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02006065 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02006066
Riku Voipio1d8b5122014-04-23 10:26:05 +03006067 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02006068 if (temp != TARGET_MCONTEXT_VERSION)
6069 goto badframe;
6070
6071 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03006072 __get_user(env->dregs[0], &gregs[0]);
6073 __get_user(env->dregs[1], &gregs[1]);
6074 __get_user(env->dregs[2], &gregs[2]);
6075 __get_user(env->dregs[3], &gregs[3]);
6076 __get_user(env->dregs[4], &gregs[4]);
6077 __get_user(env->dregs[5], &gregs[5]);
6078 __get_user(env->dregs[6], &gregs[6]);
6079 __get_user(env->dregs[7], &gregs[7]);
6080 __get_user(env->aregs[0], &gregs[8]);
6081 __get_user(env->aregs[1], &gregs[9]);
6082 __get_user(env->aregs[2], &gregs[10]);
6083 __get_user(env->aregs[3], &gregs[11]);
6084 __get_user(env->aregs[4], &gregs[12]);
6085 __get_user(env->aregs[5], &gregs[13]);
6086 __get_user(env->aregs[6], &gregs[14]);
6087 __get_user(env->aregs[7], &gregs[15]);
6088 __get_user(env->pc, &gregs[16]);
6089 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006090 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02006091
Laurent Vivieree46a462017-09-14 18:35:05 +02006092 target_rt_restore_fpu_state(env, uc);
6093
Riku Voipio1d8b5122014-04-23 10:26:05 +03006094 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006095
6096badframe:
6097 return 1;
6098}
6099
Laurent Vivier492a8742009-08-03 16:12:17 +02006100static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006101 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006102 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006103{
Laurent Vivier71811552009-08-03 16:12:18 +02006104 struct target_rt_sigframe *frame;
6105 abi_ulong frame_addr;
6106 abi_ulong retcode_addr;
6107 abi_ulong info_addr;
6108 abi_ulong uc_addr;
6109 int err = 0;
6110 int i;
6111
6112 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006113 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006114 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6115 goto give_sigsegv;
6116 }
Laurent Vivier71811552009-08-03 16:12:18 +02006117
Riku Voipio1d8b5122014-04-23 10:26:05 +03006118 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02006119
6120 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006121 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02006122
6123 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006124 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02006125
Peter Maydellf6c7a052015-01-08 12:19:48 +00006126 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02006127
6128 /* Create the ucontext */
6129
Riku Voipio1d8b5122014-04-23 10:26:05 +03006130 __put_user(0, &frame->uc.tuc_flags);
6131 __put_user(0, &frame->uc.tuc_link);
6132 __put_user(target_sigaltstack_used.ss_sp,
6133 &frame->uc.tuc_stack.ss_sp);
6134 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006135 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006136 __put_user(target_sigaltstack_used.ss_size,
6137 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02006138 err |= target_rt_setup_ucontext(&frame->uc, env);
6139
6140 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006141 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02006142
6143 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03006144 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02006145 }
6146
6147 /* Set up to return from userspace. */
6148
6149 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006150 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02006151
6152 /* moveq #,d0; notb d0; trap #0 */
6153
Riku Voipio1d8b5122014-04-23 10:26:05 +03006154 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00006155 (uint32_t *)(frame->retcode + 0));
6156 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02006157
6158 if (err)
6159 goto give_sigsegv;
6160
6161 /* Set up to return from userspace */
6162
6163 env->aregs[7] = frame_addr;
6164 env->pc = ka->_sa_handler;
6165
6166 unlock_user_struct(frame, frame_addr, 1);
6167 return;
6168
6169give_sigsegv:
6170 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006171 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006172}
6173
Andreas Färber05390242012-02-25 03:37:53 +01006174long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006175{
6176 struct target_sigframe *frame;
6177 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006178 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006179 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006180 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006181
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006182 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006183 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6184 goto badframe;
6185
6186 /* set blocked signals */
6187
Riku Voipiof5f601a2014-04-23 13:00:17 +03006188 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006189
6190 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006191 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006192 }
6193
6194 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006195 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006196
6197 /* restore registers */
6198
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006199 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006200
6201 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006202 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006203
6204badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006205 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006206 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006207}
6208
Andreas Färber05390242012-02-25 03:37:53 +01006209long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006210{
Laurent Vivier71811552009-08-03 16:12:18 +02006211 struct target_rt_sigframe *frame;
6212 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006213 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006214
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006215 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006216 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6217 goto badframe;
6218
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006219 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006220 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006221
6222 /* restore registers */
6223
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006224 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006225 goto badframe;
6226
6227 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006228 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006229 0, get_sp_from_cpustate(env)) == -EFAULT)
6230 goto badframe;
6231
6232 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006233 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006234
6235badframe:
6236 unlock_user_struct(frame, frame_addr, 0);
6237 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006238 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006239}
6240
Richard Henderson6049f4f2009-12-27 18:30:03 -08006241#elif defined(TARGET_ALPHA)
6242
6243struct target_sigcontext {
6244 abi_long sc_onstack;
6245 abi_long sc_mask;
6246 abi_long sc_pc;
6247 abi_long sc_ps;
6248 abi_long sc_regs[32];
6249 abi_long sc_ownedfp;
6250 abi_long sc_fpregs[32];
6251 abi_ulong sc_fpcr;
6252 abi_ulong sc_fp_control;
6253 abi_ulong sc_reserved1;
6254 abi_ulong sc_reserved2;
6255 abi_ulong sc_ssize;
6256 abi_ulong sc_sbase;
6257 abi_ulong sc_traparg_a0;
6258 abi_ulong sc_traparg_a1;
6259 abi_ulong sc_traparg_a2;
6260 abi_ulong sc_fp_trap_pc;
6261 abi_ulong sc_fp_trigger_sum;
6262 abi_ulong sc_fp_trigger_inst;
6263};
6264
6265struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006266 abi_ulong tuc_flags;
6267 abi_ulong tuc_link;
6268 abi_ulong tuc_osf_sigmask;
6269 target_stack_t tuc_stack;
6270 struct target_sigcontext tuc_mcontext;
6271 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006272};
6273
6274struct target_sigframe {
6275 struct target_sigcontext sc;
6276 unsigned int retcode[3];
6277};
6278
6279struct target_rt_sigframe {
6280 target_siginfo_t info;
6281 struct target_ucontext uc;
6282 unsigned int retcode[3];
6283};
6284
6285#define INSN_MOV_R30_R16 0x47fe0410
6286#define INSN_LDI_R0 0x201f0000
6287#define INSN_CALLSYS 0x00000083
6288
Riku Voipio41ecc722014-04-23 11:01:00 +03006289static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006290 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006291{
Riku Voipio41ecc722014-04-23 11:01:00 +03006292 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006293
Riku Voipio1d8b5122014-04-23 10:26:05 +03006294 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6295 __put_user(set->sig[0], &sc->sc_mask);
6296 __put_user(env->pc, &sc->sc_pc);
6297 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006298
6299 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006300 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006301 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006302 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006303
6304 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006305 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006306 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006307 __put_user(0, &sc->sc_fpregs[31]);
6308 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006309
Riku Voipio1d8b5122014-04-23 10:26:05 +03006310 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6311 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6312 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006313}
6314
Riku Voipio016d2e12014-04-23 11:19:48 +03006315static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006316 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006317{
6318 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006319 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006320
Riku Voipio1d8b5122014-04-23 10:26:05 +03006321 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006322
6323 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006324 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006325 }
6326 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006327 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006328 }
6329
Riku Voipio1d8b5122014-04-23 10:26:05 +03006330 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006331 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006332}
6333
6334static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006335 CPUAlphaState *env,
6336 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006337{
6338 abi_ulong sp = env->ir[IR_SP];
6339
6340 /* This is the X/Open sanctioned signal stack switching. */
6341 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6342 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6343 }
6344 return (sp - framesize) & -32;
6345}
6346
6347static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006348 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006349{
6350 abi_ulong frame_addr, r26;
6351 struct target_sigframe *frame;
6352 int err = 0;
6353
6354 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006355 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006356 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6357 goto give_sigsegv;
6358 }
6359
Riku Voipio41ecc722014-04-23 11:01:00 +03006360 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006361
6362 if (ka->sa_restorer) {
6363 r26 = ka->sa_restorer;
6364 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006365 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6366 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6367 &frame->retcode[1]);
6368 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006369 /* imb() */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006370 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006371 }
6372
6373 unlock_user_struct(frame, frame_addr, 1);
6374
6375 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006376give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006377 force_sigsegv(sig);
6378 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006379 }
6380
6381 env->ir[IR_RA] = r26;
6382 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6383 env->ir[IR_A0] = sig;
6384 env->ir[IR_A1] = 0;
6385 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6386 env->ir[IR_SP] = frame_addr;
6387}
6388
6389static void setup_rt_frame(int sig, struct target_sigaction *ka,
6390 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006391 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006392{
6393 abi_ulong frame_addr, r26;
6394 struct target_rt_sigframe *frame;
6395 int i, err = 0;
6396
6397 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006398 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006399 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6400 goto give_sigsegv;
6401 }
6402
Peter Maydellf6c7a052015-01-08 12:19:48 +00006403 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006404
Riku Voipio1d8b5122014-04-23 10:26:05 +03006405 __put_user(0, &frame->uc.tuc_flags);
6406 __put_user(0, &frame->uc.tuc_link);
6407 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6408 __put_user(target_sigaltstack_used.ss_sp,
6409 &frame->uc.tuc_stack.ss_sp);
6410 __put_user(sas_ss_flags(env->ir[IR_SP]),
6411 &frame->uc.tuc_stack.ss_flags);
6412 __put_user(target_sigaltstack_used.ss_size,
6413 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006414 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006415 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006416 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006417 }
6418
6419 if (ka->sa_restorer) {
6420 r26 = ka->sa_restorer;
6421 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006422 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6423 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6424 &frame->retcode[1]);
6425 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006426 /* imb(); */
Laurent Vivier95a29a42018-04-01 22:46:53 +02006427 r26 = frame_addr + offsetof(struct target_sigframe, retcode);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006428 }
6429
6430 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006431give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006432 force_sigsegv(sig);
6433 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006434 }
6435
6436 env->ir[IR_RA] = r26;
6437 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6438 env->ir[IR_A0] = sig;
6439 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6440 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6441 env->ir[IR_SP] = frame_addr;
6442}
6443
Andreas Färber05390242012-02-25 03:37:53 +01006444long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006445{
6446 struct target_sigcontext *sc;
6447 abi_ulong sc_addr = env->ir[IR_A0];
6448 target_sigset_t target_set;
6449 sigset_t set;
6450
6451 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6452 goto badframe;
6453 }
6454
6455 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006456 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006457
6458 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006459 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006460
Riku Voipio016d2e12014-04-23 11:19:48 +03006461 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006462 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006463 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006464
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006465badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006466 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006467 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006468}
6469
Andreas Färber05390242012-02-25 03:37:53 +01006470long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006471{
6472 abi_ulong frame_addr = env->ir[IR_A0];
6473 struct target_rt_sigframe *frame;
6474 sigset_t set;
6475
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006476 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006477 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6478 goto badframe;
6479 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006480 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006481 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006482
Riku Voipio016d2e12014-04-23 11:19:48 +03006483 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006484 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006485 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006486 0, env->ir[IR_SP]) == -EFAULT) {
6487 goto badframe;
6488 }
6489
6490 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006491 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006492
6493
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006494badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006495 unlock_user_struct(frame, frame_addr, 0);
6496 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006497 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006498}
6499
Chen Gangbf0f60a2015-09-27 08:10:18 +08006500#elif defined(TARGET_TILEGX)
6501
6502struct target_sigcontext {
6503 union {
6504 /* General-purpose registers. */
6505 abi_ulong gregs[56];
6506 struct {
6507 abi_ulong __gregs[53];
6508 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6509 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6510 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6511 };
6512 };
6513 abi_ulong pc; /* Program counter. */
6514 abi_ulong ics; /* In Interrupt Critical Section? */
6515 abi_ulong faultnum; /* Fault number. */
6516 abi_ulong pad[5];
6517};
6518
6519struct target_ucontext {
6520 abi_ulong tuc_flags;
6521 abi_ulong tuc_link;
6522 target_stack_t tuc_stack;
6523 struct target_sigcontext tuc_mcontext;
6524 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6525};
6526
6527struct target_rt_sigframe {
6528 unsigned char save_area[16]; /* caller save area */
6529 struct target_siginfo info;
6530 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006531 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006532};
6533
Chen Gangf1d9d102016-03-29 21:53:49 +08006534#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6535#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6536
6537
Chen Gangbf0f60a2015-09-27 08:10:18 +08006538static void setup_sigcontext(struct target_sigcontext *sc,
6539 CPUArchState *env, int signo)
6540{
6541 int i;
6542
6543 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6544 __put_user(env->regs[i], &sc->gregs[i]);
6545 }
6546
6547 __put_user(env->pc, &sc->pc);
6548 __put_user(0, &sc->ics);
6549 __put_user(signo, &sc->faultnum);
6550}
6551
6552static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6553{
6554 int i;
6555
6556 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6557 __get_user(env->regs[i], &sc->gregs[i]);
6558 }
6559
6560 __get_user(env->pc, &sc->pc);
6561}
6562
6563static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6564 size_t frame_size)
6565{
6566 unsigned long sp = env->regs[TILEGX_R_SP];
6567
6568 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6569 return -1UL;
6570 }
6571
6572 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6573 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6574 }
6575
6576 sp -= frame_size;
6577 sp &= -16UL;
6578 return sp;
6579}
6580
6581static void setup_rt_frame(int sig, struct target_sigaction *ka,
6582 target_siginfo_t *info,
6583 target_sigset_t *set, CPUArchState *env)
6584{
6585 abi_ulong frame_addr;
6586 struct target_rt_sigframe *frame;
6587 unsigned long restorer;
6588
6589 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006590 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006591 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6592 goto give_sigsegv;
6593 }
6594
6595 /* Always write at least the signal number for the stack backtracer. */
6596 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6597 /* At sigreturn time, restore the callee-save registers too. */
6598 tswap_siginfo(&frame->info, info);
6599 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6600 } else {
6601 __put_user(info->si_signo, &frame->info.si_signo);
6602 }
6603
6604 /* Create the ucontext. */
6605 __put_user(0, &frame->uc.tuc_flags);
6606 __put_user(0, &frame->uc.tuc_link);
6607 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6608 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6609 &frame->uc.tuc_stack.ss_flags);
6610 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6611 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6612
Chen Gangbf0f60a2015-09-27 08:10:18 +08006613 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006614 restorer = (unsigned long) ka->sa_restorer;
6615 } else {
6616 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6617 __put_user(INSN_SWINT1, &frame->retcode[1]);
6618 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006619 }
6620 env->pc = (unsigned long) ka->_sa_handler;
6621 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6622 env->regs[TILEGX_R_LR] = restorer;
6623 env->regs[0] = (unsigned long) sig;
6624 env->regs[1] = (unsigned long) &frame->info;
6625 env->regs[2] = (unsigned long) &frame->uc;
6626 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6627
6628 unlock_user_struct(frame, frame_addr, 1);
6629 return;
6630
6631give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006632 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006633}
6634
6635long do_rt_sigreturn(CPUTLGState *env)
6636{
6637 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6638 struct target_rt_sigframe *frame;
6639 sigset_t set;
6640
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006641 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006642 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6643 goto badframe;
6644 }
6645 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006646 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006647
6648 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6649 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6650 uc.tuc_stack),
6651 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6652 goto badframe;
6653 }
6654
6655 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006656 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006657
6658
6659 badframe:
6660 unlock_user_struct(frame, frame_addr, 0);
6661 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006662 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006663}
6664
Michael Clark47ae93c2018-03-03 01:31:11 +13006665#elif defined(TARGET_RISCV)
6666
6667/* Signal handler invocation must be transparent for the code being
6668 interrupted. Complete CPU (hart) state is saved on entry and restored
6669 before returning from the handler. Process sigmask is also saved to block
6670 signals while the handler is running. The handler gets its own stack,
6671 which also doubles as storage for the CPU state and sigmask.
6672
6673 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6674
6675struct target_sigcontext {
6676 abi_long pc;
6677 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6678 uint64_t fpr[32];
6679 uint32_t fcsr;
6680}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6681
6682struct target_ucontext {
6683 unsigned long uc_flags;
6684 struct target_ucontext *uc_link;
6685 target_stack_t uc_stack;
6686 struct target_sigcontext uc_mcontext;
6687 target_sigset_t uc_sigmask;
6688};
6689
6690struct target_rt_sigframe {
6691 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6692 struct target_siginfo info;
6693 struct target_ucontext uc;
6694};
6695
6696static abi_ulong get_sigframe(struct target_sigaction *ka,
6697 CPURISCVState *regs, size_t framesize)
6698{
6699 abi_ulong sp = regs->gpr[xSP];
6700 int onsigstack = on_sig_stack(sp);
6701
6702 /* redzone */
6703 /* This is the X/Open sanctioned signal stack switching. */
6704 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6705 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6706 }
6707
6708 sp -= framesize;
6709 sp &= ~3UL; /* align sp on 4-byte boundary */
6710
6711 /* If we are on the alternate signal stack and would overflow it, don't.
6712 Return an always-bogus address instead so we will die with SIGSEGV. */
6713 if (onsigstack && !likely(on_sig_stack(sp))) {
6714 return -1L;
6715 }
6716
6717 return sp;
6718}
6719
6720static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6721{
6722 int i;
6723
6724 __put_user(env->pc, &sc->pc);
6725
6726 for (i = 1; i < 32; i++) {
6727 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6728 }
6729 for (i = 0; i < 32; i++) {
6730 __put_user(env->fpr[i], &sc->fpr[i]);
6731 }
6732
6733 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6734 __put_user(fcsr, &sc->fcsr);
6735}
6736
6737static void setup_ucontext(struct target_ucontext *uc,
6738 CPURISCVState *env, target_sigset_t *set)
6739{
6740 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6741 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6742 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6743
6744 __put_user(0, &(uc->uc_flags));
6745 __put_user(0, &(uc->uc_link));
6746
6747 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6748 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6749 __put_user(ss_size, &(uc->uc_stack.ss_size));
6750
6751 int i;
6752 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6753 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6754 }
6755
6756 setup_sigcontext(&uc->uc_mcontext, env);
6757}
6758
6759static inline void install_sigtramp(uint32_t *tramp)
6760{
6761 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6762 __put_user(0x00000073, tramp + 1); /* ecall */
6763}
6764
6765static void setup_rt_frame(int sig, struct target_sigaction *ka,
6766 target_siginfo_t *info,
6767 target_sigset_t *set, CPURISCVState *env)
6768{
6769 abi_ulong frame_addr;
6770 struct target_rt_sigframe *frame;
6771
6772 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6773 trace_user_setup_rt_frame(env, frame_addr);
6774
6775 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6776 goto badframe;
6777 }
6778
6779 setup_ucontext(&frame->uc, env, set);
6780 tswap_siginfo(&frame->info, info);
6781 install_sigtramp(frame->tramp);
6782
6783 env->pc = ka->_sa_handler;
6784 env->gpr[xSP] = frame_addr;
6785 env->gpr[xA0] = sig;
6786 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6787 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6788 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6789
6790 return;
6791
6792badframe:
6793 unlock_user_struct(frame, frame_addr, 1);
6794 if (sig == TARGET_SIGSEGV) {
6795 ka->_sa_handler = TARGET_SIG_DFL;
6796 }
6797 force_sig(TARGET_SIGSEGV);
6798}
6799
6800static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6801{
6802 int i;
6803
6804 __get_user(env->pc, &sc->pc);
6805
6806 for (i = 1; i < 32; ++i) {
6807 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6808 }
6809 for (i = 0; i < 32; ++i) {
6810 __get_user(env->fpr[i], &sc->fpr[i]);
6811 }
6812
6813 uint32_t fcsr;
6814 __get_user(fcsr, &sc->fcsr);
6815 csr_write_helper(env, fcsr, CSR_FCSR);
6816}
6817
6818static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6819{
6820 sigset_t blocked;
6821 target_sigset_t target_set;
6822 int i;
6823
6824 target_sigemptyset(&target_set);
6825 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6826 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6827 }
6828
6829 target_to_host_sigset_internal(&blocked, &target_set);
6830 set_sigmask(&blocked);
6831
6832 restore_sigcontext(env, &uc->uc_mcontext);
6833}
6834
6835long do_rt_sigreturn(CPURISCVState *env)
6836{
6837 struct target_rt_sigframe *frame;
6838 abi_ulong frame_addr;
6839
6840 frame_addr = env->gpr[xSP];
6841 trace_user_do_sigreturn(env, frame_addr);
6842 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6843 goto badframe;
6844 }
6845
6846 restore_ucontext(env, &frame->uc);
6847
6848 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6849 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6850 goto badframe;
6851 }
6852
6853 unlock_user_struct(frame, frame_addr, 0);
6854 return -TARGET_QEMU_ESIGRETURN;
6855
6856badframe:
6857 unlock_user_struct(frame, frame_addr, 0);
6858 force_sig(TARGET_SIGSEGV);
6859 return 0;
6860}
6861
Richard Henderson1659e382016-12-15 09:59:01 -08006862#elif defined(TARGET_HPPA)
6863
6864struct target_sigcontext {
6865 abi_ulong sc_flags;
6866 abi_ulong sc_gr[32];
6867 uint64_t sc_fr[32];
6868 abi_ulong sc_iasq[2];
6869 abi_ulong sc_iaoq[2];
6870 abi_ulong sc_sar;
6871};
6872
6873struct target_ucontext {
6874 abi_uint tuc_flags;
6875 abi_ulong tuc_link;
6876 target_stack_t tuc_stack;
6877 abi_uint pad[1];
6878 struct target_sigcontext tuc_mcontext;
6879 target_sigset_t tuc_sigmask;
6880};
6881
6882struct target_rt_sigframe {
6883 abi_uint tramp[9];
6884 target_siginfo_t info;
6885 struct target_ucontext uc;
6886 /* hidden location of upper halves of pa2.0 64-bit gregs */
6887};
6888
6889static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6890{
6891 int flags = 0;
6892 int i;
6893
6894 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6895
6896 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6897 /* In the gateway page, executing a syscall. */
6898 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6899 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6900 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6901 } else {
6902 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6903 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6904 }
6905 __put_user(0, &sc->sc_iasq[0]);
6906 __put_user(0, &sc->sc_iasq[1]);
6907 __put_user(flags, &sc->sc_flags);
6908
6909 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6910 for (i = 1; i < 32; ++i) {
6911 __put_user(env->gr[i], &sc->sc_gr[i]);
6912 }
6913
6914 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6915 for (i = 1; i < 32; ++i) {
6916 __put_user(env->fr[i], &sc->sc_fr[i]);
6917 }
6918
Richard Henderson35136a72017-10-10 21:19:34 -07006919 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006920}
6921
6922static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6923{
6924 target_ulong psw;
6925 int i;
6926
6927 __get_user(psw, &sc->sc_gr[0]);
6928 cpu_hppa_put_psw(env, psw);
6929
6930 for (i = 1; i < 32; ++i) {
6931 __get_user(env->gr[i], &sc->sc_gr[i]);
6932 }
6933 for (i = 0; i < 32; ++i) {
6934 __get_user(env->fr[i], &sc->sc_fr[i]);
6935 }
6936 cpu_hppa_loaded_fr0(env);
6937
6938 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6939 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006940 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006941}
6942
6943/* No, this doesn't look right, but it's copied straight from the kernel. */
6944#define PARISC_RT_SIGFRAME_SIZE32 \
6945 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6946
6947static void setup_rt_frame(int sig, struct target_sigaction *ka,
6948 target_siginfo_t *info,
6949 target_sigset_t *set, CPUArchState *env)
6950{
6951 abi_ulong frame_addr, sp, haddr;
6952 struct target_rt_sigframe *frame;
6953 int i;
6954
6955 sp = env->gr[30];
6956 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6957 if (sas_ss_flags(sp) == 0) {
6958 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6959 }
6960 }
6961 frame_addr = QEMU_ALIGN_UP(sp, 64);
6962 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6963
6964 trace_user_setup_rt_frame(env, frame_addr);
6965
6966 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6967 goto give_sigsegv;
6968 }
6969
6970 tswap_siginfo(&frame->info, info);
6971 frame->uc.tuc_flags = 0;
6972 frame->uc.tuc_link = 0;
6973
6974 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6975 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6976 &frame->uc.tuc_stack.ss_flags);
6977 __put_user(target_sigaltstack_used.ss_size,
6978 &frame->uc.tuc_stack.ss_size);
6979
6980 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6981 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6982 }
6983
6984 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6985
6986 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6987 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6988 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6989 __put_user(0x08000240, frame->tramp + 3); /* nop */
6990
6991 unlock_user_struct(frame, frame_addr, 1);
6992
6993 env->gr[2] = h2g(frame->tramp);
6994 env->gr[30] = sp;
6995 env->gr[26] = sig;
6996 env->gr[25] = h2g(&frame->info);
6997 env->gr[24] = h2g(&frame->uc);
6998
6999 haddr = ka->_sa_handler;
7000 if (haddr & 2) {
7001 /* Function descriptor. */
7002 target_ulong *fdesc, dest;
7003
7004 haddr &= -4;
7005 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
7006 goto give_sigsegv;
7007 }
7008 __get_user(dest, fdesc);
7009 __get_user(env->gr[19], fdesc + 1);
7010 unlock_user_struct(fdesc, haddr, 1);
7011 haddr = dest;
7012 }
7013 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02007014 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08007015 return;
7016
7017 give_sigsegv:
7018 force_sigsegv(sig);
7019}
7020
7021long do_rt_sigreturn(CPUArchState *env)
7022{
7023 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
7024 struct target_rt_sigframe *frame;
7025 sigset_t set;
7026
7027 trace_user_do_rt_sigreturn(env, frame_addr);
7028 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7029 goto badframe;
7030 }
7031 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7032 set_sigmask(&set);
7033
7034 restore_sigcontext(env, &frame->uc.tuc_mcontext);
7035 unlock_user_struct(frame, frame_addr, 0);
7036
7037 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
7038 uc.tuc_stack),
7039 0, env->gr[30]) == -EFAULT) {
7040 goto badframe;
7041 }
7042
7043 unlock_user_struct(frame, frame_addr, 0);
7044 return -TARGET_QEMU_ESIGRETURN;
7045
7046 badframe:
7047 force_sig(TARGET_SIGSEGV);
7048 return -TARGET_QEMU_ESIGRETURN;
7049}
7050
Max Filippovba7651f2017-01-25 10:54:11 -08007051#elif defined(TARGET_XTENSA)
7052
7053struct target_sigcontext {
7054 abi_ulong sc_pc;
7055 abi_ulong sc_ps;
7056 abi_ulong sc_lbeg;
7057 abi_ulong sc_lend;
7058 abi_ulong sc_lcount;
7059 abi_ulong sc_sar;
7060 abi_ulong sc_acclo;
7061 abi_ulong sc_acchi;
7062 abi_ulong sc_a[16];
7063 abi_ulong sc_xtregs;
7064};
7065
7066struct target_ucontext {
7067 abi_ulong tuc_flags;
7068 abi_ulong tuc_link;
7069 target_stack_t tuc_stack;
7070 struct target_sigcontext tuc_mcontext;
7071 target_sigset_t tuc_sigmask;
7072};
7073
7074struct target_rt_sigframe {
7075 target_siginfo_t info;
7076 struct target_ucontext uc;
7077 /* TODO: xtregs */
7078 uint8_t retcode[6];
7079 abi_ulong window[4];
7080};
7081
7082static abi_ulong get_sigframe(struct target_sigaction *sa,
7083 CPUXtensaState *env,
7084 unsigned long framesize)
7085{
7086 abi_ulong sp = env->regs[1];
7087
7088 /* This is the X/Open sanctioned signal stack switching. */
7089 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
7090 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
7091 }
7092 return (sp - framesize) & -16;
7093}
7094
7095static int flush_window_regs(CPUXtensaState *env)
7096{
7097 const uint32_t nareg_mask = env->config->nareg - 1;
7098 uint32_t wb = env->sregs[WINDOW_BASE];
7099 uint32_t ws = (xtensa_replicate_windowstart(env) >> (wb + 1)) &
7100 ((1 << env->config->nareg / 4) - 1);
7101 uint32_t d = ctz32(ws) + 1;
7102 uint32_t sp;
7103 abi_long ret = 0;
7104
7105 wb += d;
7106 ws >>= d;
7107
7108 xtensa_sync_phys_from_window(env);
7109 sp = env->phys_regs[(wb * 4 + 1) & nareg_mask];
7110
7111 while (ws && ret == 0) {
7112 int d;
7113 int i;
7114 int idx;
7115
7116 if (ws & 0x1) {
7117 ws >>= 1;
7118 d = 1;
7119 } else if (ws & 0x2) {
7120 ws >>= 2;
7121 d = 2;
7122 for (i = 0; i < 4; ++i) {
7123 idx = (wb * 4 + 4 + i) & nareg_mask;
7124 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 12) * 4);
7125 }
7126 } else if (ws & 0x4) {
7127 ws >>= 3;
7128 d = 3;
7129 for (i = 0; i < 8; ++i) {
7130 idx = (wb * 4 + 4 + i) & nareg_mask;
7131 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 16) * 4);
7132 }
7133 } else {
7134 g_assert_not_reached();
7135 }
7136 sp = env->phys_regs[((wb + d) * 4 + 1) & nareg_mask];
7137 for (i = 0; i < 4; ++i) {
7138 idx = (wb * 4 + i) & nareg_mask;
7139 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 4) * 4);
7140 }
7141 wb += d;
7142 }
7143 return ret == 0;
7144}
7145
7146static int setup_sigcontext(struct target_rt_sigframe *frame,
7147 CPUXtensaState *env)
7148{
7149 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7150 int i;
7151
7152 __put_user(env->pc, &sc->sc_pc);
7153 __put_user(env->sregs[PS], &sc->sc_ps);
7154 __put_user(env->sregs[LBEG], &sc->sc_lbeg);
7155 __put_user(env->sregs[LEND], &sc->sc_lend);
7156 __put_user(env->sregs[LCOUNT], &sc->sc_lcount);
7157 if (!flush_window_regs(env)) {
7158 return 0;
7159 }
7160 for (i = 0; i < 16; ++i) {
7161 __put_user(env->regs[i], sc->sc_a + i);
7162 }
7163 __put_user(0, &sc->sc_xtregs);
7164 /* TODO: xtregs */
7165 return 1;
7166}
7167
7168static void setup_rt_frame(int sig, struct target_sigaction *ka,
7169 target_siginfo_t *info,
7170 target_sigset_t *set, CPUXtensaState *env)
7171{
7172 abi_ulong frame_addr;
7173 struct target_rt_sigframe *frame;
7174 uint32_t ra;
7175 int i;
7176
7177 frame_addr = get_sigframe(ka, env, sizeof(*frame));
7178 trace_user_setup_rt_frame(env, frame_addr);
7179
7180 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
7181 goto give_sigsegv;
7182 }
7183
7184 if (ka->sa_flags & SA_SIGINFO) {
7185 tswap_siginfo(&frame->info, info);
7186 }
7187
7188 __put_user(0, &frame->uc.tuc_flags);
7189 __put_user(0, &frame->uc.tuc_link);
7190 __put_user(target_sigaltstack_used.ss_sp,
7191 &frame->uc.tuc_stack.ss_sp);
7192 __put_user(sas_ss_flags(env->regs[1]),
7193 &frame->uc.tuc_stack.ss_flags);
7194 __put_user(target_sigaltstack_used.ss_size,
7195 &frame->uc.tuc_stack.ss_size);
7196 if (!setup_sigcontext(frame, env)) {
7197 unlock_user_struct(frame, frame_addr, 0);
7198 goto give_sigsegv;
7199 }
7200 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
7201 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7202 }
7203
7204 if (ka->sa_flags & TARGET_SA_RESTORER) {
7205 ra = ka->sa_restorer;
7206 } else {
7207 ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
7208#ifdef TARGET_WORDS_BIGENDIAN
7209 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7210 __put_user(0x22, &frame->retcode[0]);
7211 __put_user(0x0a, &frame->retcode[1]);
7212 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7213 /* Generate instruction: SYSCALL */
7214 __put_user(0x00, &frame->retcode[3]);
7215 __put_user(0x05, &frame->retcode[4]);
7216 __put_user(0x00, &frame->retcode[5]);
7217#else
7218 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7219 __put_user(0x22, &frame->retcode[0]);
7220 __put_user(0xa0, &frame->retcode[1]);
7221 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7222 /* Generate instruction: SYSCALL */
7223 __put_user(0x00, &frame->retcode[3]);
7224 __put_user(0x50, &frame->retcode[4]);
7225 __put_user(0x00, &frame->retcode[5]);
7226#endif
7227 }
7228 env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
7229 if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
7230 env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
7231 }
7232 memset(env->regs, 0, sizeof(env->regs));
7233 env->pc = ka->_sa_handler;
7234 env->regs[1] = frame_addr;
7235 env->sregs[WINDOW_BASE] = 0;
7236 env->sregs[WINDOW_START] = 1;
7237
7238 env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
7239 env->regs[6] = sig;
7240 env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
7241 env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
7242 unlock_user_struct(frame, frame_addr, 1);
7243 return;
7244
7245give_sigsegv:
7246 force_sigsegv(sig);
7247 return;
7248}
7249
7250static void restore_sigcontext(CPUXtensaState *env,
7251 struct target_rt_sigframe *frame)
7252{
7253 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7254 uint32_t ps;
7255 int i;
7256
7257 __get_user(env->pc, &sc->sc_pc);
7258 __get_user(ps, &sc->sc_ps);
7259 __get_user(env->sregs[LBEG], &sc->sc_lbeg);
7260 __get_user(env->sregs[LEND], &sc->sc_lend);
7261 __get_user(env->sregs[LCOUNT], &sc->sc_lcount);
7262
7263 env->sregs[WINDOW_BASE] = 0;
7264 env->sregs[WINDOW_START] = 1;
7265 env->sregs[PS] = deposit32(env->sregs[PS],
7266 PS_CALLINC_SHIFT,
7267 PS_CALLINC_LEN,
7268 extract32(ps, PS_CALLINC_SHIFT,
7269 PS_CALLINC_LEN));
7270 for (i = 0; i < 16; ++i) {
7271 __get_user(env->regs[i], sc->sc_a + i);
7272 }
7273 /* TODO: xtregs */
7274}
7275
7276long do_rt_sigreturn(CPUXtensaState *env)
7277{
7278 abi_ulong frame_addr = env->regs[1];
7279 struct target_rt_sigframe *frame;
7280 sigset_t set;
7281
7282 trace_user_do_rt_sigreturn(env, frame_addr);
7283 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7284 goto badframe;
7285 }
7286 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7287 set_sigmask(&set);
7288
7289 restore_sigcontext(env, frame);
7290
7291 if (do_sigaltstack(frame_addr +
7292 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7293 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) {
7294 goto badframe;
7295 }
7296 unlock_user_struct(frame, frame_addr, 0);
7297 return -TARGET_QEMU_ESIGRETURN;
7298
7299badframe:
7300 unlock_user_struct(frame, frame_addr, 0);
7301 force_sig(TARGET_SIGSEGV);
7302 return -TARGET_QEMU_ESIGRETURN;
7303}
7304
bellardb346ff42003-06-15 20:05:50 +00007305#else
Peter Maydellf8b985d2018-03-08 14:47:33 +00007306#error Target needs to add support for signal handling
bellard66fb9762003-03-23 01:06:05 +00007307#endif
7308
Peter Maydell31efaef2016-07-06 15:09:29 +01007309static void handle_pending_signal(CPUArchState *cpu_env, int sig,
7310 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01007311{
7312 CPUState *cpu = ENV_GET_CPU(cpu_env);
7313 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007314 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01007315 target_sigset_t target_old_set;
7316 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01007317 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01007318
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01007319 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00007320 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007321 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00007322
Andreas Färberdb6b81d2013-06-27 19:49:31 +02007323 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00007324 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00007325 sa = NULL;
7326 handler = TARGET_SIG_IGN;
7327 } else {
7328 sa = &sigact_table[sig - 1];
7329 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00007330 }
bellard66fb9762003-03-23 01:06:05 +00007331
Peter Maydell0cb581d2016-07-18 18:12:24 +01007332 if (do_strace) {
7333 print_taken_signal(sig, &k->info);
7334 }
7335
bellard66fb9762003-03-23 01:06:05 +00007336 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00007337 /* default handler : ignore some signal. The other are job control or fatal */
7338 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
7339 kill(getpid(),SIGSTOP);
7340 } else if (sig != TARGET_SIGCHLD &&
7341 sig != TARGET_SIGURG &&
7342 sig != TARGET_SIGWINCH &&
7343 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007344 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007345 }
7346 } else if (handler == TARGET_SIG_IGN) {
7347 /* ignore sig */
7348 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007349 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007350 } else {
bellard9de5e442003-03-23 16:49:39 +00007351 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007352 sigset_t *blocked_set;
7353
pbrook624f7972008-05-31 16:11:38 +00007354 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00007355 /* SA_NODEFER indicates that the current signal should not be
7356 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00007357 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00007358 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00007359
bellard9de5e442003-03-23 16:49:39 +00007360 /* save the previous blocked signal state to restore it at the
7361 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007362 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
7363
7364 /* block signals in the handler */
7365 blocked_set = ts->in_sigsuspend ?
7366 &ts->sigsuspend_mask : &ts->signal_mask;
7367 sigorset(&ts->signal_mask, blocked_set, &set);
7368 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00007369
bellardbc8a22c2003-03-30 21:02:40 +00007370 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00007371#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00007372 {
7373 CPUX86State *env = cpu_env;
7374 if (env->eflags & VM_MASK)
7375 save_v86_state(env);
7376 }
7377#endif
bellard9de5e442003-03-23 16:49:39 +00007378 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08007379#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10007380 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01007381 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13007382 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
Max Filippovba7651f2017-01-25 10:54:11 -08007383 || defined(TARGET_RISCV) || defined(TARGET_XTENSA)
Richard Hendersonff970902013-02-10 10:30:42 -08007384 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007385 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007386#else
pbrook624f7972008-05-31 16:11:38 +00007387 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007388 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00007389 else
pbrook624f7972008-05-31 16:11:38 +00007390 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007391#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01007392 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00007393 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01007394 }
bellard31e31b82003-02-18 22:55:36 +00007395 }
bellard31e31b82003-02-18 22:55:36 +00007396}
Peter Maydelle902d582016-05-27 15:51:44 +01007397
7398void process_pending_signals(CPUArchState *cpu_env)
7399{
7400 CPUState *cpu = ENV_GET_CPU(cpu_env);
7401 int sig;
7402 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007403 sigset_t set;
7404 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007405
Peter Maydell3d3efba2016-05-27 15:51:49 +01007406 while (atomic_read(&ts->signal_pending)) {
7407 /* FIXME: This is not threadsafe. */
7408 sigfillset(&set);
7409 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007410
Peter Maydell8bd37732016-07-28 16:44:45 +01007411 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007412 sig = ts->sync_signal.pending;
7413 if (sig) {
7414 /* Synchronous signals are forced,
7415 * see force_sig_info() and callers in Linux
7416 * Note that not all of our queue_signal() calls in QEMU correspond
7417 * to force_sig_info() calls in Linux (some are send_sig_info()).
7418 * However it seems like a kernel bug to me to allow the process
7419 * to block a synchronous signal since it could then just end up
7420 * looping round and round indefinitely.
7421 */
7422 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7423 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7424 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7425 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7426 }
7427
Peter Maydell31efaef2016-07-06 15:09:29 +01007428 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007429 }
7430
Peter Maydell3d3efba2016-05-27 15:51:49 +01007431 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7432 blocked_set = ts->in_sigsuspend ?
7433 &ts->sigsuspend_mask : &ts->signal_mask;
7434
7435 if (ts->sigtab[sig - 1].pending &&
7436 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007437 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007438 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007439 /* Restart scan from the beginning, as handle_pending_signal
7440 * might have resulted in a new synchronous signal (eg SIGSEGV).
7441 */
7442 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007443 }
Peter Maydelle902d582016-05-27 15:51:44 +01007444 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007445
7446 /* if no signal is pending, unblock signals and recheck (the act
7447 * of unblocking might cause us to take another host signal which
7448 * will set signal_pending again).
7449 */
7450 atomic_set(&ts->signal_pending, 0);
7451 ts->in_sigsuspend = 0;
7452 set = ts->signal_mask;
7453 sigdelset(&set, SIGSEGV);
7454 sigdelset(&set, SIGBUS);
7455 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007456 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007457 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007458}