blob: 24b6f38b42a5a59dc068f5d50170ce05720b71d8 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydell9eede5b2016-05-27 15:51:46 +0100256#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
Pranith Kumar1c1df012017-02-26 11:53:44 -0500257 !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100258/* Just set the guest's signal mask to the specified value; the
259 * caller is assumed to have called block_signals() already.
260 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100261static void set_sigmask(const sigset_t *set)
262{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100263 TaskState *ts = (TaskState *)thread_cpu->opaque;
264
265 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100266}
267#endif
268
bellard9de5e442003-03-23 16:49:39 +0000269/* siginfo conversion */
270
Anthony Liguoric227f092009-10-01 16:12:16 -0500271static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000272 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000273{
Richard Hendersona05c6402012-09-15 11:34:20 -0700274 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100275 int si_code = info->si_code;
276 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000279 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700280
Peter Maydell55d72a72016-06-13 11:22:05 +0100281 /* This memset serves two purposes:
282 * (1) ensure we don't leak random junk to the guest later
283 * (2) placate false positives from gcc about fields
284 * being used uninitialized if it chooses to inline both this
285 * function and tswap_siginfo() into host_to_target_siginfo().
286 */
287 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
288
Peter Maydella70dadc2016-05-27 15:51:59 +0100289 /* This is awkward, because we have to use a combination of
290 * the si_code and si_signo to figure out which of the union's
291 * members are valid. (Within the host kernel it is always possible
292 * to tell, but the kernel carefully avoids giving userspace the
293 * high 16 bits of si_code, so we don't have the information to
294 * do this the easy way...) We therefore make our best guess,
295 * bearing in mind that a guest can spoof most of the si_codes
296 * via rt_sigqueueinfo() if it likes.
297 *
298 * Once we have made our guess, we record it in the top 16 bits of
299 * the si_code, so that tswap_siginfo() later can use it.
300 * tswap_siginfo() will strip these top bits out before writing
301 * si_code to the guest (sign-extending the lower bits).
302 */
303
304 switch (si_code) {
305 case SI_USER:
306 case SI_TKILL:
307 case SI_KERNEL:
308 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
309 * These are the only unspoofable si_code values.
310 */
311 tinfo->_sifields._kill._pid = info->si_pid;
312 tinfo->_sifields._kill._uid = info->si_uid;
313 si_type = QEMU_SI_KILL;
314 break;
315 default:
316 /* Everything else is spoofable. Make best guess based on signal */
317 switch (sig) {
318 case TARGET_SIGCHLD:
319 tinfo->_sifields._sigchld._pid = info->si_pid;
320 tinfo->_sifields._sigchld._uid = info->si_uid;
321 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100322 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100323 tinfo->_sifields._sigchld._utime = info->si_utime;
324 tinfo->_sifields._sigchld._stime = info->si_stime;
325 si_type = QEMU_SI_CHLD;
326 break;
327 case TARGET_SIGIO:
328 tinfo->_sifields._sigpoll._band = info->si_band;
329 tinfo->_sifields._sigpoll._fd = info->si_fd;
330 si_type = QEMU_SI_POLL;
331 break;
332 default:
333 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
334 tinfo->_sifields._rt._pid = info->si_pid;
335 tinfo->_sifields._rt._uid = info->si_uid;
336 /* XXX: potential problem if 64 bit */
337 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100338 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100339 si_type = QEMU_SI_RT;
340 break;
341 }
342 break;
bellard9de5e442003-03-23 16:49:39 +0000343 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100344
345 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000346}
347
Anthony Liguoric227f092009-10-01 16:12:16 -0500348static void tswap_siginfo(target_siginfo_t *tinfo,
349 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000350{
Peter Maydella70dadc2016-05-27 15:51:59 +0100351 int si_type = extract32(info->si_code, 16, 16);
352 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700353
Peter Maydella70dadc2016-05-27 15:51:59 +0100354 __put_user(info->si_signo, &tinfo->si_signo);
355 __put_user(info->si_errno, &tinfo->si_errno);
356 __put_user(si_code, &tinfo->si_code);
357
358 /* We can use our internal marker of which fields in the structure
359 * are valid, rather than duplicating the guesswork of
360 * host_to_target_siginfo_noswap() here.
361 */
362 switch (si_type) {
363 case QEMU_SI_KILL:
364 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
365 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
366 break;
367 case QEMU_SI_TIMER:
368 __put_user(info->_sifields._timer._timer1,
369 &tinfo->_sifields._timer._timer1);
370 __put_user(info->_sifields._timer._timer2,
371 &tinfo->_sifields._timer._timer2);
372 break;
373 case QEMU_SI_POLL:
374 __put_user(info->_sifields._sigpoll._band,
375 &tinfo->_sifields._sigpoll._band);
376 __put_user(info->_sifields._sigpoll._fd,
377 &tinfo->_sifields._sigpoll._fd);
378 break;
379 case QEMU_SI_FAULT:
380 __put_user(info->_sifields._sigfault._addr,
381 &tinfo->_sifields._sigfault._addr);
382 break;
383 case QEMU_SI_CHLD:
384 __put_user(info->_sifields._sigchld._pid,
385 &tinfo->_sifields._sigchld._pid);
386 __put_user(info->_sifields._sigchld._uid,
387 &tinfo->_sifields._sigchld._uid);
388 __put_user(info->_sifields._sigchld._status,
389 &tinfo->_sifields._sigchld._status);
390 __put_user(info->_sifields._sigchld._utime,
391 &tinfo->_sifields._sigchld._utime);
392 __put_user(info->_sifields._sigchld._stime,
393 &tinfo->_sifields._sigchld._stime);
394 break;
395 case QEMU_SI_RT:
396 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
397 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
398 __put_user(info->_sifields._rt._sigval.sival_ptr,
399 &tinfo->_sifields._rt._sigval.sival_ptr);
400 break;
401 default:
402 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000403 }
404}
405
Anthony Liguoric227f092009-10-01 16:12:16 -0500406void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000407{
Peter Maydell55d72a72016-06-13 11:22:05 +0100408 target_siginfo_t tgt_tmp;
409 host_to_target_siginfo_noswap(&tgt_tmp, info);
410 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000411}
412
413/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000414/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500415void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000416{
Peter Maydell90c0f082016-05-27 15:52:01 +0100417 /* This conversion is used only for the rt_sigqueueinfo syscall,
418 * and so we know that the _rt fields are the valid ones.
419 */
420 abi_ulong sival_ptr;
421
422 __get_user(info->si_signo, &tinfo->si_signo);
423 __get_user(info->si_errno, &tinfo->si_errno);
424 __get_user(info->si_code, &tinfo->si_code);
425 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
426 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
427 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
428 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000429}
430
aurel32ca587a82008-12-18 22:44:13 +0000431static int fatal_signal (int sig)
432{
433 switch (sig) {
434 case TARGET_SIGCHLD:
435 case TARGET_SIGURG:
436 case TARGET_SIGWINCH:
437 /* Ignored by default. */
438 return 0;
439 case TARGET_SIGCONT:
440 case TARGET_SIGSTOP:
441 case TARGET_SIGTSTP:
442 case TARGET_SIGTTIN:
443 case TARGET_SIGTTOU:
444 /* Job control signals. */
445 return 0;
446 default:
447 return 1;
448 }
449}
450
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451/* returns 1 if given signal should dump core if not handled */
452static int core_dump_signal(int sig)
453{
454 switch (sig) {
455 case TARGET_SIGABRT:
456 case TARGET_SIGFPE:
457 case TARGET_SIGILL:
458 case TARGET_SIGQUIT:
459 case TARGET_SIGSEGV:
460 case TARGET_SIGTRAP:
461 case TARGET_SIGBUS:
462 return (1);
463 default:
464 return (0);
465 }
466}
467
bellard31e31b82003-02-18 22:55:36 +0000468void signal_init(void)
469{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100470 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000471 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000472 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000473 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000474 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000475
bellard9e5f5282003-07-13 17:33:54 +0000476 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200477 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000478 if (host_to_target_signal_table[i] == 0)
479 host_to_target_signal_table[i] = i;
480 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200481 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000482 j = host_to_target_signal_table[i];
483 target_to_host_signal_table[j] = i;
484 }
ths3b46e622007-09-17 08:09:54 +0000485
Peter Maydell3d3efba2016-05-27 15:51:49 +0100486 /* Set the signal mask from the host mask. */
487 sigprocmask(0, 0, &ts->signal_mask);
488
bellard9de5e442003-03-23 16:49:39 +0000489 /* set all host signal handlers. ALL signals are blocked during
490 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000491 memset(sigact_table, 0, sizeof(sigact_table));
492
bellard9de5e442003-03-23 16:49:39 +0000493 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000494 act.sa_flags = SA_SIGINFO;
495 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000496 for(i = 1; i <= TARGET_NSIG; i++) {
497 host_sig = target_to_host_signal(i);
498 sigaction(host_sig, NULL, &oact);
499 if (oact.sa_sigaction == (void *)SIG_IGN) {
500 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
501 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
502 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
503 }
504 /* If there's already a handler installed then something has
505 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000506 /* Install some handlers for our own use. We need at least
507 SIGSEGV and SIGBUS, to detect exceptions. We can not just
508 trap all signals because it affects syscall interrupt
509 behavior. But do trap all default-fatal signals. */
510 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000511 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000512 }
bellard31e31b82003-02-18 22:55:36 +0000513}
514
Pranith Kumar1c1df012017-02-26 11:53:44 -0500515#ifndef TARGET_UNICORE32
Peter Maydellc599d4d2016-07-28 16:44:49 +0100516/* Force a synchronously taken signal. The kernel force_sig() function
517 * also forces the signal to "not blocked, not ignored", but for QEMU
518 * that work is done in process_pending_signals().
519 */
520static void force_sig(int sig)
521{
522 CPUState *cpu = thread_cpu;
523 CPUArchState *env = cpu->env_ptr;
524 target_siginfo_t info;
525
526 info.si_signo = sig;
527 info.si_errno = 0;
528 info.si_code = TARGET_SI_KERNEL;
529 info._sifields._kill._pid = 0;
530 info._sifields._kill._uid = 0;
531 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
532}
Peter Maydell09391662016-07-28 16:44:47 +0100533
534/* Force a SIGSEGV if we couldn't write to memory trying to set
535 * up the signal frame. oldsig is the signal we were trying to handle
536 * at the point of failure.
537 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300538#if !defined(TARGET_RISCV)
Peter Maydell09391662016-07-28 16:44:47 +0100539static void force_sigsegv(int oldsig)
540{
Peter Maydell09391662016-07-28 16:44:47 +0100541 if (oldsig == SIGSEGV) {
542 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100543 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100544 */
545 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
546 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100547 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100548}
549#endif
bellard66fb9762003-03-23 01:06:05 +0000550
Michael Clark47ae93c2018-03-03 01:31:11 +1300551#endif
552
bellard9de5e442003-03-23 16:49:39 +0000553/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100554static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000555{
Andreas Färber0429a972013-08-26 18:14:44 +0200556 CPUState *cpu = thread_cpu;
557 CPUArchState *env = cpu->env_ptr;
558 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300559 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000560 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100561
Riku Voipio66393fb2009-12-04 15:16:32 +0200562 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100563 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200564 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000565
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300566 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200567 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 stop_all_tasks();
569 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200570 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300571 }
572 if (core_dumped) {
573 /* we already dumped the core of target process, we don't want
574 * a coredump of qemu itself */
575 struct rlimit nodump;
576 getrlimit(RLIMIT_CORE, &nodump);
577 nodump.rlim_cur=0;
578 setrlimit(RLIMIT_CORE, &nodump);
579 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200580 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300581 }
582
Stefan Weil0c587512011-04-28 17:20:32 +0200583 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000584 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
585 * a negative value. To get the proper exit code we need to
586 * actually die from an uncaught signal. Here the default signal
587 * handler is installed, we send ourself a signal and we wait for
588 * it to arrive. */
589 sigfillset(&act.sa_mask);
590 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000591 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000592 sigaction(host_sig, &act, NULL);
593
594 /* For some reason raise(host_sig) doesn't send the signal when
595 * statically linked on x86-64. */
596 kill(getpid(), host_sig);
597
598 /* Make sure the signal isn't masked (just reuse the mask inside
599 of act) */
600 sigdelset(&act.sa_mask, host_sig);
601 sigsuspend(&act.sa_mask);
602
603 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000604 abort();
bellard66fb9762003-03-23 01:06:05 +0000605}
606
bellard9de5e442003-03-23 16:49:39 +0000607/* queue a signal so that it will be send to the virtual CPU as soon
608 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100609int queue_signal(CPUArchState *env, int sig, int si_type,
610 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000611{
Andreas Färber0429a972013-08-26 18:14:44 +0200612 CPUState *cpu = ENV_GET_CPU(env);
613 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000614
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100615 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000616
Peter Maydell9d2803f2016-07-28 16:44:46 +0100617 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100618
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100619 ts->sync_signal.info = *info;
620 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100621 /* signal that a new signal is pending */
622 atomic_set(&ts->signal_pending, 1);
623 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000624}
625
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100626#ifndef HAVE_SAFE_SYSCALL
627static inline void rewind_if_in_safe_syscall(void *puc)
628{
629 /* Default version: never rewind */
630}
631#endif
632
ths5fafdf22007-09-16 21:08:06 +0000633static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000634 void *puc)
635{
Andreas Färbera2247f82013-06-09 19:47:04 +0200636 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100637 CPUState *cpu = ENV_GET_CPU(env);
638 TaskState *ts = cpu->opaque;
639
bellard9de5e442003-03-23 16:49:39 +0000640 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500641 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100642 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100643 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000644
645 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000646 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000647 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000648 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000649 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000650 return;
651 }
652
653 /* get target signal number */
654 sig = host_to_target_signal(host_signum);
655 if (sig < 1 || sig > TARGET_NSIG)
656 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100657 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100658
659 rewind_if_in_safe_syscall(puc);
660
bellard9de5e442003-03-23 16:49:39 +0000661 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100662 k = &ts->sigtab[sig - 1];
663 k->info = tinfo;
664 k->pending = sig;
665 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100666
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100667 /* Block host signals until target signal handler entered. We
668 * can't block SIGSEGV or SIGBUS while we're executing guest
669 * code in case the guest code provokes one in the window between
670 * now and it getting out to the main loop. Signals will be
671 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100672 *
673 * WARNING: we cannot use sigfillset() here because the uc_sigmask
674 * field is a kernel sigset_t, which is much smaller than the
675 * libc sigset_t which sigfillset() operates on. Using sigfillset()
676 * would write 0xff bytes off the end of the structure and trash
677 * data on the struct.
678 * We can't use sizeof(uc->uc_sigmask) either, because the libc
679 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100680 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100681 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100682 sigdelset(&uc->uc_sigmask, SIGSEGV);
683 sigdelset(&uc->uc_sigmask, SIGBUS);
684
685 /* interrupt the virtual CPU as soon as possible */
686 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000687}
688
ths0da46a62007-10-20 20:23:07 +0000689/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000690/* compare linux/kernel/signal.c:do_sigaltstack() */
691abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000692{
693 int ret;
694 struct target_sigaltstack oss;
695
696 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000697 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000698 {
699 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
700 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
701 __put_user(sas_ss_flags(sp), &oss.ss_flags);
702 }
703
bellard579a97f2007-11-11 14:26:47 +0000704 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000705 {
bellard579a97f2007-11-11 14:26:47 +0000706 struct target_sigaltstack *uss;
707 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500708 size_t minstacksize = TARGET_MINSIGSTKSZ;
709
710#if defined(TARGET_PPC64)
711 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
712 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
713 if (get_ppc64_abi(image) > 1) {
714 minstacksize = 4096;
715 }
716#endif
thsa04e1342007-09-27 13:57:58 +0000717
ths0da46a62007-10-20 20:23:07 +0000718 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300719 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000720 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300721 }
722 __get_user(ss.ss_sp, &uss->ss_sp);
723 __get_user(ss.ss_size, &uss->ss_size);
724 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000725 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000726
ths0da46a62007-10-20 20:23:07 +0000727 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000728 if (on_sig_stack(sp))
729 goto out;
730
ths0da46a62007-10-20 20:23:07 +0000731 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000732 if (ss.ss_flags != TARGET_SS_DISABLE
733 && ss.ss_flags != TARGET_SS_ONSTACK
734 && ss.ss_flags != 0)
735 goto out;
736
737 if (ss.ss_flags == TARGET_SS_DISABLE) {
738 ss.ss_size = 0;
739 ss.ss_sp = 0;
740 } else {
ths0da46a62007-10-20 20:23:07 +0000741 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500742 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000743 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500744 }
thsa04e1342007-09-27 13:57:58 +0000745 }
746
747 target_sigaltstack_used.ss_sp = ss.ss_sp;
748 target_sigaltstack_used.ss_size = ss.ss_size;
749 }
750
bellard579a97f2007-11-11 14:26:47 +0000751 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000752 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000753 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000754 goto out;
thsa04e1342007-09-27 13:57:58 +0000755 }
756
757 ret = 0;
758out:
759 return ret;
760}
761
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100762/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000763int do_sigaction(int sig, const struct target_sigaction *act,
764 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000765{
pbrook624f7972008-05-31 16:11:38 +0000766 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000767 struct sigaction act1;
768 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000769 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000770
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100771 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
772 return -TARGET_EINVAL;
773 }
774
775 if (block_signals()) {
776 return -TARGET_ERESTARTSYS;
777 }
778
bellard66fb9762003-03-23 01:06:05 +0000779 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000780 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->_sa_handler, &oact->_sa_handler);
782 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100783#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800784 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000785#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800786 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000787 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000788 }
789 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000790 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->_sa_handler, &act->_sa_handler);
792 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100793#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800794 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000795#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800796 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000797 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000798
799 /* we update the host linux signal state */
800 host_sig = target_to_host_signal(sig);
801 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
802 sigfillset(&act1.sa_mask);
803 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000804 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000805 act1.sa_flags |= SA_RESTART;
806 /* NOTE: it is important to update the host kernel signal
807 ignore state to avoid getting unexpected interrupted
808 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000809 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000810 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000811 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000812 if (fatal_signal (sig))
813 act1.sa_sigaction = host_signal_handler;
814 else
815 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000816 } else {
817 act1.sa_sigaction = host_signal_handler;
818 }
ths0da46a62007-10-20 20:23:07 +0000819 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000820 }
bellard66fb9762003-03-23 01:06:05 +0000821 }
ths0da46a62007-10-20 20:23:07 +0000822 return ret;
bellard66fb9762003-03-23 01:06:05 +0000823}
bellard31e31b82003-02-18 22:55:36 +0000824
Pranith Kumar1c1df012017-02-26 11:53:44 -0500825#if defined(TARGET_I386)
826/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000827
828struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100829 uint16_t significand[4];
830 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000831};
832
833struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100834 uint16_t significand[4];
835 uint16_t exponent;
836 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000837};
838
839struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500840 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000841};
842
Pranith Kumar1c1df012017-02-26 11:53:44 -0500843struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100844 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500845 uint32_t cw;
846 uint32_t sw;
847 uint32_t tag;
848 uint32_t ipoff;
849 uint32_t cssel;
850 uint32_t dataoff;
851 uint32_t datasel;
852 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100853 uint16_t status;
854 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000855
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100856 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500857 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
858 uint32_t mxcsr;
859 uint32_t reserved;
860 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
861 struct target_xmmreg xmm[8];
862 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000863};
864
Pranith Kumar1c1df012017-02-26 11:53:44 -0500865struct target_fpstate_64 {
866 /* FXSAVE format */
867 uint16_t cw;
868 uint16_t sw;
869 uint16_t twd;
870 uint16_t fop;
871 uint64_t rip;
872 uint64_t rdp;
873 uint32_t mxcsr;
874 uint32_t mxcsr_mask;
875 uint32_t st_space[32];
876 uint32_t xmm_space[64];
877 uint32_t reserved[24];
878};
bellard66fb9762003-03-23 01:06:05 +0000879
Pranith Kumar1c1df012017-02-26 11:53:44 -0500880#ifndef TARGET_X86_64
881# define target_fpstate target_fpstate_32
882#else
883# define target_fpstate target_fpstate_64
884#endif
885
886struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100887 uint16_t gs, __gsh;
888 uint16_t fs, __fsh;
889 uint16_t es, __esh;
890 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500891 uint32_t edi;
892 uint32_t esi;
893 uint32_t ebp;
894 uint32_t esp;
895 uint32_t ebx;
896 uint32_t edx;
897 uint32_t ecx;
898 uint32_t eax;
899 uint32_t trapno;
900 uint32_t err;
901 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500903 uint32_t eflags;
904 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100905 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500906 uint32_t fpstate; /* pointer */
907 uint32_t oldmask;
908 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000909};
910
Pranith Kumar1c1df012017-02-26 11:53:44 -0500911struct target_sigcontext_64 {
912 uint64_t r8;
913 uint64_t r9;
914 uint64_t r10;
915 uint64_t r11;
916 uint64_t r12;
917 uint64_t r13;
918 uint64_t r14;
919 uint64_t r15;
920
921 uint64_t rdi;
922 uint64_t rsi;
923 uint64_t rbp;
924 uint64_t rbx;
925 uint64_t rdx;
926 uint64_t rax;
927 uint64_t rcx;
928 uint64_t rsp;
929 uint64_t rip;
930
931 uint64_t eflags;
932
933 uint16_t cs;
934 uint16_t gs;
935 uint16_t fs;
936 uint16_t ss;
937
938 uint64_t err;
939 uint64_t trapno;
940 uint64_t oldmask;
941 uint64_t cr2;
942
943 uint64_t fpstate; /* pointer */
944 uint64_t padding[8];
945};
946
947#ifndef TARGET_X86_64
948# define target_sigcontext target_sigcontext_32
949#else
950# define target_sigcontext target_sigcontext_64
951#endif
952
953/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000954struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100955 abi_ulong tuc_flags;
956 abi_ulong tuc_link;
957 target_stack_t tuc_stack;
958 struct target_sigcontext tuc_mcontext;
959 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000960};
961
Pranith Kumar1c1df012017-02-26 11:53:44 -0500962#ifndef TARGET_X86_64
963struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000964 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000965 int sig;
966 struct target_sigcontext sc;
967 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000968 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000969 char retcode[8];
970};
971
Pranith Kumar1c1df012017-02-26 11:53:44 -0500972struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000973 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000974 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000975 abi_ulong pinfo;
976 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000977 struct target_siginfo info;
978 struct target_ucontext uc;
979 struct target_fpstate fpstate;
980 char retcode[8];
981};
982
Pranith Kumar1c1df012017-02-26 11:53:44 -0500983#else
984
985struct rt_sigframe {
986 abi_ulong pretcode;
987 struct target_ucontext uc;
988 struct target_siginfo info;
989 struct target_fpstate fpstate;
990};
991
992#endif
993
bellard66fb9762003-03-23 01:06:05 +0000994/*
995 * Set up a signal frame.
996 */
997
bellard66fb9762003-03-23 01:06:05 +0000998/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300999static void setup_sigcontext(struct target_sigcontext *sc,
1000 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
1001 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +00001002{
Andreas Färber27103422013-08-26 08:31:06 +02001003 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -05001004#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +02001005 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +00001006
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001007 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001008 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
1009 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
1010 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
1011 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
1012 __put_user(env->regs[R_EDI], &sc->edi);
1013 __put_user(env->regs[R_ESI], &sc->esi);
1014 __put_user(env->regs[R_EBP], &sc->ebp);
1015 __put_user(env->regs[R_ESP], &sc->esp);
1016 __put_user(env->regs[R_EBX], &sc->ebx);
1017 __put_user(env->regs[R_EDX], &sc->edx);
1018 __put_user(env->regs[R_ECX], &sc->ecx);
1019 __put_user(env->regs[R_EAX], &sc->eax);
1020 __put_user(cs->exception_index, &sc->trapno);
1021 __put_user(env->error_code, &sc->err);
1022 __put_user(env->eip, &sc->eip);
1023 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1024 __put_user(env->eflags, &sc->eflags);
1025 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1026 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001028 cpu_x86_fsave(env, fpstate_addr, 1);
1029 fpstate->status = fpstate->sw;
1030 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001031 __put_user(magic, &fpstate->magic);
1032 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001033
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001034 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001035 __put_user(mask, &sc->oldmask);
1036 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001037#else
1038 __put_user(env->regs[R_EDI], &sc->rdi);
1039 __put_user(env->regs[R_ESI], &sc->rsi);
1040 __put_user(env->regs[R_EBP], &sc->rbp);
1041 __put_user(env->regs[R_ESP], &sc->rsp);
1042 __put_user(env->regs[R_EBX], &sc->rbx);
1043 __put_user(env->regs[R_EDX], &sc->rdx);
1044 __put_user(env->regs[R_ECX], &sc->rcx);
1045 __put_user(env->regs[R_EAX], &sc->rax);
1046
1047 __put_user(env->regs[8], &sc->r8);
1048 __put_user(env->regs[9], &sc->r9);
1049 __put_user(env->regs[10], &sc->r10);
1050 __put_user(env->regs[11], &sc->r11);
1051 __put_user(env->regs[12], &sc->r12);
1052 __put_user(env->regs[13], &sc->r13);
1053 __put_user(env->regs[14], &sc->r14);
1054 __put_user(env->regs[15], &sc->r15);
1055
1056 __put_user(cs->exception_index, &sc->trapno);
1057 __put_user(env->error_code, &sc->err);
1058 __put_user(env->eip, &sc->rip);
1059
1060 __put_user(env->eflags, &sc->eflags);
1061 __put_user(env->segs[R_CS].selector, &sc->cs);
1062 __put_user((uint16_t)0, &sc->gs);
1063 __put_user((uint16_t)0, &sc->fs);
1064 __put_user(env->segs[R_SS].selector, &sc->ss);
1065
1066 __put_user(mask, &sc->oldmask);
1067 __put_user(env->cr[2], &sc->cr2);
1068
1069 /* fpstate_addr must be 16 byte aligned for fxsave */
1070 assert(!(fpstate_addr & 0xf));
1071
1072 cpu_x86_fxsave(env, fpstate_addr);
1073 __put_user(fpstate_addr, &sc->fpstate);
1074#endif
bellard66fb9762003-03-23 01:06:05 +00001075}
1076
1077/*
1078 * Determine which stack to use..
1079 */
1080
bellard579a97f2007-11-11 14:26:47 +00001081static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001082get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001083{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001084 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001085
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001086 /* Default to using normal stack */
1087 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001088#ifdef TARGET_X86_64
1089 esp -= 128; /* this is the redzone */
1090#endif
1091
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001092 /* This is the X/Open sanctioned signal stack switching. */
1093 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1094 if (sas_ss_flags(esp) == 0) {
1095 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001096 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001097 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001098#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001099 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001100 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1102 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001103 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001104 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001105#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001107
1108#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001109 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001110#else
1111 return ((esp - frame_size) & (~15ul)) - 8;
1112#endif
bellard66fb9762003-03-23 01:06:05 +00001113}
1114
Pranith Kumar1c1df012017-02-26 11:53:44 -05001115#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001116/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001117static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001118 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001119{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001120 abi_ulong frame_addr;
1121 struct sigframe *frame;
1122 int i;
bellard66fb9762003-03-23 01:06:05 +00001123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1125 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001127 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1128 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001129
Peter Maydellb6e2c932015-01-08 12:19:43 +00001130 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001132 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1133 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001134
Riku Voipio7df2fa32014-04-23 10:34:53 +03001135 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1136 __put_user(set->sig[i], &frame->extramask[i - 1]);
1137 }
bellard66fb9762003-03-23 01:06:05 +00001138
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001139 /* Set up to return from userspace. If provided, use a stub
1140 already in userspace. */
1141 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001142 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001143 } else {
1144 uint16_t val16;
1145 abi_ulong retcode_addr;
1146 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001147 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001148 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1149 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001150 __put_user(val16, (uint16_t *)(frame->retcode+0));
1151 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001152 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001153 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001154 }
bellard66fb9762003-03-23 01:06:05 +00001155
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001156 /* Set up registers for signal handler */
1157 env->regs[R_ESP] = frame_addr;
1158 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001159
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001160 cpu_x86_load_seg(env, R_DS, __USER_DS);
1161 cpu_x86_load_seg(env, R_ES, __USER_DS);
1162 cpu_x86_load_seg(env, R_SS, __USER_DS);
1163 cpu_x86_load_seg(env, R_CS, __USER_CS);
1164 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001165
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001166 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001168 return;
bellard66fb9762003-03-23 01:06:05 +00001169
1170give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001171 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001172}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001173#endif
bellard66fb9762003-03-23 01:06:05 +00001174
Pranith Kumar1c1df012017-02-26 11:53:44 -05001175/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001176static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001177 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001178 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001179{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001180 abi_ulong frame_addr;
1181#ifndef TARGET_X86_64
1182 abi_ulong addr;
1183#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001184 struct rt_sigframe *frame;
1185 int i;
bellard66fb9762003-03-23 01:06:05 +00001186
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001187 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1188 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001189
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001190 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1191 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001192
Pranith Kumar1c1df012017-02-26 11:53:44 -05001193 /* These fields are only in rt_sigframe on 32 bit */
1194#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001195 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001196 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001197 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001198 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001199 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001200#endif
1201 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1202 tswap_siginfo(&frame->info, info);
1203 }
bellard66fb9762003-03-23 01:06:05 +00001204
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001205 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001206 __put_user(0, &frame->uc.tuc_flags);
1207 __put_user(0, &frame->uc.tuc_link);
1208 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1209 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1210 &frame->uc.tuc_stack.ss_flags);
1211 __put_user(target_sigaltstack_used.ss_size,
1212 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001213 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1214 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1215
Riku Voipio0188fad2014-04-23 13:34:15 +03001216 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1217 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1218 }
bellard66fb9762003-03-23 01:06:05 +00001219
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001220 /* Set up to return from userspace. If provided, use a stub
1221 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001222#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001223 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001224 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001225 } else {
1226 uint16_t val16;
1227 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001228 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001229 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001230 __put_user(0xb8, (char *)(frame->retcode+0));
1231 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001232 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001233 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001234 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001235#else
1236 /* XXX: Would be slightly better to return -EFAULT here if test fails
1237 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1238 __put_user(ka->sa_restorer, &frame->pretcode);
1239#endif
bellard66fb9762003-03-23 01:06:05 +00001240
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001241 /* Set up registers for signal handler */
1242 env->regs[R_ESP] = frame_addr;
1243 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001244
Pranith Kumar1c1df012017-02-26 11:53:44 -05001245#ifndef TARGET_X86_64
1246 env->regs[R_EAX] = sig;
1247 env->regs[R_EDX] = (unsigned long)&frame->info;
1248 env->regs[R_ECX] = (unsigned long)&frame->uc;
1249#else
1250 env->regs[R_EAX] = 0;
1251 env->regs[R_EDI] = sig;
1252 env->regs[R_ESI] = (unsigned long)&frame->info;
1253 env->regs[R_EDX] = (unsigned long)&frame->uc;
1254#endif
1255
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001256 cpu_x86_load_seg(env, R_DS, __USER_DS);
1257 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001258 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001259 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001260 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001261
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001262 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001263
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001264 return;
bellard66fb9762003-03-23 01:06:05 +00001265
1266give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001267 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001268}
1269
1270static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001271restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001272{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001273 unsigned int err = 0;
1274 abi_ulong fpstate_addr;
1275 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001276
Pranith Kumar1c1df012017-02-26 11:53:44 -05001277#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001278 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1279 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1280 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1281 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001282
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001283 env->regs[R_EDI] = tswapl(sc->edi);
1284 env->regs[R_ESI] = tswapl(sc->esi);
1285 env->regs[R_EBP] = tswapl(sc->ebp);
1286 env->regs[R_ESP] = tswapl(sc->esp);
1287 env->regs[R_EBX] = tswapl(sc->ebx);
1288 env->regs[R_EDX] = tswapl(sc->edx);
1289 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001290 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001292 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001293#else
1294 env->regs[8] = tswapl(sc->r8);
1295 env->regs[9] = tswapl(sc->r9);
1296 env->regs[10] = tswapl(sc->r10);
1297 env->regs[11] = tswapl(sc->r11);
1298 env->regs[12] = tswapl(sc->r12);
1299 env->regs[13] = tswapl(sc->r13);
1300 env->regs[14] = tswapl(sc->r14);
1301 env->regs[15] = tswapl(sc->r15);
1302
1303 env->regs[R_EDI] = tswapl(sc->rdi);
1304 env->regs[R_ESI] = tswapl(sc->rsi);
1305 env->regs[R_EBP] = tswapl(sc->rbp);
1306 env->regs[R_EBX] = tswapl(sc->rbx);
1307 env->regs[R_EDX] = tswapl(sc->rdx);
1308 env->regs[R_EAX] = tswapl(sc->rax);
1309 env->regs[R_ECX] = tswapl(sc->rcx);
1310 env->regs[R_ESP] = tswapl(sc->rsp);
1311
1312 env->eip = tswapl(sc->rip);
1313#endif
bellard66fb9762003-03-23 01:06:05 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1316 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001317
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001318 tmpflags = tswapl(sc->eflags);
1319 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1320 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001322 fpstate_addr = tswapl(sc->fpstate);
1323 if (fpstate_addr != 0) {
1324 if (!access_ok(VERIFY_READ, fpstate_addr,
1325 sizeof(struct target_fpstate)))
1326 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001327#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001328 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001329#else
1330 cpu_x86_fxrstor(env, fpstate_addr);
1331#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001332 }
bellard66fb9762003-03-23 01:06:05 +00001333
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001334 return err;
bellard66fb9762003-03-23 01:06:05 +00001335badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001336 return 1;
bellard66fb9762003-03-23 01:06:05 +00001337}
1338
Pranith Kumar1c1df012017-02-26 11:53:44 -05001339/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1340#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001341long do_sigreturn(CPUX86State *env)
1342{
bellard579a97f2007-11-11 14:26:47 +00001343 struct sigframe *frame;
1344 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001345 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001346 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001347 int i;
bellard66fb9762003-03-23 01:06:05 +00001348
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001349 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001350 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1351 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001352 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001353 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001354 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001355 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001356 }
bellard66fb9762003-03-23 01:06:05 +00001357
bellard92319442004-06-19 16:58:13 +00001358 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001359 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001360
bellard66fb9762003-03-23 01:06:05 +00001361 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001362 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001363 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001364 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001365 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001366
1367badframe:
bellard579a97f2007-11-11 14:26:47 +00001368 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001369 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001370 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001371}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001372#endif
bellard66fb9762003-03-23 01:06:05 +00001373
1374long do_rt_sigreturn(CPUX86State *env)
1375{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001376 abi_ulong frame_addr;
1377 struct rt_sigframe *frame;
1378 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001379
Pranith Kumar1c1df012017-02-26 11:53:44 -05001380 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001381 trace_user_do_rt_sigreturn(env, frame_addr);
1382 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1383 goto badframe;
1384 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001385 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001386
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001387 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001388 goto badframe;
1389 }
bellard66fb9762003-03-23 01:06:05 +00001390
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001391 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1392 get_sp_from_cpustate(env)) == -EFAULT) {
1393 goto badframe;
1394 }
thsa04e1342007-09-27 13:57:58 +00001395
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001396 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001397 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001398
1399badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001400 unlock_user_struct(frame, frame_addr, 0);
1401 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001402 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001403}
1404
Andreas Schwab1744aea2013-09-03 20:12:16 +01001405#elif defined(TARGET_AARCH64)
1406
1407struct target_sigcontext {
1408 uint64_t fault_address;
1409 /* AArch64 registers */
1410 uint64_t regs[31];
1411 uint64_t sp;
1412 uint64_t pc;
1413 uint64_t pstate;
1414 /* 4K reserved for FP/SIMD state and future expansion */
1415 char __reserved[4096] __attribute__((__aligned__(16)));
1416};
1417
1418struct target_ucontext {
1419 abi_ulong tuc_flags;
1420 abi_ulong tuc_link;
1421 target_stack_t tuc_stack;
1422 target_sigset_t tuc_sigmask;
1423 /* glibc uses a 1024-bit sigset_t */
1424 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1425 /* last for future expansion */
1426 struct target_sigcontext tuc_mcontext;
1427};
1428
1429/*
1430 * Header to be used at the beginning of structures extending the user
1431 * context. Such structures must be placed after the rt_sigframe on the stack
1432 * and be 16-byte aligned. The last structure must be a dummy one with the
1433 * magic and size set to 0.
1434 */
1435struct target_aarch64_ctx {
1436 uint32_t magic;
1437 uint32_t size;
1438};
1439
1440#define TARGET_FPSIMD_MAGIC 0x46508001
1441
1442struct target_fpsimd_context {
1443 struct target_aarch64_ctx head;
1444 uint32_t fpsr;
1445 uint32_t fpcr;
1446 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1447};
1448
Richard Henderson7a53fb92018-03-09 17:09:43 +00001449#define TARGET_EXTRA_MAGIC 0x45585401
1450
1451struct target_extra_context {
1452 struct target_aarch64_ctx head;
1453 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
1454 uint32_t size; /* size in bytes of the extra space */
1455 uint32_t reserved[3];
1456};
1457
Richard Henderson8c5931d2018-03-09 17:09:44 +00001458#define TARGET_SVE_MAGIC 0x53564501
1459
1460struct target_sve_context {
1461 struct target_aarch64_ctx head;
1462 uint16_t vl;
1463 uint16_t reserved[3];
1464 /* The actual SVE data immediately follows. It is layed out
1465 * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
1466 * the original struct pointer.
1467 */
1468};
1469
1470#define TARGET_SVE_VQ_BYTES 16
1471
1472#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
1473#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
1474
1475#define TARGET_SVE_SIG_REGS_OFFSET \
1476 QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
1477#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
1478 (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
1479#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
1480 (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
1481#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
1482 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
1483#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
1484 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
1485
Andreas Schwab1744aea2013-09-03 20:12:16 +01001486struct target_rt_sigframe {
1487 struct target_siginfo info;
1488 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001489};
1490
1491struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001492 uint64_t fp;
1493 uint64_t lr;
1494 uint32_t tramp[2];
1495};
1496
Richard Henderson3b505bb2018-03-09 17:09:43 +00001497static void target_setup_general_frame(struct target_rt_sigframe *sf,
1498 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001499{
1500 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001501
Richard Henderson3b505bb2018-03-09 17:09:43 +00001502 __put_user(0, &sf->uc.tuc_flags);
1503 __put_user(0, &sf->uc.tuc_link);
1504
1505 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1506 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1507 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001508
1509 for (i = 0; i < 31; i++) {
1510 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1511 }
1512 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1513 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001514 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001515
Peter Maydell7af03922014-05-01 18:36:17 +01001516 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001517
1518 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1519 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1520 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001521}
1522
1523static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1524 CPUARMState *env)
1525{
1526 int i;
1527
1528 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1529 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1530 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1531 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001532
1533 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001534 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001535#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001536 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1537 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001538#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001539 __put_user(q[0], &fpsimd->vregs[i * 2]);
1540 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001541#endif
1542 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001543}
1544
Richard Henderson7a53fb92018-03-09 17:09:43 +00001545static void target_setup_extra_record(struct target_extra_context *extra,
1546 uint64_t datap, uint32_t extra_size)
1547{
1548 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
1549 __put_user(sizeof(struct target_extra_context), &extra->head.size);
1550 __put_user(datap, &extra->datap);
1551 __put_user(extra_size, &extra->size);
1552}
1553
Richard Henderson3b505bb2018-03-09 17:09:43 +00001554static void target_setup_end_record(struct target_aarch64_ctx *end)
1555{
1556 __put_user(0, &end->magic);
1557 __put_user(0, &end->size);
1558}
1559
Richard Henderson8c5931d2018-03-09 17:09:44 +00001560static void target_setup_sve_record(struct target_sve_context *sve,
1561 CPUARMState *env, int vq, int size)
1562{
1563 int i, j;
1564
1565 __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
1566 __put_user(size, &sve->head.size);
1567 __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
1568
1569 /* Note that SVE regs are stored as a byte stream, with each byte element
1570 * at a subsequent address. This corresponds to a little-endian store
1571 * of our 64-bit hunks.
1572 */
1573 for (i = 0; i < 32; ++i) {
1574 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1575 for (j = 0; j < vq * 2; ++j) {
1576 __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
1577 }
1578 }
1579 for (i = 0; i <= 16; ++i) {
1580 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1581 for (j = 0; j < vq; ++j) {
1582 uint64_t r = env->vfp.pregs[i].p[j >> 2];
1583 __put_user_e(r >> ((j & 3) * 16), p + j, le);
1584 }
1585 }
1586}
1587
Richard Henderson3b505bb2018-03-09 17:09:43 +00001588static void target_restore_general_frame(CPUARMState *env,
1589 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001590{
1591 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001592 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001593 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001594
1595 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001596 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001597
1598 for (i = 0; i < 31; i++) {
1599 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1600 }
1601
1602 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1603 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001604 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1605 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001606}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001607
Richard Henderson3b505bb2018-03-09 17:09:43 +00001608static void target_restore_fpsimd_record(CPUARMState *env,
1609 struct target_fpsimd_context *fpsimd)
1610{
1611 uint32_t fpsr, fpcr;
1612 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001613
Richard Henderson3b505bb2018-03-09 17:09:43 +00001614 __get_user(fpsr, &fpsimd->fpsr);
1615 vfp_set_fpsr(env, fpsr);
1616 __get_user(fpcr, &fpsimd->fpcr);
1617 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001618
Peter Maydell4cf23482014-03-02 19:36:38 +00001619 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001620 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001621#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001622 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1623 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001624#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001625 __get_user(q[0], &fpsimd->vregs[i * 2]);
1626 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001627#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001628 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001629}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001630
Richard Henderson8c5931d2018-03-09 17:09:44 +00001631static void target_restore_sve_record(CPUARMState *env,
1632 struct target_sve_context *sve, int vq)
1633{
1634 int i, j;
1635
1636 /* Note that SVE regs are stored as a byte stream, with each byte element
1637 * at a subsequent address. This corresponds to a little-endian load
1638 * of our 64-bit hunks.
1639 */
1640 for (i = 0; i < 32; ++i) {
1641 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
1642 for (j = 0; j < vq * 2; ++j) {
1643 __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
1644 }
1645 }
1646 for (i = 0; i <= 16; ++i) {
1647 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
1648 for (j = 0; j < vq; ++j) {
1649 uint16_t r;
1650 __get_user_e(r, p + j, le);
1651 if (j & 3) {
1652 env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
1653 } else {
1654 env->vfp.pregs[i].p[j >> 2] = r;
1655 }
1656 }
1657 }
1658}
1659
Richard Henderson3b505bb2018-03-09 17:09:43 +00001660static int target_restore_sigframe(CPUARMState *env,
1661 struct target_rt_sigframe *sf)
1662{
Richard Henderson7a53fb92018-03-09 17:09:43 +00001663 struct target_aarch64_ctx *ctx, *extra = NULL;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001664 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001665 struct target_sve_context *sve = NULL;
Richard Henderson7a53fb92018-03-09 17:09:43 +00001666 uint64_t extra_datap = 0;
1667 bool used_extra = false;
1668 bool err = false;
Richard Henderson8c5931d2018-03-09 17:09:44 +00001669 int vq = 0, sve_size = 0;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001670
1671 target_restore_general_frame(env, sf);
1672
Richard Hendersone1eecd12018-03-09 17:09:43 +00001673 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1674 while (ctx) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001675 uint32_t magic, size, extra_size;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001676
1677 __get_user(magic, &ctx->magic);
1678 __get_user(size, &ctx->size);
1679 switch (magic) {
1680 case 0:
1681 if (size != 0) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001682 err = true;
1683 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001684 }
Richard Henderson7a53fb92018-03-09 17:09:43 +00001685 if (used_extra) {
1686 ctx = NULL;
1687 } else {
1688 ctx = extra;
1689 used_extra = true;
1690 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001691 continue;
1692
1693 case TARGET_FPSIMD_MAGIC:
1694 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001695 err = true;
1696 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001697 }
1698 fpsimd = (struct target_fpsimd_context *)ctx;
1699 break;
1700
Richard Henderson8c5931d2018-03-09 17:09:44 +00001701 case TARGET_SVE_MAGIC:
1702 if (arm_feature(env, ARM_FEATURE_SVE)) {
1703 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1704 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1705 if (!sve && size == sve_size) {
1706 sve = (struct target_sve_context *)ctx;
1707 break;
1708 }
1709 }
1710 err = true;
1711 goto exit;
1712
Richard Henderson7a53fb92018-03-09 17:09:43 +00001713 case TARGET_EXTRA_MAGIC:
1714 if (extra || size != sizeof(struct target_extra_context)) {
1715 err = true;
1716 goto exit;
1717 }
1718 __get_user(extra_datap,
1719 &((struct target_extra_context *)ctx)->datap);
1720 __get_user(extra_size,
1721 &((struct target_extra_context *)ctx)->size);
1722 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
1723 break;
1724
Richard Hendersone1eecd12018-03-09 17:09:43 +00001725 default:
1726 /* Unknown record -- we certainly didn't generate it.
1727 * Did we in fact get out of sync?
1728 */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001729 err = true;
1730 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001731 }
1732 ctx = (void *)ctx + size;
1733 }
1734
1735 /* Require FPSIMD always. */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001736 if (fpsimd) {
1737 target_restore_fpsimd_record(env, fpsimd);
1738 } else {
1739 err = true;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001740 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001741
Richard Henderson8c5931d2018-03-09 17:09:44 +00001742 /* SVE data, if present, overwrites FPSIMD data. */
1743 if (sve) {
1744 target_restore_sve_record(env, sve, vq);
1745 }
1746
Richard Henderson7a53fb92018-03-09 17:09:43 +00001747 exit:
1748 unlock_user(extra, extra_datap, 0);
1749 return err;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001750}
1751
Richard Henderson8c5931d2018-03-09 17:09:44 +00001752static abi_ulong get_sigframe(struct target_sigaction *ka,
1753 CPUARMState *env, int size)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001754{
1755 abi_ulong sp;
1756
1757 sp = env->xregs[31];
1758
1759 /*
1760 * This is the X/Open sanctioned signal stack switching.
1761 */
Riku Voipiob545f632014-07-15 17:01:55 +03001762 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001763 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1764 }
1765
Richard Henderson8c5931d2018-03-09 17:09:44 +00001766 sp = (sp - size) & ~15;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001767
1768 return sp;
1769}
1770
Richard Henderson8c5931d2018-03-09 17:09:44 +00001771typedef struct {
1772 int total_size;
1773 int extra_base;
1774 int extra_size;
1775 int std_end_ofs;
1776 int extra_ofs;
1777 int extra_end_ofs;
1778} target_sigframe_layout;
1779
1780static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
1781{
1782 /* Make sure there will always be space for the end marker. */
1783 const int std_size = sizeof(struct target_rt_sigframe)
1784 - sizeof(struct target_aarch64_ctx);
1785 int this_loc = l->total_size;
1786
1787 if (l->extra_base) {
1788 /* Once we have begun an extra space, all allocations go there. */
1789 l->extra_size += this_size;
1790 } else if (this_size + this_loc > std_size) {
1791 /* This allocation does not fit in the standard space. */
1792 /* Allocate the extra record. */
1793 l->extra_ofs = this_loc;
1794 l->total_size += sizeof(struct target_extra_context);
1795
1796 /* Allocate the standard end record. */
1797 l->std_end_ofs = l->total_size;
1798 l->total_size += sizeof(struct target_aarch64_ctx);
1799
1800 /* Allocate the requested record. */
1801 l->extra_base = this_loc = l->total_size;
1802 l->extra_size = this_size;
1803 }
1804 l->total_size += this_size;
1805
1806 return this_loc;
1807}
1808
Andreas Schwab1744aea2013-09-03 20:12:16 +01001809static void target_setup_frame(int usig, struct target_sigaction *ka,
1810 target_siginfo_t *info, target_sigset_t *set,
1811 CPUARMState *env)
1812{
Richard Henderson8c5931d2018-03-09 17:09:44 +00001813 target_sigframe_layout layout = {
1814 /* Begin with the size pointing to the reserved space. */
1815 .total_size = offsetof(struct target_rt_sigframe,
1816 uc.tuc_mcontext.__reserved),
1817 };
1818 int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001819 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001820 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001821 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001822
Richard Henderson8c5931d2018-03-09 17:09:44 +00001823 /* FPSIMD record is always in the standard space. */
1824 fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
1825 &layout);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001826
Richard Henderson8c5931d2018-03-09 17:09:44 +00001827 /* SVE state needs saving only if it exists. */
1828 if (arm_feature(env, ARM_FEATURE_SVE)) {
1829 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
1830 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
1831 sve_ofs = alloc_sigframe_space(sve_size, &layout);
1832 }
1833
1834 if (layout.extra_ofs) {
1835 /* Reserve space for the extra end marker. The standard end marker
1836 * will have been allocated when we allocated the extra record.
1837 */
1838 layout.extra_end_ofs
1839 = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
1840 } else {
1841 /* Reserve space for the standard end marker.
1842 * Do not use alloc_sigframe_space because we cheat
1843 * std_size therein to reserve space for this.
1844 */
1845 layout.std_end_ofs = layout.total_size;
1846 layout.total_size += sizeof(struct target_aarch64_ctx);
1847 }
1848
1849 /* Reserve space for the return code. On a real system this would
1850 * be within the VDSO. So, despite the name this is not a "real"
1851 * record within the frame.
1852 */
1853 fr_ofs = layout.total_size;
1854 layout.total_size += sizeof(struct target_rt_frame_record);
1855
1856 frame_addr = get_sigframe(ka, env, layout.total_size);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001857 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001858 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1859 goto give_sigsegv;
1860 }
1861
Richard Henderson3b505bb2018-03-09 17:09:43 +00001862 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001863 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson8c5931d2018-03-09 17:09:44 +00001864 target_setup_end_record((void *)frame + layout.std_end_ofs);
1865 if (layout.extra_ofs) {
1866 target_setup_extra_record((void *)frame + layout.extra_ofs,
1867 frame_addr + layout.extra_base,
1868 layout.extra_size);
1869 target_setup_end_record((void *)frame + layout.extra_end_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001870 }
Richard Henderson8c5931d2018-03-09 17:09:44 +00001871 if (sve_ofs) {
1872 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001873 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001874
1875 /* Set up the stack frame for unwinding. */
1876 fr = (void *)frame + fr_ofs;
1877 __put_user(env->xregs[29], &fr->fp);
1878 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001879
Michael Matz8a3ae912014-03-02 19:36:39 +00001880 if (ka->sa_flags & TARGET_SA_RESTORER) {
1881 return_addr = ka->sa_restorer;
1882 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001883 /*
1884 * mov x8,#__NR_rt_sigreturn; svc #0
1885 * Since these are instructions they need to be put as little-endian
1886 * regardless of target default or current CPU endianness.
1887 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001888 __put_user_e(0xd2801168, &fr->tramp[0], le);
1889 __put_user_e(0xd4000001, &fr->tramp[1], le);
1890 return_addr = frame_addr + fr_ofs
1891 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001892 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001893 env->xregs[0] = usig;
1894 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001895 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001896 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001897 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001898 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001899 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001900 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1901 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1902 }
1903
1904 unlock_user_struct(frame, frame_addr, 1);
1905 return;
1906
1907 give_sigsegv:
1908 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001909 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001910}
1911
1912static void setup_rt_frame(int sig, struct target_sigaction *ka,
1913 target_siginfo_t *info, target_sigset_t *set,
1914 CPUARMState *env)
1915{
1916 target_setup_frame(sig, ka, info, set, env);
1917}
1918
1919static void setup_frame(int sig, struct target_sigaction *ka,
1920 target_sigset_t *set, CPUARMState *env)
1921{
1922 target_setup_frame(sig, ka, 0, set, env);
1923}
1924
1925long do_rt_sigreturn(CPUARMState *env)
1926{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001927 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001928 abi_ulong frame_addr = env->xregs[31];
1929
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001930 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001931 if (frame_addr & 15) {
1932 goto badframe;
1933 }
1934
1935 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1936 goto badframe;
1937 }
1938
1939 if (target_restore_sigframe(env, frame)) {
1940 goto badframe;
1941 }
1942
1943 if (do_sigaltstack(frame_addr +
1944 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1945 0, get_sp_from_cpustate(env)) == -EFAULT) {
1946 goto badframe;
1947 }
1948
1949 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001950 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001951
1952 badframe:
1953 unlock_user_struct(frame, frame_addr, 0);
1954 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001955 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001956}
1957
1958long do_sigreturn(CPUARMState *env)
1959{
1960 return do_rt_sigreturn(env);
1961}
1962
bellard43fff232003-07-09 19:31:39 +00001963#elif defined(TARGET_ARM)
1964
1965struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001966 abi_ulong trap_no;
1967 abi_ulong error_code;
1968 abi_ulong oldmask;
1969 abi_ulong arm_r0;
1970 abi_ulong arm_r1;
1971 abi_ulong arm_r2;
1972 abi_ulong arm_r3;
1973 abi_ulong arm_r4;
1974 abi_ulong arm_r5;
1975 abi_ulong arm_r6;
1976 abi_ulong arm_r7;
1977 abi_ulong arm_r8;
1978 abi_ulong arm_r9;
1979 abi_ulong arm_r10;
1980 abi_ulong arm_fp;
1981 abi_ulong arm_ip;
1982 abi_ulong arm_sp;
1983 abi_ulong arm_lr;
1984 abi_ulong arm_pc;
1985 abi_ulong arm_cpsr;
1986 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001987};
1988
pbrooka745ec62008-05-06 15:36:17 +00001989struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001990 abi_ulong tuc_flags;
1991 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001992 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001993 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001994 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001995};
1996
pbrooka745ec62008-05-06 15:36:17 +00001997struct target_ucontext_v2 {
1998 abi_ulong tuc_flags;
1999 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05002000 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00002001 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05002002 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00002003 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00002004 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
2005};
2006
Peter Maydell0d871bd2010-11-24 15:20:05 +00002007struct target_user_vfp {
2008 uint64_t fpregs[32];
2009 abi_ulong fpscr;
2010};
2011
2012struct target_user_vfp_exc {
2013 abi_ulong fpexc;
2014 abi_ulong fpinst;
2015 abi_ulong fpinst2;
2016};
2017
2018struct target_vfp_sigframe {
2019 abi_ulong magic;
2020 abi_ulong size;
2021 struct target_user_vfp ufp;
2022 struct target_user_vfp_exc ufp_exc;
2023} __attribute__((__aligned__(8)));
2024
Peter Maydell08e11252010-11-24 15:20:07 +00002025struct target_iwmmxt_sigframe {
2026 abi_ulong magic;
2027 abi_ulong size;
2028 uint64_t regs[16];
2029 /* Note that not all the coprocessor control registers are stored here */
2030 uint32_t wcssf;
2031 uint32_t wcasf;
2032 uint32_t wcgr0;
2033 uint32_t wcgr1;
2034 uint32_t wcgr2;
2035 uint32_t wcgr3;
2036} __attribute__((__aligned__(8)));
2037
Peter Maydell0d871bd2010-11-24 15:20:05 +00002038#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00002039#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00002040
pbrooka8c33202008-05-07 23:22:46 +00002041struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002042{
2043 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00002044 abi_ulong extramask[TARGET_NSIG_WORDS-1];
2045 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002046};
2047
pbrooka8c33202008-05-07 23:22:46 +00002048struct sigframe_v2
2049{
2050 struct target_ucontext_v2 uc;
2051 abi_ulong retcode;
2052};
2053
pbrooka745ec62008-05-06 15:36:17 +00002054struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00002055{
bellardf8b0aa22007-11-11 23:03:42 +00002056 abi_ulong pinfo;
2057 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00002058 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00002059 struct target_ucontext_v1 uc;
2060 abi_ulong retcode;
2061};
2062
2063struct rt_sigframe_v2
2064{
2065 struct target_siginfo info;
2066 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00002067 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00002068};
2069
2070#define TARGET_CONFIG_CPU_32 1
2071
2072/*
2073 * For ARM syscalls, we encode the syscall number into the instruction.
2074 */
2075#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
2076#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
2077
2078/*
2079 * For Thumb syscalls, we pass the syscall number via r7. We therefore
2080 * need two 16-bit instructions.
2081 */
2082#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
2083#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
2084
blueswir1992f48a2007-10-14 16:27:31 +00002085static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00002086 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
2087 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
2088};
2089
2090
Andreas Färber05390242012-02-25 03:37:53 +01002091static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00002092{
2093 return 1;
2094}
2095
pbrooka8c33202008-05-07 23:22:46 +00002096static void
bellard43fff232003-07-09 19:31:39 +00002097setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002098 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00002099{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002100 __put_user(env->regs[0], &sc->arm_r0);
2101 __put_user(env->regs[1], &sc->arm_r1);
2102 __put_user(env->regs[2], &sc->arm_r2);
2103 __put_user(env->regs[3], &sc->arm_r3);
2104 __put_user(env->regs[4], &sc->arm_r4);
2105 __put_user(env->regs[5], &sc->arm_r5);
2106 __put_user(env->regs[6], &sc->arm_r6);
2107 __put_user(env->regs[7], &sc->arm_r7);
2108 __put_user(env->regs[8], &sc->arm_r8);
2109 __put_user(env->regs[9], &sc->arm_r9);
2110 __put_user(env->regs[10], &sc->arm_r10);
2111 __put_user(env->regs[11], &sc->arm_fp);
2112 __put_user(env->regs[12], &sc->arm_ip);
2113 __put_user(env->regs[13], &sc->arm_sp);
2114 __put_user(env->regs[14], &sc->arm_lr);
2115 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002116#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002117 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00002118#endif
2119
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002120 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
2121 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
2122 __put_user(/* current->thread.address */ 0, &sc->fault_address);
2123 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00002124}
2125
bellard579a97f2007-11-11 14:26:47 +00002126static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002127get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00002128{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002129 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00002130
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002131 /*
2132 * This is the X/Open sanctioned signal stack switching.
2133 */
2134 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
2135 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2136 }
2137 /*
2138 * ATPCS B01 mandates 8-byte alignment
2139 */
2140 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00002141}
2142
Riku Voipio0188fad2014-04-23 13:34:15 +03002143static void
Andreas Färber05390242012-02-25 03:37:53 +01002144setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002145 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00002146{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002147 abi_ulong handler = ka->_sa_handler;
2148 abi_ulong retcode;
2149 int thumb = handler & 1;
2150 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01002151
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002152 cpsr &= ~CPSR_IT;
2153 if (thumb) {
2154 cpsr |= CPSR_T;
2155 } else {
2156 cpsr &= ~CPSR_T;
2157 }
bellard43fff232003-07-09 19:31:39 +00002158
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002159 if (ka->sa_flags & TARGET_SA_RESTORER) {
2160 retcode = ka->sa_restorer;
2161 } else {
2162 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00002163
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002164 if (ka->sa_flags & TARGET_SA_SIGINFO) {
2165 idx += 2;
2166 }
bellard43fff232003-07-09 19:31:39 +00002167
Riku Voipio0188fad2014-04-23 13:34:15 +03002168 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02002169
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002170 retcode = rc_addr + thumb;
2171 }
bellard43fff232003-07-09 19:31:39 +00002172
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00002173 env->regs[0] = usig;
2174 env->regs[13] = frame_addr;
2175 env->regs[14] = retcode;
2176 env->regs[15] = handler & (thumb ? ~1 : ~3);
2177 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002178}
2179
Andreas Färber05390242012-02-25 03:37:53 +01002180static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002181{
2182 int i;
2183 struct target_vfp_sigframe *vfpframe;
2184 vfpframe = (struct target_vfp_sigframe *)regspace;
2185 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2186 __put_user(sizeof(*vfpframe), &vfpframe->size);
2187 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002188 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002189 }
2190 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2191 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2192 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2193 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2194 return (abi_ulong*)(vfpframe+1);
2195}
2196
Andreas Färber05390242012-02-25 03:37:53 +01002197static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2198 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002199{
2200 int i;
2201 struct target_iwmmxt_sigframe *iwmmxtframe;
2202 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2203 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2204 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2205 for (i = 0; i < 16; i++) {
2206 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2207 }
2208 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2209 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2210 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2211 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2212 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2213 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2214 return (abi_ulong*)(iwmmxtframe+1);
2215}
2216
pbrooka8c33202008-05-07 23:22:46 +00002217static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002218 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002219{
pbrooka8c33202008-05-07 23:22:46 +00002220 struct target_sigaltstack stack;
2221 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002222 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002223
2224 /* Clear all the bits of the ucontext we don't use. */
2225 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2226
2227 memset(&stack, 0, sizeof(stack));
2228 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2229 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2230 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2231 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2232
2233 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002234 /* Save coprocessor signal frame. */
2235 regspace = uc->tuc_regspace;
2236 if (arm_feature(env, ARM_FEATURE_VFP)) {
2237 regspace = setup_sigframe_v2_vfp(regspace, env);
2238 }
Peter Maydell08e11252010-11-24 15:20:07 +00002239 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2240 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2241 }
2242
Peter Maydell0d871bd2010-11-24 15:20:05 +00002243 /* Write terminating magic word */
2244 __put_user(0, regspace);
2245
pbrooka8c33202008-05-07 23:22:46 +00002246 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2247 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2248 }
2249}
2250
2251/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002252static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002253 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002254{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002255 struct sigframe_v1 *frame;
2256 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2257 int i;
bellard43fff232003-07-09 19:31:39 +00002258
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002259 trace_user_setup_frame(regs, frame_addr);
2260 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002261 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002262 }
bellard579a97f2007-11-11 14:26:47 +00002263
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002264 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002265
Riku Voipio0188fad2014-04-23 13:34:15 +03002266 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2267 __put_user(set->sig[i], &frame->extramask[i - 1]);
2268 }
bellard43fff232003-07-09 19:31:39 +00002269
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002270 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2271 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002272
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002273 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002274 return;
2275sigsegv:
2276 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002277}
2278
pbrook624f7972008-05-31 16:11:38 +00002279static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002280 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002281{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002282 struct sigframe_v2 *frame;
2283 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002284
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 trace_user_setup_frame(regs, frame_addr);
2286 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002287 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002288 }
pbrooka8c33202008-05-07 23:22:46 +00002289
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002290 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002292 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2293 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002294
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002295 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002296 return;
2297sigsegv:
2298 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002299}
2300
pbrook624f7972008-05-31 16:11:38 +00002301static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002302 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002303{
2304 if (get_osversion() >= 0x020612) {
2305 setup_frame_v2(usig, ka, set, regs);
2306 } else {
2307 setup_frame_v1(usig, ka, set, regs);
2308 }
bellard43fff232003-07-09 19:31:39 +00002309}
2310
bellard579a97f2007-11-11 14:26:47 +00002311/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002312static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002313 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002314 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002315{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002316 struct rt_sigframe_v1 *frame;
2317 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2318 struct target_sigaltstack stack;
2319 int i;
2320 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002322 trace_user_setup_rt_frame(env, frame_addr);
2323 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002324 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002325 }
bellardedf779f2004-02-22 13:40:13 +00002326
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002327 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2328 __put_user(info_addr, &frame->pinfo);
2329 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2330 __put_user(uc_addr, &frame->puc);
2331 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002332
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002333 /* Clear all the bits of the ucontext we don't use. */
2334 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002335
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002336 memset(&stack, 0, sizeof(stack));
2337 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2338 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2339 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2340 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002341
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002342 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2343 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2344 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2345 }
bellard43fff232003-07-09 19:31:39 +00002346
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2348 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002349
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002350 env->regs[1] = info_addr;
2351 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002352
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002353 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002354 return;
2355sigsegv:
2356 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002357}
2358
pbrook624f7972008-05-31 16:11:38 +00002359static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002360 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002361 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002362{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002363 struct rt_sigframe_v2 *frame;
2364 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2365 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002366
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002367 trace_user_setup_rt_frame(env, frame_addr);
2368 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002369 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002370 }
pbrooka745ec62008-05-06 15:36:17 +00002371
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002372 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2373 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2374 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002375
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002376 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002377
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002378 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2379 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002380
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002381 env->regs[1] = info_addr;
2382 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002383
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002384 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002385 return;
2386sigsegv:
2387 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002388}
2389
pbrook624f7972008-05-31 16:11:38 +00002390static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002391 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002392 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002393{
2394 if (get_osversion() >= 0x020612) {
2395 setup_rt_frame_v2(usig, ka, info, set, env);
2396 } else {
2397 setup_rt_frame_v1(usig, ka, info, set, env);
2398 }
2399}
2400
bellard43fff232003-07-09 19:31:39 +00002401static int
Andreas Färber05390242012-02-25 03:37:53 +01002402restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002403{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002404 int err = 0;
2405 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002406
Riku Voipio1d8b5122014-04-23 10:26:05 +03002407 __get_user(env->regs[0], &sc->arm_r0);
2408 __get_user(env->regs[1], &sc->arm_r1);
2409 __get_user(env->regs[2], &sc->arm_r2);
2410 __get_user(env->regs[3], &sc->arm_r3);
2411 __get_user(env->regs[4], &sc->arm_r4);
2412 __get_user(env->regs[5], &sc->arm_r5);
2413 __get_user(env->regs[6], &sc->arm_r6);
2414 __get_user(env->regs[7], &sc->arm_r7);
2415 __get_user(env->regs[8], &sc->arm_r8);
2416 __get_user(env->regs[9], &sc->arm_r9);
2417 __get_user(env->regs[10], &sc->arm_r10);
2418 __get_user(env->regs[11], &sc->arm_fp);
2419 __get_user(env->regs[12], &sc->arm_ip);
2420 __get_user(env->regs[13], &sc->arm_sp);
2421 __get_user(env->regs[14], &sc->arm_lr);
2422 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002423#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002424 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002425 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002426#endif
2427
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002428 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002429
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002430 return err;
bellard43fff232003-07-09 19:31:39 +00002431}
2432
Andreas Färber05390242012-02-25 03:37:53 +01002433static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002434{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002435 abi_ulong frame_addr;
2436 struct sigframe_v1 *frame = NULL;
2437 target_sigset_t set;
2438 sigset_t host_set;
2439 int i;
bellard43fff232003-07-09 19:31:39 +00002440
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002441 /*
2442 * Since we stacked the signal on a 64-bit boundary,
2443 * then 'sp' should be word aligned here. If it's
2444 * not, then the user is trying to mess with us.
2445 */
2446 frame_addr = env->regs[13];
2447 trace_user_do_sigreturn(env, frame_addr);
2448 if (frame_addr & 7) {
2449 goto badframe;
2450 }
Peter Maydell978fae92013-07-29 12:00:32 +01002451
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002452 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2453 goto badframe;
2454 }
bellard43fff232003-07-09 19:31:39 +00002455
Riku Voipiof5f601a2014-04-23 13:00:17 +03002456 __get_user(set.sig[0], &frame->sc.oldmask);
2457 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2458 __get_user(set.sig[i], &frame->extramask[i - 1]);
2459 }
bellard43fff232003-07-09 19:31:39 +00002460
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002461 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002462 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002463
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002464 if (restore_sigcontext(env, &frame->sc)) {
2465 goto badframe;
2466 }
bellard43fff232003-07-09 19:31:39 +00002467
2468#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002469 /* Send SIGTRAP if we're single-stepping */
2470 if (ptrace_cancel_bpt(current))
2471 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002472#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002473 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002474 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002475
2476badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002477 force_sig(TARGET_SIGSEGV);
2478 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002479}
2480
Andreas Färber05390242012-02-25 03:37:53 +01002481static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002482{
2483 int i;
2484 abi_ulong magic, sz;
2485 uint32_t fpscr, fpexc;
2486 struct target_vfp_sigframe *vfpframe;
2487 vfpframe = (struct target_vfp_sigframe *)regspace;
2488
2489 __get_user(magic, &vfpframe->magic);
2490 __get_user(sz, &vfpframe->size);
2491 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2492 return 0;
2493 }
2494 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002495 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002496 }
2497 __get_user(fpscr, &vfpframe->ufp.fpscr);
2498 vfp_set_fpscr(env, fpscr);
2499 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2500 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2501 * and the exception flag is cleared
2502 */
2503 fpexc |= (1 << 30);
2504 fpexc &= ~((1 << 31) | (1 << 28));
2505 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2506 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2507 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2508 return (abi_ulong*)(vfpframe + 1);
2509}
2510
Andreas Färber05390242012-02-25 03:37:53 +01002511static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2512 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002513{
2514 int i;
2515 abi_ulong magic, sz;
2516 struct target_iwmmxt_sigframe *iwmmxtframe;
2517 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2518
2519 __get_user(magic, &iwmmxtframe->magic);
2520 __get_user(sz, &iwmmxtframe->size);
2521 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2522 return 0;
2523 }
2524 for (i = 0; i < 16; i++) {
2525 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2526 }
2527 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2528 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2529 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2530 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2531 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2532 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2533 return (abi_ulong*)(iwmmxtframe + 1);
2534}
2535
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002536static int do_sigframe_return_v2(CPUARMState *env,
2537 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002538 struct target_ucontext_v2 *uc)
2539{
2540 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002541 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002542
2543 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002544 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002545
2546 if (restore_sigcontext(env, &uc->tuc_mcontext))
2547 return 1;
2548
Peter Maydell5f9099d2010-11-24 15:20:06 +00002549 /* Restore coprocessor signal frame */
2550 regspace = uc->tuc_regspace;
2551 if (arm_feature(env, ARM_FEATURE_VFP)) {
2552 regspace = restore_sigframe_v2_vfp(env, regspace);
2553 if (!regspace) {
2554 return 1;
2555 }
2556 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002557 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2558 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2559 if (!regspace) {
2560 return 1;
2561 }
2562 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002563
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002564 if (do_sigaltstack(context_addr
2565 + offsetof(struct target_ucontext_v2, tuc_stack),
2566 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002567 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002568 }
pbrooka8c33202008-05-07 23:22:46 +00002569
2570#if 0
2571 /* Send SIGTRAP if we're single-stepping */
2572 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002573 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002574#endif
2575
2576 return 0;
2577}
2578
Andreas Färber05390242012-02-25 03:37:53 +01002579static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002580{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002581 abi_ulong frame_addr;
2582 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002583
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002584 /*
2585 * Since we stacked the signal on a 64-bit boundary,
2586 * then 'sp' should be word aligned here. If it's
2587 * not, then the user is trying to mess with us.
2588 */
2589 frame_addr = env->regs[13];
2590 trace_user_do_sigreturn(env, frame_addr);
2591 if (frame_addr & 7) {
2592 goto badframe;
2593 }
Peter Maydell978fae92013-07-29 12:00:32 +01002594
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002595 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2596 goto badframe;
2597 }
pbrooka8c33202008-05-07 23:22:46 +00002598
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002599 if (do_sigframe_return_v2(env,
2600 frame_addr
2601 + offsetof(struct sigframe_v2, uc),
2602 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002603 goto badframe;
2604 }
pbrooka8c33202008-05-07 23:22:46 +00002605
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002606 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002607 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002608
2609badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002610 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002611 force_sig(TARGET_SIGSEGV);
2612 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002613}
2614
Andreas Färber05390242012-02-25 03:37:53 +01002615long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002616{
2617 if (get_osversion() >= 0x020612) {
2618 return do_sigreturn_v2(env);
2619 } else {
2620 return do_sigreturn_v1(env);
2621 }
2622}
2623
Andreas Färber05390242012-02-25 03:37:53 +01002624static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002625{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002626 abi_ulong frame_addr;
2627 struct rt_sigframe_v1 *frame = NULL;
2628 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002629
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002630 /*
2631 * Since we stacked the signal on a 64-bit boundary,
2632 * then 'sp' should be word aligned here. If it's
2633 * not, then the user is trying to mess with us.
2634 */
2635 frame_addr = env->regs[13];
2636 trace_user_do_rt_sigreturn(env, frame_addr);
2637 if (frame_addr & 7) {
2638 goto badframe;
2639 }
Peter Maydell978fae92013-07-29 12:00:32 +01002640
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002641 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2642 goto badframe;
2643 }
bellard43fff232003-07-09 19:31:39 +00002644
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002645 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002646 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002647
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002648 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2649 goto badframe;
2650 }
bellard43fff232003-07-09 19:31:39 +00002651
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002652 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2653 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002654
bellard43fff232003-07-09 19:31:39 +00002655#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002656 /* Send SIGTRAP if we're single-stepping */
2657 if (ptrace_cancel_bpt(current))
2658 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002659#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002660 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002661 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002662
2663badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002664 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002665 force_sig(TARGET_SIGSEGV);
2666 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002667}
2668
Andreas Färber05390242012-02-25 03:37:53 +01002669static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002670{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002671 abi_ulong frame_addr;
2672 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002673
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002674 /*
2675 * Since we stacked the signal on a 64-bit boundary,
2676 * then 'sp' should be word aligned here. If it's
2677 * not, then the user is trying to mess with us.
2678 */
2679 frame_addr = env->regs[13];
2680 trace_user_do_rt_sigreturn(env, frame_addr);
2681 if (frame_addr & 7) {
2682 goto badframe;
2683 }
Peter Maydell978fae92013-07-29 12:00:32 +01002684
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002685 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2686 goto badframe;
2687 }
pbrooka745ec62008-05-06 15:36:17 +00002688
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002689 if (do_sigframe_return_v2(env,
2690 frame_addr
2691 + offsetof(struct rt_sigframe_v2, uc),
2692 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002693 goto badframe;
2694 }
pbrooka745ec62008-05-06 15:36:17 +00002695
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002696 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002697 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002698
2699badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002700 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002701 force_sig(TARGET_SIGSEGV);
2702 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002703}
2704
Andreas Färber05390242012-02-25 03:37:53 +01002705long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002706{
2707 if (get_osversion() >= 0x020612) {
2708 return do_rt_sigreturn_v2(env);
2709 } else {
2710 return do_rt_sigreturn_v1(env);
2711 }
2712}
2713
bellard6d5e2162004-09-30 22:04:13 +00002714#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002715
bellard6d5e2162004-09-30 22:04:13 +00002716#define __SUNOS_MAXWIN 31
2717
2718/* This is what SunOS does, so shall I. */
2719struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002720 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002721
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002722 abi_ulong sigc_mask; /* sigmask to restore */
2723 abi_ulong sigc_sp; /* stack pointer */
2724 abi_ulong sigc_pc; /* program counter */
2725 abi_ulong sigc_npc; /* next program counter */
2726 abi_ulong sigc_psr; /* for condition codes etc */
2727 abi_ulong sigc_g1; /* User uses these two registers */
2728 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002729
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002730 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002731 * at the time of the signal.
2732 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002733 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002734
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002735 /* stack ptrs for each regwin buf */
2736 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002737
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002738 /* Windows to restore after signal */
2739 struct {
2740 abi_ulong locals[8];
2741 abi_ulong ins[8];
2742 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002743};
2744/* A Sparc stack frame */
2745struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002746 abi_ulong locals[8];
2747 abi_ulong ins[8];
2748 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002749 * since we never need to access them ourselves.
2750 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002751 char *structptr;
2752 abi_ulong xargs[6];
2753 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002754};
2755
2756typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002757 struct {
2758 abi_ulong psr;
2759 abi_ulong pc;
2760 abi_ulong npc;
2761 abi_ulong y;
2762 abi_ulong u_regs[16]; /* globals and ins */
2763 } si_regs;
2764 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002765} __siginfo_t;
2766
2767typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002768 abi_ulong si_float_regs[32];
2769 unsigned long si_fsr;
2770 unsigned long si_fpqdepth;
2771 struct {
2772 unsigned long *insn_addr;
2773 unsigned long insn;
2774 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002775} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002776
2777
2778struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002779 struct sparc_stackf ss;
2780 __siginfo_t info;
2781 abi_ulong fpu_save;
2782 abi_ulong insns[2] __attribute__ ((aligned (8)));
2783 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2784 abi_ulong extra_size; /* Should be 0 */
2785 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002786};
2787struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002788 struct sparc_stackf ss;
2789 siginfo_t info;
2790 abi_ulong regs[20];
2791 sigset_t mask;
2792 abi_ulong fpu_save;
2793 unsigned int insns[2];
2794 stack_t stack;
2795 unsigned int extra_size; /* Should be 0 */
2796 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002797};
2798
bellarde80cfcf2004-12-19 23:18:01 +00002799#define UREG_O0 16
2800#define UREG_O6 22
2801#define UREG_I0 0
2802#define UREG_I1 1
2803#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002804#define UREG_I3 3
2805#define UREG_I4 4
2806#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002807#define UREG_I6 6
2808#define UREG_I7 7
2809#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002810#define UREG_FP UREG_I6
2811#define UREG_SP UREG_O6
2812
pbrook624f7972008-05-31 16:11:38 +00002813static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002814 CPUSPARCState *env,
2815 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002816{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002817 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002818
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002819 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002820
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002821 /* This is the X/Open sanctioned signal stack switching. */
2822 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2823 if (!on_sig_stack(sp)
2824 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2825 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2826 }
2827 }
2828 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002829}
2830
2831static int
Andreas Färber05390242012-02-25 03:37:53 +01002832setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002833{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002834 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002835
Riku Voipio1d8b5122014-04-23 10:26:05 +03002836 __put_user(env->psr, &si->si_regs.psr);
2837 __put_user(env->pc, &si->si_regs.pc);
2838 __put_user(env->npc, &si->si_regs.npc);
2839 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002840 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002841 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002842 }
2843 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002844 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002845 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002846 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002847 return err;
bellard6d5e2162004-09-30 22:04:13 +00002848}
bellarde80cfcf2004-12-19 23:18:01 +00002849
bellard80a9d032005-01-03 23:31:27 +00002850#if 0
bellard6d5e2162004-09-30 22:04:13 +00002851static int
2852setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002853 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002854{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002855 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002856
Riku Voipio1d8b5122014-04-23 10:26:05 +03002857 __put_user(mask, &sc->sigc_mask);
2858 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2859 __put_user(env->pc, &sc->sigc_pc);
2860 __put_user(env->npc, &sc->sigc_npc);
2861 __put_user(env->psr, &sc->sigc_psr);
2862 __put_user(env->gregs[1], &sc->sigc_g1);
2863 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002864
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002865 return err;
bellard6d5e2162004-09-30 22:04:13 +00002866}
bellard80a9d032005-01-03 23:31:27 +00002867#endif
bellard6d5e2162004-09-30 22:04:13 +00002868#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2869
pbrook624f7972008-05-31 16:11:38 +00002870static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002871 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002872{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002873 abi_ulong sf_addr;
2874 struct target_signal_frame *sf;
2875 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002876
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002877 /* 1. Make sure everything is clean */
2878 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002879
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002880 sigframe_size = NF_ALIGNEDSZ;
2881 sf_addr = get_sigframe(ka, env, sigframe_size);
2882 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002883
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002884 sf = lock_user(VERIFY_WRITE, sf_addr,
2885 sizeof(struct target_signal_frame), 0);
2886 if (!sf) {
2887 goto sigsegv;
2888 }
bellard6d5e2162004-09-30 22:04:13 +00002889#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002890 if (invalid_frame_pointer(sf, sigframe_size))
2891 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002892#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002893 /* 2. Save the current process state */
2894 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002895 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002896
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002897 //save_fpu_state(regs, &sf->fpu_state);
2898 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002899
Riku Voipio1d8b5122014-04-23 10:26:05 +03002900 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002901 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002902 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002903 }
bellard6d5e2162004-09-30 22:04:13 +00002904
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002905 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002906 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002907 }
2908 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002909 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002910 }
2911 if (err)
2912 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002913
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002914 /* 3. signal handler back-trampoline and parameters */
2915 env->regwptr[UREG_FP] = sf_addr;
2916 env->regwptr[UREG_I0] = sig;
2917 env->regwptr[UREG_I1] = sf_addr +
2918 offsetof(struct target_signal_frame, info);
2919 env->regwptr[UREG_I2] = sf_addr +
2920 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002921
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002922 /* 4. signal handler */
2923 env->pc = ka->_sa_handler;
2924 env->npc = (env->pc + 4);
2925 /* 5. return to kernel instructions */
2926 if (ka->sa_restorer) {
2927 env->regwptr[UREG_I7] = ka->sa_restorer;
2928 } else {
2929 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002930
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002931 env->regwptr[UREG_I7] = sf_addr +
2932 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002933
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002934 /* mov __NR_sigreturn, %g1 */
2935 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002936 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002937
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002938 /* t 0x10 */
2939 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002940 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002941 if (err)
2942 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002943
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002944 /* Flush instruction space. */
2945 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2946 // tb_flush(env);
2947 }
2948 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2949 return;
bellard459a4012007-11-11 19:45:10 +00002950#if 0
2951sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002952 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002953#endif
bellard6d5e2162004-09-30 22:04:13 +00002954sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002955 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002956 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002957}
bellard6d5e2162004-09-30 22:04:13 +00002958
pbrook624f7972008-05-31 16:11:38 +00002959static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002960 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002961 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002962{
2963 fprintf(stderr, "setup_rt_frame: not implemented\n");
2964}
2965
Andreas Färber05390242012-02-25 03:37:53 +01002966long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002967{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002968 abi_ulong sf_addr;
2969 struct target_signal_frame *sf;
2970 uint32_t up_psr, pc, npc;
2971 target_sigset_t set;
2972 sigset_t host_set;
2973 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002974
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002975 sf_addr = env->regwptr[UREG_FP];
2976 trace_user_do_sigreturn(env, sf_addr);
2977 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2978 goto segv_and_exit;
2979 }
bellard6d5e2162004-09-30 22:04:13 +00002980
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002981 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002982
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002983 if (sf_addr & 3)
2984 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002985
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002986 __get_user(pc, &sf->info.si_regs.pc);
2987 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002988
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002989 if ((pc | npc) & 3) {
2990 goto segv_and_exit;
2991 }
bellard6d5e2162004-09-30 22:04:13 +00002992
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002993 /* 2. Restore the state */
2994 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002995
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002996 /* User can only change condition codes and FPU enabling in %psr. */
2997 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2998 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002999
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003000 env->pc = pc;
3001 env->npc = npc;
3002 __get_user(env->y, &sf->info.si_regs.y);
3003 for (i=0; i < 8; i++) {
3004 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
3005 }
3006 for (i=0; i < 8; i++) {
3007 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
3008 }
bellard6d5e2162004-09-30 22:04:13 +00003009
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003010 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01003011 * __get_user(fpu_save, &sf->fpu_save);
3012 * if (fpu_save)
3013 * err |= restore_fpu_state(env, fpu_save);
3014 */
bellard6d5e2162004-09-30 22:04:13 +00003015
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003016 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00003017 * the races which exist anyways.
3018 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003019 __get_user(set.sig[0], &sf->info.si_mask);
3020 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3021 __get_user(set.sig[i], &sf->extramask[i - 1]);
3022 }
bellarde80cfcf2004-12-19 23:18:01 +00003023
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003024 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003025 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00003026
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003027 if (err) {
3028 goto segv_and_exit;
3029 }
3030 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01003031 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003032
3033segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003034 unlock_user_struct(sf, sf_addr, 0);
3035 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003036 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00003037}
3038
Andreas Färber05390242012-02-25 03:37:53 +01003039long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00003040{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003041 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00003042 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00003043 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00003044}
3045
bellard459a4012007-11-11 19:45:10 +00003046#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00003047#define SPARC_MC_TSTATE 0
3048#define SPARC_MC_PC 1
3049#define SPARC_MC_NPC 2
3050#define SPARC_MC_Y 3
3051#define SPARC_MC_G1 4
3052#define SPARC_MC_G2 5
3053#define SPARC_MC_G3 6
3054#define SPARC_MC_G4 7
3055#define SPARC_MC_G5 8
3056#define SPARC_MC_G6 9
3057#define SPARC_MC_G7 10
3058#define SPARC_MC_O0 11
3059#define SPARC_MC_O1 12
3060#define SPARC_MC_O2 13
3061#define SPARC_MC_O3 14
3062#define SPARC_MC_O4 15
3063#define SPARC_MC_O5 16
3064#define SPARC_MC_O6 17
3065#define SPARC_MC_O7 18
3066#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00003067
Anthony Liguoric227f092009-10-01 16:12:16 -05003068typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003069typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00003070
3071struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00003072 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003073 uint32_t mcfq_insn;
3074};
3075
3076struct target_mc_fpu {
3077 union {
3078 uint32_t sregs[32];
3079 uint64_t dregs[32];
3080 //uint128_t qregs[16];
3081 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00003082 abi_ulong mcfpu_fsr;
3083 abi_ulong mcfpu_fprs;
3084 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00003085 struct target_mc_fq *mcfpu_fq;
3086 unsigned char mcfpu_qcnt;
3087 unsigned char mcfpu_qentsz;
3088 unsigned char mcfpu_enab;
3089};
Anthony Liguoric227f092009-10-01 16:12:16 -05003090typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003091
3092typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05003093 target_mc_gregset_t mc_gregs;
3094 target_mc_greg_t mc_fp;
3095 target_mc_greg_t mc_i7;
3096 target_mc_fpu_t mc_fpregs;
3097} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00003098
3099struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003100 struct target_ucontext *tuc_link;
3101 abi_ulong tuc_flags;
3102 target_sigset_t tuc_sigmask;
3103 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003104};
3105
3106/* A V9 register window */
3107struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00003108 abi_ulong locals[8];
3109 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00003110};
3111
3112#define TARGET_STACK_BIAS 2047
3113
3114/* {set, get}context() needed for 64-bit SparcLinux userland. */
3115void sparc64_set_context(CPUSPARCState *env)
3116{
bellard459a4012007-11-11 19:45:10 +00003117 abi_ulong ucp_addr;
3118 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003119 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00003120 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00003121 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003122 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00003123
bellard459a4012007-11-11 19:45:10 +00003124 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003125 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00003126 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003127 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02003128 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003129 __get_user(pc, &((*grp)[SPARC_MC_PC]));
3130 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003131 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00003132 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003133 }
blueswir15bfb56b2007-10-05 17:01:51 +00003134 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05003135 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003136 sigset_t set;
3137
3138 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003139 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00003140 } else {
bellard459a4012007-11-11 19:45:10 +00003141 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003142 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00003143 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003144 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003145 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003146 }
blueswir15bfb56b2007-10-05 17:01:51 +00003147 }
3148 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003149 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00003150 }
3151 env->pc = pc;
3152 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00003153 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
3154 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00003155 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00003156 cpu_put_ccr(env, tstate >> 32);
3157 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00003158 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
3159 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
3160 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
3161 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
3162 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
3163 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
3164 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
3165 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
3166 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
3167 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
3168 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
3169 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
3170 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
3171 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
3172 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003173
Riku Voipio1d8b5122014-04-23 10:26:05 +03003174 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3175 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003176
bellard459a4012007-11-11 19:45:10 +00003177 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003178 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3179 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003180 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003181 }
3182 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3183 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003184 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003185 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003186 /* FIXME this does not match how the kernel handles the FPU in
3187 * its sparc64_set_context implementation. In particular the FPU
3188 * is only restored if fenab is non-zero in:
3189 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3190 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003191 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003192 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003193 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3194 for (i = 0; i < 64; i++, src++) {
3195 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003196 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003197 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003198 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003199 }
3200 }
bellard459a4012007-11-11 19:45:10 +00003201 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003202 __get_user(env->fsr,
3203 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3204 __get_user(env->gsr,
3205 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003206 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003207 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003208do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003209 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003210 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003211}
3212
3213void sparc64_get_context(CPUSPARCState *env)
3214{
bellard459a4012007-11-11 19:45:10 +00003215 abi_ulong ucp_addr;
3216 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003217 target_mc_gregset_t *grp;
3218 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003219 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003220 int err;
3221 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003222 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003223 sigset_t set;
3224
bellard459a4012007-11-11 19:45:10 +00003225 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003226 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003227 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003228 }
bellard459a4012007-11-11 19:45:10 +00003229
Aurelien Jarno60e99242010-03-29 02:12:51 +02003230 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003231 grp = &mcp->mc_gregs;
3232
3233 /* Skip over the trap instruction, first. */
3234 env->pc = env->npc;
3235 env->npc += 4;
3236
Peter Maydell3d3efba2016-05-27 15:51:49 +01003237 /* If we're only reading the signal mask then do_sigprocmask()
3238 * is guaranteed not to fail, which is important because we don't
3239 * have any way to signal a failure or restart this operation since
3240 * this is not a normal syscall.
3241 */
3242 err = do_sigprocmask(0, NULL, &set);
3243 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003244 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003245 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003246 __put_user(target_set.sig[0],
3247 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003248 } else {
3249 abi_ulong *src, *dst;
3250 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003251 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003252 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003253 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003254 }
blueswir15bfb56b2007-10-05 17:01:51 +00003255 if (err)
3256 goto do_sigsegv;
3257 }
3258
bellard459a4012007-11-11 19:45:10 +00003259 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003260 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3261 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3262 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3263 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3264 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3265 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3266 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3267 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3268 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3269 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3270 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3271 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3272 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3273 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3274 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3275 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3276 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3277 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3278 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003279
bellard459a4012007-11-11 19:45:10 +00003280 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3281 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003282 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3283 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003284 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003285 }
3286 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3287 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003288 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003289 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003290 __put_user(fp, &(mcp->mc_fp));
3291 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003292
bellard459a4012007-11-11 19:45:10 +00003293 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003294 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3295 for (i = 0; i < 64; i++, dst++) {
3296 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003297 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003298 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003299 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003300 }
3301 }
bellard459a4012007-11-11 19:45:10 +00003302 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003303 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3304 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3305 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003306
3307 if (err)
3308 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003309 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003310 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003311do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003312 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003313 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003314}
3315#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003316#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003317
Richard Hendersonff970902013-02-10 10:30:42 -08003318# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003319struct target_sigcontext {
3320 uint32_t sc_regmask; /* Unused */
3321 uint32_t sc_status;
3322 uint64_t sc_pc;
3323 uint64_t sc_regs[32];
3324 uint64_t sc_fpregs[32];
3325 uint32_t sc_ownedfp; /* Unused */
3326 uint32_t sc_fpc_csr;
3327 uint32_t sc_fpc_eir; /* Unused */
3328 uint32_t sc_used_math;
3329 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003330 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003331 uint64_t sc_mdhi;
3332 uint64_t sc_mdlo;
3333 target_ulong sc_hi1; /* Was sc_cause */
3334 target_ulong sc_lo1; /* Was sc_badvaddr */
3335 target_ulong sc_hi2; /* Was sc_sigset[4] */
3336 target_ulong sc_lo2;
3337 target_ulong sc_hi3;
3338 target_ulong sc_lo3;
3339};
Richard Hendersonff970902013-02-10 10:30:42 -08003340# else /* N32 || N64 */
3341struct target_sigcontext {
3342 uint64_t sc_regs[32];
3343 uint64_t sc_fpregs[32];
3344 uint64_t sc_mdhi;
3345 uint64_t sc_hi1;
3346 uint64_t sc_hi2;
3347 uint64_t sc_hi3;
3348 uint64_t sc_mdlo;
3349 uint64_t sc_lo1;
3350 uint64_t sc_lo2;
3351 uint64_t sc_lo3;
3352 uint64_t sc_pc;
3353 uint32_t sc_fpc_csr;
3354 uint32_t sc_used_math;
3355 uint32_t sc_dsp;
3356 uint32_t sc_reserved;
3357};
3358# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003359
3360struct sigframe {
3361 uint32_t sf_ass[4]; /* argument save space for o32 */
3362 uint32_t sf_code[2]; /* signal trampoline */
3363 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003364 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003365};
3366
pbrook0b1bcb02009-04-21 01:41:10 +00003367struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003368 target_ulong tuc_flags;
3369 target_ulong tuc_link;
3370 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003371 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003372 struct target_sigcontext tuc_mcontext;
3373 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003374};
3375
3376struct target_rt_sigframe {
3377 uint32_t rs_ass[4]; /* argument save space for o32 */
3378 uint32_t rs_code[2]; /* signal trampoline */
3379 struct target_siginfo rs_info;
3380 struct target_ucontext rs_uc;
3381};
3382
bellard106ec872006-06-27 21:08:10 +00003383/* Install trampoline to jump back from signal handler */
3384static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3385{
Richard Henderson084d0492013-02-10 10:30:44 -08003386 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003387
3388 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003389 * Set up the return code ...
3390 *
3391 * li v0, __NR__foo_sigreturn
3392 * syscall
3393 */
bellard106ec872006-06-27 21:08:10 +00003394
Riku Voipio1d8b5122014-04-23 10:26:05 +03003395 __put_user(0x24020000 + syscall, tramp + 0);
3396 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003397 return err;
3398}
3399
Riku Voipio41ecc722014-04-23 11:01:00 +03003400static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003401 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003402{
Richard Henderson084d0492013-02-10 10:30:44 -08003403 int i;
bellard106ec872006-06-27 21:08:10 +00003404
Riku Voipio1d8b5122014-04-23 10:26:05 +03003405 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003406 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003407
Richard Henderson084d0492013-02-10 10:30:44 -08003408 __put_user(0, &sc->sc_regs[0]);
3409 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003410 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003411 }
bellard106ec872006-06-27 21:08:10 +00003412
Riku Voipio1d8b5122014-04-23 10:26:05 +03003413 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3414 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003415
Richard Henderson084d0492013-02-10 10:30:44 -08003416 /* Rather than checking for dsp existence, always copy. The storage
3417 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003418 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3419 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3420 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3421 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3422 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3423 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003424 {
3425 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003426 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003427 }
Richard Henderson084d0492013-02-10 10:30:44 -08003428
Riku Voipio1d8b5122014-04-23 10:26:05 +03003429 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003430
3431 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003432 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003433 }
bellard106ec872006-06-27 21:08:10 +00003434}
3435
Riku Voipio016d2e12014-04-23 11:19:48 +03003436static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003437restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003438{
Richard Henderson084d0492013-02-10 10:30:44 -08003439 int i;
bellard106ec872006-06-27 21:08:10 +00003440
Riku Voipio1d8b5122014-04-23 10:26:05 +03003441 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003442
Riku Voipio1d8b5122014-04-23 10:26:05 +03003443 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3444 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003445
Richard Henderson084d0492013-02-10 10:30:44 -08003446 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003447 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003448 }
3449
Riku Voipio1d8b5122014-04-23 10:26:05 +03003450 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3451 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3452 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3453 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3454 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3455 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003456 {
3457 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003458 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003459 cpu_wrdsp(dsp, 0x3ff, regs);
3460 }
3461
3462 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003463 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003464 }
bellard106ec872006-06-27 21:08:10 +00003465}
Richard Hendersonff970902013-02-10 10:30:42 -08003466
bellard106ec872006-06-27 21:08:10 +00003467/*
3468 * Determine which stack to use..
3469 */
bellard579a97f2007-11-11 14:26:47 +00003470static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003471get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003472{
3473 unsigned long sp;
3474
3475 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003476 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003477
3478 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003479 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003480 * above the user stack, 16-bytes before the next lowest
3481 * 16 byte boundary. Try to avoid trashing it.
3482 */
3483 sp -= 32;
3484
bellard106ec872006-06-27 21:08:10 +00003485 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003486 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003487 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3488 }
bellard106ec872006-06-27 21:08:10 +00003489
bellard579a97f2007-11-11 14:26:47 +00003490 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003491}
3492
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003493static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3494{
3495 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3496 env->hflags &= ~MIPS_HFLAG_M16;
3497 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3498 env->active_tc.PC &= ~(target_ulong) 1;
3499 }
3500}
3501
Richard Hendersonff970902013-02-10 10:30:42 -08003502# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003503/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003504static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003505 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003506{
3507 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003508 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003509 int i;
3510
bellard579a97f2007-11-11 14:26:47 +00003511 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003512 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003513 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3514 goto give_sigsegv;
3515 }
bellard106ec872006-06-27 21:08:10 +00003516
3517 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3518
Riku Voipio41ecc722014-04-23 11:01:00 +03003519 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003520
3521 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003522 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003523 }
3524
3525 /*
3526 * Arguments to signal handler:
3527 *
3528 * a0 = signal number
3529 * a1 = 0 (should be cause)
3530 * a2 = pointer to struct sigcontext
3531 *
3532 * $25 and PC point to the signal handler, $29 points to the
3533 * struct sigframe.
3534 */
thsb5dc7732008-06-27 10:02:35 +00003535 regs->active_tc.gpr[ 4] = sig;
3536 regs->active_tc.gpr[ 5] = 0;
3537 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3538 regs->active_tc.gpr[29] = frame_addr;
3539 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003540 /* The original kernel code sets CP0_EPC to the handler
3541 * since it returns to userland using eret
3542 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003543 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003544 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003545 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003546 return;
3547
3548give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003549 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003550}
3551
Andreas Färber05390242012-02-25 03:37:53 +01003552long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003553{
ths388bb212007-05-13 13:58:00 +00003554 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003555 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003556 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003557 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003558 int i;
bellard106ec872006-06-27 21:08:10 +00003559
thsb5dc7732008-06-27 10:02:35 +00003560 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003561 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003562 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003563 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003564
ths388bb212007-05-13 13:58:00 +00003565 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003566 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003567 }
bellard106ec872006-06-27 21:08:10 +00003568
ths388bb212007-05-13 13:58:00 +00003569 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003570 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003571
Riku Voipio016d2e12014-04-23 11:19:48 +03003572 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003573
3574#if 0
ths388bb212007-05-13 13:58:00 +00003575 /*
3576 * Don't let your children do this ...
3577 */
3578 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003579 "move\t$29, %0\n\t"
3580 "j\tsyscall_exit"
3581 :/* no outputs */
3582 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003583 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003584#endif
ths3b46e622007-09-17 08:09:54 +00003585
thsb5dc7732008-06-27 10:02:35 +00003586 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003587 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003588 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003589 * maybe a problem with nested signals ? */
3590 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003591 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003592
3593badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003594 force_sig(TARGET_SIGSEGV);
3595 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003596}
Richard Hendersonff970902013-02-10 10:30:42 -08003597# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003598
pbrook624f7972008-05-31 16:11:38 +00003599static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003600 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003601 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003602{
pbrook0b1bcb02009-04-21 01:41:10 +00003603 struct target_rt_sigframe *frame;
3604 abi_ulong frame_addr;
3605 int i;
3606
3607 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003608 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003609 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3610 goto give_sigsegv;
3611 }
pbrook0b1bcb02009-04-21 01:41:10 +00003612
3613 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3614
Peter Maydellf6c7a052015-01-08 12:19:48 +00003615 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003616
Aurelien Jarno60e99242010-03-29 02:12:51 +02003617 __put_user(0, &frame->rs_uc.tuc_flags);
3618 __put_user(0, &frame->rs_uc.tuc_link);
3619 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3620 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003621 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003622 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003623
Aurelien Jarno60e99242010-03-29 02:12:51 +02003624 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003625
3626 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003627 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003628 }
3629
3630 /*
3631 * Arguments to signal handler:
3632 *
3633 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003634 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003635 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003636 *
3637 * $25 and PC point to the signal handler, $29 points to the
3638 * struct sigframe.
3639 */
3640 env->active_tc.gpr[ 4] = sig;
3641 env->active_tc.gpr[ 5] = frame_addr
3642 + offsetof(struct target_rt_sigframe, rs_info);
3643 env->active_tc.gpr[ 6] = frame_addr
3644 + offsetof(struct target_rt_sigframe, rs_uc);
3645 env->active_tc.gpr[29] = frame_addr;
3646 env->active_tc.gpr[31] = frame_addr
3647 + offsetof(struct target_rt_sigframe, rs_code);
3648 /* The original kernel code sets CP0_EPC to the handler
3649 * since it returns to userland using eret
3650 * we cannot do this here, and we must set PC directly */
3651 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003652 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003653 unlock_user_struct(frame, frame_addr, 1);
3654 return;
3655
3656give_sigsegv:
3657 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003658 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003659}
3660
Andreas Färber05390242012-02-25 03:37:53 +01003661long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003662{
pbrook0b1bcb02009-04-21 01:41:10 +00003663 struct target_rt_sigframe *frame;
3664 abi_ulong frame_addr;
3665 sigset_t blocked;
3666
pbrook0b1bcb02009-04-21 01:41:10 +00003667 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003668 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003669 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3670 goto badframe;
3671 }
pbrook0b1bcb02009-04-21 01:41:10 +00003672
Aurelien Jarno60e99242010-03-29 02:12:51 +02003673 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003674 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003675
Riku Voipio016d2e12014-04-23 11:19:48 +03003676 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003677
3678 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003679 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3680 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003681 goto badframe;
3682
3683 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003684 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003685 /* I am not sure this is right, but it seems to work
3686 * maybe a problem with nested signals ? */
3687 env->CP0_EPC = 0;
3688 return -TARGET_QEMU_ESIGRETURN;
3689
3690badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003691 force_sig(TARGET_SIGSEGV);
3692 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003693}
bellard6d5e2162004-09-30 22:04:13 +00003694
thsc3b5bc82007-12-02 06:31:25 +00003695#elif defined(TARGET_SH4)
3696
3697/*
3698 * code and data structures from linux kernel:
3699 * include/asm-sh/sigcontext.h
3700 * arch/sh/kernel/signal.c
3701 */
3702
3703struct target_sigcontext {
3704 target_ulong oldmask;
3705
3706 /* CPU registers */
3707 target_ulong sc_gregs[16];
3708 target_ulong sc_pc;
3709 target_ulong sc_pr;
3710 target_ulong sc_sr;
3711 target_ulong sc_gbr;
3712 target_ulong sc_mach;
3713 target_ulong sc_macl;
3714
3715 /* FPU registers */
3716 target_ulong sc_fpregs[16];
3717 target_ulong sc_xfpregs[16];
3718 unsigned int sc_fpscr;
3719 unsigned int sc_fpul;
3720 unsigned int sc_ownedfp;
3721};
3722
3723struct target_sigframe
3724{
3725 struct target_sigcontext sc;
3726 target_ulong extramask[TARGET_NSIG_WORDS-1];
3727 uint16_t retcode[3];
3728};
3729
3730
3731struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003732 target_ulong tuc_flags;
3733 struct target_ucontext *tuc_link;
3734 target_stack_t tuc_stack;
3735 struct target_sigcontext tuc_mcontext;
3736 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003737};
3738
3739struct target_rt_sigframe
3740{
3741 struct target_siginfo info;
3742 struct target_ucontext uc;
3743 uint16_t retcode[3];
3744};
3745
3746
3747#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3748#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3749
pbrook624f7972008-05-31 16:11:38 +00003750static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003751 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003752{
pbrook624f7972008-05-31 16:11:38 +00003753 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003754 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3755 }
3756
3757 return (sp - frame_size) & -8ul;
3758}
3759
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003760/* Notice when we're in the middle of a gUSA region and reset.
3761 Note that this will only occur for !parallel_cpus, as we will
3762 translate such sequences differently in a parallel context. */
3763static void unwind_gusa(CPUSH4State *regs)
3764{
3765 /* If the stack pointer is sufficiently negative, and we haven't
3766 completed the sequence, then reset to the entry to the region. */
3767 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3768 However, the page mappings in qemu linux-user aren't as restricted
3769 and we wind up with the normal stack mapped above 0xF0000000.
3770 That said, there is no reason why the kernel should be allowing
3771 a gUSA region that spans 1GB. Use a tighter check here, for what
3772 can actually be enabled by the immediate move. */
3773 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3774 /* Reset the PC to before the gUSA region, as computed from
3775 R0 = region end, SP = -(region size), plus one more for the
3776 insn that actually initializes SP to the region size. */
3777 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3778
3779 /* Reset the SP to the saved version in R1. */
3780 regs->gregs[15] = regs->gregs[1];
3781 }
3782}
3783
Riku Voipio41ecc722014-04-23 11:01:00 +03003784static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003785 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003786{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003787 int i;
thsc3b5bc82007-12-02 06:31:25 +00003788
Riku Voipio1d8b5122014-04-23 10:26:05 +03003789#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003790 COPY(gregs[0]); COPY(gregs[1]);
3791 COPY(gregs[2]); COPY(gregs[3]);
3792 COPY(gregs[4]); COPY(gregs[5]);
3793 COPY(gregs[6]); COPY(gregs[7]);
3794 COPY(gregs[8]); COPY(gregs[9]);
3795 COPY(gregs[10]); COPY(gregs[11]);
3796 COPY(gregs[12]); COPY(gregs[13]);
3797 COPY(gregs[14]); COPY(gregs[15]);
3798 COPY(gbr); COPY(mach);
3799 COPY(macl); COPY(pr);
3800 COPY(sr); COPY(pc);
3801#undef COPY
3802
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003803 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003804 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003805 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003806 __put_user(regs->fpscr, &sc->sc_fpscr);
3807 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003808
3809 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003810 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003811}
3812
Timothy E Baldwinba412492016-05-12 18:47:35 +01003813static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003814{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003815 int i;
thsc3b5bc82007-12-02 06:31:25 +00003816
Riku Voipio1d8b5122014-04-23 10:26:05 +03003817#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003818 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003819 COPY(gregs[2]); COPY(gregs[3]);
3820 COPY(gregs[4]); COPY(gregs[5]);
3821 COPY(gregs[6]); COPY(gregs[7]);
3822 COPY(gregs[8]); COPY(gregs[9]);
3823 COPY(gregs[10]); COPY(gregs[11]);
3824 COPY(gregs[12]); COPY(gregs[13]);
3825 COPY(gregs[14]); COPY(gregs[15]);
3826 COPY(gbr); COPY(mach);
3827 COPY(macl); COPY(pr);
3828 COPY(sr); COPY(pc);
3829#undef COPY
3830
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003831 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003832 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003833 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003834 __get_user(regs->fpscr, &sc->sc_fpscr);
3835 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003836
3837 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003838 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003839}
3840
pbrook624f7972008-05-31 16:11:38 +00003841static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003842 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003843{
3844 struct target_sigframe *frame;
3845 abi_ulong frame_addr;
3846 int i;
thsc3b5bc82007-12-02 06:31:25 +00003847
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003848 unwind_gusa(regs);
3849
thsc3b5bc82007-12-02 06:31:25 +00003850 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003851 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003852 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3853 goto give_sigsegv;
3854 }
thsc3b5bc82007-12-02 06:31:25 +00003855
Riku Voipio41ecc722014-04-23 11:01:00 +03003856 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003857
3858 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003859 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003860 }
3861
3862 /* Set up to return from userspace. If provided, use a stub
3863 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003864 if (ka->sa_flags & TARGET_SA_RESTORER) {
3865 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003866 } else {
3867 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003868 abi_ulong retcode_addr = frame_addr +
3869 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003870 __put_user(MOVW(2), &frame->retcode[0]);
3871 __put_user(TRAP_NOARG, &frame->retcode[1]);
3872 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003873 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003874 }
3875
thsc3b5bc82007-12-02 06:31:25 +00003876 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003877 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003878 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003879 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003880 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003881 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003882 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003883
3884 unlock_user_struct(frame, frame_addr, 1);
3885 return;
3886
3887give_sigsegv:
3888 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003889 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003890}
3891
pbrook624f7972008-05-31 16:11:38 +00003892static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003893 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003894 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003895{
3896 struct target_rt_sigframe *frame;
3897 abi_ulong frame_addr;
3898 int i;
thsc3b5bc82007-12-02 06:31:25 +00003899
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003900 unwind_gusa(regs);
3901
thsc3b5bc82007-12-02 06:31:25 +00003902 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003903 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003904 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3905 goto give_sigsegv;
3906 }
thsc3b5bc82007-12-02 06:31:25 +00003907
Peter Maydellf6c7a052015-01-08 12:19:48 +00003908 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003909
3910 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003911 __put_user(0, &frame->uc.tuc_flags);
3912 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3913 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3914 &frame->uc.tuc_stack.ss_sp);
3915 __put_user(sas_ss_flags(regs->gregs[15]),
3916 &frame->uc.tuc_stack.ss_flags);
3917 __put_user(target_sigaltstack_used.ss_size,
3918 &frame->uc.tuc_stack.ss_size);
3919 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003920 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003921 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003922 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003923 }
3924
3925 /* Set up to return from userspace. If provided, use a stub
3926 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003927 if (ka->sa_flags & TARGET_SA_RESTORER) {
3928 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003929 } else {
3930 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003931 abi_ulong retcode_addr = frame_addr +
3932 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003933 __put_user(MOVW(2), &frame->retcode[0]);
3934 __put_user(TRAP_NOARG, &frame->retcode[1]);
3935 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003936 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003937 }
3938
thsc3b5bc82007-12-02 06:31:25 +00003939 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003940 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003941 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003942 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3943 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003944 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003945 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003946
3947 unlock_user_struct(frame, frame_addr, 1);
3948 return;
3949
3950give_sigsegv:
3951 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003952 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003953}
3954
Andreas Färber05390242012-02-25 03:37:53 +01003955long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003956{
3957 struct target_sigframe *frame;
3958 abi_ulong frame_addr;
3959 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003960 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003961 int i;
3962 int err = 0;
3963
thsc3b5bc82007-12-02 06:31:25 +00003964 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003965 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003966 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3967 goto badframe;
3968 }
thsc3b5bc82007-12-02 06:31:25 +00003969
Riku Voipio1d8b5122014-04-23 10:26:05 +03003970 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003971 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003972 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003973 }
3974
3975 if (err)
3976 goto badframe;
3977
3978 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003979 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003980
Timothy E Baldwinba412492016-05-12 18:47:35 +01003981 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003982
3983 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003984 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003985
3986badframe:
3987 unlock_user_struct(frame, frame_addr, 0);
3988 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003989 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003990}
3991
Andreas Färber05390242012-02-25 03:37:53 +01003992long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003993{
3994 struct target_rt_sigframe *frame;
3995 abi_ulong frame_addr;
3996 sigset_t blocked;
3997
thsc3b5bc82007-12-02 06:31:25 +00003998 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003999 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004000 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4001 goto badframe;
4002 }
thsc3b5bc82007-12-02 06:31:25 +00004003
Aurelien Jarno60e99242010-03-29 02:12:51 +02004004 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004005 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00004006
Timothy E Baldwinba412492016-05-12 18:47:35 +01004007 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00004008
4009 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004010 offsetof(struct target_rt_sigframe, uc.tuc_stack),
4011 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00004012 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004013 }
thsc3b5bc82007-12-02 06:31:25 +00004014
4015 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01004016 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004017
4018badframe:
4019 unlock_user_struct(frame, frame_addr, 0);
4020 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004021 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00004022}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004023#elif defined(TARGET_MICROBLAZE)
4024
4025struct target_sigcontext {
4026 struct target_pt_regs regs; /* needs to be first */
4027 uint32_t oldmask;
4028};
4029
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004030struct target_stack_t {
4031 abi_ulong ss_sp;
4032 int ss_flags;
4033 unsigned int ss_size;
4034};
4035
4036struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08004037 abi_ulong tuc_flags;
4038 abi_ulong tuc_link;
4039 struct target_stack_t tuc_stack;
4040 struct target_sigcontext tuc_mcontext;
4041 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004042};
4043
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004044/* Signal frames. */
4045struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02004046 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004047 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4048 uint32_t tramp[2];
4049};
4050
4051struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00004052 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004053 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004054 uint32_t tramp[2];
4055};
4056
Andreas Färber05390242012-02-25 03:37:53 +01004057static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004058{
4059 __put_user(env->regs[0], &sc->regs.r0);
4060 __put_user(env->regs[1], &sc->regs.r1);
4061 __put_user(env->regs[2], &sc->regs.r2);
4062 __put_user(env->regs[3], &sc->regs.r3);
4063 __put_user(env->regs[4], &sc->regs.r4);
4064 __put_user(env->regs[5], &sc->regs.r5);
4065 __put_user(env->regs[6], &sc->regs.r6);
4066 __put_user(env->regs[7], &sc->regs.r7);
4067 __put_user(env->regs[8], &sc->regs.r8);
4068 __put_user(env->regs[9], &sc->regs.r9);
4069 __put_user(env->regs[10], &sc->regs.r10);
4070 __put_user(env->regs[11], &sc->regs.r11);
4071 __put_user(env->regs[12], &sc->regs.r12);
4072 __put_user(env->regs[13], &sc->regs.r13);
4073 __put_user(env->regs[14], &sc->regs.r14);
4074 __put_user(env->regs[15], &sc->regs.r15);
4075 __put_user(env->regs[16], &sc->regs.r16);
4076 __put_user(env->regs[17], &sc->regs.r17);
4077 __put_user(env->regs[18], &sc->regs.r18);
4078 __put_user(env->regs[19], &sc->regs.r19);
4079 __put_user(env->regs[20], &sc->regs.r20);
4080 __put_user(env->regs[21], &sc->regs.r21);
4081 __put_user(env->regs[22], &sc->regs.r22);
4082 __put_user(env->regs[23], &sc->regs.r23);
4083 __put_user(env->regs[24], &sc->regs.r24);
4084 __put_user(env->regs[25], &sc->regs.r25);
4085 __put_user(env->regs[26], &sc->regs.r26);
4086 __put_user(env->regs[27], &sc->regs.r27);
4087 __put_user(env->regs[28], &sc->regs.r28);
4088 __put_user(env->regs[29], &sc->regs.r29);
4089 __put_user(env->regs[30], &sc->regs.r30);
4090 __put_user(env->regs[31], &sc->regs.r31);
4091 __put_user(env->sregs[SR_PC], &sc->regs.pc);
4092}
4093
Andreas Färber05390242012-02-25 03:37:53 +01004094static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004095{
4096 __get_user(env->regs[0], &sc->regs.r0);
4097 __get_user(env->regs[1], &sc->regs.r1);
4098 __get_user(env->regs[2], &sc->regs.r2);
4099 __get_user(env->regs[3], &sc->regs.r3);
4100 __get_user(env->regs[4], &sc->regs.r4);
4101 __get_user(env->regs[5], &sc->regs.r5);
4102 __get_user(env->regs[6], &sc->regs.r6);
4103 __get_user(env->regs[7], &sc->regs.r7);
4104 __get_user(env->regs[8], &sc->regs.r8);
4105 __get_user(env->regs[9], &sc->regs.r9);
4106 __get_user(env->regs[10], &sc->regs.r10);
4107 __get_user(env->regs[11], &sc->regs.r11);
4108 __get_user(env->regs[12], &sc->regs.r12);
4109 __get_user(env->regs[13], &sc->regs.r13);
4110 __get_user(env->regs[14], &sc->regs.r14);
4111 __get_user(env->regs[15], &sc->regs.r15);
4112 __get_user(env->regs[16], &sc->regs.r16);
4113 __get_user(env->regs[17], &sc->regs.r17);
4114 __get_user(env->regs[18], &sc->regs.r18);
4115 __get_user(env->regs[19], &sc->regs.r19);
4116 __get_user(env->regs[20], &sc->regs.r20);
4117 __get_user(env->regs[21], &sc->regs.r21);
4118 __get_user(env->regs[22], &sc->regs.r22);
4119 __get_user(env->regs[23], &sc->regs.r23);
4120 __get_user(env->regs[24], &sc->regs.r24);
4121 __get_user(env->regs[25], &sc->regs.r25);
4122 __get_user(env->regs[26], &sc->regs.r26);
4123 __get_user(env->regs[27], &sc->regs.r27);
4124 __get_user(env->regs[28], &sc->regs.r28);
4125 __get_user(env->regs[29], &sc->regs.r29);
4126 __get_user(env->regs[30], &sc->regs.r30);
4127 __get_user(env->regs[31], &sc->regs.r31);
4128 __get_user(env->sregs[SR_PC], &sc->regs.pc);
4129}
4130
4131static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004132 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004133{
4134 abi_ulong sp = env->regs[1];
4135
Riku Voipiob545f632014-07-15 17:01:55 +03004136 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004137 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03004138 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004139
4140 return ((sp - frame_size) & -8UL);
4141}
4142
4143static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004144 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004145{
4146 struct target_signal_frame *frame;
4147 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004148 int i;
4149
4150 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004151 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004152 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4153 goto badframe;
4154
4155 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004156 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004157
4158 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03004159 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004160 }
4161
Richard Hendersonf711df62010-11-22 14:57:52 -08004162 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004163
4164 /* Set up to return from userspace. If provided, use a stub
4165 already in userspace. */
4166 /* minus 8 is offset to cater for "rtsd r15,8" offset */
4167 if (ka->sa_flags & TARGET_SA_RESTORER) {
4168 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
4169 } else {
4170 uint32_t t;
4171 /* Note, these encodings are _big endian_! */
4172 /* addi r12, r0, __NR_sigreturn */
4173 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004174 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004175 /* brki r14, 0x8 */
4176 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004177 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004178
4179 /* Return from sighandler will jump to the tramp.
4180 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004181 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4182 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004183 }
4184
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004185 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004186 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004187 /* Signal handler args: */
4188 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004189 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004190 /* arg 1: sigcontext */
4191 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004192
4193 /* Offset of 4 to handle microblaze rtid r14, 0 */
4194 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4195
4196 unlock_user_struct(frame, frame_addr, 1);
4197 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004198badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004199 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004200}
4201
4202static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004203 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004204 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004205{
4206 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4207}
4208
Andreas Färber05390242012-02-25 03:37:53 +01004209long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004210{
4211 struct target_signal_frame *frame;
4212 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004213 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004214 sigset_t set;
4215 int i;
4216
4217 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004218 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004219 /* Make sure the guest isn't playing games. */
4220 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4221 goto badframe;
4222
4223 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004224 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004225 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004226 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004227 }
4228 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004229 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004230
Richard Hendersonf711df62010-11-22 14:57:52 -08004231 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004232 /* We got here through a sigreturn syscall, our path back is via an
4233 rtb insn so setup r14 for that. */
4234 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004235
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004236 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004237 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004238badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004239 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004240 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004241}
4242
Andreas Färber05390242012-02-25 03:37:53 +01004243long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004244{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004245 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004246 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4247 return -TARGET_ENOSYS;
4248}
4249
edgar_iglb6d3abd2008-02-28 11:29:27 +00004250#elif defined(TARGET_CRIS)
4251
4252struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004253 struct target_pt_regs regs; /* needs to be first */
4254 uint32_t oldmask;
4255 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004256};
4257
4258/* Signal frames. */
4259struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004260 struct target_sigcontext sc;
4261 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4262 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004263};
4264
4265struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004266 siginfo_t *pinfo;
4267 void *puc;
4268 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004269 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004270 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004271};
4272
Andreas Färber05390242012-02-25 03:37:53 +01004273static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004274{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004275 __put_user(env->regs[0], &sc->regs.r0);
4276 __put_user(env->regs[1], &sc->regs.r1);
4277 __put_user(env->regs[2], &sc->regs.r2);
4278 __put_user(env->regs[3], &sc->regs.r3);
4279 __put_user(env->regs[4], &sc->regs.r4);
4280 __put_user(env->regs[5], &sc->regs.r5);
4281 __put_user(env->regs[6], &sc->regs.r6);
4282 __put_user(env->regs[7], &sc->regs.r7);
4283 __put_user(env->regs[8], &sc->regs.r8);
4284 __put_user(env->regs[9], &sc->regs.r9);
4285 __put_user(env->regs[10], &sc->regs.r10);
4286 __put_user(env->regs[11], &sc->regs.r11);
4287 __put_user(env->regs[12], &sc->regs.r12);
4288 __put_user(env->regs[13], &sc->regs.r13);
4289 __put_user(env->regs[14], &sc->usp);
4290 __put_user(env->regs[15], &sc->regs.acr);
4291 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4292 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4293 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004294}
edgar_igl9664d922008-03-03 22:23:53 +00004295
Andreas Färber05390242012-02-25 03:37:53 +01004296static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004297{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004298 __get_user(env->regs[0], &sc->regs.r0);
4299 __get_user(env->regs[1], &sc->regs.r1);
4300 __get_user(env->regs[2], &sc->regs.r2);
4301 __get_user(env->regs[3], &sc->regs.r3);
4302 __get_user(env->regs[4], &sc->regs.r4);
4303 __get_user(env->regs[5], &sc->regs.r5);
4304 __get_user(env->regs[6], &sc->regs.r6);
4305 __get_user(env->regs[7], &sc->regs.r7);
4306 __get_user(env->regs[8], &sc->regs.r8);
4307 __get_user(env->regs[9], &sc->regs.r9);
4308 __get_user(env->regs[10], &sc->regs.r10);
4309 __get_user(env->regs[11], &sc->regs.r11);
4310 __get_user(env->regs[12], &sc->regs.r12);
4311 __get_user(env->regs[13], &sc->regs.r13);
4312 __get_user(env->regs[14], &sc->usp);
4313 __get_user(env->regs[15], &sc->regs.acr);
4314 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4315 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4316 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004317}
4318
Andreas Färber05390242012-02-25 03:37:53 +01004319static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004320{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004321 abi_ulong sp;
4322 /* Align the stack downwards to 4. */
4323 sp = (env->regs[R_SP] & ~3);
4324 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004325}
4326
pbrook624f7972008-05-31 16:11:38 +00004327static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004328 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004329{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004330 struct target_signal_frame *frame;
4331 abi_ulong frame_addr;
4332 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004333
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004334 frame_addr = get_sigframe(env, sizeof *frame);
4335 trace_user_setup_frame(env, frame_addr);
4336 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4337 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004338
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004339 /*
4340 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4341 * use this trampoline anymore but it sets it up for GDB.
4342 * In QEMU, using the trampoline simplifies things a bit so we use it.
4343 *
4344 * This is movu.w __NR_sigreturn, r9; break 13;
4345 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004346 __put_user(0x9c5f, frame->retcode+0);
4347 __put_user(TARGET_NR_sigreturn,
4348 frame->retcode + 1);
4349 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004350
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004351 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004352 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004353
Riku Voipio0188fad2014-04-23 13:34:15 +03004354 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4355 __put_user(set->sig[i], &frame->extramask[i - 1]);
4356 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004357
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004358 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004359
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004360 /* Move the stack and setup the arguments for the handler. */
4361 env->regs[R_SP] = frame_addr;
4362 env->regs[10] = sig;
4363 env->pc = (unsigned long) ka->_sa_handler;
4364 /* Link SRP so the guest returns through the trampoline. */
4365 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004366
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004367 unlock_user_struct(frame, frame_addr, 1);
4368 return;
4369badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004370 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004371}
4372
pbrook624f7972008-05-31 16:11:38 +00004373static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004374 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004375 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004376{
4377 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4378}
4379
Andreas Färber05390242012-02-25 03:37:53 +01004380long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004381{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004382 struct target_signal_frame *frame;
4383 abi_ulong frame_addr;
4384 target_sigset_t target_set;
4385 sigset_t set;
4386 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004387
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004388 frame_addr = env->regs[R_SP];
4389 trace_user_do_sigreturn(env, frame_addr);
4390 /* Make sure the guest isn't playing games. */
4391 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4392 goto badframe;
4393 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004394
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004395 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004396 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004397 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004398 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004399 }
4400 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004401 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004402
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004403 restore_sigcontext(&frame->sc, env);
4404 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004405 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004406badframe:
4407 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004408 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004409}
4410
Andreas Färber05390242012-02-25 03:37:53 +01004411long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004412{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004413 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004414 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4415 return -TARGET_ENOSYS;
4416}
thsc3b5bc82007-12-02 06:31:25 +00004417
Marek Vasuta0a839b2017-01-18 23:01:42 +01004418#elif defined(TARGET_NIOS2)
4419
4420#define MCONTEXT_VERSION 2
4421
4422struct target_sigcontext {
4423 int version;
4424 unsigned long gregs[32];
4425};
4426
4427struct target_ucontext {
4428 abi_ulong tuc_flags;
4429 abi_ulong tuc_link;
4430 target_stack_t tuc_stack;
4431 struct target_sigcontext tuc_mcontext;
4432 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4433};
4434
4435struct target_rt_sigframe {
4436 struct target_siginfo info;
4437 struct target_ucontext uc;
4438};
4439
4440static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4441{
4442 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4443#ifdef CONFIG_STACK_GROWSUP
4444 return target_sigaltstack_used.ss_sp;
4445#else
4446 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4447#endif
4448 }
4449 return sp;
4450}
4451
4452static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4453{
4454 unsigned long *gregs = uc->tuc_mcontext.gregs;
4455
4456 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4457 __put_user(env->regs[1], &gregs[0]);
4458 __put_user(env->regs[2], &gregs[1]);
4459 __put_user(env->regs[3], &gregs[2]);
4460 __put_user(env->regs[4], &gregs[3]);
4461 __put_user(env->regs[5], &gregs[4]);
4462 __put_user(env->regs[6], &gregs[5]);
4463 __put_user(env->regs[7], &gregs[6]);
4464 __put_user(env->regs[8], &gregs[7]);
4465 __put_user(env->regs[9], &gregs[8]);
4466 __put_user(env->regs[10], &gregs[9]);
4467 __put_user(env->regs[11], &gregs[10]);
4468 __put_user(env->regs[12], &gregs[11]);
4469 __put_user(env->regs[13], &gregs[12]);
4470 __put_user(env->regs[14], &gregs[13]);
4471 __put_user(env->regs[15], &gregs[14]);
4472 __put_user(env->regs[16], &gregs[15]);
4473 __put_user(env->regs[17], &gregs[16]);
4474 __put_user(env->regs[18], &gregs[17]);
4475 __put_user(env->regs[19], &gregs[18]);
4476 __put_user(env->regs[20], &gregs[19]);
4477 __put_user(env->regs[21], &gregs[20]);
4478 __put_user(env->regs[22], &gregs[21]);
4479 __put_user(env->regs[23], &gregs[22]);
4480 __put_user(env->regs[R_RA], &gregs[23]);
4481 __put_user(env->regs[R_FP], &gregs[24]);
4482 __put_user(env->regs[R_GP], &gregs[25]);
4483 __put_user(env->regs[R_EA], &gregs[27]);
4484 __put_user(env->regs[R_SP], &gregs[28]);
4485
4486 return 0;
4487}
4488
4489static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4490 int *pr2)
4491{
4492 int temp;
4493 abi_ulong off, frame_addr = env->regs[R_SP];
4494 unsigned long *gregs = uc->tuc_mcontext.gregs;
4495 int err;
4496
4497 /* Always make any pending restarted system calls return -EINTR */
4498 /* current->restart_block.fn = do_no_restart_syscall; */
4499
4500 __get_user(temp, &uc->tuc_mcontext.version);
4501 if (temp != MCONTEXT_VERSION) {
4502 return 1;
4503 }
4504
4505 /* restore passed registers */
4506 __get_user(env->regs[1], &gregs[0]);
4507 __get_user(env->regs[2], &gregs[1]);
4508 __get_user(env->regs[3], &gregs[2]);
4509 __get_user(env->regs[4], &gregs[3]);
4510 __get_user(env->regs[5], &gregs[4]);
4511 __get_user(env->regs[6], &gregs[5]);
4512 __get_user(env->regs[7], &gregs[6]);
4513 __get_user(env->regs[8], &gregs[7]);
4514 __get_user(env->regs[9], &gregs[8]);
4515 __get_user(env->regs[10], &gregs[9]);
4516 __get_user(env->regs[11], &gregs[10]);
4517 __get_user(env->regs[12], &gregs[11]);
4518 __get_user(env->regs[13], &gregs[12]);
4519 __get_user(env->regs[14], &gregs[13]);
4520 __get_user(env->regs[15], &gregs[14]);
4521 __get_user(env->regs[16], &gregs[15]);
4522 __get_user(env->regs[17], &gregs[16]);
4523 __get_user(env->regs[18], &gregs[17]);
4524 __get_user(env->regs[19], &gregs[18]);
4525 __get_user(env->regs[20], &gregs[19]);
4526 __get_user(env->regs[21], &gregs[20]);
4527 __get_user(env->regs[22], &gregs[21]);
4528 __get_user(env->regs[23], &gregs[22]);
4529 /* gregs[23] is handled below */
4530 /* Verify, should this be settable */
4531 __get_user(env->regs[R_FP], &gregs[24]);
4532 /* Verify, should this be settable */
4533 __get_user(env->regs[R_GP], &gregs[25]);
4534 /* Not really necessary no user settable bits */
4535 __get_user(temp, &gregs[26]);
4536 __get_user(env->regs[R_EA], &gregs[27]);
4537
4538 __get_user(env->regs[R_RA], &gregs[23]);
4539 __get_user(env->regs[R_SP], &gregs[28]);
4540
4541 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4542 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4543 if (err == -EFAULT) {
4544 return 1;
4545 }
4546
4547 *pr2 = env->regs[2];
4548 return 0;
4549}
4550
4551static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4552 size_t frame_size)
4553{
4554 unsigned long usp;
4555
4556 /* Default to using normal stack. */
4557 usp = env->regs[R_SP];
4558
4559 /* This is the X/Open sanctioned signal stack switching. */
4560 usp = sigsp(usp, ka);
4561
4562 /* Verify, is it 32 or 64 bit aligned */
4563 return (void *)((usp - frame_size) & -8UL);
4564}
4565
4566static void setup_rt_frame(int sig, struct target_sigaction *ka,
4567 target_siginfo_t *info,
4568 target_sigset_t *set,
4569 CPUNios2State *env)
4570{
4571 struct target_rt_sigframe *frame;
4572 int i, err = 0;
4573
4574 frame = get_sigframe(ka, env, sizeof(*frame));
4575
4576 if (ka->sa_flags & SA_SIGINFO) {
4577 tswap_siginfo(&frame->info, info);
4578 }
4579
4580 /* Create the ucontext. */
4581 __put_user(0, &frame->uc.tuc_flags);
4582 __put_user(0, &frame->uc.tuc_link);
4583 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4584 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4585 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4586 err |= rt_setup_ucontext(&frame->uc, env);
4587 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4588 __put_user((abi_ulong)set->sig[i],
4589 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4590 }
4591
4592 if (err) {
4593 goto give_sigsegv;
4594 }
4595
4596 /* Set up to return from userspace; jump to fixed address sigreturn
4597 trampoline on kuser page. */
4598 env->regs[R_RA] = (unsigned long) (0x1044);
4599
4600 /* Set up registers for signal handler */
4601 env->regs[R_SP] = (unsigned long) frame;
4602 env->regs[4] = (unsigned long) sig;
4603 env->regs[5] = (unsigned long) &frame->info;
4604 env->regs[6] = (unsigned long) &frame->uc;
4605 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4606 return;
4607
4608give_sigsegv:
4609 if (sig == TARGET_SIGSEGV) {
4610 ka->_sa_handler = TARGET_SIG_DFL;
4611 }
4612 force_sigsegv(sig);
4613 return;
4614}
4615
4616long do_sigreturn(CPUNios2State *env)
4617{
4618 trace_user_do_sigreturn(env, 0);
4619 fprintf(stderr, "do_sigreturn: not implemented\n");
4620 return -TARGET_ENOSYS;
4621}
4622
4623long do_rt_sigreturn(CPUNios2State *env)
4624{
4625 /* Verify, can we follow the stack back */
4626 abi_ulong frame_addr = env->regs[R_SP];
4627 struct target_rt_sigframe *frame;
4628 sigset_t set;
4629 int rval;
4630
4631 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4632 goto badframe;
4633 }
4634
4635 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4636 do_sigprocmask(SIG_SETMASK, &set, NULL);
4637
4638 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4639 goto badframe;
4640 }
4641
4642 unlock_user_struct(frame, frame_addr, 0);
4643 return rval;
4644
4645badframe:
4646 unlock_user_struct(frame, frame_addr, 0);
4647 force_sig(TARGET_SIGSEGV);
4648 return 0;
4649}
4650/* TARGET_NIOS2 */
4651
Jia Liud9627832012-07-20 15:50:52 +08004652#elif defined(TARGET_OPENRISC)
4653
4654struct target_sigcontext {
4655 struct target_pt_regs regs;
4656 abi_ulong oldmask;
4657 abi_ulong usp;
4658};
4659
4660struct target_ucontext {
4661 abi_ulong tuc_flags;
4662 abi_ulong tuc_link;
4663 target_stack_t tuc_stack;
4664 struct target_sigcontext tuc_mcontext;
4665 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4666};
4667
4668struct target_rt_sigframe {
4669 abi_ulong pinfo;
4670 uint64_t puc;
4671 struct target_siginfo info;
4672 struct target_sigcontext sc;
4673 struct target_ucontext uc;
4674 unsigned char retcode[16]; /* trampoline code */
4675};
4676
4677/* This is the asm-generic/ucontext.h version */
4678#if 0
4679static int restore_sigcontext(CPUOpenRISCState *regs,
4680 struct target_sigcontext *sc)
4681{
4682 unsigned int err = 0;
4683 unsigned long old_usp;
4684
4685 /* Alwys make any pending restarted system call return -EINTR */
4686 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4687
4688 /* restore the regs from &sc->regs (same as sc, since regs is first)
4689 * (sc is already checked for VERIFY_READ since the sigframe was
4690 * checked in sys_sigreturn previously)
4691 */
4692
4693 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4694 goto badframe;
4695 }
4696
4697 /* make sure the U-flag is set so user-mode cannot fool us */
4698
4699 regs->sr &= ~SR_SM;
4700
4701 /* restore the old USP as it was before we stacked the sc etc.
4702 * (we cannot just pop the sigcontext since we aligned the sp and
4703 * stuff after pushing it)
4704 */
4705
Riku Voipio1d8b5122014-04-23 10:26:05 +03004706 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004707 phx_signal("old_usp 0x%lx", old_usp);
4708
4709 __PHX__ REALLY /* ??? */
4710 wrusp(old_usp);
4711 regs->gpr[1] = old_usp;
4712
4713 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4714 * after this completes, but we don't use that mechanism. maybe we can
4715 * use it now ?
4716 */
4717
4718 return err;
4719
4720badframe:
4721 return 1;
4722}
4723#endif
4724
4725/* Set up a signal frame. */
4726
Riku Voipio41ecc722014-04-23 11:01:00 +03004727static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004728 CPUOpenRISCState *regs,
4729 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004730{
Stafford Horned89e71e2017-04-06 06:44:56 +09004731 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004732
4733 /* copy the regs. they are first in sc so we can use sc directly */
4734
Riku Voipio1d8b5122014-04-23 10:26:05 +03004735 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004736
4737 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4738 the signal handler. The frametype will be restored to its previous
4739 value in restore_sigcontext. */
4740 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4741
4742 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004743 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004744 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004745}
4746
4747static inline unsigned long align_sigframe(unsigned long sp)
4748{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004749 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004750}
4751
4752static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4753 CPUOpenRISCState *regs,
4754 size_t frame_size)
4755{
Stafford Horned89e71e2017-04-06 06:44:56 +09004756 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004757 int onsigstack = on_sig_stack(sp);
4758
4759 /* redzone */
4760 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004761 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004762 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4763 }
4764
4765 sp = align_sigframe(sp - frame_size);
4766
4767 /*
4768 * If we are on the alternate signal stack and would overflow it, don't.
4769 * Return an always-bogus address instead so we will die with SIGSEGV.
4770 */
4771
4772 if (onsigstack && !likely(on_sig_stack(sp))) {
4773 return -1L;
4774 }
4775
4776 return sp;
4777}
4778
Jia Liud9627832012-07-20 15:50:52 +08004779static void setup_rt_frame(int sig, struct target_sigaction *ka,
4780 target_siginfo_t *info,
4781 target_sigset_t *set, CPUOpenRISCState *env)
4782{
4783 int err = 0;
4784 abi_ulong frame_addr;
4785 unsigned long return_ip;
4786 struct target_rt_sigframe *frame;
4787 abi_ulong info_addr, uc_addr;
4788
Jia Liud9627832012-07-20 15:50:52 +08004789 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004790 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004791 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4792 goto give_sigsegv;
4793 }
4794
4795 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004796 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004797 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004798 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004799
4800 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004801 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004802 }
4803
Khem Raj04b33e22017-06-28 13:44:52 -07004804 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004805 __put_user(0, &frame->uc.tuc_flags);
4806 __put_user(0, &frame->uc.tuc_link);
4807 __put_user(target_sigaltstack_used.ss_sp,
4808 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004809 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4810 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004811 __put_user(target_sigaltstack_used.ss_size,
4812 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004813 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004814
4815 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4816
Jia Liud9627832012-07-20 15:50:52 +08004817 /* trampoline - the desired return ip is the retcode itself */
4818 return_ip = (unsigned long)&frame->retcode;
4819 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004820 __put_user(0xa960, (short *)(frame->retcode + 0));
4821 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4822 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4823 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004824
4825 if (err) {
4826 goto give_sigsegv;
4827 }
4828
4829 /* TODO what is the current->exec_domain stuff and invmap ? */
4830
4831 /* Set up registers for signal handler */
4832 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004833 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4834 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4835 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4836 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004837
4838 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004839 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004840
4841 return;
4842
4843give_sigsegv:
4844 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004845 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004846}
4847
4848long do_sigreturn(CPUOpenRISCState *env)
4849{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004850 trace_user_do_sigreturn(env, 0);
4851 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004852 return -TARGET_ENOSYS;
4853}
4854
4855long do_rt_sigreturn(CPUOpenRISCState *env)
4856{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004857 trace_user_do_rt_sigreturn(env, 0);
4858 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004859 return -TARGET_ENOSYS;
4860}
4861/* TARGET_OPENRISC */
4862
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004863#elif defined(TARGET_S390X)
4864
4865#define __NUM_GPRS 16
4866#define __NUM_FPRS 16
4867#define __NUM_ACRS 16
4868
4869#define S390_SYSCALL_SIZE 2
4870#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4871
4872#define _SIGCONTEXT_NSIG 64
4873#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4874#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4875#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4876#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4877#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4878
4879typedef struct {
4880 target_psw_t psw;
4881 target_ulong gprs[__NUM_GPRS];
4882 unsigned int acrs[__NUM_ACRS];
4883} target_s390_regs_common;
4884
4885typedef struct {
4886 unsigned int fpc;
4887 double fprs[__NUM_FPRS];
4888} target_s390_fp_regs;
4889
4890typedef struct {
4891 target_s390_regs_common regs;
4892 target_s390_fp_regs fpregs;
4893} target_sigregs;
4894
4895struct target_sigcontext {
4896 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4897 target_sigregs *sregs;
4898};
4899
4900typedef struct {
4901 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4902 struct target_sigcontext sc;
4903 target_sigregs sregs;
4904 int signo;
4905 uint8_t retcode[S390_SYSCALL_SIZE];
4906} sigframe;
4907
4908struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004909 target_ulong tuc_flags;
4910 struct target_ucontext *tuc_link;
4911 target_stack_t tuc_stack;
4912 target_sigregs tuc_mcontext;
4913 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004914};
4915
4916typedef struct {
4917 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4918 uint8_t retcode[S390_SYSCALL_SIZE];
4919 struct target_siginfo info;
4920 struct target_ucontext uc;
4921} rt_sigframe;
4922
4923static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004924get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004925{
4926 abi_ulong sp;
4927
4928 /* Default to using normal stack */
4929 sp = env->regs[15];
4930
4931 /* This is the X/Open sanctioned signal stack switching. */
4932 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4933 if (!sas_ss_flags(sp)) {
4934 sp = target_sigaltstack_used.ss_sp +
4935 target_sigaltstack_used.ss_size;
4936 }
4937 }
4938
4939 /* This is the legacy signal stack switching. */
4940 else if (/* FIXME !user_mode(regs) */ 0 &&
4941 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4942 ka->sa_restorer) {
4943 sp = (abi_ulong) ka->sa_restorer;
4944 }
4945
4946 return (sp - frame_size) & -8ul;
4947}
4948
Andreas Färber05390242012-02-25 03:37:53 +01004949static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004950{
4951 int i;
4952 //save_access_regs(current->thread.acrs); FIXME
4953
4954 /* Copy a 'clean' PSW mask to the user to avoid leaking
4955 information about whether PER is currently on. */
4956 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4957 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4958 for (i = 0; i < 16; i++) {
4959 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4960 }
4961 for (i = 0; i < 16; i++) {
4962 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4963 }
4964 /*
4965 * We have to store the fp registers to current->thread.fp_regs
4966 * to merge them with the emulated registers.
4967 */
4968 //save_fp_regs(&current->thread.fp_regs); FIXME
4969 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004970 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004971 }
4972}
4973
4974static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004975 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004976{
4977 sigframe *frame;
4978 abi_ulong frame_addr;
4979
4980 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004981 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004982 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004983 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004984 }
4985
Riku Voipio0188fad2014-04-23 13:34:15 +03004986 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004987
4988 save_sigregs(env, &frame->sregs);
4989
4990 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4991 (abi_ulong *)&frame->sc.sregs);
4992
4993 /* Set up to return from userspace. If provided, use a stub
4994 already in userspace. */
4995 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004996 env->regs[14] = (unsigned long)
4997 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004998 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004999 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
5000 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005001 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
5002 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005003 }
5004
5005 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005006 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005007
5008 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005009 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005010 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5011
5012 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005013 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005014
5015 /* We forgot to include these in the sigcontext.
5016 To avoid breaking binary compatibility, they are passed as args. */
5017 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
5018 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
5019
5020 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02005021 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005022 unlock_user_struct(frame, frame_addr, 1);
5023 return;
5024
5025give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005026 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005027}
5028
5029static void setup_rt_frame(int sig, struct target_sigaction *ka,
5030 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005031 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005032{
5033 int i;
5034 rt_sigframe *frame;
5035 abi_ulong frame_addr;
5036
5037 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005038 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005039 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5040 goto give_sigsegv;
5041 }
5042
Peter Maydellf6c7a052015-01-08 12:19:48 +00005043 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005044
5045 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005046 __put_user(0, &frame->uc.tuc_flags);
5047 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
5048 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005049 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005050 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005051 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5052 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005053 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
5054 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005055 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005056 }
5057
5058 /* Set up to return from userspace. If provided, use a stub
5059 already in userspace. */
5060 if (ka->sa_flags & TARGET_SA_RESTORER) {
5061 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
5062 } else {
5063 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03005064 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
5065 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005066 }
5067
5068 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03005069 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005070
5071 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005072 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005073 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
5074
5075 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02005076 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
5077 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005078 return;
5079
5080give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005081 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005082}
5083
5084static int
Andreas Färber05390242012-02-25 03:37:53 +01005085restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005086{
5087 int err = 0;
5088 int i;
5089
5090 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005091 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005092 }
5093
Riku Voipio1d8b5122014-04-23 10:26:05 +03005094 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005095 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
5096 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005097 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005098 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
5099
5100 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005101 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005102 }
5103 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04005104 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005105 }
5106
5107 return err;
5108}
5109
Andreas Färber05390242012-02-25 03:37:53 +01005110long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005111{
5112 sigframe *frame;
5113 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005114 target_sigset_t target_set;
5115 sigset_t set;
5116
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005117 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005118 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5119 goto badframe;
5120 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03005121 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005122
5123 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005124 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005125
5126 if (restore_sigregs(env, &frame->sregs)) {
5127 goto badframe;
5128 }
5129
5130 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005131 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005132
5133badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005134 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005135 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005136}
5137
Andreas Färber05390242012-02-25 03:37:53 +01005138long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005139{
5140 rt_sigframe *frame;
5141 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005142 sigset_t set;
5143
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005144 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005145 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5146 goto badframe;
5147 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005148 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005149
Peter Maydell9eede5b2016-05-27 15:51:46 +01005150 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005151
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005152 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005153 goto badframe;
5154 }
5155
Peter Maydell6fea2ea2011-07-12 21:27:15 +01005156 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005157 get_sp_from_cpustate(env)) == -EFAULT) {
5158 goto badframe;
5159 }
5160 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01005161 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005162
5163badframe:
5164 unlock_user_struct(frame, frame_addr, 0);
5165 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005166 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005167}
5168
Tom Musta61e75fe2014-06-30 08:13:38 -05005169#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07005170
5171/* Size of dummy stack frame allocated when calling signal handler.
5172 See arch/powerpc/include/asm/ptrace.h. */
5173#if defined(TARGET_PPC64)
5174#define SIGNAL_FRAMESIZE 128
5175#else
5176#define SIGNAL_FRAMESIZE 64
5177#endif
5178
Tom Musta61e75fe2014-06-30 08:13:38 -05005179/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5180 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5181struct target_mcontext {
5182 target_ulong mc_gregs[48];
5183 /* Includes fpscr. */
5184 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005185#if defined(TARGET_PPC64)
5186 /* Pointer to the vector regs */
5187 target_ulong v_regs;
5188#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005189 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005190#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005191 /* We need to handle Altivec and SPE at the same time, which no
5192 kernel needs to do. Fortunately, the kernel defines this bit to
5193 be Altivec-register-large all the time, rather than trying to
5194 twiddle it based on the specific platform. */
5195 union {
5196 /* SPE vector registers. One extra for SPEFSCR. */
5197 uint32_t spe[33];
5198 /* Altivec vector registers. The packing of VSCR and VRSAVE
5199 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005200 them apart; PPC32 stuffs them together.
5201 We also need to account for the VSX registers on PPC64
5202 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005203#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005204#define QEMU_NVRREG (34 + 16)
5205 /* On ppc64, this mcontext structure is naturally *unaligned*,
5206 * or rather it is aligned on a 8 bytes boundary but not on
5207 * a 16 bytes one. This pad fixes it up. This is also why the
5208 * vector regs are referenced by the v_regs pointer above so
5209 * any amount of padding can be added here
5210 */
5211 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005212#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005213 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005214#define QEMU_NVRREG 33
5215#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005216 /* We cannot use ppc_avr_t here as we do *not* want the implied
5217 * 16-bytes alignment that would result from it. This would have
5218 * the effect of making the whole struct target_mcontext aligned
5219 * which breaks the layout of struct target_ucontext on ppc64.
5220 */
5221 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005222#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005223 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005224};
5225
Nathan Froydbcd49332009-05-12 19:13:18 -07005226/* See arch/powerpc/include/asm/sigcontext.h. */
5227struct target_sigcontext {
5228 target_ulong _unused[4];
5229 int32_t signal;
5230#if defined(TARGET_PPC64)
5231 int32_t pad0;
5232#endif
5233 target_ulong handler;
5234 target_ulong oldmask;
5235 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005236#if defined(TARGET_PPC64)
5237 struct target_mcontext mcontext;
5238#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005239};
5240
5241/* Indices for target_mcontext.mc_gregs, below.
5242 See arch/powerpc/include/asm/ptrace.h for details. */
5243enum {
5244 TARGET_PT_R0 = 0,
5245 TARGET_PT_R1 = 1,
5246 TARGET_PT_R2 = 2,
5247 TARGET_PT_R3 = 3,
5248 TARGET_PT_R4 = 4,
5249 TARGET_PT_R5 = 5,
5250 TARGET_PT_R6 = 6,
5251 TARGET_PT_R7 = 7,
5252 TARGET_PT_R8 = 8,
5253 TARGET_PT_R9 = 9,
5254 TARGET_PT_R10 = 10,
5255 TARGET_PT_R11 = 11,
5256 TARGET_PT_R12 = 12,
5257 TARGET_PT_R13 = 13,
5258 TARGET_PT_R14 = 14,
5259 TARGET_PT_R15 = 15,
5260 TARGET_PT_R16 = 16,
5261 TARGET_PT_R17 = 17,
5262 TARGET_PT_R18 = 18,
5263 TARGET_PT_R19 = 19,
5264 TARGET_PT_R20 = 20,
5265 TARGET_PT_R21 = 21,
5266 TARGET_PT_R22 = 22,
5267 TARGET_PT_R23 = 23,
5268 TARGET_PT_R24 = 24,
5269 TARGET_PT_R25 = 25,
5270 TARGET_PT_R26 = 26,
5271 TARGET_PT_R27 = 27,
5272 TARGET_PT_R28 = 28,
5273 TARGET_PT_R29 = 29,
5274 TARGET_PT_R30 = 30,
5275 TARGET_PT_R31 = 31,
5276 TARGET_PT_NIP = 32,
5277 TARGET_PT_MSR = 33,
5278 TARGET_PT_ORIG_R3 = 34,
5279 TARGET_PT_CTR = 35,
5280 TARGET_PT_LNK = 36,
5281 TARGET_PT_XER = 37,
5282 TARGET_PT_CCR = 38,
5283 /* Yes, there are two registers with #39. One is 64-bit only. */
5284 TARGET_PT_MQ = 39,
5285 TARGET_PT_SOFTE = 39,
5286 TARGET_PT_TRAP = 40,
5287 TARGET_PT_DAR = 41,
5288 TARGET_PT_DSISR = 42,
5289 TARGET_PT_RESULT = 43,
5290 TARGET_PT_REGS_COUNT = 44
5291};
5292
Nathan Froydbcd49332009-05-12 19:13:18 -07005293
5294struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005295 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005296 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005297 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005298#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005299 int32_t tuc_pad[7];
5300 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005301 points to uc_mcontext field */
5302#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005303 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005304#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005305 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005306 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005307#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005308 int32_t tuc_maskext[30];
5309 int32_t tuc_pad2[3];
5310 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005311#endif
5312};
5313
5314/* See arch/powerpc/kernel/signal_32.c. */
5315struct target_sigframe {
5316 struct target_sigcontext sctx;
5317 struct target_mcontext mctx;
5318 int32_t abigap[56];
5319};
5320
Tom Musta61e75fe2014-06-30 08:13:38 -05005321#if defined(TARGET_PPC64)
5322
5323#define TARGET_TRAMP_SIZE 6
5324
5325struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005326 /* sys_rt_sigreturn requires the ucontext be the first field */
5327 struct target_ucontext uc;
5328 target_ulong _unused[2];
5329 uint32_t trampoline[TARGET_TRAMP_SIZE];
5330 target_ulong pinfo; /* struct siginfo __user * */
5331 target_ulong puc; /* void __user * */
5332 struct target_siginfo info;
5333 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5334 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005335} __attribute__((aligned(16)));
5336
5337#else
5338
Nathan Froydbcd49332009-05-12 19:13:18 -07005339struct target_rt_sigframe {
5340 struct target_siginfo info;
5341 struct target_ucontext uc;
5342 int32_t abigap[56];
5343};
5344
Tom Musta61e75fe2014-06-30 08:13:38 -05005345#endif
5346
Tom Musta8d6ab332014-06-30 08:13:39 -05005347#if defined(TARGET_PPC64)
5348
5349struct target_func_ptr {
5350 target_ulong entry;
5351 target_ulong toc;
5352};
5353
5354#endif
5355
Nathan Froydbcd49332009-05-12 19:13:18 -07005356/* We use the mc_pad field for the signal return trampoline. */
5357#define tramp mc_pad
5358
5359/* See arch/powerpc/kernel/signal.c. */
5360static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005361 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005362 int frame_size)
5363{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005364 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005365
5366 oldsp = env->gpr[1];
5367
5368 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005369 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005370 oldsp = (target_sigaltstack_used.ss_sp
5371 + target_sigaltstack_used.ss_size);
5372 }
5373
Eduardo Habkost9be38592016-06-13 18:57:58 -03005374 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005375}
5376
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005377#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5378 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5379#define PPC_VEC_HI 0
5380#define PPC_VEC_LO 1
5381#else
5382#define PPC_VEC_HI 1
5383#define PPC_VEC_LO 0
5384#endif
5385
5386
Tom Musta76781082014-06-30 08:13:37 -05005387static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005388{
5389 target_ulong msr = env->msr;
5390 int i;
5391 target_ulong ccr = 0;
5392
5393 /* In general, the kernel attempts to be intelligent about what it
5394 needs to save for Altivec/FP/SPE registers. We don't care that
5395 much, so we just go ahead and save everything. */
5396
5397 /* Save general registers. */
5398 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005399 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005400 }
Riku Voipioc650c002014-04-23 13:53:45 +03005401 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5402 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5403 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5404 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005405
5406 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5407 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5408 }
Riku Voipioc650c002014-04-23 13:53:45 +03005409 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005410
5411 /* Save Altivec registers if necessary. */
5412 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005413 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005414 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005415 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005416 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005417
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005418 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5419 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005420 }
5421 /* Set MSR_VR in the saved MSR value to indicate that
5422 frame->mc_vregs contains valid data. */
5423 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005424#if defined(TARGET_PPC64)
5425 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5426 /* 64-bit needs to put a pointer to the vectors in the frame */
5427 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5428#else
5429 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5430#endif
5431 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5432 }
5433
5434 /* Save VSX second halves */
5435 if (env->insns_flags2 & PPC2_VSX) {
5436 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5437 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5438 __put_user(env->vsr[i], &vsregs[i]);
5439 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005440 }
5441
5442 /* Save floating point registers. */
5443 if (env->insns_flags & PPC_FLOAT) {
5444 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005445 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005446 }
Riku Voipioc650c002014-04-23 13:53:45 +03005447 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005448 }
5449
5450 /* Save SPE registers. The kernel only saves the high half. */
5451 if (env->insns_flags & PPC_SPE) {
5452#if defined(TARGET_PPC64)
5453 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005454 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005455 }
5456#else
5457 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005458 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005459 }
5460#endif
5461 /* Set MSR_SPE in the saved MSR value to indicate that
5462 frame->mc_vregs contains valid data. */
5463 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005464 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005465 }
5466
5467 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005468 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005469}
Nathan Froydbcd49332009-05-12 19:13:18 -07005470
Tom Musta76781082014-06-30 08:13:37 -05005471static void encode_trampoline(int sigret, uint32_t *tramp)
5472{
Nathan Froydbcd49332009-05-12 19:13:18 -07005473 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5474 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005475 __put_user(0x38000000 | sigret, &tramp[0]);
5476 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005477 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005478}
5479
Riku Voipioc650c002014-04-23 13:53:45 +03005480static void restore_user_regs(CPUPPCState *env,
5481 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005482{
5483 target_ulong save_r2 = 0;
5484 target_ulong msr;
5485 target_ulong ccr;
5486
5487 int i;
5488
5489 if (!sig) {
5490 save_r2 = env->gpr[2];
5491 }
5492
5493 /* Restore general registers. */
5494 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005495 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005496 }
Riku Voipioc650c002014-04-23 13:53:45 +03005497 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5498 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5499 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5500 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5501 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005502
5503 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5504 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5505 }
5506
5507 if (!sig) {
5508 env->gpr[2] = save_r2;
5509 }
5510 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005511 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005512
5513 /* If doing signal return, restore the previous little-endian mode. */
5514 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005515 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005516
5517 /* Restore Altivec registers if necessary. */
5518 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005519 ppc_avr_t *v_regs;
5520 uint32_t *vrsave;
5521#if defined(TARGET_PPC64)
5522 uint64_t v_addr;
5523 /* 64-bit needs to recover the pointer to the vectors from the frame */
5524 __get_user(v_addr, &frame->v_regs);
5525 v_regs = g2h(v_addr);
5526#else
5527 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5528#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005529 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005530 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005531 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005532
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005533 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5534 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005535 }
5536 /* Set MSR_VEC in the saved MSR value to indicate that
5537 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005538#if defined(TARGET_PPC64)
5539 vrsave = (uint32_t *)&v_regs[33];
5540#else
5541 vrsave = (uint32_t *)&v_regs[32];
5542#endif
5543 __get_user(env->spr[SPR_VRSAVE], vrsave);
5544 }
5545
5546 /* Restore VSX second halves */
5547 if (env->insns_flags2 & PPC2_VSX) {
5548 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5549 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5550 __get_user(env->vsr[i], &vsregs[i]);
5551 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005552 }
5553
5554 /* Restore floating point registers. */
5555 if (env->insns_flags & PPC_FLOAT) {
5556 uint64_t fpscr;
5557 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005558 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005559 }
Riku Voipioc650c002014-04-23 13:53:45 +03005560 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005561 env->fpscr = (uint32_t) fpscr;
5562 }
5563
5564 /* Save SPE registers. The kernel only saves the high half. */
5565 if (env->insns_flags & PPC_SPE) {
5566#if defined(TARGET_PPC64)
5567 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5568 uint32_t hi;
5569
Riku Voipioc650c002014-04-23 13:53:45 +03005570 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005571 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5572 }
5573#else
5574 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005575 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005576 }
5577#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005578 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005579 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005580}
5581
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005582#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005583static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005584 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005585{
5586 struct target_sigframe *frame;
5587 struct target_sigcontext *sc;
5588 target_ulong frame_addr, newsp;
5589 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005590
5591 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005592 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005593 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5594 goto sigsegv;
5595 sc = &frame->sctx;
5596
Riku Voipio1d8b5122014-04-23 10:26:05 +03005597 __put_user(ka->_sa_handler, &sc->handler);
5598 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005599 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005600 __put_user(h2g(&frame->mctx), &sc->regs);
5601 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005602
5603 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005604 save_user_regs(env, &frame->mctx);
5605
5606 /* Construct the trampoline code on the stack. */
5607 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005608
5609 /* The kernel checks for the presence of a VDSO here. We don't
5610 emulate a vdso, so use a sigreturn system call. */
5611 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5612
5613 /* Turn off all fp exceptions. */
5614 env->fpscr = 0;
5615
5616 /* Create a stack frame for the caller of the handler. */
5617 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005618 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005619
5620 if (err)
5621 goto sigsegv;
5622
5623 /* Set up registers for signal handler. */
5624 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005625 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005626 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005627
Nathan Froydbcd49332009-05-12 19:13:18 -07005628 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005629
Nathan Froydbcd49332009-05-12 19:13:18 -07005630 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005631 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005632
5633 unlock_user_struct(frame, frame_addr, 1);
5634 return;
5635
5636sigsegv:
5637 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005638 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005639}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005640#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005641
5642static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005643 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005644 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005645{
5646 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005647 uint32_t *trampptr = 0;
5648 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005649 target_ulong rt_sf_addr, newsp = 0;
5650 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005651#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005652 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005653 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5654#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005655
5656 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5657 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5658 goto sigsegv;
5659
Peter Maydellf6c7a052015-01-08 12:19:48 +00005660 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005661
Riku Voipio1d8b5122014-04-23 10:26:05 +03005662 __put_user(0, &rt_sf->uc.tuc_flags);
5663 __put_user(0, &rt_sf->uc.tuc_link);
5664 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5665 &rt_sf->uc.tuc_stack.ss_sp);
5666 __put_user(sas_ss_flags(env->gpr[1]),
5667 &rt_sf->uc.tuc_stack.ss_flags);
5668 __put_user(target_sigaltstack_used.ss_size,
5669 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005670#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005671 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5672 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005673#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005674 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005675 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005676 }
5677
Tom Musta61e75fe2014-06-30 08:13:38 -05005678#if defined(TARGET_PPC64)
5679 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5680 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005681
5682 sc = &rt_sf->uc.tuc_sigcontext;
5683 __put_user(h2g(mctx), &sc->regs);
5684 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005685#else
5686 mctx = &rt_sf->uc.tuc_mcontext;
5687 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5688#endif
5689
5690 save_user_regs(env, mctx);
5691 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005692
5693 /* The kernel checks for the presence of a VDSO here. We don't
5694 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005695 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005696
5697 /* Turn off all fp exceptions. */
5698 env->fpscr = 0;
5699
5700 /* Create a stack frame for the caller of the handler. */
5701 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005702 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005703
5704 if (err)
5705 goto sigsegv;
5706
5707 /* Set up registers for signal handler. */
5708 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005709 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005710 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5711 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5712 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005713
5714#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005715 if (get_ppc64_abi(image) < 2) {
5716 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5717 struct target_func_ptr *handler =
5718 (struct target_func_ptr *)g2h(ka->_sa_handler);
5719 env->nip = tswapl(handler->entry);
5720 env->gpr[2] = tswapl(handler->toc);
5721 } else {
5722 /* ELFv2 PPC64 function pointers are entry points, but R12
5723 * must also be set */
5724 env->nip = tswapl((target_ulong) ka->_sa_handler);
5725 env->gpr[12] = env->nip;
5726 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005727#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005728 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005729#endif
5730
Nathan Froydbcd49332009-05-12 19:13:18 -07005731 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005732 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005733
5734 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5735 return;
5736
5737sigsegv:
5738 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005739 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005740
5741}
5742
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005743#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005744long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005745{
5746 struct target_sigcontext *sc = NULL;
5747 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005748 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005749 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005750 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005751
5752 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5753 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5754 goto sigsegv;
5755
5756#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005757 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005758#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005759 __get_user(set.sig[0], &sc->oldmask);
5760 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005761#endif
5762 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005763 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005764
Riku Voipiof5f601a2014-04-23 13:00:17 +03005765 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005766 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5767 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005768 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005769
5770 unlock_user_struct(sr, sr_addr, 1);
5771 unlock_user_struct(sc, sc_addr, 1);
5772 return -TARGET_QEMU_ESIGRETURN;
5773
5774sigsegv:
5775 unlock_user_struct(sr, sr_addr, 1);
5776 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005777 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005778 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005779}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005780#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005781
5782/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005783static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005784{
5785 struct target_mcontext *mcp;
5786 target_ulong mcp_addr;
5787 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005788 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005789
Aurelien Jarno60e99242010-03-29 02:12:51 +02005790 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005791 sizeof (set)))
5792 return 1;
5793
Tom Musta19774ec2014-06-30 08:13:40 -05005794#if defined(TARGET_PPC64)
5795 mcp_addr = h2g(ucp) +
5796 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5797#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005798 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005799#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005800
5801 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5802 return 1;
5803
5804 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005805 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005806 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005807
5808 unlock_user_struct(mcp, mcp_addr, 1);
5809 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005810}
5811
Andreas Färber05390242012-02-25 03:37:53 +01005812long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005813{
5814 struct target_rt_sigframe *rt_sf = NULL;
5815 target_ulong rt_sf_addr;
5816
5817 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5818 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5819 goto sigsegv;
5820
5821 if (do_setcontext(&rt_sf->uc, env, 1))
5822 goto sigsegv;
5823
5824 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005825 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005826 0, env->gpr[1]);
5827
5828 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5829 return -TARGET_QEMU_ESIGRETURN;
5830
5831sigsegv:
5832 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005833 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005834 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005835}
5836
Laurent Vivier492a8742009-08-03 16:12:17 +02005837#elif defined(TARGET_M68K)
5838
5839struct target_sigcontext {
5840 abi_ulong sc_mask;
5841 abi_ulong sc_usp;
5842 abi_ulong sc_d0;
5843 abi_ulong sc_d1;
5844 abi_ulong sc_a0;
5845 abi_ulong sc_a1;
5846 unsigned short sc_sr;
5847 abi_ulong sc_pc;
5848};
5849
5850struct target_sigframe
5851{
5852 abi_ulong pretcode;
5853 int sig;
5854 int code;
5855 abi_ulong psc;
5856 char retcode[8];
5857 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5858 struct target_sigcontext sc;
5859};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005860
Anthony Liguoric227f092009-10-01 16:12:16 -05005861typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005862#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005863typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005864
5865typedef struct target_fpregset {
5866 int f_fpcntl[3];
5867 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005868} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005869
5870struct target_mcontext {
5871 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005872 target_gregset_t gregs;
5873 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005874};
5875
5876#define TARGET_MCONTEXT_VERSION 2
5877
5878struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005879 abi_ulong tuc_flags;
5880 abi_ulong tuc_link;
5881 target_stack_t tuc_stack;
5882 struct target_mcontext tuc_mcontext;
5883 abi_long tuc_filler[80];
5884 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005885};
5886
5887struct target_rt_sigframe
5888{
5889 abi_ulong pretcode;
5890 int sig;
5891 abi_ulong pinfo;
5892 abi_ulong puc;
5893 char retcode[8];
5894 struct target_siginfo info;
5895 struct target_ucontext uc;
5896};
Laurent Vivier492a8742009-08-03 16:12:17 +02005897
Riku Voipio41ecc722014-04-23 11:01:00 +03005898static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005899 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005900{
Laurent Vivieref597602018-01-04 02:28:59 +01005901 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005902 __put_user(mask, &sc->sc_mask);
5903 __put_user(env->aregs[7], &sc->sc_usp);
5904 __put_user(env->dregs[0], &sc->sc_d0);
5905 __put_user(env->dregs[1], &sc->sc_d1);
5906 __put_user(env->aregs[0], &sc->sc_a0);
5907 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005908 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005909 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005910}
5911
Riku Voipio016d2e12014-04-23 11:19:48 +03005912static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005913restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005914{
Laurent Vivier492a8742009-08-03 16:12:17 +02005915 int temp;
5916
Riku Voipio1d8b5122014-04-23 10:26:05 +03005917 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005918 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005919 __get_user(env->dregs[1], &sc->sc_d1);
5920 __get_user(env->aregs[0], &sc->sc_a0);
5921 __get_user(env->aregs[1], &sc->sc_a1);
5922 __get_user(env->pc, &sc->sc_pc);
5923 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005924 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005925}
5926
5927/*
5928 * Determine which stack to use..
5929 */
5930static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005931get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5932 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005933{
5934 unsigned long sp;
5935
5936 sp = regs->aregs[7];
5937
5938 /* This is the X/Open sanctioned signal stack switching. */
5939 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5940 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5941 }
5942
5943 return ((sp - frame_size) & -8UL);
5944}
5945
5946static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005947 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005948{
5949 struct target_sigframe *frame;
5950 abi_ulong frame_addr;
5951 abi_ulong retcode_addr;
5952 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005953 int i;
5954
5955 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005956 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005957 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5958 goto give_sigsegv;
5959 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005960
Riku Voipio1d8b5122014-04-23 10:26:05 +03005961 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005962
5963 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005964 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005965
Riku Voipio41ecc722014-04-23 11:01:00 +03005966 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005967
5968 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005969 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005970 }
5971
5972 /* Set up to return from userspace. */
5973
5974 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005975 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005976
5977 /* moveq #,d0; trap #0 */
5978
Riku Voipio1d8b5122014-04-23 10:26:05 +03005979 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005980 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005981
Laurent Vivier492a8742009-08-03 16:12:17 +02005982 /* Set up to return from userspace */
5983
5984 env->aregs[7] = frame_addr;
5985 env->pc = ka->_sa_handler;
5986
5987 unlock_user_struct(frame, frame_addr, 1);
5988 return;
5989
5990give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005991 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005992}
5993
Laurent Vivieree46a462017-09-14 18:35:05 +02005994static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5995 CPUM68KState *env)
5996{
5997 int i;
5998 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5999
6000 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
6001 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
6002 /* fpiar is not emulated */
6003
6004 for (i = 0; i < 8; i++) {
6005 uint32_t high = env->fregs[i].d.high << 16;
6006 __put_user(high, &fpregs->f_fpregs[i * 3]);
6007 __put_user(env->fregs[i].d.low,
6008 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6009 }
6010}
6011
Laurent Vivier71811552009-08-03 16:12:18 +02006012static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01006013 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02006014{
Aurelien Jarno60e99242010-03-29 02:12:51 +02006015 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01006016 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02006017
Riku Voipio1d8b5122014-04-23 10:26:05 +03006018 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
6019 __put_user(env->dregs[0], &gregs[0]);
6020 __put_user(env->dregs[1], &gregs[1]);
6021 __put_user(env->dregs[2], &gregs[2]);
6022 __put_user(env->dregs[3], &gregs[3]);
6023 __put_user(env->dregs[4], &gregs[4]);
6024 __put_user(env->dregs[5], &gregs[5]);
6025 __put_user(env->dregs[6], &gregs[6]);
6026 __put_user(env->dregs[7], &gregs[7]);
6027 __put_user(env->aregs[0], &gregs[8]);
6028 __put_user(env->aregs[1], &gregs[9]);
6029 __put_user(env->aregs[2], &gregs[10]);
6030 __put_user(env->aregs[3], &gregs[11]);
6031 __put_user(env->aregs[4], &gregs[12]);
6032 __put_user(env->aregs[5], &gregs[13]);
6033 __put_user(env->aregs[6], &gregs[14]);
6034 __put_user(env->aregs[7], &gregs[15]);
6035 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006036 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02006037
Laurent Vivieree46a462017-09-14 18:35:05 +02006038 target_rt_save_fpu_state(uc, env);
6039
Riku Voipio1d8b5122014-04-23 10:26:05 +03006040 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006041}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006042
Laurent Vivieree46a462017-09-14 18:35:05 +02006043static inline void target_rt_restore_fpu_state(CPUM68KState *env,
6044 struct target_ucontext *uc)
6045{
6046 int i;
6047 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
6048 uint32_t fpcr;
6049
6050 __get_user(fpcr, &fpregs->f_fpcntl[0]);
6051 cpu_m68k_set_fpcr(env, fpcr);
6052 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
6053 /* fpiar is not emulated */
6054
6055 for (i = 0; i < 8; i++) {
6056 uint32_t high;
6057 __get_user(high, &fpregs->f_fpregs[i * 3]);
6058 env->fregs[i].d.high = high >> 16;
6059 __get_user(env->fregs[i].d.low,
6060 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
6061 }
6062}
6063
Andreas Färber05390242012-02-25 03:37:53 +01006064static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006065 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02006066{
6067 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02006068 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02006069
Riku Voipio1d8b5122014-04-23 10:26:05 +03006070 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02006071 if (temp != TARGET_MCONTEXT_VERSION)
6072 goto badframe;
6073
6074 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03006075 __get_user(env->dregs[0], &gregs[0]);
6076 __get_user(env->dregs[1], &gregs[1]);
6077 __get_user(env->dregs[2], &gregs[2]);
6078 __get_user(env->dregs[3], &gregs[3]);
6079 __get_user(env->dregs[4], &gregs[4]);
6080 __get_user(env->dregs[5], &gregs[5]);
6081 __get_user(env->dregs[6], &gregs[6]);
6082 __get_user(env->dregs[7], &gregs[7]);
6083 __get_user(env->aregs[0], &gregs[8]);
6084 __get_user(env->aregs[1], &gregs[9]);
6085 __get_user(env->aregs[2], &gregs[10]);
6086 __get_user(env->aregs[3], &gregs[11]);
6087 __get_user(env->aregs[4], &gregs[12]);
6088 __get_user(env->aregs[5], &gregs[13]);
6089 __get_user(env->aregs[6], &gregs[14]);
6090 __get_user(env->aregs[7], &gregs[15]);
6091 __get_user(env->pc, &gregs[16]);
6092 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01006093 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02006094
Laurent Vivieree46a462017-09-14 18:35:05 +02006095 target_rt_restore_fpu_state(env, uc);
6096
Riku Voipio1d8b5122014-04-23 10:26:05 +03006097 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02006098
6099badframe:
6100 return 1;
6101}
6102
Laurent Vivier492a8742009-08-03 16:12:17 +02006103static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006104 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006105 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006106{
Laurent Vivier71811552009-08-03 16:12:18 +02006107 struct target_rt_sigframe *frame;
6108 abi_ulong frame_addr;
6109 abi_ulong retcode_addr;
6110 abi_ulong info_addr;
6111 abi_ulong uc_addr;
6112 int err = 0;
6113 int i;
6114
6115 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006116 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006117 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6118 goto give_sigsegv;
6119 }
Laurent Vivier71811552009-08-03 16:12:18 +02006120
Riku Voipio1d8b5122014-04-23 10:26:05 +03006121 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02006122
6123 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006124 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02006125
6126 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006127 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02006128
Peter Maydellf6c7a052015-01-08 12:19:48 +00006129 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02006130
6131 /* Create the ucontext */
6132
Riku Voipio1d8b5122014-04-23 10:26:05 +03006133 __put_user(0, &frame->uc.tuc_flags);
6134 __put_user(0, &frame->uc.tuc_link);
6135 __put_user(target_sigaltstack_used.ss_sp,
6136 &frame->uc.tuc_stack.ss_sp);
6137 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006138 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006139 __put_user(target_sigaltstack_used.ss_size,
6140 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02006141 err |= target_rt_setup_ucontext(&frame->uc, env);
6142
6143 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006144 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02006145
6146 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03006147 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02006148 }
6149
6150 /* Set up to return from userspace. */
6151
6152 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03006153 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02006154
6155 /* moveq #,d0; notb d0; trap #0 */
6156
Riku Voipio1d8b5122014-04-23 10:26:05 +03006157 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00006158 (uint32_t *)(frame->retcode + 0));
6159 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02006160
6161 if (err)
6162 goto give_sigsegv;
6163
6164 /* Set up to return from userspace */
6165
6166 env->aregs[7] = frame_addr;
6167 env->pc = ka->_sa_handler;
6168
6169 unlock_user_struct(frame, frame_addr, 1);
6170 return;
6171
6172give_sigsegv:
6173 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006174 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006175}
6176
Andreas Färber05390242012-02-25 03:37:53 +01006177long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006178{
6179 struct target_sigframe *frame;
6180 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006181 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006182 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006183 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006184
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006185 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006186 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6187 goto badframe;
6188
6189 /* set blocked signals */
6190
Riku Voipiof5f601a2014-04-23 13:00:17 +03006191 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006192
6193 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006194 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006195 }
6196
6197 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006198 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006199
6200 /* restore registers */
6201
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006202 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006203
6204 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006205 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006206
6207badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006208 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006209 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006210}
6211
Andreas Färber05390242012-02-25 03:37:53 +01006212long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006213{
Laurent Vivier71811552009-08-03 16:12:18 +02006214 struct target_rt_sigframe *frame;
6215 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006216 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006217
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006218 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006219 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6220 goto badframe;
6221
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006222 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006223 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006224
6225 /* restore registers */
6226
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006227 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006228 goto badframe;
6229
6230 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006231 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006232 0, get_sp_from_cpustate(env)) == -EFAULT)
6233 goto badframe;
6234
6235 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006236 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006237
6238badframe:
6239 unlock_user_struct(frame, frame_addr, 0);
6240 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006241 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006242}
6243
Richard Henderson6049f4f2009-12-27 18:30:03 -08006244#elif defined(TARGET_ALPHA)
6245
6246struct target_sigcontext {
6247 abi_long sc_onstack;
6248 abi_long sc_mask;
6249 abi_long sc_pc;
6250 abi_long sc_ps;
6251 abi_long sc_regs[32];
6252 abi_long sc_ownedfp;
6253 abi_long sc_fpregs[32];
6254 abi_ulong sc_fpcr;
6255 abi_ulong sc_fp_control;
6256 abi_ulong sc_reserved1;
6257 abi_ulong sc_reserved2;
6258 abi_ulong sc_ssize;
6259 abi_ulong sc_sbase;
6260 abi_ulong sc_traparg_a0;
6261 abi_ulong sc_traparg_a1;
6262 abi_ulong sc_traparg_a2;
6263 abi_ulong sc_fp_trap_pc;
6264 abi_ulong sc_fp_trigger_sum;
6265 abi_ulong sc_fp_trigger_inst;
6266};
6267
6268struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006269 abi_ulong tuc_flags;
6270 abi_ulong tuc_link;
6271 abi_ulong tuc_osf_sigmask;
6272 target_stack_t tuc_stack;
6273 struct target_sigcontext tuc_mcontext;
6274 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006275};
6276
6277struct target_sigframe {
6278 struct target_sigcontext sc;
6279 unsigned int retcode[3];
6280};
6281
6282struct target_rt_sigframe {
6283 target_siginfo_t info;
6284 struct target_ucontext uc;
6285 unsigned int retcode[3];
6286};
6287
6288#define INSN_MOV_R30_R16 0x47fe0410
6289#define INSN_LDI_R0 0x201f0000
6290#define INSN_CALLSYS 0x00000083
6291
Riku Voipio41ecc722014-04-23 11:01:00 +03006292static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006293 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006294{
Riku Voipio41ecc722014-04-23 11:01:00 +03006295 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006296
Riku Voipio1d8b5122014-04-23 10:26:05 +03006297 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6298 __put_user(set->sig[0], &sc->sc_mask);
6299 __put_user(env->pc, &sc->sc_pc);
6300 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006301
6302 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006303 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006304 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006305 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006306
6307 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006308 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006309 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006310 __put_user(0, &sc->sc_fpregs[31]);
6311 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006312
Riku Voipio1d8b5122014-04-23 10:26:05 +03006313 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6314 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6315 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006316}
6317
Riku Voipio016d2e12014-04-23 11:19:48 +03006318static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006319 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006320{
6321 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006322 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006323
Riku Voipio1d8b5122014-04-23 10:26:05 +03006324 __get_user(env->pc, &sc->sc_pc);
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->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006328 }
6329 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006330 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006331 }
6332
Riku Voipio1d8b5122014-04-23 10:26:05 +03006333 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006334 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006335}
6336
6337static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006338 CPUAlphaState *env,
6339 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006340{
6341 abi_ulong sp = env->ir[IR_SP];
6342
6343 /* This is the X/Open sanctioned signal stack switching. */
6344 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6345 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6346 }
6347 return (sp - framesize) & -32;
6348}
6349
6350static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006351 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006352{
6353 abi_ulong frame_addr, r26;
6354 struct target_sigframe *frame;
6355 int err = 0;
6356
6357 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006358 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006359 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6360 goto give_sigsegv;
6361 }
6362
Riku Voipio41ecc722014-04-23 11:01:00 +03006363 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006364
6365 if (ka->sa_restorer) {
6366 r26 = ka->sa_restorer;
6367 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006368 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6369 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6370 &frame->retcode[1]);
6371 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006372 /* imb() */
6373 r26 = frame_addr;
6374 }
6375
6376 unlock_user_struct(frame, frame_addr, 1);
6377
6378 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006379give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006380 force_sigsegv(sig);
6381 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006382 }
6383
6384 env->ir[IR_RA] = r26;
6385 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6386 env->ir[IR_A0] = sig;
6387 env->ir[IR_A1] = 0;
6388 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6389 env->ir[IR_SP] = frame_addr;
6390}
6391
6392static void setup_rt_frame(int sig, struct target_sigaction *ka,
6393 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006394 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006395{
6396 abi_ulong frame_addr, r26;
6397 struct target_rt_sigframe *frame;
6398 int i, err = 0;
6399
6400 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006401 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006402 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6403 goto give_sigsegv;
6404 }
6405
Peter Maydellf6c7a052015-01-08 12:19:48 +00006406 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006407
Riku Voipio1d8b5122014-04-23 10:26:05 +03006408 __put_user(0, &frame->uc.tuc_flags);
6409 __put_user(0, &frame->uc.tuc_link);
6410 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6411 __put_user(target_sigaltstack_used.ss_sp,
6412 &frame->uc.tuc_stack.ss_sp);
6413 __put_user(sas_ss_flags(env->ir[IR_SP]),
6414 &frame->uc.tuc_stack.ss_flags);
6415 __put_user(target_sigaltstack_used.ss_size,
6416 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006417 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006418 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006419 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006420 }
6421
6422 if (ka->sa_restorer) {
6423 r26 = ka->sa_restorer;
6424 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006425 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6426 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6427 &frame->retcode[1]);
6428 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006429 /* imb(); */
6430 r26 = frame_addr;
6431 }
6432
6433 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006434give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006435 force_sigsegv(sig);
6436 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006437 }
6438
6439 env->ir[IR_RA] = r26;
6440 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6441 env->ir[IR_A0] = sig;
6442 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6443 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6444 env->ir[IR_SP] = frame_addr;
6445}
6446
Andreas Färber05390242012-02-25 03:37:53 +01006447long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006448{
6449 struct target_sigcontext *sc;
6450 abi_ulong sc_addr = env->ir[IR_A0];
6451 target_sigset_t target_set;
6452 sigset_t set;
6453
6454 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6455 goto badframe;
6456 }
6457
6458 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006459 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006460
6461 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006462 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006463
Riku Voipio016d2e12014-04-23 11:19:48 +03006464 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006465 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006466 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006467
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006468badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006469 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006470 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006471}
6472
Andreas Färber05390242012-02-25 03:37:53 +01006473long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006474{
6475 abi_ulong frame_addr = env->ir[IR_A0];
6476 struct target_rt_sigframe *frame;
6477 sigset_t set;
6478
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006479 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006480 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6481 goto badframe;
6482 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006483 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006484 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006485
Riku Voipio016d2e12014-04-23 11:19:48 +03006486 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006487 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006488 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006489 0, env->ir[IR_SP]) == -EFAULT) {
6490 goto badframe;
6491 }
6492
6493 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006494 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006495
6496
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006497badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006498 unlock_user_struct(frame, frame_addr, 0);
6499 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006500 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006501}
6502
Chen Gangbf0f60a2015-09-27 08:10:18 +08006503#elif defined(TARGET_TILEGX)
6504
6505struct target_sigcontext {
6506 union {
6507 /* General-purpose registers. */
6508 abi_ulong gregs[56];
6509 struct {
6510 abi_ulong __gregs[53];
6511 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6512 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6513 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6514 };
6515 };
6516 abi_ulong pc; /* Program counter. */
6517 abi_ulong ics; /* In Interrupt Critical Section? */
6518 abi_ulong faultnum; /* Fault number. */
6519 abi_ulong pad[5];
6520};
6521
6522struct target_ucontext {
6523 abi_ulong tuc_flags;
6524 abi_ulong tuc_link;
6525 target_stack_t tuc_stack;
6526 struct target_sigcontext tuc_mcontext;
6527 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6528};
6529
6530struct target_rt_sigframe {
6531 unsigned char save_area[16]; /* caller save area */
6532 struct target_siginfo info;
6533 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006534 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006535};
6536
Chen Gangf1d9d102016-03-29 21:53:49 +08006537#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6538#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6539
6540
Chen Gangbf0f60a2015-09-27 08:10:18 +08006541static void setup_sigcontext(struct target_sigcontext *sc,
6542 CPUArchState *env, int signo)
6543{
6544 int i;
6545
6546 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6547 __put_user(env->regs[i], &sc->gregs[i]);
6548 }
6549
6550 __put_user(env->pc, &sc->pc);
6551 __put_user(0, &sc->ics);
6552 __put_user(signo, &sc->faultnum);
6553}
6554
6555static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6556{
6557 int i;
6558
6559 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6560 __get_user(env->regs[i], &sc->gregs[i]);
6561 }
6562
6563 __get_user(env->pc, &sc->pc);
6564}
6565
6566static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6567 size_t frame_size)
6568{
6569 unsigned long sp = env->regs[TILEGX_R_SP];
6570
6571 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6572 return -1UL;
6573 }
6574
6575 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6576 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6577 }
6578
6579 sp -= frame_size;
6580 sp &= -16UL;
6581 return sp;
6582}
6583
6584static void setup_rt_frame(int sig, struct target_sigaction *ka,
6585 target_siginfo_t *info,
6586 target_sigset_t *set, CPUArchState *env)
6587{
6588 abi_ulong frame_addr;
6589 struct target_rt_sigframe *frame;
6590 unsigned long restorer;
6591
6592 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006593 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006594 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6595 goto give_sigsegv;
6596 }
6597
6598 /* Always write at least the signal number for the stack backtracer. */
6599 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6600 /* At sigreturn time, restore the callee-save registers too. */
6601 tswap_siginfo(&frame->info, info);
6602 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6603 } else {
6604 __put_user(info->si_signo, &frame->info.si_signo);
6605 }
6606
6607 /* Create the ucontext. */
6608 __put_user(0, &frame->uc.tuc_flags);
6609 __put_user(0, &frame->uc.tuc_link);
6610 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6611 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6612 &frame->uc.tuc_stack.ss_flags);
6613 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6614 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6615
Chen Gangbf0f60a2015-09-27 08:10:18 +08006616 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006617 restorer = (unsigned long) ka->sa_restorer;
6618 } else {
6619 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6620 __put_user(INSN_SWINT1, &frame->retcode[1]);
6621 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006622 }
6623 env->pc = (unsigned long) ka->_sa_handler;
6624 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6625 env->regs[TILEGX_R_LR] = restorer;
6626 env->regs[0] = (unsigned long) sig;
6627 env->regs[1] = (unsigned long) &frame->info;
6628 env->regs[2] = (unsigned long) &frame->uc;
6629 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6630
6631 unlock_user_struct(frame, frame_addr, 1);
6632 return;
6633
6634give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006635 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006636}
6637
6638long do_rt_sigreturn(CPUTLGState *env)
6639{
6640 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6641 struct target_rt_sigframe *frame;
6642 sigset_t set;
6643
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006644 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006645 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6646 goto badframe;
6647 }
6648 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006649 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006650
6651 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6652 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6653 uc.tuc_stack),
6654 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6655 goto badframe;
6656 }
6657
6658 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006659 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006660
6661
6662 badframe:
6663 unlock_user_struct(frame, frame_addr, 0);
6664 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006665 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006666}
6667
Michael Clark47ae93c2018-03-03 01:31:11 +13006668#elif defined(TARGET_RISCV)
6669
6670/* Signal handler invocation must be transparent for the code being
6671 interrupted. Complete CPU (hart) state is saved on entry and restored
6672 before returning from the handler. Process sigmask is also saved to block
6673 signals while the handler is running. The handler gets its own stack,
6674 which also doubles as storage for the CPU state and sigmask.
6675
6676 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6677
6678struct target_sigcontext {
6679 abi_long pc;
6680 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6681 uint64_t fpr[32];
6682 uint32_t fcsr;
6683}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6684
6685struct target_ucontext {
6686 unsigned long uc_flags;
6687 struct target_ucontext *uc_link;
6688 target_stack_t uc_stack;
6689 struct target_sigcontext uc_mcontext;
6690 target_sigset_t uc_sigmask;
6691};
6692
6693struct target_rt_sigframe {
6694 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6695 struct target_siginfo info;
6696 struct target_ucontext uc;
6697};
6698
6699static abi_ulong get_sigframe(struct target_sigaction *ka,
6700 CPURISCVState *regs, size_t framesize)
6701{
6702 abi_ulong sp = regs->gpr[xSP];
6703 int onsigstack = on_sig_stack(sp);
6704
6705 /* redzone */
6706 /* This is the X/Open sanctioned signal stack switching. */
6707 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6708 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6709 }
6710
6711 sp -= framesize;
6712 sp &= ~3UL; /* align sp on 4-byte boundary */
6713
6714 /* If we are on the alternate signal stack and would overflow it, don't.
6715 Return an always-bogus address instead so we will die with SIGSEGV. */
6716 if (onsigstack && !likely(on_sig_stack(sp))) {
6717 return -1L;
6718 }
6719
6720 return sp;
6721}
6722
6723static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6724{
6725 int i;
6726
6727 __put_user(env->pc, &sc->pc);
6728
6729 for (i = 1; i < 32; i++) {
6730 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6731 }
6732 for (i = 0; i < 32; i++) {
6733 __put_user(env->fpr[i], &sc->fpr[i]);
6734 }
6735
6736 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6737 __put_user(fcsr, &sc->fcsr);
6738}
6739
6740static void setup_ucontext(struct target_ucontext *uc,
6741 CPURISCVState *env, target_sigset_t *set)
6742{
6743 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6744 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6745 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6746
6747 __put_user(0, &(uc->uc_flags));
6748 __put_user(0, &(uc->uc_link));
6749
6750 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6751 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6752 __put_user(ss_size, &(uc->uc_stack.ss_size));
6753
6754 int i;
6755 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6756 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6757 }
6758
6759 setup_sigcontext(&uc->uc_mcontext, env);
6760}
6761
6762static inline void install_sigtramp(uint32_t *tramp)
6763{
6764 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6765 __put_user(0x00000073, tramp + 1); /* ecall */
6766}
6767
6768static void setup_rt_frame(int sig, struct target_sigaction *ka,
6769 target_siginfo_t *info,
6770 target_sigset_t *set, CPURISCVState *env)
6771{
6772 abi_ulong frame_addr;
6773 struct target_rt_sigframe *frame;
6774
6775 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6776 trace_user_setup_rt_frame(env, frame_addr);
6777
6778 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6779 goto badframe;
6780 }
6781
6782 setup_ucontext(&frame->uc, env, set);
6783 tswap_siginfo(&frame->info, info);
6784 install_sigtramp(frame->tramp);
6785
6786 env->pc = ka->_sa_handler;
6787 env->gpr[xSP] = frame_addr;
6788 env->gpr[xA0] = sig;
6789 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6790 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6791 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6792
6793 return;
6794
6795badframe:
6796 unlock_user_struct(frame, frame_addr, 1);
6797 if (sig == TARGET_SIGSEGV) {
6798 ka->_sa_handler = TARGET_SIG_DFL;
6799 }
6800 force_sig(TARGET_SIGSEGV);
6801}
6802
6803static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6804{
6805 int i;
6806
6807 __get_user(env->pc, &sc->pc);
6808
6809 for (i = 1; i < 32; ++i) {
6810 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6811 }
6812 for (i = 0; i < 32; ++i) {
6813 __get_user(env->fpr[i], &sc->fpr[i]);
6814 }
6815
6816 uint32_t fcsr;
6817 __get_user(fcsr, &sc->fcsr);
6818 csr_write_helper(env, fcsr, CSR_FCSR);
6819}
6820
6821static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6822{
6823 sigset_t blocked;
6824 target_sigset_t target_set;
6825 int i;
6826
6827 target_sigemptyset(&target_set);
6828 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6829 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6830 }
6831
6832 target_to_host_sigset_internal(&blocked, &target_set);
6833 set_sigmask(&blocked);
6834
6835 restore_sigcontext(env, &uc->uc_mcontext);
6836}
6837
6838long do_rt_sigreturn(CPURISCVState *env)
6839{
6840 struct target_rt_sigframe *frame;
6841 abi_ulong frame_addr;
6842
6843 frame_addr = env->gpr[xSP];
6844 trace_user_do_sigreturn(env, frame_addr);
6845 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6846 goto badframe;
6847 }
6848
6849 restore_ucontext(env, &frame->uc);
6850
6851 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6852 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6853 goto badframe;
6854 }
6855
6856 unlock_user_struct(frame, frame_addr, 0);
6857 return -TARGET_QEMU_ESIGRETURN;
6858
6859badframe:
6860 unlock_user_struct(frame, frame_addr, 0);
6861 force_sig(TARGET_SIGSEGV);
6862 return 0;
6863}
6864
Richard Henderson1659e382016-12-15 09:59:01 -08006865#elif defined(TARGET_HPPA)
6866
6867struct target_sigcontext {
6868 abi_ulong sc_flags;
6869 abi_ulong sc_gr[32];
6870 uint64_t sc_fr[32];
6871 abi_ulong sc_iasq[2];
6872 abi_ulong sc_iaoq[2];
6873 abi_ulong sc_sar;
6874};
6875
6876struct target_ucontext {
6877 abi_uint tuc_flags;
6878 abi_ulong tuc_link;
6879 target_stack_t tuc_stack;
6880 abi_uint pad[1];
6881 struct target_sigcontext tuc_mcontext;
6882 target_sigset_t tuc_sigmask;
6883};
6884
6885struct target_rt_sigframe {
6886 abi_uint tramp[9];
6887 target_siginfo_t info;
6888 struct target_ucontext uc;
6889 /* hidden location of upper halves of pa2.0 64-bit gregs */
6890};
6891
6892static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6893{
6894 int flags = 0;
6895 int i;
6896
6897 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6898
6899 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6900 /* In the gateway page, executing a syscall. */
6901 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6902 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6903 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6904 } else {
6905 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6906 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6907 }
6908 __put_user(0, &sc->sc_iasq[0]);
6909 __put_user(0, &sc->sc_iasq[1]);
6910 __put_user(flags, &sc->sc_flags);
6911
6912 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6913 for (i = 1; i < 32; ++i) {
6914 __put_user(env->gr[i], &sc->sc_gr[i]);
6915 }
6916
6917 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6918 for (i = 1; i < 32; ++i) {
6919 __put_user(env->fr[i], &sc->sc_fr[i]);
6920 }
6921
Richard Henderson35136a72017-10-10 21:19:34 -07006922 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006923}
6924
6925static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6926{
6927 target_ulong psw;
6928 int i;
6929
6930 __get_user(psw, &sc->sc_gr[0]);
6931 cpu_hppa_put_psw(env, psw);
6932
6933 for (i = 1; i < 32; ++i) {
6934 __get_user(env->gr[i], &sc->sc_gr[i]);
6935 }
6936 for (i = 0; i < 32; ++i) {
6937 __get_user(env->fr[i], &sc->sc_fr[i]);
6938 }
6939 cpu_hppa_loaded_fr0(env);
6940
6941 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6942 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006943 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006944}
6945
6946/* No, this doesn't look right, but it's copied straight from the kernel. */
6947#define PARISC_RT_SIGFRAME_SIZE32 \
6948 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6949
6950static void setup_rt_frame(int sig, struct target_sigaction *ka,
6951 target_siginfo_t *info,
6952 target_sigset_t *set, CPUArchState *env)
6953{
6954 abi_ulong frame_addr, sp, haddr;
6955 struct target_rt_sigframe *frame;
6956 int i;
6957
6958 sp = env->gr[30];
6959 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6960 if (sas_ss_flags(sp) == 0) {
6961 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6962 }
6963 }
6964 frame_addr = QEMU_ALIGN_UP(sp, 64);
6965 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6966
6967 trace_user_setup_rt_frame(env, frame_addr);
6968
6969 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6970 goto give_sigsegv;
6971 }
6972
6973 tswap_siginfo(&frame->info, info);
6974 frame->uc.tuc_flags = 0;
6975 frame->uc.tuc_link = 0;
6976
6977 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6978 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6979 &frame->uc.tuc_stack.ss_flags);
6980 __put_user(target_sigaltstack_used.ss_size,
6981 &frame->uc.tuc_stack.ss_size);
6982
6983 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6984 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6985 }
6986
6987 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6988
6989 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6990 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6991 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6992 __put_user(0x08000240, frame->tramp + 3); /* nop */
6993
6994 unlock_user_struct(frame, frame_addr, 1);
6995
6996 env->gr[2] = h2g(frame->tramp);
6997 env->gr[30] = sp;
6998 env->gr[26] = sig;
6999 env->gr[25] = h2g(&frame->info);
7000 env->gr[24] = h2g(&frame->uc);
7001
7002 haddr = ka->_sa_handler;
7003 if (haddr & 2) {
7004 /* Function descriptor. */
7005 target_ulong *fdesc, dest;
7006
7007 haddr &= -4;
7008 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
7009 goto give_sigsegv;
7010 }
7011 __get_user(dest, fdesc);
7012 __get_user(env->gr[19], fdesc + 1);
7013 unlock_user_struct(fdesc, haddr, 1);
7014 haddr = dest;
7015 }
7016 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02007017 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08007018 return;
7019
7020 give_sigsegv:
7021 force_sigsegv(sig);
7022}
7023
7024long do_rt_sigreturn(CPUArchState *env)
7025{
7026 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
7027 struct target_rt_sigframe *frame;
7028 sigset_t set;
7029
7030 trace_user_do_rt_sigreturn(env, frame_addr);
7031 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7032 goto badframe;
7033 }
7034 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7035 set_sigmask(&set);
7036
7037 restore_sigcontext(env, &frame->uc.tuc_mcontext);
7038 unlock_user_struct(frame, frame_addr, 0);
7039
7040 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
7041 uc.tuc_stack),
7042 0, env->gr[30]) == -EFAULT) {
7043 goto badframe;
7044 }
7045
7046 unlock_user_struct(frame, frame_addr, 0);
7047 return -TARGET_QEMU_ESIGRETURN;
7048
7049 badframe:
7050 force_sig(TARGET_SIGSEGV);
7051 return -TARGET_QEMU_ESIGRETURN;
7052}
7053
Max Filippovba7651f2017-01-25 10:54:11 -08007054#elif defined(TARGET_XTENSA)
7055
7056struct target_sigcontext {
7057 abi_ulong sc_pc;
7058 abi_ulong sc_ps;
7059 abi_ulong sc_lbeg;
7060 abi_ulong sc_lend;
7061 abi_ulong sc_lcount;
7062 abi_ulong sc_sar;
7063 abi_ulong sc_acclo;
7064 abi_ulong sc_acchi;
7065 abi_ulong sc_a[16];
7066 abi_ulong sc_xtregs;
7067};
7068
7069struct target_ucontext {
7070 abi_ulong tuc_flags;
7071 abi_ulong tuc_link;
7072 target_stack_t tuc_stack;
7073 struct target_sigcontext tuc_mcontext;
7074 target_sigset_t tuc_sigmask;
7075};
7076
7077struct target_rt_sigframe {
7078 target_siginfo_t info;
7079 struct target_ucontext uc;
7080 /* TODO: xtregs */
7081 uint8_t retcode[6];
7082 abi_ulong window[4];
7083};
7084
7085static abi_ulong get_sigframe(struct target_sigaction *sa,
7086 CPUXtensaState *env,
7087 unsigned long framesize)
7088{
7089 abi_ulong sp = env->regs[1];
7090
7091 /* This is the X/Open sanctioned signal stack switching. */
7092 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
7093 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
7094 }
7095 return (sp - framesize) & -16;
7096}
7097
7098static int flush_window_regs(CPUXtensaState *env)
7099{
7100 const uint32_t nareg_mask = env->config->nareg - 1;
7101 uint32_t wb = env->sregs[WINDOW_BASE];
7102 uint32_t ws = (xtensa_replicate_windowstart(env) >> (wb + 1)) &
7103 ((1 << env->config->nareg / 4) - 1);
7104 uint32_t d = ctz32(ws) + 1;
7105 uint32_t sp;
7106 abi_long ret = 0;
7107
7108 wb += d;
7109 ws >>= d;
7110
7111 xtensa_sync_phys_from_window(env);
7112 sp = env->phys_regs[(wb * 4 + 1) & nareg_mask];
7113
7114 while (ws && ret == 0) {
7115 int d;
7116 int i;
7117 int idx;
7118
7119 if (ws & 0x1) {
7120 ws >>= 1;
7121 d = 1;
7122 } else if (ws & 0x2) {
7123 ws >>= 2;
7124 d = 2;
7125 for (i = 0; i < 4; ++i) {
7126 idx = (wb * 4 + 4 + i) & nareg_mask;
7127 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 12) * 4);
7128 }
7129 } else if (ws & 0x4) {
7130 ws >>= 3;
7131 d = 3;
7132 for (i = 0; i < 8; ++i) {
7133 idx = (wb * 4 + 4 + i) & nareg_mask;
7134 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 16) * 4);
7135 }
7136 } else {
7137 g_assert_not_reached();
7138 }
7139 sp = env->phys_regs[((wb + d) * 4 + 1) & nareg_mask];
7140 for (i = 0; i < 4; ++i) {
7141 idx = (wb * 4 + i) & nareg_mask;
7142 ret |= put_user_ual(env->phys_regs[idx], sp + (i - 4) * 4);
7143 }
7144 wb += d;
7145 }
7146 return ret == 0;
7147}
7148
7149static int setup_sigcontext(struct target_rt_sigframe *frame,
7150 CPUXtensaState *env)
7151{
7152 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7153 int i;
7154
7155 __put_user(env->pc, &sc->sc_pc);
7156 __put_user(env->sregs[PS], &sc->sc_ps);
7157 __put_user(env->sregs[LBEG], &sc->sc_lbeg);
7158 __put_user(env->sregs[LEND], &sc->sc_lend);
7159 __put_user(env->sregs[LCOUNT], &sc->sc_lcount);
7160 if (!flush_window_regs(env)) {
7161 return 0;
7162 }
7163 for (i = 0; i < 16; ++i) {
7164 __put_user(env->regs[i], sc->sc_a + i);
7165 }
7166 __put_user(0, &sc->sc_xtregs);
7167 /* TODO: xtregs */
7168 return 1;
7169}
7170
7171static void setup_rt_frame(int sig, struct target_sigaction *ka,
7172 target_siginfo_t *info,
7173 target_sigset_t *set, CPUXtensaState *env)
7174{
7175 abi_ulong frame_addr;
7176 struct target_rt_sigframe *frame;
7177 uint32_t ra;
7178 int i;
7179
7180 frame_addr = get_sigframe(ka, env, sizeof(*frame));
7181 trace_user_setup_rt_frame(env, frame_addr);
7182
7183 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
7184 goto give_sigsegv;
7185 }
7186
7187 if (ka->sa_flags & SA_SIGINFO) {
7188 tswap_siginfo(&frame->info, info);
7189 }
7190
7191 __put_user(0, &frame->uc.tuc_flags);
7192 __put_user(0, &frame->uc.tuc_link);
7193 __put_user(target_sigaltstack_used.ss_sp,
7194 &frame->uc.tuc_stack.ss_sp);
7195 __put_user(sas_ss_flags(env->regs[1]),
7196 &frame->uc.tuc_stack.ss_flags);
7197 __put_user(target_sigaltstack_used.ss_size,
7198 &frame->uc.tuc_stack.ss_size);
7199 if (!setup_sigcontext(frame, env)) {
7200 unlock_user_struct(frame, frame_addr, 0);
7201 goto give_sigsegv;
7202 }
7203 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
7204 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7205 }
7206
7207 if (ka->sa_flags & TARGET_SA_RESTORER) {
7208 ra = ka->sa_restorer;
7209 } else {
7210 ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
7211#ifdef TARGET_WORDS_BIGENDIAN
7212 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7213 __put_user(0x22, &frame->retcode[0]);
7214 __put_user(0x0a, &frame->retcode[1]);
7215 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7216 /* Generate instruction: SYSCALL */
7217 __put_user(0x00, &frame->retcode[3]);
7218 __put_user(0x05, &frame->retcode[4]);
7219 __put_user(0x00, &frame->retcode[5]);
7220#else
7221 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
7222 __put_user(0x22, &frame->retcode[0]);
7223 __put_user(0xa0, &frame->retcode[1]);
7224 __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
7225 /* Generate instruction: SYSCALL */
7226 __put_user(0x00, &frame->retcode[3]);
7227 __put_user(0x50, &frame->retcode[4]);
7228 __put_user(0x00, &frame->retcode[5]);
7229#endif
7230 }
7231 env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
7232 if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
7233 env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
7234 }
7235 memset(env->regs, 0, sizeof(env->regs));
7236 env->pc = ka->_sa_handler;
7237 env->regs[1] = frame_addr;
7238 env->sregs[WINDOW_BASE] = 0;
7239 env->sregs[WINDOW_START] = 1;
7240
7241 env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
7242 env->regs[6] = sig;
7243 env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
7244 env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
7245 unlock_user_struct(frame, frame_addr, 1);
7246 return;
7247
7248give_sigsegv:
7249 force_sigsegv(sig);
7250 return;
7251}
7252
7253static void restore_sigcontext(CPUXtensaState *env,
7254 struct target_rt_sigframe *frame)
7255{
7256 struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
7257 uint32_t ps;
7258 int i;
7259
7260 __get_user(env->pc, &sc->sc_pc);
7261 __get_user(ps, &sc->sc_ps);
7262 __get_user(env->sregs[LBEG], &sc->sc_lbeg);
7263 __get_user(env->sregs[LEND], &sc->sc_lend);
7264 __get_user(env->sregs[LCOUNT], &sc->sc_lcount);
7265
7266 env->sregs[WINDOW_BASE] = 0;
7267 env->sregs[WINDOW_START] = 1;
7268 env->sregs[PS] = deposit32(env->sregs[PS],
7269 PS_CALLINC_SHIFT,
7270 PS_CALLINC_LEN,
7271 extract32(ps, PS_CALLINC_SHIFT,
7272 PS_CALLINC_LEN));
7273 for (i = 0; i < 16; ++i) {
7274 __get_user(env->regs[i], sc->sc_a + i);
7275 }
7276 /* TODO: xtregs */
7277}
7278
7279long do_rt_sigreturn(CPUXtensaState *env)
7280{
7281 abi_ulong frame_addr = env->regs[1];
7282 struct target_rt_sigframe *frame;
7283 sigset_t set;
7284
7285 trace_user_do_rt_sigreturn(env, frame_addr);
7286 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
7287 goto badframe;
7288 }
7289 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
7290 set_sigmask(&set);
7291
7292 restore_sigcontext(env, frame);
7293
7294 if (do_sigaltstack(frame_addr +
7295 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7296 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) {
7297 goto badframe;
7298 }
7299 unlock_user_struct(frame, frame_addr, 0);
7300 return -TARGET_QEMU_ESIGRETURN;
7301
7302badframe:
7303 unlock_user_struct(frame, frame_addr, 0);
7304 force_sig(TARGET_SIGSEGV);
7305 return -TARGET_QEMU_ESIGRETURN;
7306}
7307
bellardb346ff42003-06-15 20:05:50 +00007308#else
7309
pbrook624f7972008-05-31 16:11:38 +00007310static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01007311 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00007312{
7313 fprintf(stderr, "setup_frame: not implemented\n");
7314}
7315
pbrook624f7972008-05-31 16:11:38 +00007316static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05007317 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01007318 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00007319{
7320 fprintf(stderr, "setup_rt_frame: not implemented\n");
7321}
7322
Andreas Färber9349b4f2012-03-14 01:38:32 +01007323long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00007324{
7325 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00007326 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00007327}
7328
Andreas Färber9349b4f2012-03-14 01:38:32 +01007329long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00007330{
7331 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00007332 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00007333}
7334
bellard66fb9762003-03-23 01:06:05 +00007335#endif
7336
Peter Maydell31efaef2016-07-06 15:09:29 +01007337static void handle_pending_signal(CPUArchState *cpu_env, int sig,
7338 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01007339{
7340 CPUState *cpu = ENV_GET_CPU(cpu_env);
7341 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007342 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01007343 target_sigset_t target_old_set;
7344 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01007345 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01007346
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01007347 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00007348 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007349 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00007350
Andreas Färberdb6b81d2013-06-27 19:49:31 +02007351 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00007352 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00007353 sa = NULL;
7354 handler = TARGET_SIG_IGN;
7355 } else {
7356 sa = &sigact_table[sig - 1];
7357 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00007358 }
bellard66fb9762003-03-23 01:06:05 +00007359
Peter Maydell0cb581d2016-07-18 18:12:24 +01007360 if (do_strace) {
7361 print_taken_signal(sig, &k->info);
7362 }
7363
bellard66fb9762003-03-23 01:06:05 +00007364 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00007365 /* default handler : ignore some signal. The other are job control or fatal */
7366 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
7367 kill(getpid(),SIGSTOP);
7368 } else if (sig != TARGET_SIGCHLD &&
7369 sig != TARGET_SIGURG &&
7370 sig != TARGET_SIGWINCH &&
7371 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007372 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007373 }
7374 } else if (handler == TARGET_SIG_IGN) {
7375 /* ignore sig */
7376 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01007377 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00007378 } else {
bellard9de5e442003-03-23 16:49:39 +00007379 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007380 sigset_t *blocked_set;
7381
pbrook624f7972008-05-31 16:11:38 +00007382 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00007383 /* SA_NODEFER indicates that the current signal should not be
7384 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00007385 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00007386 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00007387
bellard9de5e442003-03-23 16:49:39 +00007388 /* save the previous blocked signal state to restore it at the
7389 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01007390 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
7391
7392 /* block signals in the handler */
7393 blocked_set = ts->in_sigsuspend ?
7394 &ts->sigsuspend_mask : &ts->signal_mask;
7395 sigorset(&ts->signal_mask, blocked_set, &set);
7396 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00007397
bellardbc8a22c2003-03-30 21:02:40 +00007398 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00007399#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00007400 {
7401 CPUX86State *env = cpu_env;
7402 if (env->eflags & VM_MASK)
7403 save_v86_state(env);
7404 }
7405#endif
bellard9de5e442003-03-23 16:49:39 +00007406 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08007407#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10007408 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01007409 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13007410 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
Max Filippovba7651f2017-01-25 10:54:11 -08007411 || defined(TARGET_RISCV) || defined(TARGET_XTENSA)
Richard Hendersonff970902013-02-10 10:30:42 -08007412 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007413 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007414#else
pbrook624f7972008-05-31 16:11:38 +00007415 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01007416 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00007417 else
pbrook624f7972008-05-31 16:11:38 +00007418 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08007419#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01007420 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00007421 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01007422 }
bellard31e31b82003-02-18 22:55:36 +00007423 }
bellard31e31b82003-02-18 22:55:36 +00007424}
Peter Maydelle902d582016-05-27 15:51:44 +01007425
7426void process_pending_signals(CPUArchState *cpu_env)
7427{
7428 CPUState *cpu = ENV_GET_CPU(cpu_env);
7429 int sig;
7430 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007431 sigset_t set;
7432 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007433
Peter Maydell3d3efba2016-05-27 15:51:49 +01007434 while (atomic_read(&ts->signal_pending)) {
7435 /* FIXME: This is not threadsafe. */
7436 sigfillset(&set);
7437 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007438
Peter Maydell8bd37732016-07-28 16:44:45 +01007439 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007440 sig = ts->sync_signal.pending;
7441 if (sig) {
7442 /* Synchronous signals are forced,
7443 * see force_sig_info() and callers in Linux
7444 * Note that not all of our queue_signal() calls in QEMU correspond
7445 * to force_sig_info() calls in Linux (some are send_sig_info()).
7446 * However it seems like a kernel bug to me to allow the process
7447 * to block a synchronous signal since it could then just end up
7448 * looping round and round indefinitely.
7449 */
7450 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7451 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7452 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7453 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7454 }
7455
Peter Maydell31efaef2016-07-06 15:09:29 +01007456 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007457 }
7458
Peter Maydell3d3efba2016-05-27 15:51:49 +01007459 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7460 blocked_set = ts->in_sigsuspend ?
7461 &ts->sigsuspend_mask : &ts->signal_mask;
7462
7463 if (ts->sigtab[sig - 1].pending &&
7464 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007465 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007466 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007467 /* Restart scan from the beginning, as handle_pending_signal
7468 * might have resulted in a new synchronous signal (eg SIGSEGV).
7469 */
7470 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007471 }
Peter Maydelle902d582016-05-27 15:51:44 +01007472 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007473
7474 /* if no signal is pending, unblock signals and recheck (the act
7475 * of unblocking might cause us to take another host signal which
7476 * will set signal_pending again).
7477 */
7478 atomic_set(&ts->signal_pending, 0);
7479 ts->in_sigsuspend = 0;
7480 set = ts->signal_mask;
7481 sigdelset(&set, SIGSEGV);
7482 sigdelset(&set, SIGBUS);
7483 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007484 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007485 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007486}