blob: 0f2b155c3390a269941dffcae4c6b303ddcbe9ae [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
Andreas Schwab1744aea2013-09-03 20:12:16 +01001449struct target_rt_sigframe {
1450 struct target_siginfo info;
1451 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001452};
1453
1454struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001455 uint64_t fp;
1456 uint64_t lr;
1457 uint32_t tramp[2];
1458};
1459
Richard Henderson3b505bb2018-03-09 17:09:43 +00001460static void target_setup_general_frame(struct target_rt_sigframe *sf,
1461 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001462{
1463 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001464
Richard Henderson3b505bb2018-03-09 17:09:43 +00001465 __put_user(0, &sf->uc.tuc_flags);
1466 __put_user(0, &sf->uc.tuc_link);
1467
1468 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1469 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1470 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001471
1472 for (i = 0; i < 31; i++) {
1473 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1474 }
1475 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1476 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001477 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001478
Peter Maydell7af03922014-05-01 18:36:17 +01001479 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001480
1481 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1482 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1483 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001484}
1485
1486static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1487 CPUARMState *env)
1488{
1489 int i;
1490
1491 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1492 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1493 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1494 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001495
1496 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001497 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001498#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001499 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1500 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001501#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001502 __put_user(q[0], &fpsimd->vregs[i * 2]);
1503 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001504#endif
1505 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001506}
1507
Richard Henderson3b505bb2018-03-09 17:09:43 +00001508static void target_setup_end_record(struct target_aarch64_ctx *end)
1509{
1510 __put_user(0, &end->magic);
1511 __put_user(0, &end->size);
1512}
1513
1514static void target_restore_general_frame(CPUARMState *env,
1515 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001516{
1517 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001518 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001519 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001520
1521 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001522 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001523
1524 for (i = 0; i < 31; i++) {
1525 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1526 }
1527
1528 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1529 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001530 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1531 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001532}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001533
Richard Henderson3b505bb2018-03-09 17:09:43 +00001534static void target_restore_fpsimd_record(CPUARMState *env,
1535 struct target_fpsimd_context *fpsimd)
1536{
1537 uint32_t fpsr, fpcr;
1538 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001539
Richard Henderson3b505bb2018-03-09 17:09:43 +00001540 __get_user(fpsr, &fpsimd->fpsr);
1541 vfp_set_fpsr(env, fpsr);
1542 __get_user(fpcr, &fpsimd->fpcr);
1543 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001544
Peter Maydell4cf23482014-03-02 19:36:38 +00001545 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001546 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001547#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001548 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1549 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001550#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001551 __get_user(q[0], &fpsimd->vregs[i * 2]);
1552 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001553#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001554 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001555}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001556
Richard Henderson3b505bb2018-03-09 17:09:43 +00001557static int target_restore_sigframe(CPUARMState *env,
1558 struct target_rt_sigframe *sf)
1559{
Richard Hendersone1eecd12018-03-09 17:09:43 +00001560 struct target_aarch64_ctx *ctx;
1561 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001562
1563 target_restore_general_frame(env, sf);
1564
Richard Hendersone1eecd12018-03-09 17:09:43 +00001565 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1566 while (ctx) {
1567 uint32_t magic, size;
1568
1569 __get_user(magic, &ctx->magic);
1570 __get_user(size, &ctx->size);
1571 switch (magic) {
1572 case 0:
1573 if (size != 0) {
1574 return 1;
1575 }
1576 ctx = NULL;
1577 continue;
1578
1579 case TARGET_FPSIMD_MAGIC:
1580 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
1581 return 1;
1582 }
1583 fpsimd = (struct target_fpsimd_context *)ctx;
1584 break;
1585
1586 default:
1587 /* Unknown record -- we certainly didn't generate it.
1588 * Did we in fact get out of sync?
1589 */
1590 return 1;
1591 }
1592 ctx = (void *)ctx + size;
1593 }
1594
1595 /* Require FPSIMD always. */
1596 if (!fpsimd) {
Richard Henderson3b505bb2018-03-09 17:09:43 +00001597 return 1;
1598 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001599 target_restore_fpsimd_record(env, fpsimd);
1600
Andreas Schwab1744aea2013-09-03 20:12:16 +01001601 return 0;
1602}
1603
1604static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1605{
1606 abi_ulong sp;
1607
1608 sp = env->xregs[31];
1609
1610 /*
1611 * This is the X/Open sanctioned signal stack switching.
1612 */
Riku Voipiob545f632014-07-15 17:01:55 +03001613 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001614 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1615 }
1616
1617 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1618
1619 return sp;
1620}
1621
1622static void target_setup_frame(int usig, struct target_sigaction *ka,
1623 target_siginfo_t *info, target_sigset_t *set,
1624 CPUARMState *env)
1625{
Richard Hendersone1eecd12018-03-09 17:09:43 +00001626 int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
1627 int fpsimd_ofs, end1_ofs, fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001628 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001629 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001630 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001631
Richard Hendersone1eecd12018-03-09 17:09:43 +00001632 fpsimd_ofs = size;
1633 size += sizeof(struct target_fpsimd_context);
1634 end1_ofs = size;
1635 size += sizeof(struct target_aarch64_ctx);
1636 fr_ofs = size;
1637 size += sizeof(struct target_rt_frame_record);
1638
Andreas Schwab1744aea2013-09-03 20:12:16 +01001639 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001640 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001641 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1642 goto give_sigsegv;
1643 }
1644
Richard Henderson3b505bb2018-03-09 17:09:43 +00001645 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001646 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
1647 target_setup_end_record((void *)frame + end1_ofs);
1648
1649 /* Set up the stack frame for unwinding. */
1650 fr = (void *)frame + fr_ofs;
1651 __put_user(env->xregs[29], &fr->fp);
1652 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001653
Michael Matz8a3ae912014-03-02 19:36:39 +00001654 if (ka->sa_flags & TARGET_SA_RESTORER) {
1655 return_addr = ka->sa_restorer;
1656 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001657 /*
1658 * mov x8,#__NR_rt_sigreturn; svc #0
1659 * Since these are instructions they need to be put as little-endian
1660 * regardless of target default or current CPU endianness.
1661 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001662 __put_user_e(0xd2801168, &fr->tramp[0], le);
1663 __put_user_e(0xd4000001, &fr->tramp[1], le);
1664 return_addr = frame_addr + fr_ofs
1665 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001666 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001667 env->xregs[0] = usig;
1668 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001669 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001670 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001671 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001672 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001673 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001674 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1675 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1676 }
1677
1678 unlock_user_struct(frame, frame_addr, 1);
1679 return;
1680
1681 give_sigsegv:
1682 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001683 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001684}
1685
1686static void setup_rt_frame(int sig, struct target_sigaction *ka,
1687 target_siginfo_t *info, target_sigset_t *set,
1688 CPUARMState *env)
1689{
1690 target_setup_frame(sig, ka, info, set, env);
1691}
1692
1693static void setup_frame(int sig, struct target_sigaction *ka,
1694 target_sigset_t *set, CPUARMState *env)
1695{
1696 target_setup_frame(sig, ka, 0, set, env);
1697}
1698
1699long do_rt_sigreturn(CPUARMState *env)
1700{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001701 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001702 abi_ulong frame_addr = env->xregs[31];
1703
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001704 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001705 if (frame_addr & 15) {
1706 goto badframe;
1707 }
1708
1709 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1710 goto badframe;
1711 }
1712
1713 if (target_restore_sigframe(env, frame)) {
1714 goto badframe;
1715 }
1716
1717 if (do_sigaltstack(frame_addr +
1718 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1719 0, get_sp_from_cpustate(env)) == -EFAULT) {
1720 goto badframe;
1721 }
1722
1723 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001724 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001725
1726 badframe:
1727 unlock_user_struct(frame, frame_addr, 0);
1728 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001729 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001730}
1731
1732long do_sigreturn(CPUARMState *env)
1733{
1734 return do_rt_sigreturn(env);
1735}
1736
bellard43fff232003-07-09 19:31:39 +00001737#elif defined(TARGET_ARM)
1738
1739struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001740 abi_ulong trap_no;
1741 abi_ulong error_code;
1742 abi_ulong oldmask;
1743 abi_ulong arm_r0;
1744 abi_ulong arm_r1;
1745 abi_ulong arm_r2;
1746 abi_ulong arm_r3;
1747 abi_ulong arm_r4;
1748 abi_ulong arm_r5;
1749 abi_ulong arm_r6;
1750 abi_ulong arm_r7;
1751 abi_ulong arm_r8;
1752 abi_ulong arm_r9;
1753 abi_ulong arm_r10;
1754 abi_ulong arm_fp;
1755 abi_ulong arm_ip;
1756 abi_ulong arm_sp;
1757 abi_ulong arm_lr;
1758 abi_ulong arm_pc;
1759 abi_ulong arm_cpsr;
1760 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001761};
1762
pbrooka745ec62008-05-06 15:36:17 +00001763struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001764 abi_ulong tuc_flags;
1765 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001766 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001767 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001768 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001769};
1770
pbrooka745ec62008-05-06 15:36:17 +00001771struct target_ucontext_v2 {
1772 abi_ulong tuc_flags;
1773 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001774 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001775 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001776 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001777 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001778 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1779};
1780
Peter Maydell0d871bd2010-11-24 15:20:05 +00001781struct target_user_vfp {
1782 uint64_t fpregs[32];
1783 abi_ulong fpscr;
1784};
1785
1786struct target_user_vfp_exc {
1787 abi_ulong fpexc;
1788 abi_ulong fpinst;
1789 abi_ulong fpinst2;
1790};
1791
1792struct target_vfp_sigframe {
1793 abi_ulong magic;
1794 abi_ulong size;
1795 struct target_user_vfp ufp;
1796 struct target_user_vfp_exc ufp_exc;
1797} __attribute__((__aligned__(8)));
1798
Peter Maydell08e11252010-11-24 15:20:07 +00001799struct target_iwmmxt_sigframe {
1800 abi_ulong magic;
1801 abi_ulong size;
1802 uint64_t regs[16];
1803 /* Note that not all the coprocessor control registers are stored here */
1804 uint32_t wcssf;
1805 uint32_t wcasf;
1806 uint32_t wcgr0;
1807 uint32_t wcgr1;
1808 uint32_t wcgr2;
1809 uint32_t wcgr3;
1810} __attribute__((__aligned__(8)));
1811
Peter Maydell0d871bd2010-11-24 15:20:05 +00001812#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001813#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001814
pbrooka8c33202008-05-07 23:22:46 +00001815struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001816{
1817 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001818 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1819 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001820};
1821
pbrooka8c33202008-05-07 23:22:46 +00001822struct sigframe_v2
1823{
1824 struct target_ucontext_v2 uc;
1825 abi_ulong retcode;
1826};
1827
pbrooka745ec62008-05-06 15:36:17 +00001828struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001829{
bellardf8b0aa22007-11-11 23:03:42 +00001830 abi_ulong pinfo;
1831 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001832 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001833 struct target_ucontext_v1 uc;
1834 abi_ulong retcode;
1835};
1836
1837struct rt_sigframe_v2
1838{
1839 struct target_siginfo info;
1840 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001841 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001842};
1843
1844#define TARGET_CONFIG_CPU_32 1
1845
1846/*
1847 * For ARM syscalls, we encode the syscall number into the instruction.
1848 */
1849#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1850#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1851
1852/*
1853 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1854 * need two 16-bit instructions.
1855 */
1856#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1857#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1858
blueswir1992f48a2007-10-14 16:27:31 +00001859static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001860 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1861 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1862};
1863
1864
Andreas Färber05390242012-02-25 03:37:53 +01001865static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001866{
1867 return 1;
1868}
1869
pbrooka8c33202008-05-07 23:22:46 +00001870static void
bellard43fff232003-07-09 19:31:39 +00001871setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001872 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001873{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001874 __put_user(env->regs[0], &sc->arm_r0);
1875 __put_user(env->regs[1], &sc->arm_r1);
1876 __put_user(env->regs[2], &sc->arm_r2);
1877 __put_user(env->regs[3], &sc->arm_r3);
1878 __put_user(env->regs[4], &sc->arm_r4);
1879 __put_user(env->regs[5], &sc->arm_r5);
1880 __put_user(env->regs[6], &sc->arm_r6);
1881 __put_user(env->regs[7], &sc->arm_r7);
1882 __put_user(env->regs[8], &sc->arm_r8);
1883 __put_user(env->regs[9], &sc->arm_r9);
1884 __put_user(env->regs[10], &sc->arm_r10);
1885 __put_user(env->regs[11], &sc->arm_fp);
1886 __put_user(env->regs[12], &sc->arm_ip);
1887 __put_user(env->regs[13], &sc->arm_sp);
1888 __put_user(env->regs[14], &sc->arm_lr);
1889 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001890#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001891 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001892#endif
1893
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001894 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1895 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1896 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1897 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001898}
1899
bellard579a97f2007-11-11 14:26:47 +00001900static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001901get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001902{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001903 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001904
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001905 /*
1906 * This is the X/Open sanctioned signal stack switching.
1907 */
1908 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1909 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1910 }
1911 /*
1912 * ATPCS B01 mandates 8-byte alignment
1913 */
1914 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001915}
1916
Riku Voipio0188fad2014-04-23 13:34:15 +03001917static void
Andreas Färber05390242012-02-25 03:37:53 +01001918setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001919 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001920{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001921 abi_ulong handler = ka->_sa_handler;
1922 abi_ulong retcode;
1923 int thumb = handler & 1;
1924 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001925
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001926 cpsr &= ~CPSR_IT;
1927 if (thumb) {
1928 cpsr |= CPSR_T;
1929 } else {
1930 cpsr &= ~CPSR_T;
1931 }
bellard43fff232003-07-09 19:31:39 +00001932
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001933 if (ka->sa_flags & TARGET_SA_RESTORER) {
1934 retcode = ka->sa_restorer;
1935 } else {
1936 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001937
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001938 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1939 idx += 2;
1940 }
bellard43fff232003-07-09 19:31:39 +00001941
Riku Voipio0188fad2014-04-23 13:34:15 +03001942 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001943
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001944 retcode = rc_addr + thumb;
1945 }
bellard43fff232003-07-09 19:31:39 +00001946
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001947 env->regs[0] = usig;
1948 env->regs[13] = frame_addr;
1949 env->regs[14] = retcode;
1950 env->regs[15] = handler & (thumb ? ~1 : ~3);
1951 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001952}
1953
Andreas Färber05390242012-02-25 03:37:53 +01001954static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001955{
1956 int i;
1957 struct target_vfp_sigframe *vfpframe;
1958 vfpframe = (struct target_vfp_sigframe *)regspace;
1959 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1960 __put_user(sizeof(*vfpframe), &vfpframe->size);
1961 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001962 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001963 }
1964 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1965 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1966 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1967 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1968 return (abi_ulong*)(vfpframe+1);
1969}
1970
Andreas Färber05390242012-02-25 03:37:53 +01001971static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1972 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001973{
1974 int i;
1975 struct target_iwmmxt_sigframe *iwmmxtframe;
1976 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1977 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1978 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1979 for (i = 0; i < 16; i++) {
1980 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1981 }
1982 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1983 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1984 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1985 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1986 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1987 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1988 return (abi_ulong*)(iwmmxtframe+1);
1989}
1990
pbrooka8c33202008-05-07 23:22:46 +00001991static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001992 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001993{
pbrooka8c33202008-05-07 23:22:46 +00001994 struct target_sigaltstack stack;
1995 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001996 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001997
1998 /* Clear all the bits of the ucontext we don't use. */
1999 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2000
2001 memset(&stack, 0, sizeof(stack));
2002 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2003 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2004 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2005 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2006
2007 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002008 /* Save coprocessor signal frame. */
2009 regspace = uc->tuc_regspace;
2010 if (arm_feature(env, ARM_FEATURE_VFP)) {
2011 regspace = setup_sigframe_v2_vfp(regspace, env);
2012 }
Peter Maydell08e11252010-11-24 15:20:07 +00002013 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2014 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2015 }
2016
Peter Maydell0d871bd2010-11-24 15:20:05 +00002017 /* Write terminating magic word */
2018 __put_user(0, regspace);
2019
pbrooka8c33202008-05-07 23:22:46 +00002020 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2021 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2022 }
2023}
2024
2025/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002026static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002027 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002028{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002029 struct sigframe_v1 *frame;
2030 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2031 int i;
bellard43fff232003-07-09 19:31:39 +00002032
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002033 trace_user_setup_frame(regs, frame_addr);
2034 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002035 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002036 }
bellard579a97f2007-11-11 14:26:47 +00002037
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002038 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002039
Riku Voipio0188fad2014-04-23 13:34:15 +03002040 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2041 __put_user(set->sig[i], &frame->extramask[i - 1]);
2042 }
bellard43fff232003-07-09 19:31:39 +00002043
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002044 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2045 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002046
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002047 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002048 return;
2049sigsegv:
2050 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002051}
2052
pbrook624f7972008-05-31 16:11:38 +00002053static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002054 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002055{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002056 struct sigframe_v2 *frame;
2057 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002058
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002059 trace_user_setup_frame(regs, frame_addr);
2060 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002061 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002062 }
pbrooka8c33202008-05-07 23:22:46 +00002063
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002064 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002065
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002066 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2067 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002068
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002069 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002070 return;
2071sigsegv:
2072 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002073}
2074
pbrook624f7972008-05-31 16:11:38 +00002075static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002076 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002077{
2078 if (get_osversion() >= 0x020612) {
2079 setup_frame_v2(usig, ka, set, regs);
2080 } else {
2081 setup_frame_v1(usig, ka, set, regs);
2082 }
bellard43fff232003-07-09 19:31:39 +00002083}
2084
bellard579a97f2007-11-11 14:26:47 +00002085/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002086static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002087 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002088 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002089{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002090 struct rt_sigframe_v1 *frame;
2091 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2092 struct target_sigaltstack stack;
2093 int i;
2094 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002095
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002096 trace_user_setup_rt_frame(env, frame_addr);
2097 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002098 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002099 }
bellardedf779f2004-02-22 13:40:13 +00002100
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002101 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2102 __put_user(info_addr, &frame->pinfo);
2103 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2104 __put_user(uc_addr, &frame->puc);
2105 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002106
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002107 /* Clear all the bits of the ucontext we don't use. */
2108 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002109
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002110 memset(&stack, 0, sizeof(stack));
2111 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2112 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2113 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2114 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002115
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002116 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2117 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2118 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2119 }
bellard43fff232003-07-09 19:31:39 +00002120
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002121 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2122 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002124 env->regs[1] = info_addr;
2125 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002127 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002128 return;
2129sigsegv:
2130 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002131}
2132
pbrook624f7972008-05-31 16:11:38 +00002133static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002134 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002135 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002136{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002137 struct rt_sigframe_v2 *frame;
2138 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2139 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002140
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002141 trace_user_setup_rt_frame(env, frame_addr);
2142 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002143 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002144 }
pbrooka745ec62008-05-06 15:36:17 +00002145
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002146 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2147 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2148 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002149
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002150 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002151
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002152 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2153 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002154
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002155 env->regs[1] = info_addr;
2156 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002157
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002158 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002159 return;
2160sigsegv:
2161 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002162}
2163
pbrook624f7972008-05-31 16:11:38 +00002164static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002165 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002166 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002167{
2168 if (get_osversion() >= 0x020612) {
2169 setup_rt_frame_v2(usig, ka, info, set, env);
2170 } else {
2171 setup_rt_frame_v1(usig, ka, info, set, env);
2172 }
2173}
2174
bellard43fff232003-07-09 19:31:39 +00002175static int
Andreas Färber05390242012-02-25 03:37:53 +01002176restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002177{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002178 int err = 0;
2179 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002180
Riku Voipio1d8b5122014-04-23 10:26:05 +03002181 __get_user(env->regs[0], &sc->arm_r0);
2182 __get_user(env->regs[1], &sc->arm_r1);
2183 __get_user(env->regs[2], &sc->arm_r2);
2184 __get_user(env->regs[3], &sc->arm_r3);
2185 __get_user(env->regs[4], &sc->arm_r4);
2186 __get_user(env->regs[5], &sc->arm_r5);
2187 __get_user(env->regs[6], &sc->arm_r6);
2188 __get_user(env->regs[7], &sc->arm_r7);
2189 __get_user(env->regs[8], &sc->arm_r8);
2190 __get_user(env->regs[9], &sc->arm_r9);
2191 __get_user(env->regs[10], &sc->arm_r10);
2192 __get_user(env->regs[11], &sc->arm_fp);
2193 __get_user(env->regs[12], &sc->arm_ip);
2194 __get_user(env->regs[13], &sc->arm_sp);
2195 __get_user(env->regs[14], &sc->arm_lr);
2196 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002197#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002198 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002199 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002200#endif
2201
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002202 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002203
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002204 return err;
bellard43fff232003-07-09 19:31:39 +00002205}
2206
Andreas Färber05390242012-02-25 03:37:53 +01002207static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002208{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002209 abi_ulong frame_addr;
2210 struct sigframe_v1 *frame = NULL;
2211 target_sigset_t set;
2212 sigset_t host_set;
2213 int i;
bellard43fff232003-07-09 19:31:39 +00002214
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002215 /*
2216 * Since we stacked the signal on a 64-bit boundary,
2217 * then 'sp' should be word aligned here. If it's
2218 * not, then the user is trying to mess with us.
2219 */
2220 frame_addr = env->regs[13];
2221 trace_user_do_sigreturn(env, frame_addr);
2222 if (frame_addr & 7) {
2223 goto badframe;
2224 }
Peter Maydell978fae92013-07-29 12:00:32 +01002225
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002226 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2227 goto badframe;
2228 }
bellard43fff232003-07-09 19:31:39 +00002229
Riku Voipiof5f601a2014-04-23 13:00:17 +03002230 __get_user(set.sig[0], &frame->sc.oldmask);
2231 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2232 __get_user(set.sig[i], &frame->extramask[i - 1]);
2233 }
bellard43fff232003-07-09 19:31:39 +00002234
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002235 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002236 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002237
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002238 if (restore_sigcontext(env, &frame->sc)) {
2239 goto badframe;
2240 }
bellard43fff232003-07-09 19:31:39 +00002241
2242#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002243 /* Send SIGTRAP if we're single-stepping */
2244 if (ptrace_cancel_bpt(current))
2245 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002246#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002247 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002248 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002249
2250badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002251 force_sig(TARGET_SIGSEGV);
2252 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002253}
2254
Andreas Färber05390242012-02-25 03:37:53 +01002255static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002256{
2257 int i;
2258 abi_ulong magic, sz;
2259 uint32_t fpscr, fpexc;
2260 struct target_vfp_sigframe *vfpframe;
2261 vfpframe = (struct target_vfp_sigframe *)regspace;
2262
2263 __get_user(magic, &vfpframe->magic);
2264 __get_user(sz, &vfpframe->size);
2265 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2266 return 0;
2267 }
2268 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002269 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002270 }
2271 __get_user(fpscr, &vfpframe->ufp.fpscr);
2272 vfp_set_fpscr(env, fpscr);
2273 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2274 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2275 * and the exception flag is cleared
2276 */
2277 fpexc |= (1 << 30);
2278 fpexc &= ~((1 << 31) | (1 << 28));
2279 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2280 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2281 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2282 return (abi_ulong*)(vfpframe + 1);
2283}
2284
Andreas Färber05390242012-02-25 03:37:53 +01002285static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2286 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002287{
2288 int i;
2289 abi_ulong magic, sz;
2290 struct target_iwmmxt_sigframe *iwmmxtframe;
2291 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2292
2293 __get_user(magic, &iwmmxtframe->magic);
2294 __get_user(sz, &iwmmxtframe->size);
2295 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2296 return 0;
2297 }
2298 for (i = 0; i < 16; i++) {
2299 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2300 }
2301 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2302 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2303 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2304 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2305 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2306 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2307 return (abi_ulong*)(iwmmxtframe + 1);
2308}
2309
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002310static int do_sigframe_return_v2(CPUARMState *env,
2311 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002312 struct target_ucontext_v2 *uc)
2313{
2314 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002315 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002316
2317 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002318 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002319
2320 if (restore_sigcontext(env, &uc->tuc_mcontext))
2321 return 1;
2322
Peter Maydell5f9099d2010-11-24 15:20:06 +00002323 /* Restore coprocessor signal frame */
2324 regspace = uc->tuc_regspace;
2325 if (arm_feature(env, ARM_FEATURE_VFP)) {
2326 regspace = restore_sigframe_v2_vfp(env, regspace);
2327 if (!regspace) {
2328 return 1;
2329 }
2330 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002331 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2332 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2333 if (!regspace) {
2334 return 1;
2335 }
2336 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002337
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002338 if (do_sigaltstack(context_addr
2339 + offsetof(struct target_ucontext_v2, tuc_stack),
2340 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002341 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002342 }
pbrooka8c33202008-05-07 23:22:46 +00002343
2344#if 0
2345 /* Send SIGTRAP if we're single-stepping */
2346 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002348#endif
2349
2350 return 0;
2351}
2352
Andreas Färber05390242012-02-25 03:37:53 +01002353static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002354{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002355 abi_ulong frame_addr;
2356 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002357
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002358 /*
2359 * Since we stacked the signal on a 64-bit boundary,
2360 * then 'sp' should be word aligned here. If it's
2361 * not, then the user is trying to mess with us.
2362 */
2363 frame_addr = env->regs[13];
2364 trace_user_do_sigreturn(env, frame_addr);
2365 if (frame_addr & 7) {
2366 goto badframe;
2367 }
Peter Maydell978fae92013-07-29 12:00:32 +01002368
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002369 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2370 goto badframe;
2371 }
pbrooka8c33202008-05-07 23:22:46 +00002372
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002373 if (do_sigframe_return_v2(env,
2374 frame_addr
2375 + offsetof(struct sigframe_v2, uc),
2376 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002377 goto badframe;
2378 }
pbrooka8c33202008-05-07 23:22:46 +00002379
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002380 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002381 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002382
2383badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002384 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002385 force_sig(TARGET_SIGSEGV);
2386 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002387}
2388
Andreas Färber05390242012-02-25 03:37:53 +01002389long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002390{
2391 if (get_osversion() >= 0x020612) {
2392 return do_sigreturn_v2(env);
2393 } else {
2394 return do_sigreturn_v1(env);
2395 }
2396}
2397
Andreas Färber05390242012-02-25 03:37:53 +01002398static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002399{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002400 abi_ulong frame_addr;
2401 struct rt_sigframe_v1 *frame = NULL;
2402 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002403
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002404 /*
2405 * Since we stacked the signal on a 64-bit boundary,
2406 * then 'sp' should be word aligned here. If it's
2407 * not, then the user is trying to mess with us.
2408 */
2409 frame_addr = env->regs[13];
2410 trace_user_do_rt_sigreturn(env, frame_addr);
2411 if (frame_addr & 7) {
2412 goto badframe;
2413 }
Peter Maydell978fae92013-07-29 12:00:32 +01002414
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002415 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2416 goto badframe;
2417 }
bellard43fff232003-07-09 19:31:39 +00002418
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002419 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002420 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002421
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002422 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2423 goto badframe;
2424 }
bellard43fff232003-07-09 19:31:39 +00002425
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002426 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2427 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002428
bellard43fff232003-07-09 19:31:39 +00002429#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002430 /* Send SIGTRAP if we're single-stepping */
2431 if (ptrace_cancel_bpt(current))
2432 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002433#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002434 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002435 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002436
2437badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002438 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002439 force_sig(TARGET_SIGSEGV);
2440 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002441}
2442
Andreas Färber05390242012-02-25 03:37:53 +01002443static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002444{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002445 abi_ulong frame_addr;
2446 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002447
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002448 /*
2449 * Since we stacked the signal on a 64-bit boundary,
2450 * then 'sp' should be word aligned here. If it's
2451 * not, then the user is trying to mess with us.
2452 */
2453 frame_addr = env->regs[13];
2454 trace_user_do_rt_sigreturn(env, frame_addr);
2455 if (frame_addr & 7) {
2456 goto badframe;
2457 }
Peter Maydell978fae92013-07-29 12:00:32 +01002458
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002459 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2460 goto badframe;
2461 }
pbrooka745ec62008-05-06 15:36:17 +00002462
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002463 if (do_sigframe_return_v2(env,
2464 frame_addr
2465 + offsetof(struct rt_sigframe_v2, uc),
2466 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002467 goto badframe;
2468 }
pbrooka745ec62008-05-06 15:36:17 +00002469
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002470 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002471 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002472
2473badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002474 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002475 force_sig(TARGET_SIGSEGV);
2476 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002477}
2478
Andreas Färber05390242012-02-25 03:37:53 +01002479long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002480{
2481 if (get_osversion() >= 0x020612) {
2482 return do_rt_sigreturn_v2(env);
2483 } else {
2484 return do_rt_sigreturn_v1(env);
2485 }
2486}
2487
bellard6d5e2162004-09-30 22:04:13 +00002488#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002489
bellard6d5e2162004-09-30 22:04:13 +00002490#define __SUNOS_MAXWIN 31
2491
2492/* This is what SunOS does, so shall I. */
2493struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002494 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002495
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002496 abi_ulong sigc_mask; /* sigmask to restore */
2497 abi_ulong sigc_sp; /* stack pointer */
2498 abi_ulong sigc_pc; /* program counter */
2499 abi_ulong sigc_npc; /* next program counter */
2500 abi_ulong sigc_psr; /* for condition codes etc */
2501 abi_ulong sigc_g1; /* User uses these two registers */
2502 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002503
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002504 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002505 * at the time of the signal.
2506 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002507 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002508
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002509 /* stack ptrs for each regwin buf */
2510 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002511
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002512 /* Windows to restore after signal */
2513 struct {
2514 abi_ulong locals[8];
2515 abi_ulong ins[8];
2516 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002517};
2518/* A Sparc stack frame */
2519struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002520 abi_ulong locals[8];
2521 abi_ulong ins[8];
2522 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002523 * since we never need to access them ourselves.
2524 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002525 char *structptr;
2526 abi_ulong xargs[6];
2527 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002528};
2529
2530typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002531 struct {
2532 abi_ulong psr;
2533 abi_ulong pc;
2534 abi_ulong npc;
2535 abi_ulong y;
2536 abi_ulong u_regs[16]; /* globals and ins */
2537 } si_regs;
2538 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002539} __siginfo_t;
2540
2541typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002542 abi_ulong si_float_regs[32];
2543 unsigned long si_fsr;
2544 unsigned long si_fpqdepth;
2545 struct {
2546 unsigned long *insn_addr;
2547 unsigned long insn;
2548 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002549} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002550
2551
2552struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002553 struct sparc_stackf ss;
2554 __siginfo_t info;
2555 abi_ulong fpu_save;
2556 abi_ulong insns[2] __attribute__ ((aligned (8)));
2557 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2558 abi_ulong extra_size; /* Should be 0 */
2559 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002560};
2561struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002562 struct sparc_stackf ss;
2563 siginfo_t info;
2564 abi_ulong regs[20];
2565 sigset_t mask;
2566 abi_ulong fpu_save;
2567 unsigned int insns[2];
2568 stack_t stack;
2569 unsigned int extra_size; /* Should be 0 */
2570 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002571};
2572
bellarde80cfcf2004-12-19 23:18:01 +00002573#define UREG_O0 16
2574#define UREG_O6 22
2575#define UREG_I0 0
2576#define UREG_I1 1
2577#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002578#define UREG_I3 3
2579#define UREG_I4 4
2580#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002581#define UREG_I6 6
2582#define UREG_I7 7
2583#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002584#define UREG_FP UREG_I6
2585#define UREG_SP UREG_O6
2586
pbrook624f7972008-05-31 16:11:38 +00002587static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002588 CPUSPARCState *env,
2589 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002590{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002591 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002592
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002593 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002594
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002595 /* This is the X/Open sanctioned signal stack switching. */
2596 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2597 if (!on_sig_stack(sp)
2598 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2599 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2600 }
2601 }
2602 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002603}
2604
2605static int
Andreas Färber05390242012-02-25 03:37:53 +01002606setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002607{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002608 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002609
Riku Voipio1d8b5122014-04-23 10:26:05 +03002610 __put_user(env->psr, &si->si_regs.psr);
2611 __put_user(env->pc, &si->si_regs.pc);
2612 __put_user(env->npc, &si->si_regs.npc);
2613 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002614 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002615 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002616 }
2617 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002618 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002619 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002620 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002621 return err;
bellard6d5e2162004-09-30 22:04:13 +00002622}
bellarde80cfcf2004-12-19 23:18:01 +00002623
bellard80a9d032005-01-03 23:31:27 +00002624#if 0
bellard6d5e2162004-09-30 22:04:13 +00002625static int
2626setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002627 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002628{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002629 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002630
Riku Voipio1d8b5122014-04-23 10:26:05 +03002631 __put_user(mask, &sc->sigc_mask);
2632 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2633 __put_user(env->pc, &sc->sigc_pc);
2634 __put_user(env->npc, &sc->sigc_npc);
2635 __put_user(env->psr, &sc->sigc_psr);
2636 __put_user(env->gregs[1], &sc->sigc_g1);
2637 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002638
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002639 return err;
bellard6d5e2162004-09-30 22:04:13 +00002640}
bellard80a9d032005-01-03 23:31:27 +00002641#endif
bellard6d5e2162004-09-30 22:04:13 +00002642#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2643
pbrook624f7972008-05-31 16:11:38 +00002644static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002645 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002646{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002647 abi_ulong sf_addr;
2648 struct target_signal_frame *sf;
2649 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002650
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002651 /* 1. Make sure everything is clean */
2652 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002653
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002654 sigframe_size = NF_ALIGNEDSZ;
2655 sf_addr = get_sigframe(ka, env, sigframe_size);
2656 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002657
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002658 sf = lock_user(VERIFY_WRITE, sf_addr,
2659 sizeof(struct target_signal_frame), 0);
2660 if (!sf) {
2661 goto sigsegv;
2662 }
bellard6d5e2162004-09-30 22:04:13 +00002663#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002664 if (invalid_frame_pointer(sf, sigframe_size))
2665 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002666#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002667 /* 2. Save the current process state */
2668 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002669 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002670
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002671 //save_fpu_state(regs, &sf->fpu_state);
2672 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002673
Riku Voipio1d8b5122014-04-23 10:26:05 +03002674 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002675 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002676 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002677 }
bellard6d5e2162004-09-30 22:04:13 +00002678
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002679 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002680 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002681 }
2682 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002683 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002684 }
2685 if (err)
2686 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002687
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002688 /* 3. signal handler back-trampoline and parameters */
2689 env->regwptr[UREG_FP] = sf_addr;
2690 env->regwptr[UREG_I0] = sig;
2691 env->regwptr[UREG_I1] = sf_addr +
2692 offsetof(struct target_signal_frame, info);
2693 env->regwptr[UREG_I2] = sf_addr +
2694 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002695
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002696 /* 4. signal handler */
2697 env->pc = ka->_sa_handler;
2698 env->npc = (env->pc + 4);
2699 /* 5. return to kernel instructions */
2700 if (ka->sa_restorer) {
2701 env->regwptr[UREG_I7] = ka->sa_restorer;
2702 } else {
2703 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002704
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002705 env->regwptr[UREG_I7] = sf_addr +
2706 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002707
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002708 /* mov __NR_sigreturn, %g1 */
2709 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002710 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002711
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002712 /* t 0x10 */
2713 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002714 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002715 if (err)
2716 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002717
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002718 /* Flush instruction space. */
2719 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2720 // tb_flush(env);
2721 }
2722 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2723 return;
bellard459a4012007-11-11 19:45:10 +00002724#if 0
2725sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002726 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002727#endif
bellard6d5e2162004-09-30 22:04:13 +00002728sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002729 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002730 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002731}
bellard6d5e2162004-09-30 22:04:13 +00002732
pbrook624f7972008-05-31 16:11:38 +00002733static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002734 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002735 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002736{
2737 fprintf(stderr, "setup_rt_frame: not implemented\n");
2738}
2739
Andreas Färber05390242012-02-25 03:37:53 +01002740long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002741{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002742 abi_ulong sf_addr;
2743 struct target_signal_frame *sf;
2744 uint32_t up_psr, pc, npc;
2745 target_sigset_t set;
2746 sigset_t host_set;
2747 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002748
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002749 sf_addr = env->regwptr[UREG_FP];
2750 trace_user_do_sigreturn(env, sf_addr);
2751 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2752 goto segv_and_exit;
2753 }
bellard6d5e2162004-09-30 22:04:13 +00002754
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002755 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002756
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002757 if (sf_addr & 3)
2758 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002759
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002760 __get_user(pc, &sf->info.si_regs.pc);
2761 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002762
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002763 if ((pc | npc) & 3) {
2764 goto segv_and_exit;
2765 }
bellard6d5e2162004-09-30 22:04:13 +00002766
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002767 /* 2. Restore the state */
2768 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002769
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002770 /* User can only change condition codes and FPU enabling in %psr. */
2771 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2772 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002773
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002774 env->pc = pc;
2775 env->npc = npc;
2776 __get_user(env->y, &sf->info.si_regs.y);
2777 for (i=0; i < 8; i++) {
2778 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2779 }
2780 for (i=0; i < 8; i++) {
2781 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2782 }
bellard6d5e2162004-09-30 22:04:13 +00002783
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002784 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002785 * __get_user(fpu_save, &sf->fpu_save);
2786 * if (fpu_save)
2787 * err |= restore_fpu_state(env, fpu_save);
2788 */
bellard6d5e2162004-09-30 22:04:13 +00002789
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002790 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002791 * the races which exist anyways.
2792 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002793 __get_user(set.sig[0], &sf->info.si_mask);
2794 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2795 __get_user(set.sig[i], &sf->extramask[i - 1]);
2796 }
bellarde80cfcf2004-12-19 23:18:01 +00002797
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002798 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002799 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002800
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002801 if (err) {
2802 goto segv_and_exit;
2803 }
2804 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002805 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002806
2807segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002808 unlock_user_struct(sf, sf_addr, 0);
2809 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002810 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002811}
2812
Andreas Färber05390242012-02-25 03:37:53 +01002813long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002814{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002815 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002816 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002817 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002818}
2819
bellard459a4012007-11-11 19:45:10 +00002820#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00002821#define SPARC_MC_TSTATE 0
2822#define SPARC_MC_PC 1
2823#define SPARC_MC_NPC 2
2824#define SPARC_MC_Y 3
2825#define SPARC_MC_G1 4
2826#define SPARC_MC_G2 5
2827#define SPARC_MC_G3 6
2828#define SPARC_MC_G4 7
2829#define SPARC_MC_G5 8
2830#define SPARC_MC_G6 9
2831#define SPARC_MC_G7 10
2832#define SPARC_MC_O0 11
2833#define SPARC_MC_O1 12
2834#define SPARC_MC_O2 13
2835#define SPARC_MC_O3 14
2836#define SPARC_MC_O4 15
2837#define SPARC_MC_O5 16
2838#define SPARC_MC_O6 17
2839#define SPARC_MC_O7 18
2840#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00002841
Anthony Liguoric227f092009-10-01 16:12:16 -05002842typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002843typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002844
2845struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002846 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002847 uint32_t mcfq_insn;
2848};
2849
2850struct target_mc_fpu {
2851 union {
2852 uint32_t sregs[32];
2853 uint64_t dregs[32];
2854 //uint128_t qregs[16];
2855 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002856 abi_ulong mcfpu_fsr;
2857 abi_ulong mcfpu_fprs;
2858 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002859 struct target_mc_fq *mcfpu_fq;
2860 unsigned char mcfpu_qcnt;
2861 unsigned char mcfpu_qentsz;
2862 unsigned char mcfpu_enab;
2863};
Anthony Liguoric227f092009-10-01 16:12:16 -05002864typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002865
2866typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002867 target_mc_gregset_t mc_gregs;
2868 target_mc_greg_t mc_fp;
2869 target_mc_greg_t mc_i7;
2870 target_mc_fpu_t mc_fpregs;
2871} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002872
2873struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002874 struct target_ucontext *tuc_link;
2875 abi_ulong tuc_flags;
2876 target_sigset_t tuc_sigmask;
2877 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002878};
2879
2880/* A V9 register window */
2881struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002882 abi_ulong locals[8];
2883 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002884};
2885
2886#define TARGET_STACK_BIAS 2047
2887
2888/* {set, get}context() needed for 64-bit SparcLinux userland. */
2889void sparc64_set_context(CPUSPARCState *env)
2890{
bellard459a4012007-11-11 19:45:10 +00002891 abi_ulong ucp_addr;
2892 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002893 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002894 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002895 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002896 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002897
bellard459a4012007-11-11 19:45:10 +00002898 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002899 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002900 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002901 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002902 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002903 __get_user(pc, &((*grp)[SPARC_MC_PC]));
2904 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002905 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002906 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002907 }
blueswir15bfb56b2007-10-05 17:01:51 +00002908 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002909 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002910 sigset_t set;
2911
2912 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002913 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002914 } else {
bellard459a4012007-11-11 19:45:10 +00002915 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002916 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002917 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002918 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002919 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002920 }
blueswir15bfb56b2007-10-05 17:01:51 +00002921 }
2922 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002923 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002924 }
2925 env->pc = pc;
2926 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002927 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
2928 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002929 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002930 cpu_put_ccr(env, tstate >> 32);
2931 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00002932 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
2933 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
2934 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
2935 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
2936 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
2937 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
2938 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
2939 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
2940 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
2941 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
2942 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
2943 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
2944 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
2945 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
2946 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002947
Riku Voipio1d8b5122014-04-23 10:26:05 +03002948 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2949 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002950
bellard459a4012007-11-11 19:45:10 +00002951 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002952 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2953 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002954 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002955 }
2956 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2957 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002958 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002959 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002960 /* FIXME this does not match how the kernel handles the FPU in
2961 * its sparc64_set_context implementation. In particular the FPU
2962 * is only restored if fenab is non-zero in:
2963 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2964 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002965 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002966 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002967 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2968 for (i = 0; i < 64; i++, src++) {
2969 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002970 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002971 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002972 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002973 }
2974 }
bellard459a4012007-11-11 19:45:10 +00002975 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002976 __get_user(env->fsr,
2977 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2978 __get_user(env->gsr,
2979 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002980 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002981 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002982do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002983 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002984 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002985}
2986
2987void sparc64_get_context(CPUSPARCState *env)
2988{
bellard459a4012007-11-11 19:45:10 +00002989 abi_ulong ucp_addr;
2990 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002991 target_mc_gregset_t *grp;
2992 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002993 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002994 int err;
2995 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002996 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002997 sigset_t set;
2998
bellard459a4012007-11-11 19:45:10 +00002999 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003000 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003001 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003002 }
bellard459a4012007-11-11 19:45:10 +00003003
Aurelien Jarno60e99242010-03-29 02:12:51 +02003004 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003005 grp = &mcp->mc_gregs;
3006
3007 /* Skip over the trap instruction, first. */
3008 env->pc = env->npc;
3009 env->npc += 4;
3010
Peter Maydell3d3efba2016-05-27 15:51:49 +01003011 /* If we're only reading the signal mask then do_sigprocmask()
3012 * is guaranteed not to fail, which is important because we don't
3013 * have any way to signal a failure or restart this operation since
3014 * this is not a normal syscall.
3015 */
3016 err = do_sigprocmask(0, NULL, &set);
3017 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003018 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003019 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003020 __put_user(target_set.sig[0],
3021 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003022 } else {
3023 abi_ulong *src, *dst;
3024 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003025 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003026 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003027 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003028 }
blueswir15bfb56b2007-10-05 17:01:51 +00003029 if (err)
3030 goto do_sigsegv;
3031 }
3032
bellard459a4012007-11-11 19:45:10 +00003033 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003034 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3035 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3036 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3037 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3038 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3039 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3040 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3041 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3042 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3043 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3044 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3045 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3046 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3047 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3048 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3049 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3050 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3051 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3052 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003053
bellard459a4012007-11-11 19:45:10 +00003054 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3055 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003056 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3057 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003058 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003059 }
3060 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3061 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003062 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003063 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003064 __put_user(fp, &(mcp->mc_fp));
3065 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003066
bellard459a4012007-11-11 19:45:10 +00003067 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003068 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3069 for (i = 0; i < 64; i++, dst++) {
3070 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003071 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003072 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003073 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003074 }
3075 }
bellard459a4012007-11-11 19:45:10 +00003076 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003077 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3078 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3079 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003080
3081 if (err)
3082 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003083 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003084 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003085do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003086 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003087 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003088}
3089#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003090#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003091
Richard Hendersonff970902013-02-10 10:30:42 -08003092# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003093struct target_sigcontext {
3094 uint32_t sc_regmask; /* Unused */
3095 uint32_t sc_status;
3096 uint64_t sc_pc;
3097 uint64_t sc_regs[32];
3098 uint64_t sc_fpregs[32];
3099 uint32_t sc_ownedfp; /* Unused */
3100 uint32_t sc_fpc_csr;
3101 uint32_t sc_fpc_eir; /* Unused */
3102 uint32_t sc_used_math;
3103 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003104 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003105 uint64_t sc_mdhi;
3106 uint64_t sc_mdlo;
3107 target_ulong sc_hi1; /* Was sc_cause */
3108 target_ulong sc_lo1; /* Was sc_badvaddr */
3109 target_ulong sc_hi2; /* Was sc_sigset[4] */
3110 target_ulong sc_lo2;
3111 target_ulong sc_hi3;
3112 target_ulong sc_lo3;
3113};
Richard Hendersonff970902013-02-10 10:30:42 -08003114# else /* N32 || N64 */
3115struct target_sigcontext {
3116 uint64_t sc_regs[32];
3117 uint64_t sc_fpregs[32];
3118 uint64_t sc_mdhi;
3119 uint64_t sc_hi1;
3120 uint64_t sc_hi2;
3121 uint64_t sc_hi3;
3122 uint64_t sc_mdlo;
3123 uint64_t sc_lo1;
3124 uint64_t sc_lo2;
3125 uint64_t sc_lo3;
3126 uint64_t sc_pc;
3127 uint32_t sc_fpc_csr;
3128 uint32_t sc_used_math;
3129 uint32_t sc_dsp;
3130 uint32_t sc_reserved;
3131};
3132# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003133
3134struct sigframe {
3135 uint32_t sf_ass[4]; /* argument save space for o32 */
3136 uint32_t sf_code[2]; /* signal trampoline */
3137 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003138 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003139};
3140
pbrook0b1bcb02009-04-21 01:41:10 +00003141struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003142 target_ulong tuc_flags;
3143 target_ulong tuc_link;
3144 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003145 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003146 struct target_sigcontext tuc_mcontext;
3147 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003148};
3149
3150struct target_rt_sigframe {
3151 uint32_t rs_ass[4]; /* argument save space for o32 */
3152 uint32_t rs_code[2]; /* signal trampoline */
3153 struct target_siginfo rs_info;
3154 struct target_ucontext rs_uc;
3155};
3156
bellard106ec872006-06-27 21:08:10 +00003157/* Install trampoline to jump back from signal handler */
3158static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3159{
Richard Henderson084d0492013-02-10 10:30:44 -08003160 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003161
3162 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003163 * Set up the return code ...
3164 *
3165 * li v0, __NR__foo_sigreturn
3166 * syscall
3167 */
bellard106ec872006-06-27 21:08:10 +00003168
Riku Voipio1d8b5122014-04-23 10:26:05 +03003169 __put_user(0x24020000 + syscall, tramp + 0);
3170 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003171 return err;
3172}
3173
Riku Voipio41ecc722014-04-23 11:01:00 +03003174static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003175 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003176{
Richard Henderson084d0492013-02-10 10:30:44 -08003177 int i;
bellard106ec872006-06-27 21:08:10 +00003178
Riku Voipio1d8b5122014-04-23 10:26:05 +03003179 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003180 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003181
Richard Henderson084d0492013-02-10 10:30:44 -08003182 __put_user(0, &sc->sc_regs[0]);
3183 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003184 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003185 }
bellard106ec872006-06-27 21:08:10 +00003186
Riku Voipio1d8b5122014-04-23 10:26:05 +03003187 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3188 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003189
Richard Henderson084d0492013-02-10 10:30:44 -08003190 /* Rather than checking for dsp existence, always copy. The storage
3191 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003192 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3193 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3194 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3195 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3196 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3197 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003198 {
3199 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003200 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003201 }
Richard Henderson084d0492013-02-10 10:30:44 -08003202
Riku Voipio1d8b5122014-04-23 10:26:05 +03003203 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003204
3205 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003206 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003207 }
bellard106ec872006-06-27 21:08:10 +00003208}
3209
Riku Voipio016d2e12014-04-23 11:19:48 +03003210static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003211restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003212{
Richard Henderson084d0492013-02-10 10:30:44 -08003213 int i;
bellard106ec872006-06-27 21:08:10 +00003214
Riku Voipio1d8b5122014-04-23 10:26:05 +03003215 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003216
Riku Voipio1d8b5122014-04-23 10:26:05 +03003217 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3218 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003219
Richard Henderson084d0492013-02-10 10:30:44 -08003220 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003221 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003222 }
3223
Riku Voipio1d8b5122014-04-23 10:26:05 +03003224 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3225 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3226 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3227 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3228 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3229 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003230 {
3231 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003232 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003233 cpu_wrdsp(dsp, 0x3ff, regs);
3234 }
3235
3236 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003237 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003238 }
bellard106ec872006-06-27 21:08:10 +00003239}
Richard Hendersonff970902013-02-10 10:30:42 -08003240
bellard106ec872006-06-27 21:08:10 +00003241/*
3242 * Determine which stack to use..
3243 */
bellard579a97f2007-11-11 14:26:47 +00003244static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003245get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003246{
3247 unsigned long sp;
3248
3249 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003250 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003251
3252 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003253 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003254 * above the user stack, 16-bytes before the next lowest
3255 * 16 byte boundary. Try to avoid trashing it.
3256 */
3257 sp -= 32;
3258
bellard106ec872006-06-27 21:08:10 +00003259 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003260 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003261 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3262 }
bellard106ec872006-06-27 21:08:10 +00003263
bellard579a97f2007-11-11 14:26:47 +00003264 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003265}
3266
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003267static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3268{
3269 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3270 env->hflags &= ~MIPS_HFLAG_M16;
3271 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3272 env->active_tc.PC &= ~(target_ulong) 1;
3273 }
3274}
3275
Richard Hendersonff970902013-02-10 10:30:42 -08003276# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003277/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003278static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003279 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003280{
3281 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003282 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003283 int i;
3284
bellard579a97f2007-11-11 14:26:47 +00003285 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003286 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003287 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3288 goto give_sigsegv;
3289 }
bellard106ec872006-06-27 21:08:10 +00003290
3291 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3292
Riku Voipio41ecc722014-04-23 11:01:00 +03003293 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003294
3295 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003296 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003297 }
3298
3299 /*
3300 * Arguments to signal handler:
3301 *
3302 * a0 = signal number
3303 * a1 = 0 (should be cause)
3304 * a2 = pointer to struct sigcontext
3305 *
3306 * $25 and PC point to the signal handler, $29 points to the
3307 * struct sigframe.
3308 */
thsb5dc7732008-06-27 10:02:35 +00003309 regs->active_tc.gpr[ 4] = sig;
3310 regs->active_tc.gpr[ 5] = 0;
3311 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3312 regs->active_tc.gpr[29] = frame_addr;
3313 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003314 /* The original kernel code sets CP0_EPC to the handler
3315 * since it returns to userland using eret
3316 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003317 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003318 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003319 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003320 return;
3321
3322give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003323 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003324}
3325
Andreas Färber05390242012-02-25 03:37:53 +01003326long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003327{
ths388bb212007-05-13 13:58:00 +00003328 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003329 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003330 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003331 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003332 int i;
bellard106ec872006-06-27 21:08:10 +00003333
thsb5dc7732008-06-27 10:02:35 +00003334 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003335 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003336 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003337 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003338
ths388bb212007-05-13 13:58:00 +00003339 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003340 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003341 }
bellard106ec872006-06-27 21:08:10 +00003342
ths388bb212007-05-13 13:58:00 +00003343 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003344 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003345
Riku Voipio016d2e12014-04-23 11:19:48 +03003346 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003347
3348#if 0
ths388bb212007-05-13 13:58:00 +00003349 /*
3350 * Don't let your children do this ...
3351 */
3352 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003353 "move\t$29, %0\n\t"
3354 "j\tsyscall_exit"
3355 :/* no outputs */
3356 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003357 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003358#endif
ths3b46e622007-09-17 08:09:54 +00003359
thsb5dc7732008-06-27 10:02:35 +00003360 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003361 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003362 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003363 * maybe a problem with nested signals ? */
3364 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003365 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003366
3367badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003368 force_sig(TARGET_SIGSEGV);
3369 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003370}
Richard Hendersonff970902013-02-10 10:30:42 -08003371# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003372
pbrook624f7972008-05-31 16:11:38 +00003373static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003374 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003375 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003376{
pbrook0b1bcb02009-04-21 01:41:10 +00003377 struct target_rt_sigframe *frame;
3378 abi_ulong frame_addr;
3379 int i;
3380
3381 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003382 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003383 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3384 goto give_sigsegv;
3385 }
pbrook0b1bcb02009-04-21 01:41:10 +00003386
3387 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3388
Peter Maydellf6c7a052015-01-08 12:19:48 +00003389 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003390
Aurelien Jarno60e99242010-03-29 02:12:51 +02003391 __put_user(0, &frame->rs_uc.tuc_flags);
3392 __put_user(0, &frame->rs_uc.tuc_link);
3393 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3394 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003395 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003396 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003397
Aurelien Jarno60e99242010-03-29 02:12:51 +02003398 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003399
3400 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003401 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003402 }
3403
3404 /*
3405 * Arguments to signal handler:
3406 *
3407 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003408 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003409 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003410 *
3411 * $25 and PC point to the signal handler, $29 points to the
3412 * struct sigframe.
3413 */
3414 env->active_tc.gpr[ 4] = sig;
3415 env->active_tc.gpr[ 5] = frame_addr
3416 + offsetof(struct target_rt_sigframe, rs_info);
3417 env->active_tc.gpr[ 6] = frame_addr
3418 + offsetof(struct target_rt_sigframe, rs_uc);
3419 env->active_tc.gpr[29] = frame_addr;
3420 env->active_tc.gpr[31] = frame_addr
3421 + offsetof(struct target_rt_sigframe, rs_code);
3422 /* The original kernel code sets CP0_EPC to the handler
3423 * since it returns to userland using eret
3424 * we cannot do this here, and we must set PC directly */
3425 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003426 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003427 unlock_user_struct(frame, frame_addr, 1);
3428 return;
3429
3430give_sigsegv:
3431 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003432 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003433}
3434
Andreas Färber05390242012-02-25 03:37:53 +01003435long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003436{
pbrook0b1bcb02009-04-21 01:41:10 +00003437 struct target_rt_sigframe *frame;
3438 abi_ulong frame_addr;
3439 sigset_t blocked;
3440
pbrook0b1bcb02009-04-21 01:41:10 +00003441 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003442 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003443 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3444 goto badframe;
3445 }
pbrook0b1bcb02009-04-21 01:41:10 +00003446
Aurelien Jarno60e99242010-03-29 02:12:51 +02003447 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003448 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003449
Riku Voipio016d2e12014-04-23 11:19:48 +03003450 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003451
3452 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003453 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3454 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003455 goto badframe;
3456
3457 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003458 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003459 /* I am not sure this is right, but it seems to work
3460 * maybe a problem with nested signals ? */
3461 env->CP0_EPC = 0;
3462 return -TARGET_QEMU_ESIGRETURN;
3463
3464badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003465 force_sig(TARGET_SIGSEGV);
3466 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003467}
bellard6d5e2162004-09-30 22:04:13 +00003468
thsc3b5bc82007-12-02 06:31:25 +00003469#elif defined(TARGET_SH4)
3470
3471/*
3472 * code and data structures from linux kernel:
3473 * include/asm-sh/sigcontext.h
3474 * arch/sh/kernel/signal.c
3475 */
3476
3477struct target_sigcontext {
3478 target_ulong oldmask;
3479
3480 /* CPU registers */
3481 target_ulong sc_gregs[16];
3482 target_ulong sc_pc;
3483 target_ulong sc_pr;
3484 target_ulong sc_sr;
3485 target_ulong sc_gbr;
3486 target_ulong sc_mach;
3487 target_ulong sc_macl;
3488
3489 /* FPU registers */
3490 target_ulong sc_fpregs[16];
3491 target_ulong sc_xfpregs[16];
3492 unsigned int sc_fpscr;
3493 unsigned int sc_fpul;
3494 unsigned int sc_ownedfp;
3495};
3496
3497struct target_sigframe
3498{
3499 struct target_sigcontext sc;
3500 target_ulong extramask[TARGET_NSIG_WORDS-1];
3501 uint16_t retcode[3];
3502};
3503
3504
3505struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003506 target_ulong tuc_flags;
3507 struct target_ucontext *tuc_link;
3508 target_stack_t tuc_stack;
3509 struct target_sigcontext tuc_mcontext;
3510 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003511};
3512
3513struct target_rt_sigframe
3514{
3515 struct target_siginfo info;
3516 struct target_ucontext uc;
3517 uint16_t retcode[3];
3518};
3519
3520
3521#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3522#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3523
pbrook624f7972008-05-31 16:11:38 +00003524static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003525 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003526{
pbrook624f7972008-05-31 16:11:38 +00003527 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003528 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3529 }
3530
3531 return (sp - frame_size) & -8ul;
3532}
3533
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003534/* Notice when we're in the middle of a gUSA region and reset.
3535 Note that this will only occur for !parallel_cpus, as we will
3536 translate such sequences differently in a parallel context. */
3537static void unwind_gusa(CPUSH4State *regs)
3538{
3539 /* If the stack pointer is sufficiently negative, and we haven't
3540 completed the sequence, then reset to the entry to the region. */
3541 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3542 However, the page mappings in qemu linux-user aren't as restricted
3543 and we wind up with the normal stack mapped above 0xF0000000.
3544 That said, there is no reason why the kernel should be allowing
3545 a gUSA region that spans 1GB. Use a tighter check here, for what
3546 can actually be enabled by the immediate move. */
3547 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3548 /* Reset the PC to before the gUSA region, as computed from
3549 R0 = region end, SP = -(region size), plus one more for the
3550 insn that actually initializes SP to the region size. */
3551 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3552
3553 /* Reset the SP to the saved version in R1. */
3554 regs->gregs[15] = regs->gregs[1];
3555 }
3556}
3557
Riku Voipio41ecc722014-04-23 11:01:00 +03003558static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003559 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003560{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003561 int i;
thsc3b5bc82007-12-02 06:31:25 +00003562
Riku Voipio1d8b5122014-04-23 10:26:05 +03003563#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003564 COPY(gregs[0]); COPY(gregs[1]);
3565 COPY(gregs[2]); COPY(gregs[3]);
3566 COPY(gregs[4]); COPY(gregs[5]);
3567 COPY(gregs[6]); COPY(gregs[7]);
3568 COPY(gregs[8]); COPY(gregs[9]);
3569 COPY(gregs[10]); COPY(gregs[11]);
3570 COPY(gregs[12]); COPY(gregs[13]);
3571 COPY(gregs[14]); COPY(gregs[15]);
3572 COPY(gbr); COPY(mach);
3573 COPY(macl); COPY(pr);
3574 COPY(sr); COPY(pc);
3575#undef COPY
3576
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003577 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003578 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003579 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003580 __put_user(regs->fpscr, &sc->sc_fpscr);
3581 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003582
3583 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003584 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003585}
3586
Timothy E Baldwinba412492016-05-12 18:47:35 +01003587static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003588{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003589 int i;
thsc3b5bc82007-12-02 06:31:25 +00003590
Riku Voipio1d8b5122014-04-23 10:26:05 +03003591#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003592 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003593 COPY(gregs[2]); COPY(gregs[3]);
3594 COPY(gregs[4]); COPY(gregs[5]);
3595 COPY(gregs[6]); COPY(gregs[7]);
3596 COPY(gregs[8]); COPY(gregs[9]);
3597 COPY(gregs[10]); COPY(gregs[11]);
3598 COPY(gregs[12]); COPY(gregs[13]);
3599 COPY(gregs[14]); COPY(gregs[15]);
3600 COPY(gbr); COPY(mach);
3601 COPY(macl); COPY(pr);
3602 COPY(sr); COPY(pc);
3603#undef COPY
3604
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003605 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003606 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003607 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003608 __get_user(regs->fpscr, &sc->sc_fpscr);
3609 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003610
3611 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003612 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003613}
3614
pbrook624f7972008-05-31 16:11:38 +00003615static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003616 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003617{
3618 struct target_sigframe *frame;
3619 abi_ulong frame_addr;
3620 int i;
thsc3b5bc82007-12-02 06:31:25 +00003621
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003622 unwind_gusa(regs);
3623
thsc3b5bc82007-12-02 06:31:25 +00003624 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003625 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003626 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3627 goto give_sigsegv;
3628 }
thsc3b5bc82007-12-02 06:31:25 +00003629
Riku Voipio41ecc722014-04-23 11:01:00 +03003630 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003631
3632 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003633 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003634 }
3635
3636 /* Set up to return from userspace. If provided, use a stub
3637 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003638 if (ka->sa_flags & TARGET_SA_RESTORER) {
3639 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003640 } else {
3641 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003642 abi_ulong retcode_addr = frame_addr +
3643 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003644 __put_user(MOVW(2), &frame->retcode[0]);
3645 __put_user(TRAP_NOARG, &frame->retcode[1]);
3646 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003647 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003648 }
3649
thsc3b5bc82007-12-02 06:31:25 +00003650 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003651 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003652 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003653 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003654 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003655 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003656 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003657
3658 unlock_user_struct(frame, frame_addr, 1);
3659 return;
3660
3661give_sigsegv:
3662 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003663 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003664}
3665
pbrook624f7972008-05-31 16:11:38 +00003666static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003667 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003668 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003669{
3670 struct target_rt_sigframe *frame;
3671 abi_ulong frame_addr;
3672 int i;
thsc3b5bc82007-12-02 06:31:25 +00003673
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003674 unwind_gusa(regs);
3675
thsc3b5bc82007-12-02 06:31:25 +00003676 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003677 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003678 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3679 goto give_sigsegv;
3680 }
thsc3b5bc82007-12-02 06:31:25 +00003681
Peter Maydellf6c7a052015-01-08 12:19:48 +00003682 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003683
3684 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003685 __put_user(0, &frame->uc.tuc_flags);
3686 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3687 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3688 &frame->uc.tuc_stack.ss_sp);
3689 __put_user(sas_ss_flags(regs->gregs[15]),
3690 &frame->uc.tuc_stack.ss_flags);
3691 __put_user(target_sigaltstack_used.ss_size,
3692 &frame->uc.tuc_stack.ss_size);
3693 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003694 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003695 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003696 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003697 }
3698
3699 /* Set up to return from userspace. If provided, use a stub
3700 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003701 if (ka->sa_flags & TARGET_SA_RESTORER) {
3702 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003703 } else {
3704 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003705 abi_ulong retcode_addr = frame_addr +
3706 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003707 __put_user(MOVW(2), &frame->retcode[0]);
3708 __put_user(TRAP_NOARG, &frame->retcode[1]);
3709 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003710 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003711 }
3712
thsc3b5bc82007-12-02 06:31:25 +00003713 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003714 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003715 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003716 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3717 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003718 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003719 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003720
3721 unlock_user_struct(frame, frame_addr, 1);
3722 return;
3723
3724give_sigsegv:
3725 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003726 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003727}
3728
Andreas Färber05390242012-02-25 03:37:53 +01003729long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003730{
3731 struct target_sigframe *frame;
3732 abi_ulong frame_addr;
3733 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003734 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003735 int i;
3736 int err = 0;
3737
thsc3b5bc82007-12-02 06:31:25 +00003738 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003739 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003740 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3741 goto badframe;
3742 }
thsc3b5bc82007-12-02 06:31:25 +00003743
Riku Voipio1d8b5122014-04-23 10:26:05 +03003744 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003745 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003746 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003747 }
3748
3749 if (err)
3750 goto badframe;
3751
3752 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003753 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003754
Timothy E Baldwinba412492016-05-12 18:47:35 +01003755 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003756
3757 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003758 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003759
3760badframe:
3761 unlock_user_struct(frame, frame_addr, 0);
3762 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003763 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003764}
3765
Andreas Färber05390242012-02-25 03:37:53 +01003766long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003767{
3768 struct target_rt_sigframe *frame;
3769 abi_ulong frame_addr;
3770 sigset_t blocked;
3771
thsc3b5bc82007-12-02 06:31:25 +00003772 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003773 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003774 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3775 goto badframe;
3776 }
thsc3b5bc82007-12-02 06:31:25 +00003777
Aurelien Jarno60e99242010-03-29 02:12:51 +02003778 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003779 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003780
Timothy E Baldwinba412492016-05-12 18:47:35 +01003781 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003782
3783 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003784 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3785 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003786 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003787 }
thsc3b5bc82007-12-02 06:31:25 +00003788
3789 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003790 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003791
3792badframe:
3793 unlock_user_struct(frame, frame_addr, 0);
3794 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003795 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003796}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003797#elif defined(TARGET_MICROBLAZE)
3798
3799struct target_sigcontext {
3800 struct target_pt_regs regs; /* needs to be first */
3801 uint32_t oldmask;
3802};
3803
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003804struct target_stack_t {
3805 abi_ulong ss_sp;
3806 int ss_flags;
3807 unsigned int ss_size;
3808};
3809
3810struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003811 abi_ulong tuc_flags;
3812 abi_ulong tuc_link;
3813 struct target_stack_t tuc_stack;
3814 struct target_sigcontext tuc_mcontext;
3815 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003816};
3817
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003818/* Signal frames. */
3819struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003820 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003821 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3822 uint32_t tramp[2];
3823};
3824
3825struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003826 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07003827 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003828 uint32_t tramp[2];
3829};
3830
Andreas Färber05390242012-02-25 03:37:53 +01003831static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003832{
3833 __put_user(env->regs[0], &sc->regs.r0);
3834 __put_user(env->regs[1], &sc->regs.r1);
3835 __put_user(env->regs[2], &sc->regs.r2);
3836 __put_user(env->regs[3], &sc->regs.r3);
3837 __put_user(env->regs[4], &sc->regs.r4);
3838 __put_user(env->regs[5], &sc->regs.r5);
3839 __put_user(env->regs[6], &sc->regs.r6);
3840 __put_user(env->regs[7], &sc->regs.r7);
3841 __put_user(env->regs[8], &sc->regs.r8);
3842 __put_user(env->regs[9], &sc->regs.r9);
3843 __put_user(env->regs[10], &sc->regs.r10);
3844 __put_user(env->regs[11], &sc->regs.r11);
3845 __put_user(env->regs[12], &sc->regs.r12);
3846 __put_user(env->regs[13], &sc->regs.r13);
3847 __put_user(env->regs[14], &sc->regs.r14);
3848 __put_user(env->regs[15], &sc->regs.r15);
3849 __put_user(env->regs[16], &sc->regs.r16);
3850 __put_user(env->regs[17], &sc->regs.r17);
3851 __put_user(env->regs[18], &sc->regs.r18);
3852 __put_user(env->regs[19], &sc->regs.r19);
3853 __put_user(env->regs[20], &sc->regs.r20);
3854 __put_user(env->regs[21], &sc->regs.r21);
3855 __put_user(env->regs[22], &sc->regs.r22);
3856 __put_user(env->regs[23], &sc->regs.r23);
3857 __put_user(env->regs[24], &sc->regs.r24);
3858 __put_user(env->regs[25], &sc->regs.r25);
3859 __put_user(env->regs[26], &sc->regs.r26);
3860 __put_user(env->regs[27], &sc->regs.r27);
3861 __put_user(env->regs[28], &sc->regs.r28);
3862 __put_user(env->regs[29], &sc->regs.r29);
3863 __put_user(env->regs[30], &sc->regs.r30);
3864 __put_user(env->regs[31], &sc->regs.r31);
3865 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3866}
3867
Andreas Färber05390242012-02-25 03:37:53 +01003868static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003869{
3870 __get_user(env->regs[0], &sc->regs.r0);
3871 __get_user(env->regs[1], &sc->regs.r1);
3872 __get_user(env->regs[2], &sc->regs.r2);
3873 __get_user(env->regs[3], &sc->regs.r3);
3874 __get_user(env->regs[4], &sc->regs.r4);
3875 __get_user(env->regs[5], &sc->regs.r5);
3876 __get_user(env->regs[6], &sc->regs.r6);
3877 __get_user(env->regs[7], &sc->regs.r7);
3878 __get_user(env->regs[8], &sc->regs.r8);
3879 __get_user(env->regs[9], &sc->regs.r9);
3880 __get_user(env->regs[10], &sc->regs.r10);
3881 __get_user(env->regs[11], &sc->regs.r11);
3882 __get_user(env->regs[12], &sc->regs.r12);
3883 __get_user(env->regs[13], &sc->regs.r13);
3884 __get_user(env->regs[14], &sc->regs.r14);
3885 __get_user(env->regs[15], &sc->regs.r15);
3886 __get_user(env->regs[16], &sc->regs.r16);
3887 __get_user(env->regs[17], &sc->regs.r17);
3888 __get_user(env->regs[18], &sc->regs.r18);
3889 __get_user(env->regs[19], &sc->regs.r19);
3890 __get_user(env->regs[20], &sc->regs.r20);
3891 __get_user(env->regs[21], &sc->regs.r21);
3892 __get_user(env->regs[22], &sc->regs.r22);
3893 __get_user(env->regs[23], &sc->regs.r23);
3894 __get_user(env->regs[24], &sc->regs.r24);
3895 __get_user(env->regs[25], &sc->regs.r25);
3896 __get_user(env->regs[26], &sc->regs.r26);
3897 __get_user(env->regs[27], &sc->regs.r27);
3898 __get_user(env->regs[28], &sc->regs.r28);
3899 __get_user(env->regs[29], &sc->regs.r29);
3900 __get_user(env->regs[30], &sc->regs.r30);
3901 __get_user(env->regs[31], &sc->regs.r31);
3902 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3903}
3904
3905static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003906 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003907{
3908 abi_ulong sp = env->regs[1];
3909
Riku Voipiob545f632014-07-15 17:01:55 +03003910 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003911 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003912 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003913
3914 return ((sp - frame_size) & -8UL);
3915}
3916
3917static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003918 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003919{
3920 struct target_signal_frame *frame;
3921 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003922 int i;
3923
3924 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003925 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003926 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3927 goto badframe;
3928
3929 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003930 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003931
3932 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003933 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003934 }
3935
Richard Hendersonf711df62010-11-22 14:57:52 -08003936 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003937
3938 /* Set up to return from userspace. If provided, use a stub
3939 already in userspace. */
3940 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3941 if (ka->sa_flags & TARGET_SA_RESTORER) {
3942 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3943 } else {
3944 uint32_t t;
3945 /* Note, these encodings are _big endian_! */
3946 /* addi r12, r0, __NR_sigreturn */
3947 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003948 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003949 /* brki r14, 0x8 */
3950 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003951 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003952
3953 /* Return from sighandler will jump to the tramp.
3954 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003955 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3956 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003957 }
3958
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003959 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003960 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003961 /* Signal handler args: */
3962 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003963 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003964 /* arg 1: sigcontext */
3965 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003966
3967 /* Offset of 4 to handle microblaze rtid r14, 0 */
3968 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3969
3970 unlock_user_struct(frame, frame_addr, 1);
3971 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003972badframe:
Peter Maydell09391662016-07-28 16:44:47 +01003973 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003974}
3975
3976static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003977 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003978 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003979{
3980 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3981}
3982
Andreas Färber05390242012-02-25 03:37:53 +01003983long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003984{
3985 struct target_signal_frame *frame;
3986 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003987 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003988 sigset_t set;
3989 int i;
3990
3991 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003992 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003993 /* Make sure the guest isn't playing games. */
3994 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3995 goto badframe;
3996
3997 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003998 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003999 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004000 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004001 }
4002 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004003 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004004
Richard Hendersonf711df62010-11-22 14:57:52 -08004005 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004006 /* We got here through a sigreturn syscall, our path back is via an
4007 rtb insn so setup r14 for that. */
4008 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004009
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004010 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004011 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004012badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004013 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004014 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004015}
4016
Andreas Färber05390242012-02-25 03:37:53 +01004017long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004018{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004019 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004020 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4021 return -TARGET_ENOSYS;
4022}
4023
edgar_iglb6d3abd2008-02-28 11:29:27 +00004024#elif defined(TARGET_CRIS)
4025
4026struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004027 struct target_pt_regs regs; /* needs to be first */
4028 uint32_t oldmask;
4029 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004030};
4031
4032/* Signal frames. */
4033struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004034 struct target_sigcontext sc;
4035 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4036 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004037};
4038
4039struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004040 siginfo_t *pinfo;
4041 void *puc;
4042 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004043 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004044 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004045};
4046
Andreas Färber05390242012-02-25 03:37:53 +01004047static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004048{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004049 __put_user(env->regs[0], &sc->regs.r0);
4050 __put_user(env->regs[1], &sc->regs.r1);
4051 __put_user(env->regs[2], &sc->regs.r2);
4052 __put_user(env->regs[3], &sc->regs.r3);
4053 __put_user(env->regs[4], &sc->regs.r4);
4054 __put_user(env->regs[5], &sc->regs.r5);
4055 __put_user(env->regs[6], &sc->regs.r6);
4056 __put_user(env->regs[7], &sc->regs.r7);
4057 __put_user(env->regs[8], &sc->regs.r8);
4058 __put_user(env->regs[9], &sc->regs.r9);
4059 __put_user(env->regs[10], &sc->regs.r10);
4060 __put_user(env->regs[11], &sc->regs.r11);
4061 __put_user(env->regs[12], &sc->regs.r12);
4062 __put_user(env->regs[13], &sc->regs.r13);
4063 __put_user(env->regs[14], &sc->usp);
4064 __put_user(env->regs[15], &sc->regs.acr);
4065 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4066 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4067 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004068}
edgar_igl9664d922008-03-03 22:23:53 +00004069
Andreas Färber05390242012-02-25 03:37:53 +01004070static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004071{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004072 __get_user(env->regs[0], &sc->regs.r0);
4073 __get_user(env->regs[1], &sc->regs.r1);
4074 __get_user(env->regs[2], &sc->regs.r2);
4075 __get_user(env->regs[3], &sc->regs.r3);
4076 __get_user(env->regs[4], &sc->regs.r4);
4077 __get_user(env->regs[5], &sc->regs.r5);
4078 __get_user(env->regs[6], &sc->regs.r6);
4079 __get_user(env->regs[7], &sc->regs.r7);
4080 __get_user(env->regs[8], &sc->regs.r8);
4081 __get_user(env->regs[9], &sc->regs.r9);
4082 __get_user(env->regs[10], &sc->regs.r10);
4083 __get_user(env->regs[11], &sc->regs.r11);
4084 __get_user(env->regs[12], &sc->regs.r12);
4085 __get_user(env->regs[13], &sc->regs.r13);
4086 __get_user(env->regs[14], &sc->usp);
4087 __get_user(env->regs[15], &sc->regs.acr);
4088 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4089 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4090 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004091}
4092
Andreas Färber05390242012-02-25 03:37:53 +01004093static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004094{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004095 abi_ulong sp;
4096 /* Align the stack downwards to 4. */
4097 sp = (env->regs[R_SP] & ~3);
4098 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004099}
4100
pbrook624f7972008-05-31 16:11:38 +00004101static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004102 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004103{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004104 struct target_signal_frame *frame;
4105 abi_ulong frame_addr;
4106 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004107
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004108 frame_addr = get_sigframe(env, sizeof *frame);
4109 trace_user_setup_frame(env, frame_addr);
4110 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4111 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004112
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004113 /*
4114 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4115 * use this trampoline anymore but it sets it up for GDB.
4116 * In QEMU, using the trampoline simplifies things a bit so we use it.
4117 *
4118 * This is movu.w __NR_sigreturn, r9; break 13;
4119 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004120 __put_user(0x9c5f, frame->retcode+0);
4121 __put_user(TARGET_NR_sigreturn,
4122 frame->retcode + 1);
4123 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004124
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004125 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004126 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004127
Riku Voipio0188fad2014-04-23 13:34:15 +03004128 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4129 __put_user(set->sig[i], &frame->extramask[i - 1]);
4130 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004132 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004133
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004134 /* Move the stack and setup the arguments for the handler. */
4135 env->regs[R_SP] = frame_addr;
4136 env->regs[10] = sig;
4137 env->pc = (unsigned long) ka->_sa_handler;
4138 /* Link SRP so the guest returns through the trampoline. */
4139 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004140
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004141 unlock_user_struct(frame, frame_addr, 1);
4142 return;
4143badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004144 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004145}
4146
pbrook624f7972008-05-31 16:11:38 +00004147static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004148 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004149 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004150{
4151 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4152}
4153
Andreas Färber05390242012-02-25 03:37:53 +01004154long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004155{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004156 struct target_signal_frame *frame;
4157 abi_ulong frame_addr;
4158 target_sigset_t target_set;
4159 sigset_t set;
4160 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004161
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004162 frame_addr = env->regs[R_SP];
4163 trace_user_do_sigreturn(env, frame_addr);
4164 /* Make sure the guest isn't playing games. */
4165 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4166 goto badframe;
4167 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004168
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004169 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004170 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004171 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004172 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004173 }
4174 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004175 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004176
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004177 restore_sigcontext(&frame->sc, env);
4178 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004179 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004180badframe:
4181 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004182 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004183}
4184
Andreas Färber05390242012-02-25 03:37:53 +01004185long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004186{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004187 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004188 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4189 return -TARGET_ENOSYS;
4190}
thsc3b5bc82007-12-02 06:31:25 +00004191
Marek Vasuta0a839b2017-01-18 23:01:42 +01004192#elif defined(TARGET_NIOS2)
4193
4194#define MCONTEXT_VERSION 2
4195
4196struct target_sigcontext {
4197 int version;
4198 unsigned long gregs[32];
4199};
4200
4201struct target_ucontext {
4202 abi_ulong tuc_flags;
4203 abi_ulong tuc_link;
4204 target_stack_t tuc_stack;
4205 struct target_sigcontext tuc_mcontext;
4206 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4207};
4208
4209struct target_rt_sigframe {
4210 struct target_siginfo info;
4211 struct target_ucontext uc;
4212};
4213
4214static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4215{
4216 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4217#ifdef CONFIG_STACK_GROWSUP
4218 return target_sigaltstack_used.ss_sp;
4219#else
4220 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4221#endif
4222 }
4223 return sp;
4224}
4225
4226static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4227{
4228 unsigned long *gregs = uc->tuc_mcontext.gregs;
4229
4230 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4231 __put_user(env->regs[1], &gregs[0]);
4232 __put_user(env->regs[2], &gregs[1]);
4233 __put_user(env->regs[3], &gregs[2]);
4234 __put_user(env->regs[4], &gregs[3]);
4235 __put_user(env->regs[5], &gregs[4]);
4236 __put_user(env->regs[6], &gregs[5]);
4237 __put_user(env->regs[7], &gregs[6]);
4238 __put_user(env->regs[8], &gregs[7]);
4239 __put_user(env->regs[9], &gregs[8]);
4240 __put_user(env->regs[10], &gregs[9]);
4241 __put_user(env->regs[11], &gregs[10]);
4242 __put_user(env->regs[12], &gregs[11]);
4243 __put_user(env->regs[13], &gregs[12]);
4244 __put_user(env->regs[14], &gregs[13]);
4245 __put_user(env->regs[15], &gregs[14]);
4246 __put_user(env->regs[16], &gregs[15]);
4247 __put_user(env->regs[17], &gregs[16]);
4248 __put_user(env->regs[18], &gregs[17]);
4249 __put_user(env->regs[19], &gregs[18]);
4250 __put_user(env->regs[20], &gregs[19]);
4251 __put_user(env->regs[21], &gregs[20]);
4252 __put_user(env->regs[22], &gregs[21]);
4253 __put_user(env->regs[23], &gregs[22]);
4254 __put_user(env->regs[R_RA], &gregs[23]);
4255 __put_user(env->regs[R_FP], &gregs[24]);
4256 __put_user(env->regs[R_GP], &gregs[25]);
4257 __put_user(env->regs[R_EA], &gregs[27]);
4258 __put_user(env->regs[R_SP], &gregs[28]);
4259
4260 return 0;
4261}
4262
4263static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4264 int *pr2)
4265{
4266 int temp;
4267 abi_ulong off, frame_addr = env->regs[R_SP];
4268 unsigned long *gregs = uc->tuc_mcontext.gregs;
4269 int err;
4270
4271 /* Always make any pending restarted system calls return -EINTR */
4272 /* current->restart_block.fn = do_no_restart_syscall; */
4273
4274 __get_user(temp, &uc->tuc_mcontext.version);
4275 if (temp != MCONTEXT_VERSION) {
4276 return 1;
4277 }
4278
4279 /* restore passed registers */
4280 __get_user(env->regs[1], &gregs[0]);
4281 __get_user(env->regs[2], &gregs[1]);
4282 __get_user(env->regs[3], &gregs[2]);
4283 __get_user(env->regs[4], &gregs[3]);
4284 __get_user(env->regs[5], &gregs[4]);
4285 __get_user(env->regs[6], &gregs[5]);
4286 __get_user(env->regs[7], &gregs[6]);
4287 __get_user(env->regs[8], &gregs[7]);
4288 __get_user(env->regs[9], &gregs[8]);
4289 __get_user(env->regs[10], &gregs[9]);
4290 __get_user(env->regs[11], &gregs[10]);
4291 __get_user(env->regs[12], &gregs[11]);
4292 __get_user(env->regs[13], &gregs[12]);
4293 __get_user(env->regs[14], &gregs[13]);
4294 __get_user(env->regs[15], &gregs[14]);
4295 __get_user(env->regs[16], &gregs[15]);
4296 __get_user(env->regs[17], &gregs[16]);
4297 __get_user(env->regs[18], &gregs[17]);
4298 __get_user(env->regs[19], &gregs[18]);
4299 __get_user(env->regs[20], &gregs[19]);
4300 __get_user(env->regs[21], &gregs[20]);
4301 __get_user(env->regs[22], &gregs[21]);
4302 __get_user(env->regs[23], &gregs[22]);
4303 /* gregs[23] is handled below */
4304 /* Verify, should this be settable */
4305 __get_user(env->regs[R_FP], &gregs[24]);
4306 /* Verify, should this be settable */
4307 __get_user(env->regs[R_GP], &gregs[25]);
4308 /* Not really necessary no user settable bits */
4309 __get_user(temp, &gregs[26]);
4310 __get_user(env->regs[R_EA], &gregs[27]);
4311
4312 __get_user(env->regs[R_RA], &gregs[23]);
4313 __get_user(env->regs[R_SP], &gregs[28]);
4314
4315 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4316 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4317 if (err == -EFAULT) {
4318 return 1;
4319 }
4320
4321 *pr2 = env->regs[2];
4322 return 0;
4323}
4324
4325static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4326 size_t frame_size)
4327{
4328 unsigned long usp;
4329
4330 /* Default to using normal stack. */
4331 usp = env->regs[R_SP];
4332
4333 /* This is the X/Open sanctioned signal stack switching. */
4334 usp = sigsp(usp, ka);
4335
4336 /* Verify, is it 32 or 64 bit aligned */
4337 return (void *)((usp - frame_size) & -8UL);
4338}
4339
4340static void setup_rt_frame(int sig, struct target_sigaction *ka,
4341 target_siginfo_t *info,
4342 target_sigset_t *set,
4343 CPUNios2State *env)
4344{
4345 struct target_rt_sigframe *frame;
4346 int i, err = 0;
4347
4348 frame = get_sigframe(ka, env, sizeof(*frame));
4349
4350 if (ka->sa_flags & SA_SIGINFO) {
4351 tswap_siginfo(&frame->info, info);
4352 }
4353
4354 /* Create the ucontext. */
4355 __put_user(0, &frame->uc.tuc_flags);
4356 __put_user(0, &frame->uc.tuc_link);
4357 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4358 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4359 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4360 err |= rt_setup_ucontext(&frame->uc, env);
4361 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4362 __put_user((abi_ulong)set->sig[i],
4363 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4364 }
4365
4366 if (err) {
4367 goto give_sigsegv;
4368 }
4369
4370 /* Set up to return from userspace; jump to fixed address sigreturn
4371 trampoline on kuser page. */
4372 env->regs[R_RA] = (unsigned long) (0x1044);
4373
4374 /* Set up registers for signal handler */
4375 env->regs[R_SP] = (unsigned long) frame;
4376 env->regs[4] = (unsigned long) sig;
4377 env->regs[5] = (unsigned long) &frame->info;
4378 env->regs[6] = (unsigned long) &frame->uc;
4379 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4380 return;
4381
4382give_sigsegv:
4383 if (sig == TARGET_SIGSEGV) {
4384 ka->_sa_handler = TARGET_SIG_DFL;
4385 }
4386 force_sigsegv(sig);
4387 return;
4388}
4389
4390long do_sigreturn(CPUNios2State *env)
4391{
4392 trace_user_do_sigreturn(env, 0);
4393 fprintf(stderr, "do_sigreturn: not implemented\n");
4394 return -TARGET_ENOSYS;
4395}
4396
4397long do_rt_sigreturn(CPUNios2State *env)
4398{
4399 /* Verify, can we follow the stack back */
4400 abi_ulong frame_addr = env->regs[R_SP];
4401 struct target_rt_sigframe *frame;
4402 sigset_t set;
4403 int rval;
4404
4405 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4406 goto badframe;
4407 }
4408
4409 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4410 do_sigprocmask(SIG_SETMASK, &set, NULL);
4411
4412 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4413 goto badframe;
4414 }
4415
4416 unlock_user_struct(frame, frame_addr, 0);
4417 return rval;
4418
4419badframe:
4420 unlock_user_struct(frame, frame_addr, 0);
4421 force_sig(TARGET_SIGSEGV);
4422 return 0;
4423}
4424/* TARGET_NIOS2 */
4425
Jia Liud9627832012-07-20 15:50:52 +08004426#elif defined(TARGET_OPENRISC)
4427
4428struct target_sigcontext {
4429 struct target_pt_regs regs;
4430 abi_ulong oldmask;
4431 abi_ulong usp;
4432};
4433
4434struct target_ucontext {
4435 abi_ulong tuc_flags;
4436 abi_ulong tuc_link;
4437 target_stack_t tuc_stack;
4438 struct target_sigcontext tuc_mcontext;
4439 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4440};
4441
4442struct target_rt_sigframe {
4443 abi_ulong pinfo;
4444 uint64_t puc;
4445 struct target_siginfo info;
4446 struct target_sigcontext sc;
4447 struct target_ucontext uc;
4448 unsigned char retcode[16]; /* trampoline code */
4449};
4450
4451/* This is the asm-generic/ucontext.h version */
4452#if 0
4453static int restore_sigcontext(CPUOpenRISCState *regs,
4454 struct target_sigcontext *sc)
4455{
4456 unsigned int err = 0;
4457 unsigned long old_usp;
4458
4459 /* Alwys make any pending restarted system call return -EINTR */
4460 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4461
4462 /* restore the regs from &sc->regs (same as sc, since regs is first)
4463 * (sc is already checked for VERIFY_READ since the sigframe was
4464 * checked in sys_sigreturn previously)
4465 */
4466
4467 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4468 goto badframe;
4469 }
4470
4471 /* make sure the U-flag is set so user-mode cannot fool us */
4472
4473 regs->sr &= ~SR_SM;
4474
4475 /* restore the old USP as it was before we stacked the sc etc.
4476 * (we cannot just pop the sigcontext since we aligned the sp and
4477 * stuff after pushing it)
4478 */
4479
Riku Voipio1d8b5122014-04-23 10:26:05 +03004480 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004481 phx_signal("old_usp 0x%lx", old_usp);
4482
4483 __PHX__ REALLY /* ??? */
4484 wrusp(old_usp);
4485 regs->gpr[1] = old_usp;
4486
4487 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4488 * after this completes, but we don't use that mechanism. maybe we can
4489 * use it now ?
4490 */
4491
4492 return err;
4493
4494badframe:
4495 return 1;
4496}
4497#endif
4498
4499/* Set up a signal frame. */
4500
Riku Voipio41ecc722014-04-23 11:01:00 +03004501static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004502 CPUOpenRISCState *regs,
4503 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004504{
Stafford Horned89e71e2017-04-06 06:44:56 +09004505 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004506
4507 /* copy the regs. they are first in sc so we can use sc directly */
4508
Riku Voipio1d8b5122014-04-23 10:26:05 +03004509 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004510
4511 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4512 the signal handler. The frametype will be restored to its previous
4513 value in restore_sigcontext. */
4514 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4515
4516 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004517 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004518 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004519}
4520
4521static inline unsigned long align_sigframe(unsigned long sp)
4522{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004523 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004524}
4525
4526static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4527 CPUOpenRISCState *regs,
4528 size_t frame_size)
4529{
Stafford Horned89e71e2017-04-06 06:44:56 +09004530 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004531 int onsigstack = on_sig_stack(sp);
4532
4533 /* redzone */
4534 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004535 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004536 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4537 }
4538
4539 sp = align_sigframe(sp - frame_size);
4540
4541 /*
4542 * If we are on the alternate signal stack and would overflow it, don't.
4543 * Return an always-bogus address instead so we will die with SIGSEGV.
4544 */
4545
4546 if (onsigstack && !likely(on_sig_stack(sp))) {
4547 return -1L;
4548 }
4549
4550 return sp;
4551}
4552
Jia Liud9627832012-07-20 15:50:52 +08004553static void setup_rt_frame(int sig, struct target_sigaction *ka,
4554 target_siginfo_t *info,
4555 target_sigset_t *set, CPUOpenRISCState *env)
4556{
4557 int err = 0;
4558 abi_ulong frame_addr;
4559 unsigned long return_ip;
4560 struct target_rt_sigframe *frame;
4561 abi_ulong info_addr, uc_addr;
4562
Jia Liud9627832012-07-20 15:50:52 +08004563 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004564 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004565 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4566 goto give_sigsegv;
4567 }
4568
4569 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004570 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004571 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004572 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004573
4574 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004575 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004576 }
4577
Khem Raj04b33e22017-06-28 13:44:52 -07004578 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004579 __put_user(0, &frame->uc.tuc_flags);
4580 __put_user(0, &frame->uc.tuc_link);
4581 __put_user(target_sigaltstack_used.ss_sp,
4582 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004583 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4584 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004585 __put_user(target_sigaltstack_used.ss_size,
4586 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004587 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004588
4589 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4590
Jia Liud9627832012-07-20 15:50:52 +08004591 /* trampoline - the desired return ip is the retcode itself */
4592 return_ip = (unsigned long)&frame->retcode;
4593 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004594 __put_user(0xa960, (short *)(frame->retcode + 0));
4595 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4596 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4597 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004598
4599 if (err) {
4600 goto give_sigsegv;
4601 }
4602
4603 /* TODO what is the current->exec_domain stuff and invmap ? */
4604
4605 /* Set up registers for signal handler */
4606 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004607 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4608 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4609 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4610 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004611
4612 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004613 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004614
4615 return;
4616
4617give_sigsegv:
4618 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004619 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004620}
4621
4622long do_sigreturn(CPUOpenRISCState *env)
4623{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004624 trace_user_do_sigreturn(env, 0);
4625 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004626 return -TARGET_ENOSYS;
4627}
4628
4629long do_rt_sigreturn(CPUOpenRISCState *env)
4630{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004631 trace_user_do_rt_sigreturn(env, 0);
4632 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004633 return -TARGET_ENOSYS;
4634}
4635/* TARGET_OPENRISC */
4636
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004637#elif defined(TARGET_S390X)
4638
4639#define __NUM_GPRS 16
4640#define __NUM_FPRS 16
4641#define __NUM_ACRS 16
4642
4643#define S390_SYSCALL_SIZE 2
4644#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4645
4646#define _SIGCONTEXT_NSIG 64
4647#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4648#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4649#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4650#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4651#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4652
4653typedef struct {
4654 target_psw_t psw;
4655 target_ulong gprs[__NUM_GPRS];
4656 unsigned int acrs[__NUM_ACRS];
4657} target_s390_regs_common;
4658
4659typedef struct {
4660 unsigned int fpc;
4661 double fprs[__NUM_FPRS];
4662} target_s390_fp_regs;
4663
4664typedef struct {
4665 target_s390_regs_common regs;
4666 target_s390_fp_regs fpregs;
4667} target_sigregs;
4668
4669struct target_sigcontext {
4670 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4671 target_sigregs *sregs;
4672};
4673
4674typedef struct {
4675 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4676 struct target_sigcontext sc;
4677 target_sigregs sregs;
4678 int signo;
4679 uint8_t retcode[S390_SYSCALL_SIZE];
4680} sigframe;
4681
4682struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004683 target_ulong tuc_flags;
4684 struct target_ucontext *tuc_link;
4685 target_stack_t tuc_stack;
4686 target_sigregs tuc_mcontext;
4687 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004688};
4689
4690typedef struct {
4691 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4692 uint8_t retcode[S390_SYSCALL_SIZE];
4693 struct target_siginfo info;
4694 struct target_ucontext uc;
4695} rt_sigframe;
4696
4697static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004698get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004699{
4700 abi_ulong sp;
4701
4702 /* Default to using normal stack */
4703 sp = env->regs[15];
4704
4705 /* This is the X/Open sanctioned signal stack switching. */
4706 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4707 if (!sas_ss_flags(sp)) {
4708 sp = target_sigaltstack_used.ss_sp +
4709 target_sigaltstack_used.ss_size;
4710 }
4711 }
4712
4713 /* This is the legacy signal stack switching. */
4714 else if (/* FIXME !user_mode(regs) */ 0 &&
4715 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4716 ka->sa_restorer) {
4717 sp = (abi_ulong) ka->sa_restorer;
4718 }
4719
4720 return (sp - frame_size) & -8ul;
4721}
4722
Andreas Färber05390242012-02-25 03:37:53 +01004723static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004724{
4725 int i;
4726 //save_access_regs(current->thread.acrs); FIXME
4727
4728 /* Copy a 'clean' PSW mask to the user to avoid leaking
4729 information about whether PER is currently on. */
4730 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4731 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4732 for (i = 0; i < 16; i++) {
4733 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4734 }
4735 for (i = 0; i < 16; i++) {
4736 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4737 }
4738 /*
4739 * We have to store the fp registers to current->thread.fp_regs
4740 * to merge them with the emulated registers.
4741 */
4742 //save_fp_regs(&current->thread.fp_regs); FIXME
4743 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004744 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004745 }
4746}
4747
4748static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004749 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004750{
4751 sigframe *frame;
4752 abi_ulong frame_addr;
4753
4754 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004755 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004756 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004757 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004758 }
4759
Riku Voipio0188fad2014-04-23 13:34:15 +03004760 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004761
4762 save_sigregs(env, &frame->sregs);
4763
4764 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4765 (abi_ulong *)&frame->sc.sregs);
4766
4767 /* Set up to return from userspace. If provided, use a stub
4768 already in userspace. */
4769 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004770 env->regs[14] = (unsigned long)
4771 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004772 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004773 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4774 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004775 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4776 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004777 }
4778
4779 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004780 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004781
4782 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004783 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004784 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4785
4786 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004787 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004788
4789 /* We forgot to include these in the sigcontext.
4790 To avoid breaking binary compatibility, they are passed as args. */
4791 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4792 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4793
4794 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02004795 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004796 unlock_user_struct(frame, frame_addr, 1);
4797 return;
4798
4799give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004800 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004801}
4802
4803static void setup_rt_frame(int sig, struct target_sigaction *ka,
4804 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004805 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004806{
4807 int i;
4808 rt_sigframe *frame;
4809 abi_ulong frame_addr;
4810
4811 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004812 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004813 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4814 goto give_sigsegv;
4815 }
4816
Peter Maydellf6c7a052015-01-08 12:19:48 +00004817 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004818
4819 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004820 __put_user(0, &frame->uc.tuc_flags);
4821 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4822 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004823 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004824 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004825 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4826 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004827 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4828 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004829 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004830 }
4831
4832 /* Set up to return from userspace. If provided, use a stub
4833 already in userspace. */
4834 if (ka->sa_flags & TARGET_SA_RESTORER) {
4835 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4836 } else {
4837 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004838 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4839 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004840 }
4841
4842 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004843 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004844
4845 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004846 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004847 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4848
4849 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004850 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4851 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004852 return;
4853
4854give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004855 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004856}
4857
4858static int
Andreas Färber05390242012-02-25 03:37:53 +01004859restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004860{
4861 int err = 0;
4862 int i;
4863
4864 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004865 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004866 }
4867
Riku Voipio1d8b5122014-04-23 10:26:05 +03004868 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004869 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4870 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004871 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004872 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4873
4874 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004875 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004876 }
4877 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004878 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004879 }
4880
4881 return err;
4882}
4883
Andreas Färber05390242012-02-25 03:37:53 +01004884long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004885{
4886 sigframe *frame;
4887 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004888 target_sigset_t target_set;
4889 sigset_t set;
4890
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004891 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004892 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4893 goto badframe;
4894 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004895 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004896
4897 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004898 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004899
4900 if (restore_sigregs(env, &frame->sregs)) {
4901 goto badframe;
4902 }
4903
4904 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004905 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004906
4907badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004908 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004909 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004910}
4911
Andreas Färber05390242012-02-25 03:37:53 +01004912long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004913{
4914 rt_sigframe *frame;
4915 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004916 sigset_t set;
4917
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004918 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004919 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4920 goto badframe;
4921 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004922 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004923
Peter Maydell9eede5b2016-05-27 15:51:46 +01004924 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004925
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004926 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004927 goto badframe;
4928 }
4929
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004930 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004931 get_sp_from_cpustate(env)) == -EFAULT) {
4932 goto badframe;
4933 }
4934 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004935 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004936
4937badframe:
4938 unlock_user_struct(frame, frame_addr, 0);
4939 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004940 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004941}
4942
Tom Musta61e75fe2014-06-30 08:13:38 -05004943#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004944
4945/* Size of dummy stack frame allocated when calling signal handler.
4946 See arch/powerpc/include/asm/ptrace.h. */
4947#if defined(TARGET_PPC64)
4948#define SIGNAL_FRAMESIZE 128
4949#else
4950#define SIGNAL_FRAMESIZE 64
4951#endif
4952
Tom Musta61e75fe2014-06-30 08:13:38 -05004953/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4954 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4955struct target_mcontext {
4956 target_ulong mc_gregs[48];
4957 /* Includes fpscr. */
4958 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004959#if defined(TARGET_PPC64)
4960 /* Pointer to the vector regs */
4961 target_ulong v_regs;
4962#else
Tom Musta61e75fe2014-06-30 08:13:38 -05004963 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004964#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05004965 /* We need to handle Altivec and SPE at the same time, which no
4966 kernel needs to do. Fortunately, the kernel defines this bit to
4967 be Altivec-register-large all the time, rather than trying to
4968 twiddle it based on the specific platform. */
4969 union {
4970 /* SPE vector registers. One extra for SPEFSCR. */
4971 uint32_t spe[33];
4972 /* Altivec vector registers. The packing of VSCR and VRSAVE
4973 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004974 them apart; PPC32 stuffs them together.
4975 We also need to account for the VSX registers on PPC64
4976 */
Tom Musta61e75fe2014-06-30 08:13:38 -05004977#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004978#define QEMU_NVRREG (34 + 16)
4979 /* On ppc64, this mcontext structure is naturally *unaligned*,
4980 * or rather it is aligned on a 8 bytes boundary but not on
4981 * a 16 bytes one. This pad fixes it up. This is also why the
4982 * vector regs are referenced by the v_regs pointer above so
4983 * any amount of padding can be added here
4984 */
4985 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05004986#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004987 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05004988#define QEMU_NVRREG 33
4989#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004990 /* We cannot use ppc_avr_t here as we do *not* want the implied
4991 * 16-bytes alignment that would result from it. This would have
4992 * the effect of making the whole struct target_mcontext aligned
4993 * which breaks the layout of struct target_ucontext on ppc64.
4994 */
4995 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05004996#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10004997 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05004998};
4999
Nathan Froydbcd49332009-05-12 19:13:18 -07005000/* See arch/powerpc/include/asm/sigcontext.h. */
5001struct target_sigcontext {
5002 target_ulong _unused[4];
5003 int32_t signal;
5004#if defined(TARGET_PPC64)
5005 int32_t pad0;
5006#endif
5007 target_ulong handler;
5008 target_ulong oldmask;
5009 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005010#if defined(TARGET_PPC64)
5011 struct target_mcontext mcontext;
5012#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005013};
5014
5015/* Indices for target_mcontext.mc_gregs, below.
5016 See arch/powerpc/include/asm/ptrace.h for details. */
5017enum {
5018 TARGET_PT_R0 = 0,
5019 TARGET_PT_R1 = 1,
5020 TARGET_PT_R2 = 2,
5021 TARGET_PT_R3 = 3,
5022 TARGET_PT_R4 = 4,
5023 TARGET_PT_R5 = 5,
5024 TARGET_PT_R6 = 6,
5025 TARGET_PT_R7 = 7,
5026 TARGET_PT_R8 = 8,
5027 TARGET_PT_R9 = 9,
5028 TARGET_PT_R10 = 10,
5029 TARGET_PT_R11 = 11,
5030 TARGET_PT_R12 = 12,
5031 TARGET_PT_R13 = 13,
5032 TARGET_PT_R14 = 14,
5033 TARGET_PT_R15 = 15,
5034 TARGET_PT_R16 = 16,
5035 TARGET_PT_R17 = 17,
5036 TARGET_PT_R18 = 18,
5037 TARGET_PT_R19 = 19,
5038 TARGET_PT_R20 = 20,
5039 TARGET_PT_R21 = 21,
5040 TARGET_PT_R22 = 22,
5041 TARGET_PT_R23 = 23,
5042 TARGET_PT_R24 = 24,
5043 TARGET_PT_R25 = 25,
5044 TARGET_PT_R26 = 26,
5045 TARGET_PT_R27 = 27,
5046 TARGET_PT_R28 = 28,
5047 TARGET_PT_R29 = 29,
5048 TARGET_PT_R30 = 30,
5049 TARGET_PT_R31 = 31,
5050 TARGET_PT_NIP = 32,
5051 TARGET_PT_MSR = 33,
5052 TARGET_PT_ORIG_R3 = 34,
5053 TARGET_PT_CTR = 35,
5054 TARGET_PT_LNK = 36,
5055 TARGET_PT_XER = 37,
5056 TARGET_PT_CCR = 38,
5057 /* Yes, there are two registers with #39. One is 64-bit only. */
5058 TARGET_PT_MQ = 39,
5059 TARGET_PT_SOFTE = 39,
5060 TARGET_PT_TRAP = 40,
5061 TARGET_PT_DAR = 41,
5062 TARGET_PT_DSISR = 42,
5063 TARGET_PT_RESULT = 43,
5064 TARGET_PT_REGS_COUNT = 44
5065};
5066
Nathan Froydbcd49332009-05-12 19:13:18 -07005067
5068struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005069 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005070 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005071 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005072#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005073 int32_t tuc_pad[7];
5074 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005075 points to uc_mcontext field */
5076#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005077 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005078#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005079 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005080 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005081#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005082 int32_t tuc_maskext[30];
5083 int32_t tuc_pad2[3];
5084 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005085#endif
5086};
5087
5088/* See arch/powerpc/kernel/signal_32.c. */
5089struct target_sigframe {
5090 struct target_sigcontext sctx;
5091 struct target_mcontext mctx;
5092 int32_t abigap[56];
5093};
5094
Tom Musta61e75fe2014-06-30 08:13:38 -05005095#if defined(TARGET_PPC64)
5096
5097#define TARGET_TRAMP_SIZE 6
5098
5099struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005100 /* sys_rt_sigreturn requires the ucontext be the first field */
5101 struct target_ucontext uc;
5102 target_ulong _unused[2];
5103 uint32_t trampoline[TARGET_TRAMP_SIZE];
5104 target_ulong pinfo; /* struct siginfo __user * */
5105 target_ulong puc; /* void __user * */
5106 struct target_siginfo info;
5107 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5108 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005109} __attribute__((aligned(16)));
5110
5111#else
5112
Nathan Froydbcd49332009-05-12 19:13:18 -07005113struct target_rt_sigframe {
5114 struct target_siginfo info;
5115 struct target_ucontext uc;
5116 int32_t abigap[56];
5117};
5118
Tom Musta61e75fe2014-06-30 08:13:38 -05005119#endif
5120
Tom Musta8d6ab332014-06-30 08:13:39 -05005121#if defined(TARGET_PPC64)
5122
5123struct target_func_ptr {
5124 target_ulong entry;
5125 target_ulong toc;
5126};
5127
5128#endif
5129
Nathan Froydbcd49332009-05-12 19:13:18 -07005130/* We use the mc_pad field for the signal return trampoline. */
5131#define tramp mc_pad
5132
5133/* See arch/powerpc/kernel/signal.c. */
5134static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005135 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005136 int frame_size)
5137{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005138 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005139
5140 oldsp = env->gpr[1];
5141
5142 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005143 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005144 oldsp = (target_sigaltstack_used.ss_sp
5145 + target_sigaltstack_used.ss_size);
5146 }
5147
Eduardo Habkost9be38592016-06-13 18:57:58 -03005148 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005149}
5150
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005151#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5152 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5153#define PPC_VEC_HI 0
5154#define PPC_VEC_LO 1
5155#else
5156#define PPC_VEC_HI 1
5157#define PPC_VEC_LO 0
5158#endif
5159
5160
Tom Musta76781082014-06-30 08:13:37 -05005161static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005162{
5163 target_ulong msr = env->msr;
5164 int i;
5165 target_ulong ccr = 0;
5166
5167 /* In general, the kernel attempts to be intelligent about what it
5168 needs to save for Altivec/FP/SPE registers. We don't care that
5169 much, so we just go ahead and save everything. */
5170
5171 /* Save general registers. */
5172 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005173 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005174 }
Riku Voipioc650c002014-04-23 13:53:45 +03005175 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5176 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5177 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5178 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005179
5180 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5181 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5182 }
Riku Voipioc650c002014-04-23 13:53:45 +03005183 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005184
5185 /* Save Altivec registers if necessary. */
5186 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005187 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005188 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005189 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005190 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005191
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005192 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5193 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005194 }
5195 /* Set MSR_VR in the saved MSR value to indicate that
5196 frame->mc_vregs contains valid data. */
5197 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005198#if defined(TARGET_PPC64)
5199 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5200 /* 64-bit needs to put a pointer to the vectors in the frame */
5201 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5202#else
5203 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5204#endif
5205 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5206 }
5207
5208 /* Save VSX second halves */
5209 if (env->insns_flags2 & PPC2_VSX) {
5210 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5211 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5212 __put_user(env->vsr[i], &vsregs[i]);
5213 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005214 }
5215
5216 /* Save floating point registers. */
5217 if (env->insns_flags & PPC_FLOAT) {
5218 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005219 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005220 }
Riku Voipioc650c002014-04-23 13:53:45 +03005221 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005222 }
5223
5224 /* Save SPE registers. The kernel only saves the high half. */
5225 if (env->insns_flags & PPC_SPE) {
5226#if defined(TARGET_PPC64)
5227 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005228 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005229 }
5230#else
5231 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005232 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005233 }
5234#endif
5235 /* Set MSR_SPE in the saved MSR value to indicate that
5236 frame->mc_vregs contains valid data. */
5237 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005238 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005239 }
5240
5241 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005242 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005243}
Nathan Froydbcd49332009-05-12 19:13:18 -07005244
Tom Musta76781082014-06-30 08:13:37 -05005245static void encode_trampoline(int sigret, uint32_t *tramp)
5246{
Nathan Froydbcd49332009-05-12 19:13:18 -07005247 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5248 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005249 __put_user(0x38000000 | sigret, &tramp[0]);
5250 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005251 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005252}
5253
Riku Voipioc650c002014-04-23 13:53:45 +03005254static void restore_user_regs(CPUPPCState *env,
5255 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005256{
5257 target_ulong save_r2 = 0;
5258 target_ulong msr;
5259 target_ulong ccr;
5260
5261 int i;
5262
5263 if (!sig) {
5264 save_r2 = env->gpr[2];
5265 }
5266
5267 /* Restore general registers. */
5268 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005269 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005270 }
Riku Voipioc650c002014-04-23 13:53:45 +03005271 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5272 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5273 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5274 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5275 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005276
5277 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5278 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5279 }
5280
5281 if (!sig) {
5282 env->gpr[2] = save_r2;
5283 }
5284 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005285 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005286
5287 /* If doing signal return, restore the previous little-endian mode. */
5288 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005289 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005290
5291 /* Restore Altivec registers if necessary. */
5292 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005293 ppc_avr_t *v_regs;
5294 uint32_t *vrsave;
5295#if defined(TARGET_PPC64)
5296 uint64_t v_addr;
5297 /* 64-bit needs to recover the pointer to the vectors from the frame */
5298 __get_user(v_addr, &frame->v_regs);
5299 v_regs = g2h(v_addr);
5300#else
5301 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5302#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005303 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005304 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005305 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005306
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005307 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5308 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005309 }
5310 /* Set MSR_VEC in the saved MSR value to indicate that
5311 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005312#if defined(TARGET_PPC64)
5313 vrsave = (uint32_t *)&v_regs[33];
5314#else
5315 vrsave = (uint32_t *)&v_regs[32];
5316#endif
5317 __get_user(env->spr[SPR_VRSAVE], vrsave);
5318 }
5319
5320 /* Restore VSX second halves */
5321 if (env->insns_flags2 & PPC2_VSX) {
5322 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5323 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5324 __get_user(env->vsr[i], &vsregs[i]);
5325 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005326 }
5327
5328 /* Restore floating point registers. */
5329 if (env->insns_flags & PPC_FLOAT) {
5330 uint64_t fpscr;
5331 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005332 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005333 }
Riku Voipioc650c002014-04-23 13:53:45 +03005334 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005335 env->fpscr = (uint32_t) fpscr;
5336 }
5337
5338 /* Save SPE registers. The kernel only saves the high half. */
5339 if (env->insns_flags & PPC_SPE) {
5340#if defined(TARGET_PPC64)
5341 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5342 uint32_t hi;
5343
Riku Voipioc650c002014-04-23 13:53:45 +03005344 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005345 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5346 }
5347#else
5348 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005349 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005350 }
5351#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005352 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005353 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005354}
5355
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005356#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005357static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005358 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005359{
5360 struct target_sigframe *frame;
5361 struct target_sigcontext *sc;
5362 target_ulong frame_addr, newsp;
5363 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005364
5365 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005366 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005367 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5368 goto sigsegv;
5369 sc = &frame->sctx;
5370
Riku Voipio1d8b5122014-04-23 10:26:05 +03005371 __put_user(ka->_sa_handler, &sc->handler);
5372 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005373 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005374 __put_user(h2g(&frame->mctx), &sc->regs);
5375 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005376
5377 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005378 save_user_regs(env, &frame->mctx);
5379
5380 /* Construct the trampoline code on the stack. */
5381 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005382
5383 /* The kernel checks for the presence of a VDSO here. We don't
5384 emulate a vdso, so use a sigreturn system call. */
5385 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5386
5387 /* Turn off all fp exceptions. */
5388 env->fpscr = 0;
5389
5390 /* Create a stack frame for the caller of the handler. */
5391 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005392 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005393
5394 if (err)
5395 goto sigsegv;
5396
5397 /* Set up registers for signal handler. */
5398 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005399 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005400 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005401
Nathan Froydbcd49332009-05-12 19:13:18 -07005402 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005403
Nathan Froydbcd49332009-05-12 19:13:18 -07005404 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005405 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005406
5407 unlock_user_struct(frame, frame_addr, 1);
5408 return;
5409
5410sigsegv:
5411 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005412 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005413}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005414#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005415
5416static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005417 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005418 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005419{
5420 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005421 uint32_t *trampptr = 0;
5422 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005423 target_ulong rt_sf_addr, newsp = 0;
5424 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005425#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005426 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005427 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5428#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005429
5430 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5431 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5432 goto sigsegv;
5433
Peter Maydellf6c7a052015-01-08 12:19:48 +00005434 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005435
Riku Voipio1d8b5122014-04-23 10:26:05 +03005436 __put_user(0, &rt_sf->uc.tuc_flags);
5437 __put_user(0, &rt_sf->uc.tuc_link);
5438 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5439 &rt_sf->uc.tuc_stack.ss_sp);
5440 __put_user(sas_ss_flags(env->gpr[1]),
5441 &rt_sf->uc.tuc_stack.ss_flags);
5442 __put_user(target_sigaltstack_used.ss_size,
5443 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005444#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005445 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5446 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005447#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005448 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005449 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005450 }
5451
Tom Musta61e75fe2014-06-30 08:13:38 -05005452#if defined(TARGET_PPC64)
5453 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5454 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005455
5456 sc = &rt_sf->uc.tuc_sigcontext;
5457 __put_user(h2g(mctx), &sc->regs);
5458 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005459#else
5460 mctx = &rt_sf->uc.tuc_mcontext;
5461 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5462#endif
5463
5464 save_user_regs(env, mctx);
5465 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005466
5467 /* The kernel checks for the presence of a VDSO here. We don't
5468 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005469 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005470
5471 /* Turn off all fp exceptions. */
5472 env->fpscr = 0;
5473
5474 /* Create a stack frame for the caller of the handler. */
5475 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005476 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005477
5478 if (err)
5479 goto sigsegv;
5480
5481 /* Set up registers for signal handler. */
5482 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005483 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005484 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5485 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5486 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005487
5488#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005489 if (get_ppc64_abi(image) < 2) {
5490 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5491 struct target_func_ptr *handler =
5492 (struct target_func_ptr *)g2h(ka->_sa_handler);
5493 env->nip = tswapl(handler->entry);
5494 env->gpr[2] = tswapl(handler->toc);
5495 } else {
5496 /* ELFv2 PPC64 function pointers are entry points, but R12
5497 * must also be set */
5498 env->nip = tswapl((target_ulong) ka->_sa_handler);
5499 env->gpr[12] = env->nip;
5500 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005501#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005502 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005503#endif
5504
Nathan Froydbcd49332009-05-12 19:13:18 -07005505 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005506 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005507
5508 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5509 return;
5510
5511sigsegv:
5512 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005513 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005514
5515}
5516
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005517#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005518long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005519{
5520 struct target_sigcontext *sc = NULL;
5521 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005522 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005523 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005524 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005525
5526 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5527 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5528 goto sigsegv;
5529
5530#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005531 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005532#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005533 __get_user(set.sig[0], &sc->oldmask);
5534 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005535#endif
5536 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005537 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005538
Riku Voipiof5f601a2014-04-23 13:00:17 +03005539 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005540 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5541 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005542 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005543
5544 unlock_user_struct(sr, sr_addr, 1);
5545 unlock_user_struct(sc, sc_addr, 1);
5546 return -TARGET_QEMU_ESIGRETURN;
5547
5548sigsegv:
5549 unlock_user_struct(sr, sr_addr, 1);
5550 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005551 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005552 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005553}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005554#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005555
5556/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005557static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005558{
5559 struct target_mcontext *mcp;
5560 target_ulong mcp_addr;
5561 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005562 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005563
Aurelien Jarno60e99242010-03-29 02:12:51 +02005564 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005565 sizeof (set)))
5566 return 1;
5567
Tom Musta19774ec2014-06-30 08:13:40 -05005568#if defined(TARGET_PPC64)
5569 mcp_addr = h2g(ucp) +
5570 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5571#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005572 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005573#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005574
5575 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5576 return 1;
5577
5578 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005579 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005580 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005581
5582 unlock_user_struct(mcp, mcp_addr, 1);
5583 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005584}
5585
Andreas Färber05390242012-02-25 03:37:53 +01005586long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005587{
5588 struct target_rt_sigframe *rt_sf = NULL;
5589 target_ulong rt_sf_addr;
5590
5591 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5592 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5593 goto sigsegv;
5594
5595 if (do_setcontext(&rt_sf->uc, env, 1))
5596 goto sigsegv;
5597
5598 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005599 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005600 0, env->gpr[1]);
5601
5602 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5603 return -TARGET_QEMU_ESIGRETURN;
5604
5605sigsegv:
5606 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005607 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005608 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005609}
5610
Laurent Vivier492a8742009-08-03 16:12:17 +02005611#elif defined(TARGET_M68K)
5612
5613struct target_sigcontext {
5614 abi_ulong sc_mask;
5615 abi_ulong sc_usp;
5616 abi_ulong sc_d0;
5617 abi_ulong sc_d1;
5618 abi_ulong sc_a0;
5619 abi_ulong sc_a1;
5620 unsigned short sc_sr;
5621 abi_ulong sc_pc;
5622};
5623
5624struct target_sigframe
5625{
5626 abi_ulong pretcode;
5627 int sig;
5628 int code;
5629 abi_ulong psc;
5630 char retcode[8];
5631 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5632 struct target_sigcontext sc;
5633};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005634
Anthony Liguoric227f092009-10-01 16:12:16 -05005635typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005636#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005637typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005638
5639typedef struct target_fpregset {
5640 int f_fpcntl[3];
5641 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005642} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005643
5644struct target_mcontext {
5645 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005646 target_gregset_t gregs;
5647 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005648};
5649
5650#define TARGET_MCONTEXT_VERSION 2
5651
5652struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005653 abi_ulong tuc_flags;
5654 abi_ulong tuc_link;
5655 target_stack_t tuc_stack;
5656 struct target_mcontext tuc_mcontext;
5657 abi_long tuc_filler[80];
5658 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005659};
5660
5661struct target_rt_sigframe
5662{
5663 abi_ulong pretcode;
5664 int sig;
5665 abi_ulong pinfo;
5666 abi_ulong puc;
5667 char retcode[8];
5668 struct target_siginfo info;
5669 struct target_ucontext uc;
5670};
Laurent Vivier492a8742009-08-03 16:12:17 +02005671
Riku Voipio41ecc722014-04-23 11:01:00 +03005672static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005673 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005674{
Laurent Vivieref597602018-01-04 02:28:59 +01005675 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005676 __put_user(mask, &sc->sc_mask);
5677 __put_user(env->aregs[7], &sc->sc_usp);
5678 __put_user(env->dregs[0], &sc->sc_d0);
5679 __put_user(env->dregs[1], &sc->sc_d1);
5680 __put_user(env->aregs[0], &sc->sc_a0);
5681 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005682 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005683 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005684}
5685
Riku Voipio016d2e12014-04-23 11:19:48 +03005686static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005687restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005688{
Laurent Vivier492a8742009-08-03 16:12:17 +02005689 int temp;
5690
Riku Voipio1d8b5122014-04-23 10:26:05 +03005691 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005692 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005693 __get_user(env->dregs[1], &sc->sc_d1);
5694 __get_user(env->aregs[0], &sc->sc_a0);
5695 __get_user(env->aregs[1], &sc->sc_a1);
5696 __get_user(env->pc, &sc->sc_pc);
5697 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005698 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005699}
5700
5701/*
5702 * Determine which stack to use..
5703 */
5704static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005705get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5706 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005707{
5708 unsigned long sp;
5709
5710 sp = regs->aregs[7];
5711
5712 /* This is the X/Open sanctioned signal stack switching. */
5713 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5714 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5715 }
5716
5717 return ((sp - frame_size) & -8UL);
5718}
5719
5720static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005721 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005722{
5723 struct target_sigframe *frame;
5724 abi_ulong frame_addr;
5725 abi_ulong retcode_addr;
5726 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005727 int i;
5728
5729 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005730 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005731 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5732 goto give_sigsegv;
5733 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005734
Riku Voipio1d8b5122014-04-23 10:26:05 +03005735 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005736
5737 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005738 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005739
Riku Voipio41ecc722014-04-23 11:01:00 +03005740 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005741
5742 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005743 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005744 }
5745
5746 /* Set up to return from userspace. */
5747
5748 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005749 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005750
5751 /* moveq #,d0; trap #0 */
5752
Riku Voipio1d8b5122014-04-23 10:26:05 +03005753 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005754 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005755
Laurent Vivier492a8742009-08-03 16:12:17 +02005756 /* Set up to return from userspace */
5757
5758 env->aregs[7] = frame_addr;
5759 env->pc = ka->_sa_handler;
5760
5761 unlock_user_struct(frame, frame_addr, 1);
5762 return;
5763
5764give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005765 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005766}
5767
Laurent Vivieree46a462017-09-14 18:35:05 +02005768static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5769 CPUM68KState *env)
5770{
5771 int i;
5772 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5773
5774 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
5775 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
5776 /* fpiar is not emulated */
5777
5778 for (i = 0; i < 8; i++) {
5779 uint32_t high = env->fregs[i].d.high << 16;
5780 __put_user(high, &fpregs->f_fpregs[i * 3]);
5781 __put_user(env->fregs[i].d.low,
5782 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5783 }
5784}
5785
Laurent Vivier71811552009-08-03 16:12:18 +02005786static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005787 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005788{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005789 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01005790 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02005791
Riku Voipio1d8b5122014-04-23 10:26:05 +03005792 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5793 __put_user(env->dregs[0], &gregs[0]);
5794 __put_user(env->dregs[1], &gregs[1]);
5795 __put_user(env->dregs[2], &gregs[2]);
5796 __put_user(env->dregs[3], &gregs[3]);
5797 __put_user(env->dregs[4], &gregs[4]);
5798 __put_user(env->dregs[5], &gregs[5]);
5799 __put_user(env->dregs[6], &gregs[6]);
5800 __put_user(env->dregs[7], &gregs[7]);
5801 __put_user(env->aregs[0], &gregs[8]);
5802 __put_user(env->aregs[1], &gregs[9]);
5803 __put_user(env->aregs[2], &gregs[10]);
5804 __put_user(env->aregs[3], &gregs[11]);
5805 __put_user(env->aregs[4], &gregs[12]);
5806 __put_user(env->aregs[5], &gregs[13]);
5807 __put_user(env->aregs[6], &gregs[14]);
5808 __put_user(env->aregs[7], &gregs[15]);
5809 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005810 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005811
Laurent Vivieree46a462017-09-14 18:35:05 +02005812 target_rt_save_fpu_state(uc, env);
5813
Riku Voipio1d8b5122014-04-23 10:26:05 +03005814 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005815}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005816
Laurent Vivieree46a462017-09-14 18:35:05 +02005817static inline void target_rt_restore_fpu_state(CPUM68KState *env,
5818 struct target_ucontext *uc)
5819{
5820 int i;
5821 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5822 uint32_t fpcr;
5823
5824 __get_user(fpcr, &fpregs->f_fpcntl[0]);
5825 cpu_m68k_set_fpcr(env, fpcr);
5826 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
5827 /* fpiar is not emulated */
5828
5829 for (i = 0; i < 8; i++) {
5830 uint32_t high;
5831 __get_user(high, &fpregs->f_fpregs[i * 3]);
5832 env->fregs[i].d.high = high >> 16;
5833 __get_user(env->fregs[i].d.low,
5834 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5835 }
5836}
5837
Andreas Färber05390242012-02-25 03:37:53 +01005838static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005839 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005840{
5841 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005842 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005843
Riku Voipio1d8b5122014-04-23 10:26:05 +03005844 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005845 if (temp != TARGET_MCONTEXT_VERSION)
5846 goto badframe;
5847
5848 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005849 __get_user(env->dregs[0], &gregs[0]);
5850 __get_user(env->dregs[1], &gregs[1]);
5851 __get_user(env->dregs[2], &gregs[2]);
5852 __get_user(env->dregs[3], &gregs[3]);
5853 __get_user(env->dregs[4], &gregs[4]);
5854 __get_user(env->dregs[5], &gregs[5]);
5855 __get_user(env->dregs[6], &gregs[6]);
5856 __get_user(env->dregs[7], &gregs[7]);
5857 __get_user(env->aregs[0], &gregs[8]);
5858 __get_user(env->aregs[1], &gregs[9]);
5859 __get_user(env->aregs[2], &gregs[10]);
5860 __get_user(env->aregs[3], &gregs[11]);
5861 __get_user(env->aregs[4], &gregs[12]);
5862 __get_user(env->aregs[5], &gregs[13]);
5863 __get_user(env->aregs[6], &gregs[14]);
5864 __get_user(env->aregs[7], &gregs[15]);
5865 __get_user(env->pc, &gregs[16]);
5866 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005867 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02005868
Laurent Vivieree46a462017-09-14 18:35:05 +02005869 target_rt_restore_fpu_state(env, uc);
5870
Riku Voipio1d8b5122014-04-23 10:26:05 +03005871 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005872
5873badframe:
5874 return 1;
5875}
5876
Laurent Vivier492a8742009-08-03 16:12:17 +02005877static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005878 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005879 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005880{
Laurent Vivier71811552009-08-03 16:12:18 +02005881 struct target_rt_sigframe *frame;
5882 abi_ulong frame_addr;
5883 abi_ulong retcode_addr;
5884 abi_ulong info_addr;
5885 abi_ulong uc_addr;
5886 int err = 0;
5887 int i;
5888
5889 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005890 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005891 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5892 goto give_sigsegv;
5893 }
Laurent Vivier71811552009-08-03 16:12:18 +02005894
Riku Voipio1d8b5122014-04-23 10:26:05 +03005895 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005896
5897 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005898 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005899
5900 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005901 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005902
Peter Maydellf6c7a052015-01-08 12:19:48 +00005903 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005904
5905 /* Create the ucontext */
5906
Riku Voipio1d8b5122014-04-23 10:26:05 +03005907 __put_user(0, &frame->uc.tuc_flags);
5908 __put_user(0, &frame->uc.tuc_link);
5909 __put_user(target_sigaltstack_used.ss_sp,
5910 &frame->uc.tuc_stack.ss_sp);
5911 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005912 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005913 __put_user(target_sigaltstack_used.ss_size,
5914 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005915 err |= target_rt_setup_ucontext(&frame->uc, env);
5916
5917 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005918 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005919
5920 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005921 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005922 }
5923
5924 /* Set up to return from userspace. */
5925
5926 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005927 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005928
5929 /* moveq #,d0; notb d0; trap #0 */
5930
Riku Voipio1d8b5122014-04-23 10:26:05 +03005931 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005932 (uint32_t *)(frame->retcode + 0));
5933 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005934
5935 if (err)
5936 goto give_sigsegv;
5937
5938 /* Set up to return from userspace */
5939
5940 env->aregs[7] = frame_addr;
5941 env->pc = ka->_sa_handler;
5942
5943 unlock_user_struct(frame, frame_addr, 1);
5944 return;
5945
5946give_sigsegv:
5947 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005948 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005949}
5950
Andreas Färber05390242012-02-25 03:37:53 +01005951long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005952{
5953 struct target_sigframe *frame;
5954 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005955 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005956 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005957 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005958
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005959 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005960 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5961 goto badframe;
5962
5963 /* set blocked signals */
5964
Riku Voipiof5f601a2014-04-23 13:00:17 +03005965 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005966
5967 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005968 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005969 }
5970
5971 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005972 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005973
5974 /* restore registers */
5975
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005976 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005977
5978 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005979 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005980
5981badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005982 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005983 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005984}
5985
Andreas Färber05390242012-02-25 03:37:53 +01005986long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005987{
Laurent Vivier71811552009-08-03 16:12:18 +02005988 struct target_rt_sigframe *frame;
5989 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02005990 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005991
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005992 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005993 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5994 goto badframe;
5995
Michael Karcher59ebb6e2017-02-25 12:05:17 +01005996 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005997 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005998
5999 /* restore registers */
6000
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006001 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006002 goto badframe;
6003
6004 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006005 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006006 0, get_sp_from_cpustate(env)) == -EFAULT)
6007 goto badframe;
6008
6009 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006010 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006011
6012badframe:
6013 unlock_user_struct(frame, frame_addr, 0);
6014 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006015 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006016}
6017
Richard Henderson6049f4f2009-12-27 18:30:03 -08006018#elif defined(TARGET_ALPHA)
6019
6020struct target_sigcontext {
6021 abi_long sc_onstack;
6022 abi_long sc_mask;
6023 abi_long sc_pc;
6024 abi_long sc_ps;
6025 abi_long sc_regs[32];
6026 abi_long sc_ownedfp;
6027 abi_long sc_fpregs[32];
6028 abi_ulong sc_fpcr;
6029 abi_ulong sc_fp_control;
6030 abi_ulong sc_reserved1;
6031 abi_ulong sc_reserved2;
6032 abi_ulong sc_ssize;
6033 abi_ulong sc_sbase;
6034 abi_ulong sc_traparg_a0;
6035 abi_ulong sc_traparg_a1;
6036 abi_ulong sc_traparg_a2;
6037 abi_ulong sc_fp_trap_pc;
6038 abi_ulong sc_fp_trigger_sum;
6039 abi_ulong sc_fp_trigger_inst;
6040};
6041
6042struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006043 abi_ulong tuc_flags;
6044 abi_ulong tuc_link;
6045 abi_ulong tuc_osf_sigmask;
6046 target_stack_t tuc_stack;
6047 struct target_sigcontext tuc_mcontext;
6048 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006049};
6050
6051struct target_sigframe {
6052 struct target_sigcontext sc;
6053 unsigned int retcode[3];
6054};
6055
6056struct target_rt_sigframe {
6057 target_siginfo_t info;
6058 struct target_ucontext uc;
6059 unsigned int retcode[3];
6060};
6061
6062#define INSN_MOV_R30_R16 0x47fe0410
6063#define INSN_LDI_R0 0x201f0000
6064#define INSN_CALLSYS 0x00000083
6065
Riku Voipio41ecc722014-04-23 11:01:00 +03006066static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006067 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006068{
Riku Voipio41ecc722014-04-23 11:01:00 +03006069 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006070
Riku Voipio1d8b5122014-04-23 10:26:05 +03006071 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6072 __put_user(set->sig[0], &sc->sc_mask);
6073 __put_user(env->pc, &sc->sc_pc);
6074 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006075
6076 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006077 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006078 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006079 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006080
6081 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006082 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006083 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006084 __put_user(0, &sc->sc_fpregs[31]);
6085 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006086
Riku Voipio1d8b5122014-04-23 10:26:05 +03006087 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6088 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6089 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006090}
6091
Riku Voipio016d2e12014-04-23 11:19:48 +03006092static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006093 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006094{
6095 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006096 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006097
Riku Voipio1d8b5122014-04-23 10:26:05 +03006098 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006099
6100 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006101 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006102 }
6103 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006104 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006105 }
6106
Riku Voipio1d8b5122014-04-23 10:26:05 +03006107 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006108 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006109}
6110
6111static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006112 CPUAlphaState *env,
6113 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006114{
6115 abi_ulong sp = env->ir[IR_SP];
6116
6117 /* This is the X/Open sanctioned signal stack switching. */
6118 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6119 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6120 }
6121 return (sp - framesize) & -32;
6122}
6123
6124static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006125 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006126{
6127 abi_ulong frame_addr, r26;
6128 struct target_sigframe *frame;
6129 int err = 0;
6130
6131 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006132 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006133 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6134 goto give_sigsegv;
6135 }
6136
Riku Voipio41ecc722014-04-23 11:01:00 +03006137 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006138
6139 if (ka->sa_restorer) {
6140 r26 = ka->sa_restorer;
6141 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006142 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6143 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6144 &frame->retcode[1]);
6145 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006146 /* imb() */
6147 r26 = frame_addr;
6148 }
6149
6150 unlock_user_struct(frame, frame_addr, 1);
6151
6152 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006153give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006154 force_sigsegv(sig);
6155 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006156 }
6157
6158 env->ir[IR_RA] = r26;
6159 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6160 env->ir[IR_A0] = sig;
6161 env->ir[IR_A1] = 0;
6162 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6163 env->ir[IR_SP] = frame_addr;
6164}
6165
6166static void setup_rt_frame(int sig, struct target_sigaction *ka,
6167 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006168 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006169{
6170 abi_ulong frame_addr, r26;
6171 struct target_rt_sigframe *frame;
6172 int i, err = 0;
6173
6174 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006175 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006176 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6177 goto give_sigsegv;
6178 }
6179
Peter Maydellf6c7a052015-01-08 12:19:48 +00006180 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006181
Riku Voipio1d8b5122014-04-23 10:26:05 +03006182 __put_user(0, &frame->uc.tuc_flags);
6183 __put_user(0, &frame->uc.tuc_link);
6184 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6185 __put_user(target_sigaltstack_used.ss_sp,
6186 &frame->uc.tuc_stack.ss_sp);
6187 __put_user(sas_ss_flags(env->ir[IR_SP]),
6188 &frame->uc.tuc_stack.ss_flags);
6189 __put_user(target_sigaltstack_used.ss_size,
6190 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006191 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006192 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006193 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006194 }
6195
6196 if (ka->sa_restorer) {
6197 r26 = ka->sa_restorer;
6198 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006199 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6200 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6201 &frame->retcode[1]);
6202 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006203 /* imb(); */
6204 r26 = frame_addr;
6205 }
6206
6207 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006208give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006209 force_sigsegv(sig);
6210 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006211 }
6212
6213 env->ir[IR_RA] = r26;
6214 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6215 env->ir[IR_A0] = sig;
6216 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6217 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6218 env->ir[IR_SP] = frame_addr;
6219}
6220
Andreas Färber05390242012-02-25 03:37:53 +01006221long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006222{
6223 struct target_sigcontext *sc;
6224 abi_ulong sc_addr = env->ir[IR_A0];
6225 target_sigset_t target_set;
6226 sigset_t set;
6227
6228 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6229 goto badframe;
6230 }
6231
6232 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006233 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006234
6235 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006236 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006237
Riku Voipio016d2e12014-04-23 11:19:48 +03006238 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006239 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006240 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006241
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006242badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006243 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006244 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006245}
6246
Andreas Färber05390242012-02-25 03:37:53 +01006247long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006248{
6249 abi_ulong frame_addr = env->ir[IR_A0];
6250 struct target_rt_sigframe *frame;
6251 sigset_t set;
6252
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006253 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006254 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6255 goto badframe;
6256 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006257 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006258 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006259
Riku Voipio016d2e12014-04-23 11:19:48 +03006260 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006261 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006262 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006263 0, env->ir[IR_SP]) == -EFAULT) {
6264 goto badframe;
6265 }
6266
6267 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006268 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006269
6270
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006271badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006272 unlock_user_struct(frame, frame_addr, 0);
6273 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006274 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006275}
6276
Chen Gangbf0f60a2015-09-27 08:10:18 +08006277#elif defined(TARGET_TILEGX)
6278
6279struct target_sigcontext {
6280 union {
6281 /* General-purpose registers. */
6282 abi_ulong gregs[56];
6283 struct {
6284 abi_ulong __gregs[53];
6285 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6286 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6287 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6288 };
6289 };
6290 abi_ulong pc; /* Program counter. */
6291 abi_ulong ics; /* In Interrupt Critical Section? */
6292 abi_ulong faultnum; /* Fault number. */
6293 abi_ulong pad[5];
6294};
6295
6296struct target_ucontext {
6297 abi_ulong tuc_flags;
6298 abi_ulong tuc_link;
6299 target_stack_t tuc_stack;
6300 struct target_sigcontext tuc_mcontext;
6301 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6302};
6303
6304struct target_rt_sigframe {
6305 unsigned char save_area[16]; /* caller save area */
6306 struct target_siginfo info;
6307 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006308 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006309};
6310
Chen Gangf1d9d102016-03-29 21:53:49 +08006311#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6312#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6313
6314
Chen Gangbf0f60a2015-09-27 08:10:18 +08006315static void setup_sigcontext(struct target_sigcontext *sc,
6316 CPUArchState *env, int signo)
6317{
6318 int i;
6319
6320 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6321 __put_user(env->regs[i], &sc->gregs[i]);
6322 }
6323
6324 __put_user(env->pc, &sc->pc);
6325 __put_user(0, &sc->ics);
6326 __put_user(signo, &sc->faultnum);
6327}
6328
6329static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6330{
6331 int i;
6332
6333 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6334 __get_user(env->regs[i], &sc->gregs[i]);
6335 }
6336
6337 __get_user(env->pc, &sc->pc);
6338}
6339
6340static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6341 size_t frame_size)
6342{
6343 unsigned long sp = env->regs[TILEGX_R_SP];
6344
6345 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6346 return -1UL;
6347 }
6348
6349 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6350 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6351 }
6352
6353 sp -= frame_size;
6354 sp &= -16UL;
6355 return sp;
6356}
6357
6358static void setup_rt_frame(int sig, struct target_sigaction *ka,
6359 target_siginfo_t *info,
6360 target_sigset_t *set, CPUArchState *env)
6361{
6362 abi_ulong frame_addr;
6363 struct target_rt_sigframe *frame;
6364 unsigned long restorer;
6365
6366 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006367 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006368 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6369 goto give_sigsegv;
6370 }
6371
6372 /* Always write at least the signal number for the stack backtracer. */
6373 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6374 /* At sigreturn time, restore the callee-save registers too. */
6375 tswap_siginfo(&frame->info, info);
6376 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6377 } else {
6378 __put_user(info->si_signo, &frame->info.si_signo);
6379 }
6380
6381 /* Create the ucontext. */
6382 __put_user(0, &frame->uc.tuc_flags);
6383 __put_user(0, &frame->uc.tuc_link);
6384 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6385 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6386 &frame->uc.tuc_stack.ss_flags);
6387 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6388 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6389
Chen Gangbf0f60a2015-09-27 08:10:18 +08006390 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006391 restorer = (unsigned long) ka->sa_restorer;
6392 } else {
6393 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6394 __put_user(INSN_SWINT1, &frame->retcode[1]);
6395 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006396 }
6397 env->pc = (unsigned long) ka->_sa_handler;
6398 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6399 env->regs[TILEGX_R_LR] = restorer;
6400 env->regs[0] = (unsigned long) sig;
6401 env->regs[1] = (unsigned long) &frame->info;
6402 env->regs[2] = (unsigned long) &frame->uc;
6403 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6404
6405 unlock_user_struct(frame, frame_addr, 1);
6406 return;
6407
6408give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006409 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006410}
6411
6412long do_rt_sigreturn(CPUTLGState *env)
6413{
6414 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6415 struct target_rt_sigframe *frame;
6416 sigset_t set;
6417
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006418 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006419 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6420 goto badframe;
6421 }
6422 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006423 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006424
6425 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6426 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6427 uc.tuc_stack),
6428 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6429 goto badframe;
6430 }
6431
6432 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006433 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006434
6435
6436 badframe:
6437 unlock_user_struct(frame, frame_addr, 0);
6438 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006439 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006440}
6441
Michael Clark47ae93c2018-03-03 01:31:11 +13006442#elif defined(TARGET_RISCV)
6443
6444/* Signal handler invocation must be transparent for the code being
6445 interrupted. Complete CPU (hart) state is saved on entry and restored
6446 before returning from the handler. Process sigmask is also saved to block
6447 signals while the handler is running. The handler gets its own stack,
6448 which also doubles as storage for the CPU state and sigmask.
6449
6450 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6451
6452struct target_sigcontext {
6453 abi_long pc;
6454 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6455 uint64_t fpr[32];
6456 uint32_t fcsr;
6457}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6458
6459struct target_ucontext {
6460 unsigned long uc_flags;
6461 struct target_ucontext *uc_link;
6462 target_stack_t uc_stack;
6463 struct target_sigcontext uc_mcontext;
6464 target_sigset_t uc_sigmask;
6465};
6466
6467struct target_rt_sigframe {
6468 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6469 struct target_siginfo info;
6470 struct target_ucontext uc;
6471};
6472
6473static abi_ulong get_sigframe(struct target_sigaction *ka,
6474 CPURISCVState *regs, size_t framesize)
6475{
6476 abi_ulong sp = regs->gpr[xSP];
6477 int onsigstack = on_sig_stack(sp);
6478
6479 /* redzone */
6480 /* This is the X/Open sanctioned signal stack switching. */
6481 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6482 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6483 }
6484
6485 sp -= framesize;
6486 sp &= ~3UL; /* align sp on 4-byte boundary */
6487
6488 /* If we are on the alternate signal stack and would overflow it, don't.
6489 Return an always-bogus address instead so we will die with SIGSEGV. */
6490 if (onsigstack && !likely(on_sig_stack(sp))) {
6491 return -1L;
6492 }
6493
6494 return sp;
6495}
6496
6497static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6498{
6499 int i;
6500
6501 __put_user(env->pc, &sc->pc);
6502
6503 for (i = 1; i < 32; i++) {
6504 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6505 }
6506 for (i = 0; i < 32; i++) {
6507 __put_user(env->fpr[i], &sc->fpr[i]);
6508 }
6509
6510 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6511 __put_user(fcsr, &sc->fcsr);
6512}
6513
6514static void setup_ucontext(struct target_ucontext *uc,
6515 CPURISCVState *env, target_sigset_t *set)
6516{
6517 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6518 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6519 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6520
6521 __put_user(0, &(uc->uc_flags));
6522 __put_user(0, &(uc->uc_link));
6523
6524 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6525 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6526 __put_user(ss_size, &(uc->uc_stack.ss_size));
6527
6528 int i;
6529 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6530 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6531 }
6532
6533 setup_sigcontext(&uc->uc_mcontext, env);
6534}
6535
6536static inline void install_sigtramp(uint32_t *tramp)
6537{
6538 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6539 __put_user(0x00000073, tramp + 1); /* ecall */
6540}
6541
6542static void setup_rt_frame(int sig, struct target_sigaction *ka,
6543 target_siginfo_t *info,
6544 target_sigset_t *set, CPURISCVState *env)
6545{
6546 abi_ulong frame_addr;
6547 struct target_rt_sigframe *frame;
6548
6549 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6550 trace_user_setup_rt_frame(env, frame_addr);
6551
6552 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6553 goto badframe;
6554 }
6555
6556 setup_ucontext(&frame->uc, env, set);
6557 tswap_siginfo(&frame->info, info);
6558 install_sigtramp(frame->tramp);
6559
6560 env->pc = ka->_sa_handler;
6561 env->gpr[xSP] = frame_addr;
6562 env->gpr[xA0] = sig;
6563 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6564 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6565 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6566
6567 return;
6568
6569badframe:
6570 unlock_user_struct(frame, frame_addr, 1);
6571 if (sig == TARGET_SIGSEGV) {
6572 ka->_sa_handler = TARGET_SIG_DFL;
6573 }
6574 force_sig(TARGET_SIGSEGV);
6575}
6576
6577static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6578{
6579 int i;
6580
6581 __get_user(env->pc, &sc->pc);
6582
6583 for (i = 1; i < 32; ++i) {
6584 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6585 }
6586 for (i = 0; i < 32; ++i) {
6587 __get_user(env->fpr[i], &sc->fpr[i]);
6588 }
6589
6590 uint32_t fcsr;
6591 __get_user(fcsr, &sc->fcsr);
6592 csr_write_helper(env, fcsr, CSR_FCSR);
6593}
6594
6595static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6596{
6597 sigset_t blocked;
6598 target_sigset_t target_set;
6599 int i;
6600
6601 target_sigemptyset(&target_set);
6602 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6603 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6604 }
6605
6606 target_to_host_sigset_internal(&blocked, &target_set);
6607 set_sigmask(&blocked);
6608
6609 restore_sigcontext(env, &uc->uc_mcontext);
6610}
6611
6612long do_rt_sigreturn(CPURISCVState *env)
6613{
6614 struct target_rt_sigframe *frame;
6615 abi_ulong frame_addr;
6616
6617 frame_addr = env->gpr[xSP];
6618 trace_user_do_sigreturn(env, frame_addr);
6619 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6620 goto badframe;
6621 }
6622
6623 restore_ucontext(env, &frame->uc);
6624
6625 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6626 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6627 goto badframe;
6628 }
6629
6630 unlock_user_struct(frame, frame_addr, 0);
6631 return -TARGET_QEMU_ESIGRETURN;
6632
6633badframe:
6634 unlock_user_struct(frame, frame_addr, 0);
6635 force_sig(TARGET_SIGSEGV);
6636 return 0;
6637}
6638
Richard Henderson1659e382016-12-15 09:59:01 -08006639#elif defined(TARGET_HPPA)
6640
6641struct target_sigcontext {
6642 abi_ulong sc_flags;
6643 abi_ulong sc_gr[32];
6644 uint64_t sc_fr[32];
6645 abi_ulong sc_iasq[2];
6646 abi_ulong sc_iaoq[2];
6647 abi_ulong sc_sar;
6648};
6649
6650struct target_ucontext {
6651 abi_uint tuc_flags;
6652 abi_ulong tuc_link;
6653 target_stack_t tuc_stack;
6654 abi_uint pad[1];
6655 struct target_sigcontext tuc_mcontext;
6656 target_sigset_t tuc_sigmask;
6657};
6658
6659struct target_rt_sigframe {
6660 abi_uint tramp[9];
6661 target_siginfo_t info;
6662 struct target_ucontext uc;
6663 /* hidden location of upper halves of pa2.0 64-bit gregs */
6664};
6665
6666static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6667{
6668 int flags = 0;
6669 int i;
6670
6671 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6672
6673 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6674 /* In the gateway page, executing a syscall. */
6675 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6676 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6677 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6678 } else {
6679 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6680 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6681 }
6682 __put_user(0, &sc->sc_iasq[0]);
6683 __put_user(0, &sc->sc_iasq[1]);
6684 __put_user(flags, &sc->sc_flags);
6685
6686 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6687 for (i = 1; i < 32; ++i) {
6688 __put_user(env->gr[i], &sc->sc_gr[i]);
6689 }
6690
6691 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6692 for (i = 1; i < 32; ++i) {
6693 __put_user(env->fr[i], &sc->sc_fr[i]);
6694 }
6695
Richard Henderson35136a72017-10-10 21:19:34 -07006696 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006697}
6698
6699static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6700{
6701 target_ulong psw;
6702 int i;
6703
6704 __get_user(psw, &sc->sc_gr[0]);
6705 cpu_hppa_put_psw(env, psw);
6706
6707 for (i = 1; i < 32; ++i) {
6708 __get_user(env->gr[i], &sc->sc_gr[i]);
6709 }
6710 for (i = 0; i < 32; ++i) {
6711 __get_user(env->fr[i], &sc->sc_fr[i]);
6712 }
6713 cpu_hppa_loaded_fr0(env);
6714
6715 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6716 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006717 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006718}
6719
6720/* No, this doesn't look right, but it's copied straight from the kernel. */
6721#define PARISC_RT_SIGFRAME_SIZE32 \
6722 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6723
6724static void setup_rt_frame(int sig, struct target_sigaction *ka,
6725 target_siginfo_t *info,
6726 target_sigset_t *set, CPUArchState *env)
6727{
6728 abi_ulong frame_addr, sp, haddr;
6729 struct target_rt_sigframe *frame;
6730 int i;
6731
6732 sp = env->gr[30];
6733 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6734 if (sas_ss_flags(sp) == 0) {
6735 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6736 }
6737 }
6738 frame_addr = QEMU_ALIGN_UP(sp, 64);
6739 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6740
6741 trace_user_setup_rt_frame(env, frame_addr);
6742
6743 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6744 goto give_sigsegv;
6745 }
6746
6747 tswap_siginfo(&frame->info, info);
6748 frame->uc.tuc_flags = 0;
6749 frame->uc.tuc_link = 0;
6750
6751 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6752 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6753 &frame->uc.tuc_stack.ss_flags);
6754 __put_user(target_sigaltstack_used.ss_size,
6755 &frame->uc.tuc_stack.ss_size);
6756
6757 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6758 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6759 }
6760
6761 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6762
6763 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6764 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6765 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6766 __put_user(0x08000240, frame->tramp + 3); /* nop */
6767
6768 unlock_user_struct(frame, frame_addr, 1);
6769
6770 env->gr[2] = h2g(frame->tramp);
6771 env->gr[30] = sp;
6772 env->gr[26] = sig;
6773 env->gr[25] = h2g(&frame->info);
6774 env->gr[24] = h2g(&frame->uc);
6775
6776 haddr = ka->_sa_handler;
6777 if (haddr & 2) {
6778 /* Function descriptor. */
6779 target_ulong *fdesc, dest;
6780
6781 haddr &= -4;
6782 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
6783 goto give_sigsegv;
6784 }
6785 __get_user(dest, fdesc);
6786 __get_user(env->gr[19], fdesc + 1);
6787 unlock_user_struct(fdesc, haddr, 1);
6788 haddr = dest;
6789 }
6790 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02006791 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08006792 return;
6793
6794 give_sigsegv:
6795 force_sigsegv(sig);
6796}
6797
6798long do_rt_sigreturn(CPUArchState *env)
6799{
6800 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
6801 struct target_rt_sigframe *frame;
6802 sigset_t set;
6803
6804 trace_user_do_rt_sigreturn(env, frame_addr);
6805 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6806 goto badframe;
6807 }
6808 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
6809 set_sigmask(&set);
6810
6811 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6812 unlock_user_struct(frame, frame_addr, 0);
6813
6814 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6815 uc.tuc_stack),
6816 0, env->gr[30]) == -EFAULT) {
6817 goto badframe;
6818 }
6819
6820 unlock_user_struct(frame, frame_addr, 0);
6821 return -TARGET_QEMU_ESIGRETURN;
6822
6823 badframe:
6824 force_sig(TARGET_SIGSEGV);
6825 return -TARGET_QEMU_ESIGRETURN;
6826}
6827
bellardb346ff42003-06-15 20:05:50 +00006828#else
6829
pbrook624f7972008-05-31 16:11:38 +00006830static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006831 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006832{
6833 fprintf(stderr, "setup_frame: not implemented\n");
6834}
6835
pbrook624f7972008-05-31 16:11:38 +00006836static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006837 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006838 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006839{
6840 fprintf(stderr, "setup_rt_frame: not implemented\n");
6841}
6842
Andreas Färber9349b4f2012-03-14 01:38:32 +01006843long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006844{
6845 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006846 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006847}
6848
Andreas Färber9349b4f2012-03-14 01:38:32 +01006849long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006850{
6851 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006852 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006853}
6854
bellard66fb9762003-03-23 01:06:05 +00006855#endif
6856
Peter Maydell31efaef2016-07-06 15:09:29 +01006857static void handle_pending_signal(CPUArchState *cpu_env, int sig,
6858 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01006859{
6860 CPUState *cpu = ENV_GET_CPU(cpu_env);
6861 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006862 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01006863 target_sigset_t target_old_set;
6864 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01006865 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01006866
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006867 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00006868 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006869 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00006870
Andreas Färberdb6b81d2013-06-27 19:49:31 +02006871 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00006872 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00006873 sa = NULL;
6874 handler = TARGET_SIG_IGN;
6875 } else {
6876 sa = &sigact_table[sig - 1];
6877 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00006878 }
bellard66fb9762003-03-23 01:06:05 +00006879
Peter Maydell0cb581d2016-07-18 18:12:24 +01006880 if (do_strace) {
6881 print_taken_signal(sig, &k->info);
6882 }
6883
bellard66fb9762003-03-23 01:06:05 +00006884 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00006885 /* default handler : ignore some signal. The other are job control or fatal */
6886 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
6887 kill(getpid(),SIGSTOP);
6888 } else if (sig != TARGET_SIGCHLD &&
6889 sig != TARGET_SIGURG &&
6890 sig != TARGET_SIGWINCH &&
6891 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006892 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006893 }
6894 } else if (handler == TARGET_SIG_IGN) {
6895 /* ignore sig */
6896 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006897 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006898 } else {
bellard9de5e442003-03-23 16:49:39 +00006899 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006900 sigset_t *blocked_set;
6901
pbrook624f7972008-05-31 16:11:38 +00006902 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00006903 /* SA_NODEFER indicates that the current signal should not be
6904 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00006905 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00006906 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00006907
bellard9de5e442003-03-23 16:49:39 +00006908 /* save the previous blocked signal state to restore it at the
6909 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006910 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
6911
6912 /* block signals in the handler */
6913 blocked_set = ts->in_sigsuspend ?
6914 &ts->sigsuspend_mask : &ts->signal_mask;
6915 sigorset(&ts->signal_mask, blocked_set, &set);
6916 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00006917
bellardbc8a22c2003-03-30 21:02:40 +00006918 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00006919#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00006920 {
6921 CPUX86State *env = cpu_env;
6922 if (env->eflags & VM_MASK)
6923 save_v86_state(env);
6924 }
6925#endif
bellard9de5e442003-03-23 16:49:39 +00006926 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08006927#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10006928 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01006929 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13006930 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
6931 || defined(TARGET_RISCV)
Richard Hendersonff970902013-02-10 10:30:42 -08006932 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006933 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006934#else
pbrook624f7972008-05-31 16:11:38 +00006935 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006936 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00006937 else
pbrook624f7972008-05-31 16:11:38 +00006938 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006939#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01006940 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00006941 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01006942 }
bellard31e31b82003-02-18 22:55:36 +00006943 }
bellard31e31b82003-02-18 22:55:36 +00006944}
Peter Maydelle902d582016-05-27 15:51:44 +01006945
6946void process_pending_signals(CPUArchState *cpu_env)
6947{
6948 CPUState *cpu = ENV_GET_CPU(cpu_env);
6949 int sig;
6950 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006951 sigset_t set;
6952 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01006953
Peter Maydell3d3efba2016-05-27 15:51:49 +01006954 while (atomic_read(&ts->signal_pending)) {
6955 /* FIXME: This is not threadsafe. */
6956 sigfillset(&set);
6957 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01006958
Peter Maydell8bd37732016-07-28 16:44:45 +01006959 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006960 sig = ts->sync_signal.pending;
6961 if (sig) {
6962 /* Synchronous signals are forced,
6963 * see force_sig_info() and callers in Linux
6964 * Note that not all of our queue_signal() calls in QEMU correspond
6965 * to force_sig_info() calls in Linux (some are send_sig_info()).
6966 * However it seems like a kernel bug to me to allow the process
6967 * to block a synchronous signal since it could then just end up
6968 * looping round and round indefinitely.
6969 */
6970 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
6971 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
6972 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
6973 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
6974 }
6975
Peter Maydell31efaef2016-07-06 15:09:29 +01006976 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006977 }
6978
Peter Maydell3d3efba2016-05-27 15:51:49 +01006979 for (sig = 1; sig <= TARGET_NSIG; sig++) {
6980 blocked_set = ts->in_sigsuspend ?
6981 &ts->sigsuspend_mask : &ts->signal_mask;
6982
6983 if (ts->sigtab[sig - 1].pending &&
6984 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01006985 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01006986 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01006987 /* Restart scan from the beginning, as handle_pending_signal
6988 * might have resulted in a new synchronous signal (eg SIGSEGV).
6989 */
6990 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006991 }
Peter Maydelle902d582016-05-27 15:51:44 +01006992 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01006993
6994 /* if no signal is pending, unblock signals and recheck (the act
6995 * of unblocking might cause us to take another host signal which
6996 * will set signal_pending again).
6997 */
6998 atomic_set(&ts->signal_pending, 0);
6999 ts->in_sigsuspend = 0;
7000 set = ts->signal_mask;
7001 sigdelset(&set, SIGSEGV);
7002 sigdelset(&set, SIGBUS);
7003 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007004 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007005 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007006}