blob: f8bc0aa3978e24bbb2fb035da29dfb5de7bd1e9e [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
Peter Maydella70dadc2016-05-27 15:51:59 +010020#include "qemu/bitops.h"
bellard31e31b82003-02-18 22:55:36 +000021#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030022#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000023
bellard3ef693a2003-03-23 20:17:16 +000024#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000025#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000026#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010027#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000028
blueswir1249c4c32008-10-05 11:09:37 +000029static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000030 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
pbrook624f7972008-05-31 16:11:38 +000035static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000036
ths5fafdf22007-09-16 21:08:06 +000037static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000038 void *puc);
39
Arnaud Patard3ca05582009-03-30 01:18:20 +020040static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000041 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000047/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000076 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080077 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000078 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000082};
Arnaud Patard3ca05582009-03-30 01:18:20 +020083static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000084
thsa04e1342007-09-27 13:57:58 +000085static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
pbrook1d9d8b52009-04-16 15:17:02 +000097int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000098{
Andreas Schwab167c50d2013-07-02 14:04:12 +010099 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000100 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000101 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000102}
103
pbrook4cb05962008-05-30 18:05:19 +0000104int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000105{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100106 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000107 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000108 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000109}
110
Anthony Liguoric227f092009-10-01 16:12:16 -0500111static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000112{
113 memset(set, 0, sizeof(*set));
114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
Anthony Liguoric227f092009-10-01 16:12:16 -0500123static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
Anthony Liguoric227f092009-10-01 16:12:16 -0500130static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000131 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000132{
133 int i;
pbrookf5545b52008-05-30 22:37:07 +0000134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
bellard9e5f5282003-07-13 17:33:54 +0000139 }
bellard66fb9762003-03-23 01:06:05 +0000140}
141
Anthony Liguoric227f092009-10-01 16:12:16 -0500142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000143{
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200149 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000150}
151
blueswir18fcd3692008-08-17 20:26:25 +0000152static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500153 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000154{
155 int i;
pbrookf5545b52008-05-30 22:37:07 +0000156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100161 }
bellard66fb9762003-03-23 01:06:05 +0000162}
163
Anthony Liguoric227f092009-10-01 16:12:16 -0500164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200170 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000171 target_to_host_sigset_internal(d, &s1);
172}
ths3b46e622007-09-17 08:09:54 +0000173
blueswir1992f48a2007-10-14 16:27:31 +0000174void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000175 const sigset_t *sigset)
176{
Anthony Liguoric227f092009-10-01 16:12:16 -0500177 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000180}
181
ths5fafdf22007-09-16 21:08:06 +0000182void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000183 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000184{
Anthony Liguoric227f092009-10-01 16:12:16 -0500185 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000192}
193
Peter Maydell3d3efba2016-05-27 15:51:49 +0100194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
Eduardo Habkost9be38592016-06-13 18:57:58 -0300206 return atomic_xchg(&ts->signal_pending, 1);
Peter Maydell3d3efba2016-05-27 15:51:49 +0100207}
208
Alex Barcelo1c275922014-03-14 14:36:55 +0000209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000223
224 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100225 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000226
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000230
231 switch (how) {
232 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000234 break;
235 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000240 }
241 break;
242 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100243 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000244 break;
245 default:
246 g_assert_not_reached();
247 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100248
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000252 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100253 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000254}
255
Peter Maydell9eede5b2016-05-27 15:51:46 +0100256#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
Pranith Kumar1c1df012017-02-26 11:53:44 -0500257 !defined(TARGET_NIOS2)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100258/* Just set the guest's signal mask to the specified value; the
259 * caller is assumed to have called block_signals() already.
260 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100261static void set_sigmask(const sigset_t *set)
262{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100263 TaskState *ts = (TaskState *)thread_cpu->opaque;
264
265 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100266}
267#endif
268
bellard9de5e442003-03-23 16:49:39 +0000269/* siginfo conversion */
270
Anthony Liguoric227f092009-10-01 16:12:16 -0500271static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000272 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000273{
Richard Hendersona05c6402012-09-15 11:34:20 -0700274 int sig = host_to_target_signal(info->si_signo);
Peter Maydella70dadc2016-05-27 15:51:59 +0100275 int si_code = info->si_code;
276 int si_type;
bellard9de5e442003-03-23 16:49:39 +0000277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000279 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700280
Peter Maydell55d72a72016-06-13 11:22:05 +0100281 /* This memset serves two purposes:
282 * (1) ensure we don't leak random junk to the guest later
283 * (2) placate false positives from gcc about fields
284 * being used uninitialized if it chooses to inline both this
285 * function and tswap_siginfo() into host_to_target_siginfo().
286 */
287 memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
288
Peter Maydella70dadc2016-05-27 15:51:59 +0100289 /* This is awkward, because we have to use a combination of
290 * the si_code and si_signo to figure out which of the union's
291 * members are valid. (Within the host kernel it is always possible
292 * to tell, but the kernel carefully avoids giving userspace the
293 * high 16 bits of si_code, so we don't have the information to
294 * do this the easy way...) We therefore make our best guess,
295 * bearing in mind that a guest can spoof most of the si_codes
296 * via rt_sigqueueinfo() if it likes.
297 *
298 * Once we have made our guess, we record it in the top 16 bits of
299 * the si_code, so that tswap_siginfo() later can use it.
300 * tswap_siginfo() will strip these top bits out before writing
301 * si_code to the guest (sign-extending the lower bits).
302 */
303
304 switch (si_code) {
305 case SI_USER:
306 case SI_TKILL:
307 case SI_KERNEL:
308 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
309 * These are the only unspoofable si_code values.
310 */
311 tinfo->_sifields._kill._pid = info->si_pid;
312 tinfo->_sifields._kill._uid = info->si_uid;
313 si_type = QEMU_SI_KILL;
314 break;
315 default:
316 /* Everything else is spoofable. Make best guess based on signal */
317 switch (sig) {
318 case TARGET_SIGCHLD:
319 tinfo->_sifields._sigchld._pid = info->si_pid;
320 tinfo->_sifields._sigchld._uid = info->si_uid;
321 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100322 = host_to_target_waitstatus(info->si_status);
Peter Maydella70dadc2016-05-27 15:51:59 +0100323 tinfo->_sifields._sigchld._utime = info->si_utime;
324 tinfo->_sifields._sigchld._stime = info->si_stime;
325 si_type = QEMU_SI_CHLD;
326 break;
327 case TARGET_SIGIO:
328 tinfo->_sifields._sigpoll._band = info->si_band;
329 tinfo->_sifields._sigpoll._fd = info->si_fd;
330 si_type = QEMU_SI_POLL;
331 break;
332 default:
333 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
334 tinfo->_sifields._rt._pid = info->si_pid;
335 tinfo->_sifields._rt._uid = info->si_uid;
336 /* XXX: potential problem if 64 bit */
337 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100338 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
Peter Maydella70dadc2016-05-27 15:51:59 +0100339 si_type = QEMU_SI_RT;
340 break;
341 }
342 break;
bellard9de5e442003-03-23 16:49:39 +0000343 }
Peter Maydella70dadc2016-05-27 15:51:59 +0100344
345 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
bellard66fb9762003-03-23 01:06:05 +0000346}
347
Anthony Liguoric227f092009-10-01 16:12:16 -0500348static void tswap_siginfo(target_siginfo_t *tinfo,
349 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000350{
Peter Maydella70dadc2016-05-27 15:51:59 +0100351 int si_type = extract32(info->si_code, 16, 16);
352 int si_code = sextract32(info->si_code, 0, 16);
Richard Hendersona05c6402012-09-15 11:34:20 -0700353
Peter Maydella70dadc2016-05-27 15:51:59 +0100354 __put_user(info->si_signo, &tinfo->si_signo);
355 __put_user(info->si_errno, &tinfo->si_errno);
356 __put_user(si_code, &tinfo->si_code);
357
358 /* We can use our internal marker of which fields in the structure
359 * are valid, rather than duplicating the guesswork of
360 * host_to_target_siginfo_noswap() here.
361 */
362 switch (si_type) {
363 case QEMU_SI_KILL:
364 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
365 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
366 break;
367 case QEMU_SI_TIMER:
368 __put_user(info->_sifields._timer._timer1,
369 &tinfo->_sifields._timer._timer1);
370 __put_user(info->_sifields._timer._timer2,
371 &tinfo->_sifields._timer._timer2);
372 break;
373 case QEMU_SI_POLL:
374 __put_user(info->_sifields._sigpoll._band,
375 &tinfo->_sifields._sigpoll._band);
376 __put_user(info->_sifields._sigpoll._fd,
377 &tinfo->_sifields._sigpoll._fd);
378 break;
379 case QEMU_SI_FAULT:
380 __put_user(info->_sifields._sigfault._addr,
381 &tinfo->_sifields._sigfault._addr);
382 break;
383 case QEMU_SI_CHLD:
384 __put_user(info->_sifields._sigchld._pid,
385 &tinfo->_sifields._sigchld._pid);
386 __put_user(info->_sifields._sigchld._uid,
387 &tinfo->_sifields._sigchld._uid);
388 __put_user(info->_sifields._sigchld._status,
389 &tinfo->_sifields._sigchld._status);
390 __put_user(info->_sifields._sigchld._utime,
391 &tinfo->_sifields._sigchld._utime);
392 __put_user(info->_sifields._sigchld._stime,
393 &tinfo->_sifields._sigchld._stime);
394 break;
395 case QEMU_SI_RT:
396 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
397 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
398 __put_user(info->_sifields._rt._sigval.sival_ptr,
399 &tinfo->_sifields._rt._sigval.sival_ptr);
400 break;
401 default:
402 g_assert_not_reached();
bellard9de5e442003-03-23 16:49:39 +0000403 }
404}
405
Anthony Liguoric227f092009-10-01 16:12:16 -0500406void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000407{
Peter Maydell55d72a72016-06-13 11:22:05 +0100408 target_siginfo_t tgt_tmp;
409 host_to_target_siginfo_noswap(&tgt_tmp, info);
410 tswap_siginfo(tinfo, &tgt_tmp);
bellard9de5e442003-03-23 16:49:39 +0000411}
412
413/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000414/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500415void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000416{
Peter Maydell90c0f082016-05-27 15:52:01 +0100417 /* This conversion is used only for the rt_sigqueueinfo syscall,
418 * and so we know that the _rt fields are the valid ones.
419 */
420 abi_ulong sival_ptr;
421
422 __get_user(info->si_signo, &tinfo->si_signo);
423 __get_user(info->si_errno, &tinfo->si_errno);
424 __get_user(info->si_code, &tinfo->si_code);
425 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
426 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
427 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
428 info->si_value.sival_ptr = (void *)(long)sival_ptr;
bellard66fb9762003-03-23 01:06:05 +0000429}
430
aurel32ca587a82008-12-18 22:44:13 +0000431static int fatal_signal (int sig)
432{
433 switch (sig) {
434 case TARGET_SIGCHLD:
435 case TARGET_SIGURG:
436 case TARGET_SIGWINCH:
437 /* Ignored by default. */
438 return 0;
439 case TARGET_SIGCONT:
440 case TARGET_SIGSTOP:
441 case TARGET_SIGTSTP:
442 case TARGET_SIGTTIN:
443 case TARGET_SIGTTOU:
444 /* Job control signals. */
445 return 0;
446 default:
447 return 1;
448 }
449}
450
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451/* returns 1 if given signal should dump core if not handled */
452static int core_dump_signal(int sig)
453{
454 switch (sig) {
455 case TARGET_SIGABRT:
456 case TARGET_SIGFPE:
457 case TARGET_SIGILL:
458 case TARGET_SIGQUIT:
459 case TARGET_SIGSEGV:
460 case TARGET_SIGTRAP:
461 case TARGET_SIGBUS:
462 return (1);
463 default:
464 return (0);
465 }
466}
467
bellard31e31b82003-02-18 22:55:36 +0000468void signal_init(void)
469{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100470 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000471 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000472 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000473 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000474 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000475
bellard9e5f5282003-07-13 17:33:54 +0000476 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200477 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000478 if (host_to_target_signal_table[i] == 0)
479 host_to_target_signal_table[i] = i;
480 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200481 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000482 j = host_to_target_signal_table[i];
483 target_to_host_signal_table[j] = i;
484 }
ths3b46e622007-09-17 08:09:54 +0000485
Peter Maydell3d3efba2016-05-27 15:51:49 +0100486 /* Set the signal mask from the host mask. */
487 sigprocmask(0, 0, &ts->signal_mask);
488
bellard9de5e442003-03-23 16:49:39 +0000489 /* set all host signal handlers. ALL signals are blocked during
490 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000491 memset(sigact_table, 0, sizeof(sigact_table));
492
bellard9de5e442003-03-23 16:49:39 +0000493 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000494 act.sa_flags = SA_SIGINFO;
495 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000496 for(i = 1; i <= TARGET_NSIG; i++) {
497 host_sig = target_to_host_signal(i);
498 sigaction(host_sig, NULL, &oact);
499 if (oact.sa_sigaction == (void *)SIG_IGN) {
500 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
501 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
502 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
503 }
504 /* If there's already a handler installed then something has
505 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000506 /* Install some handlers for our own use. We need at least
507 SIGSEGV and SIGBUS, to detect exceptions. We can not just
508 trap all signals because it affects syscall interrupt
509 behavior. But do trap all default-fatal signals. */
510 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000511 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000512 }
bellard31e31b82003-02-18 22:55:36 +0000513}
514
Pranith Kumar1c1df012017-02-26 11:53:44 -0500515#ifndef TARGET_UNICORE32
Peter Maydellc599d4d2016-07-28 16:44:49 +0100516/* Force a synchronously taken signal. The kernel force_sig() function
517 * also forces the signal to "not blocked, not ignored", but for QEMU
518 * that work is done in process_pending_signals().
519 */
520static void force_sig(int sig)
521{
522 CPUState *cpu = thread_cpu;
523 CPUArchState *env = cpu->env_ptr;
524 target_siginfo_t info;
525
526 info.si_signo = sig;
527 info.si_errno = 0;
528 info.si_code = TARGET_SI_KERNEL;
529 info._sifields._kill._pid = 0;
530 info._sifields._kill._uid = 0;
531 queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
532}
Peter Maydell09391662016-07-28 16:44:47 +0100533
534/* Force a SIGSEGV if we couldn't write to memory trying to set
535 * up the signal frame. oldsig is the signal we were trying to handle
536 * at the point of failure.
537 */
Michael Clark47ae93c2018-03-03 01:31:11 +1300538#if !defined(TARGET_RISCV)
Peter Maydell09391662016-07-28 16:44:47 +0100539static void force_sigsegv(int oldsig)
540{
Peter Maydell09391662016-07-28 16:44:47 +0100541 if (oldsig == SIGSEGV) {
542 /* Make sure we don't try to deliver the signal again; this will
Peter Maydellc599d4d2016-07-28 16:44:49 +0100543 * end up with handle_pending_signal() calling dump_core_and_abort().
Peter Maydell09391662016-07-28 16:44:47 +0100544 */
545 sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
546 }
Peter Maydellc4b35742016-07-28 16:44:50 +0100547 force_sig(TARGET_SIGSEGV);
Peter Maydell09391662016-07-28 16:44:47 +0100548}
549#endif
bellard66fb9762003-03-23 01:06:05 +0000550
Michael Clark47ae93c2018-03-03 01:31:11 +1300551#endif
552
bellard9de5e442003-03-23 16:49:39 +0000553/* abort execution with signal */
Peter Maydellc599d4d2016-07-28 16:44:49 +0100554static void QEMU_NORETURN dump_core_and_abort(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000555{
Andreas Färber0429a972013-08-26 18:14:44 +0200556 CPUState *cpu = thread_cpu;
557 CPUArchState *env = cpu->env_ptr;
558 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300559 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000560 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100561
Riku Voipio66393fb2009-12-04 15:16:32 +0200562 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100563 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200564 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000565
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300566 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200567 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300568 stop_all_tasks();
569 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200570 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300571 }
572 if (core_dumped) {
573 /* we already dumped the core of target process, we don't want
574 * a coredump of qemu itself */
575 struct rlimit nodump;
576 getrlimit(RLIMIT_CORE, &nodump);
577 nodump.rlim_cur=0;
578 setrlimit(RLIMIT_CORE, &nodump);
579 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200580 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300581 }
582
Stefan Weil0c587512011-04-28 17:20:32 +0200583 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000584 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
585 * a negative value. To get the proper exit code we need to
586 * actually die from an uncaught signal. Here the default signal
587 * handler is installed, we send ourself a signal and we wait for
588 * it to arrive. */
589 sigfillset(&act.sa_mask);
590 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000591 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000592 sigaction(host_sig, &act, NULL);
593
594 /* For some reason raise(host_sig) doesn't send the signal when
595 * statically linked on x86-64. */
596 kill(getpid(), host_sig);
597
598 /* Make sure the signal isn't masked (just reuse the mask inside
599 of act) */
600 sigdelset(&act.sa_mask, host_sig);
601 sigsuspend(&act.sa_mask);
602
603 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000604 abort();
bellard66fb9762003-03-23 01:06:05 +0000605}
606
bellard9de5e442003-03-23 16:49:39 +0000607/* queue a signal so that it will be send to the virtual CPU as soon
608 as possible */
Peter Maydell9d2803f2016-07-28 16:44:46 +0100609int queue_signal(CPUArchState *env, int sig, int si_type,
610 target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000611{
Andreas Färber0429a972013-08-26 18:14:44 +0200612 CPUState *cpu = ENV_GET_CPU(env);
613 TaskState *ts = cpu->opaque;
bellard66fb9762003-03-23 01:06:05 +0000614
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100615 trace_user_queue_signal(env, sig);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000616
Peter Maydell9d2803f2016-07-28 16:44:46 +0100617 info->si_code = deposit32(info->si_code, 16, 16, si_type);
Peter Maydella70dadc2016-05-27 15:51:59 +0100618
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100619 ts->sync_signal.info = *info;
620 ts->sync_signal.pending = sig;
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +0100621 /* signal that a new signal is pending */
622 atomic_set(&ts->signal_pending, 1);
623 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000624}
625
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100626#ifndef HAVE_SAFE_SYSCALL
627static inline void rewind_if_in_safe_syscall(void *puc)
628{
629 /* Default version: never rewind */
630}
631#endif
632
ths5fafdf22007-09-16 21:08:06 +0000633static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000634 void *puc)
635{
Andreas Färbera2247f82013-06-09 19:47:04 +0200636 CPUArchState *env = thread_cpu->env_ptr;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100637 CPUState *cpu = ENV_GET_CPU(env);
638 TaskState *ts = cpu->opaque;
639
bellard9de5e442003-03-23 16:49:39 +0000640 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500641 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100642 ucontext_t *uc = puc;
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100643 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000644
645 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000646 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000647 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000648 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000649 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000650 return;
651 }
652
653 /* get target signal number */
654 sig = host_to_target_signal(host_signum);
655 if (sig < 1 || sig > TARGET_NSIG)
656 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100657 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100658
659 rewind_if_in_safe_syscall(puc);
660
bellard9de5e442003-03-23 16:49:39 +0000661 host_to_target_siginfo_noswap(&tinfo, info);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100662 k = &ts->sigtab[sig - 1];
663 k->info = tinfo;
664 k->pending = sig;
665 ts->signal_pending = 1;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100666
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100667 /* Block host signals until target signal handler entered. We
668 * can't block SIGSEGV or SIGBUS while we're executing guest
669 * code in case the guest code provokes one in the window between
670 * now and it getting out to the main loop. Signals will be
671 * unblocked again in process_pending_signals().
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100672 *
673 * WARNING: we cannot use sigfillset() here because the uc_sigmask
674 * field is a kernel sigset_t, which is much smaller than the
675 * libc sigset_t which sigfillset() operates on. Using sigfillset()
676 * would write 0xff bytes off the end of the structure and trash
677 * data on the struct.
678 * We can't use sizeof(uc->uc_sigmask) either, because the libc
679 * headers define the struct field with the wrong (too large) type.
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100680 */
Peter Maydell1d48fdd2016-06-14 12:49:18 +0100681 memset(&uc->uc_sigmask, 0xff, SIGSET_T_SIZE);
Timothy E Baldwin655ed672016-05-27 15:51:53 +0100682 sigdelset(&uc->uc_sigmask, SIGSEGV);
683 sigdelset(&uc->uc_sigmask, SIGBUS);
684
685 /* interrupt the virtual CPU as soon as possible */
686 cpu_exit(thread_cpu);
bellard31e31b82003-02-18 22:55:36 +0000687}
688
ths0da46a62007-10-20 20:23:07 +0000689/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000690/* compare linux/kernel/signal.c:do_sigaltstack() */
691abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000692{
693 int ret;
694 struct target_sigaltstack oss;
695
696 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000697 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000698 {
699 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
700 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
701 __put_user(sas_ss_flags(sp), &oss.ss_flags);
702 }
703
bellard579a97f2007-11-11 14:26:47 +0000704 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000705 {
bellard579a97f2007-11-11 14:26:47 +0000706 struct target_sigaltstack *uss;
707 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500708 size_t minstacksize = TARGET_MINSIGSTKSZ;
709
710#if defined(TARGET_PPC64)
711 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
712 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
713 if (get_ppc64_abi(image) > 1) {
714 minstacksize = 4096;
715 }
716#endif
thsa04e1342007-09-27 13:57:58 +0000717
ths0da46a62007-10-20 20:23:07 +0000718 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300719 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000720 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300721 }
722 __get_user(ss.ss_sp, &uss->ss_sp);
723 __get_user(ss.ss_size, &uss->ss_size);
724 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000725 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000726
ths0da46a62007-10-20 20:23:07 +0000727 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000728 if (on_sig_stack(sp))
729 goto out;
730
ths0da46a62007-10-20 20:23:07 +0000731 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000732 if (ss.ss_flags != TARGET_SS_DISABLE
733 && ss.ss_flags != TARGET_SS_ONSTACK
734 && ss.ss_flags != 0)
735 goto out;
736
737 if (ss.ss_flags == TARGET_SS_DISABLE) {
738 ss.ss_size = 0;
739 ss.ss_sp = 0;
740 } else {
ths0da46a62007-10-20 20:23:07 +0000741 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500742 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000743 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500744 }
thsa04e1342007-09-27 13:57:58 +0000745 }
746
747 target_sigaltstack_used.ss_sp = ss.ss_sp;
748 target_sigaltstack_used.ss_size = ss.ss_size;
749 }
750
bellard579a97f2007-11-11 14:26:47 +0000751 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000752 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000753 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000754 goto out;
thsa04e1342007-09-27 13:57:58 +0000755 }
756
757 ret = 0;
758out:
759 return ret;
760}
761
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100762/* do_sigaction() return target values and host errnos */
bellard66fb9762003-03-23 01:06:05 +0000763int do_sigaction(int sig, const struct target_sigaction *act,
764 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000765{
pbrook624f7972008-05-31 16:11:38 +0000766 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000767 struct sigaction act1;
768 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000769 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000770
Timothy E Baldwinef6a7782016-05-27 15:51:54 +0100771 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
772 return -TARGET_EINVAL;
773 }
774
775 if (block_signals()) {
776 return -TARGET_ERESTARTSYS;
777 }
778
bellard66fb9762003-03-23 01:06:05 +0000779 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000780 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800781 __put_user(k->_sa_handler, &oact->_sa_handler);
782 __put_user(k->sa_flags, &oact->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100783#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800784 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000785#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800786 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000787 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000788 }
789 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000790 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800791 __get_user(k->_sa_handler, &act->_sa_handler);
792 __get_user(k->sa_flags, &act->sa_flags);
Richard Henderson7f047de2017-10-31 13:53:52 +0100793#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Hendersond2565872013-01-04 16:39:32 -0800794 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000795#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800796 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000797 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000798
799 /* we update the host linux signal state */
800 host_sig = target_to_host_signal(sig);
801 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
802 sigfillset(&act1.sa_mask);
803 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000804 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000805 act1.sa_flags |= SA_RESTART;
806 /* NOTE: it is important to update the host kernel signal
807 ignore state to avoid getting unexpected interrupted
808 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000809 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000810 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000811 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000812 if (fatal_signal (sig))
813 act1.sa_sigaction = host_signal_handler;
814 else
815 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000816 } else {
817 act1.sa_sigaction = host_signal_handler;
818 }
ths0da46a62007-10-20 20:23:07 +0000819 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000820 }
bellard66fb9762003-03-23 01:06:05 +0000821 }
ths0da46a62007-10-20 20:23:07 +0000822 return ret;
bellard66fb9762003-03-23 01:06:05 +0000823}
bellard31e31b82003-02-18 22:55:36 +0000824
Pranith Kumar1c1df012017-02-26 11:53:44 -0500825#if defined(TARGET_I386)
826/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
bellard66fb9762003-03-23 01:06:05 +0000827
828struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100829 uint16_t significand[4];
830 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000831};
832
833struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100834 uint16_t significand[4];
835 uint16_t exponent;
836 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000837};
838
839struct target_xmmreg {
Pranith Kumar1c1df012017-02-26 11:53:44 -0500840 uint32_t element[4];
bellard66fb9762003-03-23 01:06:05 +0000841};
842
Pranith Kumar1c1df012017-02-26 11:53:44 -0500843struct target_fpstate_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100844 /* Regular FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500845 uint32_t cw;
846 uint32_t sw;
847 uint32_t tag;
848 uint32_t ipoff;
849 uint32_t cssel;
850 uint32_t dataoff;
851 uint32_t datasel;
852 struct target_fpreg st[8];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100853 uint16_t status;
854 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000855
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100856 /* FXSR FPU environment */
Pranith Kumar1c1df012017-02-26 11:53:44 -0500857 uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */
858 uint32_t mxcsr;
859 uint32_t reserved;
860 struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */
861 struct target_xmmreg xmm[8];
862 uint32_t padding[56];
bellard66fb9762003-03-23 01:06:05 +0000863};
864
Pranith Kumar1c1df012017-02-26 11:53:44 -0500865struct target_fpstate_64 {
866 /* FXSAVE format */
867 uint16_t cw;
868 uint16_t sw;
869 uint16_t twd;
870 uint16_t fop;
871 uint64_t rip;
872 uint64_t rdp;
873 uint32_t mxcsr;
874 uint32_t mxcsr_mask;
875 uint32_t st_space[32];
876 uint32_t xmm_space[64];
877 uint32_t reserved[24];
878};
bellard66fb9762003-03-23 01:06:05 +0000879
Pranith Kumar1c1df012017-02-26 11:53:44 -0500880#ifndef TARGET_X86_64
881# define target_fpstate target_fpstate_32
882#else
883# define target_fpstate target_fpstate_64
884#endif
885
886struct target_sigcontext_32 {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100887 uint16_t gs, __gsh;
888 uint16_t fs, __fsh;
889 uint16_t es, __esh;
890 uint16_t ds, __dsh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500891 uint32_t edi;
892 uint32_t esi;
893 uint32_t ebp;
894 uint32_t esp;
895 uint32_t ebx;
896 uint32_t edx;
897 uint32_t ecx;
898 uint32_t eax;
899 uint32_t trapno;
900 uint32_t err;
901 uint32_t eip;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 uint16_t cs, __csh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500903 uint32_t eflags;
904 uint32_t esp_at_signal;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100905 uint16_t ss, __ssh;
Pranith Kumar1c1df012017-02-26 11:53:44 -0500906 uint32_t fpstate; /* pointer */
907 uint32_t oldmask;
908 uint32_t cr2;
bellard66fb9762003-03-23 01:06:05 +0000909};
910
Pranith Kumar1c1df012017-02-26 11:53:44 -0500911struct target_sigcontext_64 {
912 uint64_t r8;
913 uint64_t r9;
914 uint64_t r10;
915 uint64_t r11;
916 uint64_t r12;
917 uint64_t r13;
918 uint64_t r14;
919 uint64_t r15;
920
921 uint64_t rdi;
922 uint64_t rsi;
923 uint64_t rbp;
924 uint64_t rbx;
925 uint64_t rdx;
926 uint64_t rax;
927 uint64_t rcx;
928 uint64_t rsp;
929 uint64_t rip;
930
931 uint64_t eflags;
932
933 uint16_t cs;
934 uint16_t gs;
935 uint16_t fs;
936 uint16_t ss;
937
938 uint64_t err;
939 uint64_t trapno;
940 uint64_t oldmask;
941 uint64_t cr2;
942
943 uint64_t fpstate; /* pointer */
944 uint64_t padding[8];
945};
946
947#ifndef TARGET_X86_64
948# define target_sigcontext target_sigcontext_32
949#else
950# define target_sigcontext target_sigcontext_64
951#endif
952
953/* see Linux/include/uapi/asm-generic/ucontext.h */
bellard66fb9762003-03-23 01:06:05 +0000954struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100955 abi_ulong tuc_flags;
956 abi_ulong tuc_link;
957 target_stack_t tuc_stack;
958 struct target_sigcontext tuc_mcontext;
959 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000960};
961
Pranith Kumar1c1df012017-02-26 11:53:44 -0500962#ifndef TARGET_X86_64
963struct sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000964 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000965 int sig;
966 struct target_sigcontext sc;
967 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000968 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000969 char retcode[8];
970};
971
Pranith Kumar1c1df012017-02-26 11:53:44 -0500972struct rt_sigframe {
blueswir1992f48a2007-10-14 16:27:31 +0000973 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000974 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000975 abi_ulong pinfo;
976 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000977 struct target_siginfo info;
978 struct target_ucontext uc;
979 struct target_fpstate fpstate;
980 char retcode[8];
981};
982
Pranith Kumar1c1df012017-02-26 11:53:44 -0500983#else
984
985struct rt_sigframe {
986 abi_ulong pretcode;
987 struct target_ucontext uc;
988 struct target_siginfo info;
989 struct target_fpstate fpstate;
990};
991
992#endif
993
bellard66fb9762003-03-23 01:06:05 +0000994/*
995 * Set up a signal frame.
996 */
997
bellard66fb9762003-03-23 01:06:05 +0000998/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300999static void setup_sigcontext(struct target_sigcontext *sc,
1000 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
1001 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +00001002{
Andreas Färber27103422013-08-26 08:31:06 +02001003 CPUState *cs = CPU(x86_env_get_cpu(env));
Pranith Kumar1c1df012017-02-26 11:53:44 -05001004#ifndef TARGET_X86_64
Andreas Färber27103422013-08-26 08:31:06 +02001005 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +00001006
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001007 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001008 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
1009 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
1010 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
1011 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
1012 __put_user(env->regs[R_EDI], &sc->edi);
1013 __put_user(env->regs[R_ESI], &sc->esi);
1014 __put_user(env->regs[R_EBP], &sc->ebp);
1015 __put_user(env->regs[R_ESP], &sc->esp);
1016 __put_user(env->regs[R_EBX], &sc->ebx);
1017 __put_user(env->regs[R_EDX], &sc->edx);
1018 __put_user(env->regs[R_ECX], &sc->ecx);
1019 __put_user(env->regs[R_EAX], &sc->eax);
1020 __put_user(cs->exception_index, &sc->trapno);
1021 __put_user(env->error_code, &sc->err);
1022 __put_user(env->eip, &sc->eip);
1023 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
1024 __put_user(env->eflags, &sc->eflags);
1025 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
1026 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +00001027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001028 cpu_x86_fsave(env, fpstate_addr, 1);
1029 fpstate->status = fpstate->sw;
1030 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001031 __put_user(magic, &fpstate->magic);
1032 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +00001033
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001034 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001035 __put_user(mask, &sc->oldmask);
1036 __put_user(env->cr[2], &sc->cr2);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001037#else
1038 __put_user(env->regs[R_EDI], &sc->rdi);
1039 __put_user(env->regs[R_ESI], &sc->rsi);
1040 __put_user(env->regs[R_EBP], &sc->rbp);
1041 __put_user(env->regs[R_ESP], &sc->rsp);
1042 __put_user(env->regs[R_EBX], &sc->rbx);
1043 __put_user(env->regs[R_EDX], &sc->rdx);
1044 __put_user(env->regs[R_ECX], &sc->rcx);
1045 __put_user(env->regs[R_EAX], &sc->rax);
1046
1047 __put_user(env->regs[8], &sc->r8);
1048 __put_user(env->regs[9], &sc->r9);
1049 __put_user(env->regs[10], &sc->r10);
1050 __put_user(env->regs[11], &sc->r11);
1051 __put_user(env->regs[12], &sc->r12);
1052 __put_user(env->regs[13], &sc->r13);
1053 __put_user(env->regs[14], &sc->r14);
1054 __put_user(env->regs[15], &sc->r15);
1055
1056 __put_user(cs->exception_index, &sc->trapno);
1057 __put_user(env->error_code, &sc->err);
1058 __put_user(env->eip, &sc->rip);
1059
1060 __put_user(env->eflags, &sc->eflags);
1061 __put_user(env->segs[R_CS].selector, &sc->cs);
1062 __put_user((uint16_t)0, &sc->gs);
1063 __put_user((uint16_t)0, &sc->fs);
1064 __put_user(env->segs[R_SS].selector, &sc->ss);
1065
1066 __put_user(mask, &sc->oldmask);
1067 __put_user(env->cr[2], &sc->cr2);
1068
1069 /* fpstate_addr must be 16 byte aligned for fxsave */
1070 assert(!(fpstate_addr & 0xf));
1071
1072 cpu_x86_fxsave(env, fpstate_addr);
1073 __put_user(fpstate_addr, &sc->fpstate);
1074#endif
bellard66fb9762003-03-23 01:06:05 +00001075}
1076
1077/*
1078 * Determine which stack to use..
1079 */
1080
bellard579a97f2007-11-11 14:26:47 +00001081static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +00001082get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +00001083{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001084 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +00001085
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001086 /* Default to using normal stack */
1087 esp = env->regs[R_ESP];
Pranith Kumar1c1df012017-02-26 11:53:44 -05001088#ifdef TARGET_X86_64
1089 esp -= 128; /* this is the redzone */
1090#endif
1091
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001092 /* This is the X/Open sanctioned signal stack switching. */
1093 if (ka->sa_flags & TARGET_SA_ONSTACK) {
1094 if (sas_ss_flags(esp) == 0) {
1095 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +00001096 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001097 } else {
Pranith Kumar1c1df012017-02-26 11:53:44 -05001098#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001099 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +00001100 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001101 !(ka->sa_flags & TARGET_SA_RESTORER) &&
1102 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +00001103 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001104 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001105#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001107
1108#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001109 return (esp - frame_size) & -8ul;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001110#else
1111 return ((esp - frame_size) & (~15ul)) - 8;
1112#endif
bellard66fb9762003-03-23 01:06:05 +00001113}
1114
Pranith Kumar1c1df012017-02-26 11:53:44 -05001115#ifndef TARGET_X86_64
bellard579a97f2007-11-11 14:26:47 +00001116/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001117static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001118 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001119{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001120 abi_ulong frame_addr;
1121 struct sigframe *frame;
1122 int i;
bellard66fb9762003-03-23 01:06:05 +00001123
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1125 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001127 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1128 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +00001129
Peter Maydellb6e2c932015-01-08 12:19:43 +00001130 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +00001131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001132 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
1133 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +00001134
Riku Voipio7df2fa32014-04-23 10:34:53 +03001135 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1136 __put_user(set->sig[i], &frame->extramask[i - 1]);
1137 }
bellard66fb9762003-03-23 01:06:05 +00001138
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001139 /* Set up to return from userspace. If provided, use a stub
1140 already in userspace. */
1141 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001142 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001143 } else {
1144 uint16_t val16;
1145 abi_ulong retcode_addr;
1146 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001147 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001148 /* This is popl %eax ; movl $,%eax ; int $0x80 */
1149 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001150 __put_user(val16, (uint16_t *)(frame->retcode+0));
1151 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001152 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001153 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001154 }
bellard66fb9762003-03-23 01:06:05 +00001155
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001156 /* Set up registers for signal handler */
1157 env->regs[R_ESP] = frame_addr;
1158 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001159
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001160 cpu_x86_load_seg(env, R_DS, __USER_DS);
1161 cpu_x86_load_seg(env, R_ES, __USER_DS);
1162 cpu_x86_load_seg(env, R_SS, __USER_DS);
1163 cpu_x86_load_seg(env, R_CS, __USER_CS);
1164 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001165
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001166 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001168 return;
bellard66fb9762003-03-23 01:06:05 +00001169
1170give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001171 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001172}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001173#endif
bellard66fb9762003-03-23 01:06:05 +00001174
Pranith Kumar1c1df012017-02-26 11:53:44 -05001175/* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001176static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001177 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001178 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +00001179{
Pranith Kumar1c1df012017-02-26 11:53:44 -05001180 abi_ulong frame_addr;
1181#ifndef TARGET_X86_64
1182 abi_ulong addr;
1183#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001184 struct rt_sigframe *frame;
1185 int i;
bellard66fb9762003-03-23 01:06:05 +00001186
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001187 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1188 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +00001189
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001190 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1191 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +00001192
Pranith Kumar1c1df012017-02-26 11:53:44 -05001193 /* These fields are only in rt_sigframe on 32 bit */
1194#ifndef TARGET_X86_64
Peter Maydellb6e2c932015-01-08 12:19:43 +00001195 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001196 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001197 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001198 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001199 __put_user(addr, &frame->puc);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001200#endif
1201 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1202 tswap_siginfo(&frame->info, info);
1203 }
bellard66fb9762003-03-23 01:06:05 +00001204
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001205 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001206 __put_user(0, &frame->uc.tuc_flags);
1207 __put_user(0, &frame->uc.tuc_link);
1208 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1209 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1210 &frame->uc.tuc_stack.ss_flags);
1211 __put_user(target_sigaltstack_used.ss_size,
1212 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001213 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1214 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1215
Riku Voipio0188fad2014-04-23 13:34:15 +03001216 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1217 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1218 }
bellard66fb9762003-03-23 01:06:05 +00001219
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001220 /* Set up to return from userspace. If provided, use a stub
1221 already in userspace. */
Pranith Kumar1c1df012017-02-26 11:53:44 -05001222#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001223 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001224 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001225 } else {
1226 uint16_t val16;
1227 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001228 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001229 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001230 __put_user(0xb8, (char *)(frame->retcode+0));
1231 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001232 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001233 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001234 }
Pranith Kumar1c1df012017-02-26 11:53:44 -05001235#else
1236 /* XXX: Would be slightly better to return -EFAULT here if test fails
1237 assert(ka->sa_flags & TARGET_SA_RESTORER); */
1238 __put_user(ka->sa_restorer, &frame->pretcode);
1239#endif
bellard66fb9762003-03-23 01:06:05 +00001240
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001241 /* Set up registers for signal handler */
1242 env->regs[R_ESP] = frame_addr;
1243 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001244
Pranith Kumar1c1df012017-02-26 11:53:44 -05001245#ifndef TARGET_X86_64
1246 env->regs[R_EAX] = sig;
1247 env->regs[R_EDX] = (unsigned long)&frame->info;
1248 env->regs[R_ECX] = (unsigned long)&frame->uc;
1249#else
1250 env->regs[R_EAX] = 0;
1251 env->regs[R_EDI] = sig;
1252 env->regs[R_ESI] = (unsigned long)&frame->info;
1253 env->regs[R_EDX] = (unsigned long)&frame->uc;
1254#endif
1255
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001256 cpu_x86_load_seg(env, R_DS, __USER_DS);
1257 cpu_x86_load_seg(env, R_ES, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001258 cpu_x86_load_seg(env, R_CS, __USER_CS);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001259 cpu_x86_load_seg(env, R_SS, __USER_DS);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001260 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001261
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001262 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001263
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001264 return;
bellard66fb9762003-03-23 01:06:05 +00001265
1266give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01001267 force_sigsegv(sig);
bellard66fb9762003-03-23 01:06:05 +00001268}
1269
1270static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001271restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001272{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001273 unsigned int err = 0;
1274 abi_ulong fpstate_addr;
1275 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001276
Pranith Kumar1c1df012017-02-26 11:53:44 -05001277#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001278 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1279 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1280 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1281 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001282
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001283 env->regs[R_EDI] = tswapl(sc->edi);
1284 env->regs[R_ESI] = tswapl(sc->esi);
1285 env->regs[R_EBP] = tswapl(sc->ebp);
1286 env->regs[R_ESP] = tswapl(sc->esp);
1287 env->regs[R_EBX] = tswapl(sc->ebx);
1288 env->regs[R_EDX] = tswapl(sc->edx);
1289 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001290 env->regs[R_EAX] = tswapl(sc->eax);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001291
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001292 env->eip = tswapl(sc->eip);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001293#else
1294 env->regs[8] = tswapl(sc->r8);
1295 env->regs[9] = tswapl(sc->r9);
1296 env->regs[10] = tswapl(sc->r10);
1297 env->regs[11] = tswapl(sc->r11);
1298 env->regs[12] = tswapl(sc->r12);
1299 env->regs[13] = tswapl(sc->r13);
1300 env->regs[14] = tswapl(sc->r14);
1301 env->regs[15] = tswapl(sc->r15);
1302
1303 env->regs[R_EDI] = tswapl(sc->rdi);
1304 env->regs[R_ESI] = tswapl(sc->rsi);
1305 env->regs[R_EBP] = tswapl(sc->rbp);
1306 env->regs[R_EBX] = tswapl(sc->rbx);
1307 env->regs[R_EDX] = tswapl(sc->rdx);
1308 env->regs[R_EAX] = tswapl(sc->rax);
1309 env->regs[R_ECX] = tswapl(sc->rcx);
1310 env->regs[R_ESP] = tswapl(sc->rsp);
1311
1312 env->eip = tswapl(sc->rip);
1313#endif
bellard66fb9762003-03-23 01:06:05 +00001314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001315 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1316 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001317
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001318 tmpflags = tswapl(sc->eflags);
1319 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1320 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001322 fpstate_addr = tswapl(sc->fpstate);
1323 if (fpstate_addr != 0) {
1324 if (!access_ok(VERIFY_READ, fpstate_addr,
1325 sizeof(struct target_fpstate)))
1326 goto badframe;
Pranith Kumar1c1df012017-02-26 11:53:44 -05001327#ifndef TARGET_X86_64
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001328 cpu_x86_frstor(env, fpstate_addr, 1);
Pranith Kumar1c1df012017-02-26 11:53:44 -05001329#else
1330 cpu_x86_fxrstor(env, fpstate_addr);
1331#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001332 }
bellard66fb9762003-03-23 01:06:05 +00001333
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001334 return err;
bellard66fb9762003-03-23 01:06:05 +00001335badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001336 return 1;
bellard66fb9762003-03-23 01:06:05 +00001337}
1338
Pranith Kumar1c1df012017-02-26 11:53:44 -05001339/* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */
1340#ifndef TARGET_X86_64
bellard66fb9762003-03-23 01:06:05 +00001341long do_sigreturn(CPUX86State *env)
1342{
bellard579a97f2007-11-11 14:26:47 +00001343 struct sigframe *frame;
1344 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001345 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001346 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001347 int i;
bellard66fb9762003-03-23 01:06:05 +00001348
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001349 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001350 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1351 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001352 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001353 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001354 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001355 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001356 }
bellard66fb9762003-03-23 01:06:05 +00001357
bellard92319442004-06-19 16:58:13 +00001358 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001359 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001360
bellard66fb9762003-03-23 01:06:05 +00001361 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001362 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001363 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001364 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001365 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001366
1367badframe:
bellard579a97f2007-11-11 14:26:47 +00001368 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001369 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001370 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001371}
Pranith Kumar1c1df012017-02-26 11:53:44 -05001372#endif
bellard66fb9762003-03-23 01:06:05 +00001373
1374long do_rt_sigreturn(CPUX86State *env)
1375{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001376 abi_ulong frame_addr;
1377 struct rt_sigframe *frame;
1378 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001379
Pranith Kumar1c1df012017-02-26 11:53:44 -05001380 frame_addr = env->regs[R_ESP] - sizeof(abi_ulong);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001381 trace_user_do_rt_sigreturn(env, frame_addr);
1382 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1383 goto badframe;
1384 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001385 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001386
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001387 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001388 goto badframe;
1389 }
bellard66fb9762003-03-23 01:06:05 +00001390
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001391 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1392 get_sp_from_cpustate(env)) == -EFAULT) {
1393 goto badframe;
1394 }
thsa04e1342007-09-27 13:57:58 +00001395
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001396 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001397 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001398
1399badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001400 unlock_user_struct(frame, frame_addr, 0);
1401 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001402 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001403}
1404
Andreas Schwab1744aea2013-09-03 20:12:16 +01001405#elif defined(TARGET_AARCH64)
1406
1407struct target_sigcontext {
1408 uint64_t fault_address;
1409 /* AArch64 registers */
1410 uint64_t regs[31];
1411 uint64_t sp;
1412 uint64_t pc;
1413 uint64_t pstate;
1414 /* 4K reserved for FP/SIMD state and future expansion */
1415 char __reserved[4096] __attribute__((__aligned__(16)));
1416};
1417
1418struct target_ucontext {
1419 abi_ulong tuc_flags;
1420 abi_ulong tuc_link;
1421 target_stack_t tuc_stack;
1422 target_sigset_t tuc_sigmask;
1423 /* glibc uses a 1024-bit sigset_t */
1424 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1425 /* last for future expansion */
1426 struct target_sigcontext tuc_mcontext;
1427};
1428
1429/*
1430 * Header to be used at the beginning of structures extending the user
1431 * context. Such structures must be placed after the rt_sigframe on the stack
1432 * and be 16-byte aligned. The last structure must be a dummy one with the
1433 * magic and size set to 0.
1434 */
1435struct target_aarch64_ctx {
1436 uint32_t magic;
1437 uint32_t size;
1438};
1439
1440#define TARGET_FPSIMD_MAGIC 0x46508001
1441
1442struct target_fpsimd_context {
1443 struct target_aarch64_ctx head;
1444 uint32_t fpsr;
1445 uint32_t fpcr;
1446 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1447};
1448
Richard Henderson7a53fb92018-03-09 17:09:43 +00001449#define TARGET_EXTRA_MAGIC 0x45585401
1450
1451struct target_extra_context {
1452 struct target_aarch64_ctx head;
1453 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
1454 uint32_t size; /* size in bytes of the extra space */
1455 uint32_t reserved[3];
1456};
1457
Andreas Schwab1744aea2013-09-03 20:12:16 +01001458struct target_rt_sigframe {
1459 struct target_siginfo info;
1460 struct target_ucontext uc;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001461};
1462
1463struct target_rt_frame_record {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001464 uint64_t fp;
1465 uint64_t lr;
1466 uint32_t tramp[2];
1467};
1468
Richard Henderson3b505bb2018-03-09 17:09:43 +00001469static void target_setup_general_frame(struct target_rt_sigframe *sf,
1470 CPUARMState *env, target_sigset_t *set)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001471{
1472 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001473
Richard Henderson3b505bb2018-03-09 17:09:43 +00001474 __put_user(0, &sf->uc.tuc_flags);
1475 __put_user(0, &sf->uc.tuc_link);
1476
1477 __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
1478 __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
1479 __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001480
1481 for (i = 0; i < 31; i++) {
1482 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1483 }
1484 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1485 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001486 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001487
Peter Maydell7af03922014-05-01 18:36:17 +01001488 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001489
1490 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1491 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1492 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001493}
1494
1495static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
1496 CPUARMState *env)
1497{
1498 int i;
1499
1500 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
1501 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
1502 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
1503 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001504
1505 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001506 uint64_t *q = aa64_vfp_qreg(env, i);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001507#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001508 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1509 __put_user(q[1], &fpsimd->vregs[i * 2]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001510#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001511 __put_user(q[0], &fpsimd->vregs[i * 2]);
1512 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001513#endif
1514 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001515}
1516
Richard Henderson7a53fb92018-03-09 17:09:43 +00001517static void target_setup_extra_record(struct target_extra_context *extra,
1518 uint64_t datap, uint32_t extra_size)
1519{
1520 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
1521 __put_user(sizeof(struct target_extra_context), &extra->head.size);
1522 __put_user(datap, &extra->datap);
1523 __put_user(extra_size, &extra->size);
1524}
1525
Richard Henderson3b505bb2018-03-09 17:09:43 +00001526static void target_setup_end_record(struct target_aarch64_ctx *end)
1527{
1528 __put_user(0, &end->magic);
1529 __put_user(0, &end->size);
1530}
1531
1532static void target_restore_general_frame(CPUARMState *env,
1533 struct target_rt_sigframe *sf)
Andreas Schwab1744aea2013-09-03 20:12:16 +01001534{
1535 sigset_t set;
Peter Maydelld3563122013-12-17 19:42:30 +00001536 uint64_t pstate;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001537 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001538
1539 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001540 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001541
1542 for (i = 0; i < 31; i++) {
1543 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1544 }
1545
1546 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1547 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001548 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1549 pstate_write(env, pstate);
Richard Henderson3b505bb2018-03-09 17:09:43 +00001550}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001551
Richard Henderson3b505bb2018-03-09 17:09:43 +00001552static void target_restore_fpsimd_record(CPUARMState *env,
1553 struct target_fpsimd_context *fpsimd)
1554{
1555 uint32_t fpsr, fpcr;
1556 int i;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001557
Richard Henderson3b505bb2018-03-09 17:09:43 +00001558 __get_user(fpsr, &fpsimd->fpsr);
1559 vfp_set_fpsr(env, fpsr);
1560 __get_user(fpcr, &fpsimd->fpcr);
1561 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001562
Peter Maydell4cf23482014-03-02 19:36:38 +00001563 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00001564 uint64_t *q = aa64_vfp_qreg(env, i);
Peter Maydell4cf23482014-03-02 19:36:38 +00001565#ifdef TARGET_WORDS_BIGENDIAN
Richard Henderson3b505bb2018-03-09 17:09:43 +00001566 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
1567 __get_user(q[1], &fpsimd->vregs[i * 2]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001568#else
Richard Henderson3b505bb2018-03-09 17:09:43 +00001569 __get_user(q[0], &fpsimd->vregs[i * 2]);
1570 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
Peter Maydell4cf23482014-03-02 19:36:38 +00001571#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001572 }
Richard Henderson3b505bb2018-03-09 17:09:43 +00001573}
Andreas Schwab1744aea2013-09-03 20:12:16 +01001574
Richard Henderson3b505bb2018-03-09 17:09:43 +00001575static int target_restore_sigframe(CPUARMState *env,
1576 struct target_rt_sigframe *sf)
1577{
Richard Henderson7a53fb92018-03-09 17:09:43 +00001578 struct target_aarch64_ctx *ctx, *extra = NULL;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001579 struct target_fpsimd_context *fpsimd = NULL;
Richard Henderson7a53fb92018-03-09 17:09:43 +00001580 uint64_t extra_datap = 0;
1581 bool used_extra = false;
1582 bool err = false;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001583
1584 target_restore_general_frame(env, sf);
1585
Richard Hendersone1eecd12018-03-09 17:09:43 +00001586 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
1587 while (ctx) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001588 uint32_t magic, size, extra_size;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001589
1590 __get_user(magic, &ctx->magic);
1591 __get_user(size, &ctx->size);
1592 switch (magic) {
1593 case 0:
1594 if (size != 0) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001595 err = true;
1596 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001597 }
Richard Henderson7a53fb92018-03-09 17:09:43 +00001598 if (used_extra) {
1599 ctx = NULL;
1600 } else {
1601 ctx = extra;
1602 used_extra = true;
1603 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001604 continue;
1605
1606 case TARGET_FPSIMD_MAGIC:
1607 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
Richard Henderson7a53fb92018-03-09 17:09:43 +00001608 err = true;
1609 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001610 }
1611 fpsimd = (struct target_fpsimd_context *)ctx;
1612 break;
1613
Richard Henderson7a53fb92018-03-09 17:09:43 +00001614 case TARGET_EXTRA_MAGIC:
1615 if (extra || size != sizeof(struct target_extra_context)) {
1616 err = true;
1617 goto exit;
1618 }
1619 __get_user(extra_datap,
1620 &((struct target_extra_context *)ctx)->datap);
1621 __get_user(extra_size,
1622 &((struct target_extra_context *)ctx)->size);
1623 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
1624 break;
1625
Richard Hendersone1eecd12018-03-09 17:09:43 +00001626 default:
1627 /* Unknown record -- we certainly didn't generate it.
1628 * Did we in fact get out of sync?
1629 */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001630 err = true;
1631 goto exit;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001632 }
1633 ctx = (void *)ctx + size;
1634 }
1635
1636 /* Require FPSIMD always. */
Richard Henderson7a53fb92018-03-09 17:09:43 +00001637 if (fpsimd) {
1638 target_restore_fpsimd_record(env, fpsimd);
1639 } else {
1640 err = true;
Richard Henderson3b505bb2018-03-09 17:09:43 +00001641 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001642
Richard Henderson7a53fb92018-03-09 17:09:43 +00001643 exit:
1644 unlock_user(extra, extra_datap, 0);
1645 return err;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001646}
1647
1648static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1649{
1650 abi_ulong sp;
1651
1652 sp = env->xregs[31];
1653
1654 /*
1655 * This is the X/Open sanctioned signal stack switching.
1656 */
Riku Voipiob545f632014-07-15 17:01:55 +03001657 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001658 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1659 }
1660
1661 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1662
1663 return sp;
1664}
1665
1666static void target_setup_frame(int usig, struct target_sigaction *ka,
1667 target_siginfo_t *info, target_sigset_t *set,
1668 CPUARMState *env)
1669{
Richard Hendersone1eecd12018-03-09 17:09:43 +00001670 int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001671 int fpsimd_ofs, end1_ofs, fr_ofs, end2_ofs = 0;
1672 int extra_ofs = 0, extra_base = 0, extra_size = 0;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001673 struct target_rt_sigframe *frame;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001674 struct target_rt_frame_record *fr;
Michael Matz8a3ae912014-03-02 19:36:39 +00001675 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001676
Richard Hendersone1eecd12018-03-09 17:09:43 +00001677 fpsimd_ofs = size;
1678 size += sizeof(struct target_fpsimd_context);
1679 end1_ofs = size;
1680 size += sizeof(struct target_aarch64_ctx);
1681 fr_ofs = size;
1682 size += sizeof(struct target_rt_frame_record);
1683
Andreas Schwab1744aea2013-09-03 20:12:16 +01001684 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001685 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001686 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1687 goto give_sigsegv;
1688 }
1689
Richard Henderson3b505bb2018-03-09 17:09:43 +00001690 target_setup_general_frame(frame, env, set);
Richard Hendersone1eecd12018-03-09 17:09:43 +00001691 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001692 if (extra_ofs) {
1693 target_setup_extra_record((void *)frame + extra_ofs,
1694 frame_addr + extra_base, extra_size);
1695 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001696 target_setup_end_record((void *)frame + end1_ofs);
Richard Henderson7a53fb92018-03-09 17:09:43 +00001697 if (end2_ofs) {
1698 target_setup_end_record((void *)frame + end2_ofs);
1699 }
Richard Hendersone1eecd12018-03-09 17:09:43 +00001700
1701 /* Set up the stack frame for unwinding. */
1702 fr = (void *)frame + fr_ofs;
1703 __put_user(env->xregs[29], &fr->fp);
1704 __put_user(env->xregs[30], &fr->lr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001705
Michael Matz8a3ae912014-03-02 19:36:39 +00001706 if (ka->sa_flags & TARGET_SA_RESTORER) {
1707 return_addr = ka->sa_restorer;
1708 } else {
Michael Weiser50f22fa2018-01-11 13:25:31 +00001709 /*
1710 * mov x8,#__NR_rt_sigreturn; svc #0
1711 * Since these are instructions they need to be put as little-endian
1712 * regardless of target default or current CPU endianness.
1713 */
Richard Hendersone1eecd12018-03-09 17:09:43 +00001714 __put_user_e(0xd2801168, &fr->tramp[0], le);
1715 __put_user_e(0xd4000001, &fr->tramp[1], le);
1716 return_addr = frame_addr + fr_ofs
1717 + offsetof(struct target_rt_frame_record, tramp);
Michael Matz8a3ae912014-03-02 19:36:39 +00001718 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001719 env->xregs[0] = usig;
1720 env->xregs[31] = frame_addr;
Richard Hendersone1eecd12018-03-09 17:09:43 +00001721 env->xregs[29] = frame_addr + fr_ofs;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001722 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001723 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001724 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001725 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001726 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1727 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1728 }
1729
1730 unlock_user_struct(frame, frame_addr, 1);
1731 return;
1732
1733 give_sigsegv:
1734 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01001735 force_sigsegv(usig);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001736}
1737
1738static void setup_rt_frame(int sig, struct target_sigaction *ka,
1739 target_siginfo_t *info, target_sigset_t *set,
1740 CPUARMState *env)
1741{
1742 target_setup_frame(sig, ka, info, set, env);
1743}
1744
1745static void setup_frame(int sig, struct target_sigaction *ka,
1746 target_sigset_t *set, CPUARMState *env)
1747{
1748 target_setup_frame(sig, ka, 0, set, env);
1749}
1750
1751long do_rt_sigreturn(CPUARMState *env)
1752{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001753 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001754 abi_ulong frame_addr = env->xregs[31];
1755
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001756 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001757 if (frame_addr & 15) {
1758 goto badframe;
1759 }
1760
1761 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1762 goto badframe;
1763 }
1764
1765 if (target_restore_sigframe(env, frame)) {
1766 goto badframe;
1767 }
1768
1769 if (do_sigaltstack(frame_addr +
1770 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1771 0, get_sp_from_cpustate(env)) == -EFAULT) {
1772 goto badframe;
1773 }
1774
1775 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001776 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001777
1778 badframe:
1779 unlock_user_struct(frame, frame_addr, 0);
1780 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01001781 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001782}
1783
1784long do_sigreturn(CPUARMState *env)
1785{
1786 return do_rt_sigreturn(env);
1787}
1788
bellard43fff232003-07-09 19:31:39 +00001789#elif defined(TARGET_ARM)
1790
1791struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001792 abi_ulong trap_no;
1793 abi_ulong error_code;
1794 abi_ulong oldmask;
1795 abi_ulong arm_r0;
1796 abi_ulong arm_r1;
1797 abi_ulong arm_r2;
1798 abi_ulong arm_r3;
1799 abi_ulong arm_r4;
1800 abi_ulong arm_r5;
1801 abi_ulong arm_r6;
1802 abi_ulong arm_r7;
1803 abi_ulong arm_r8;
1804 abi_ulong arm_r9;
1805 abi_ulong arm_r10;
1806 abi_ulong arm_fp;
1807 abi_ulong arm_ip;
1808 abi_ulong arm_sp;
1809 abi_ulong arm_lr;
1810 abi_ulong arm_pc;
1811 abi_ulong arm_cpsr;
1812 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001813};
1814
pbrooka745ec62008-05-06 15:36:17 +00001815struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001816 abi_ulong tuc_flags;
1817 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001818 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001819 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001820 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001821};
1822
pbrooka745ec62008-05-06 15:36:17 +00001823struct target_ucontext_v2 {
1824 abi_ulong tuc_flags;
1825 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001826 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001827 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001828 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001829 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001830 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1831};
1832
Peter Maydell0d871bd2010-11-24 15:20:05 +00001833struct target_user_vfp {
1834 uint64_t fpregs[32];
1835 abi_ulong fpscr;
1836};
1837
1838struct target_user_vfp_exc {
1839 abi_ulong fpexc;
1840 abi_ulong fpinst;
1841 abi_ulong fpinst2;
1842};
1843
1844struct target_vfp_sigframe {
1845 abi_ulong magic;
1846 abi_ulong size;
1847 struct target_user_vfp ufp;
1848 struct target_user_vfp_exc ufp_exc;
1849} __attribute__((__aligned__(8)));
1850
Peter Maydell08e11252010-11-24 15:20:07 +00001851struct target_iwmmxt_sigframe {
1852 abi_ulong magic;
1853 abi_ulong size;
1854 uint64_t regs[16];
1855 /* Note that not all the coprocessor control registers are stored here */
1856 uint32_t wcssf;
1857 uint32_t wcasf;
1858 uint32_t wcgr0;
1859 uint32_t wcgr1;
1860 uint32_t wcgr2;
1861 uint32_t wcgr3;
1862} __attribute__((__aligned__(8)));
1863
Peter Maydell0d871bd2010-11-24 15:20:05 +00001864#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001865#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001866
pbrooka8c33202008-05-07 23:22:46 +00001867struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001868{
1869 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001870 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1871 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001872};
1873
pbrooka8c33202008-05-07 23:22:46 +00001874struct sigframe_v2
1875{
1876 struct target_ucontext_v2 uc;
1877 abi_ulong retcode;
1878};
1879
pbrooka745ec62008-05-06 15:36:17 +00001880struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001881{
bellardf8b0aa22007-11-11 23:03:42 +00001882 abi_ulong pinfo;
1883 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001884 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001885 struct target_ucontext_v1 uc;
1886 abi_ulong retcode;
1887};
1888
1889struct rt_sigframe_v2
1890{
1891 struct target_siginfo info;
1892 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001893 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001894};
1895
1896#define TARGET_CONFIG_CPU_32 1
1897
1898/*
1899 * For ARM syscalls, we encode the syscall number into the instruction.
1900 */
1901#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1902#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1903
1904/*
1905 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1906 * need two 16-bit instructions.
1907 */
1908#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1909#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1910
blueswir1992f48a2007-10-14 16:27:31 +00001911static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001912 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1913 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1914};
1915
1916
Andreas Färber05390242012-02-25 03:37:53 +01001917static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001918{
1919 return 1;
1920}
1921
pbrooka8c33202008-05-07 23:22:46 +00001922static void
bellard43fff232003-07-09 19:31:39 +00001923setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001924 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001925{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001926 __put_user(env->regs[0], &sc->arm_r0);
1927 __put_user(env->regs[1], &sc->arm_r1);
1928 __put_user(env->regs[2], &sc->arm_r2);
1929 __put_user(env->regs[3], &sc->arm_r3);
1930 __put_user(env->regs[4], &sc->arm_r4);
1931 __put_user(env->regs[5], &sc->arm_r5);
1932 __put_user(env->regs[6], &sc->arm_r6);
1933 __put_user(env->regs[7], &sc->arm_r7);
1934 __put_user(env->regs[8], &sc->arm_r8);
1935 __put_user(env->regs[9], &sc->arm_r9);
1936 __put_user(env->regs[10], &sc->arm_r10);
1937 __put_user(env->regs[11], &sc->arm_fp);
1938 __put_user(env->regs[12], &sc->arm_ip);
1939 __put_user(env->regs[13], &sc->arm_sp);
1940 __put_user(env->regs[14], &sc->arm_lr);
1941 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001942#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001943 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001944#endif
1945
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001946 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1947 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1948 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1949 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001950}
1951
bellard579a97f2007-11-11 14:26:47 +00001952static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001953get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001954{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001955 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001956
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001957 /*
1958 * This is the X/Open sanctioned signal stack switching.
1959 */
1960 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1961 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1962 }
1963 /*
1964 * ATPCS B01 mandates 8-byte alignment
1965 */
1966 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001967}
1968
Riku Voipio0188fad2014-04-23 13:34:15 +03001969static void
Andreas Färber05390242012-02-25 03:37:53 +01001970setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001971 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001972{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001973 abi_ulong handler = ka->_sa_handler;
1974 abi_ulong retcode;
1975 int thumb = handler & 1;
1976 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001977
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001978 cpsr &= ~CPSR_IT;
1979 if (thumb) {
1980 cpsr |= CPSR_T;
1981 } else {
1982 cpsr &= ~CPSR_T;
1983 }
bellard43fff232003-07-09 19:31:39 +00001984
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001985 if (ka->sa_flags & TARGET_SA_RESTORER) {
1986 retcode = ka->sa_restorer;
1987 } else {
1988 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001989
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001990 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1991 idx += 2;
1992 }
bellard43fff232003-07-09 19:31:39 +00001993
Riku Voipio0188fad2014-04-23 13:34:15 +03001994 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001995
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001996 retcode = rc_addr + thumb;
1997 }
bellard43fff232003-07-09 19:31:39 +00001998
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001999 env->regs[0] = usig;
2000 env->regs[13] = frame_addr;
2001 env->regs[14] = retcode;
2002 env->regs[15] = handler & (thumb ? ~1 : ~3);
2003 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002004}
2005
Andreas Färber05390242012-02-25 03:37:53 +01002006static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00002007{
2008 int i;
2009 struct target_vfp_sigframe *vfpframe;
2010 vfpframe = (struct target_vfp_sigframe *)regspace;
2011 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
2012 __put_user(sizeof(*vfpframe), &vfpframe->size);
2013 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002014 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002015 }
2016 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
2017 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
2018 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2019 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2020 return (abi_ulong*)(vfpframe+1);
2021}
2022
Andreas Färber05390242012-02-25 03:37:53 +01002023static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
2024 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00002025{
2026 int i;
2027 struct target_iwmmxt_sigframe *iwmmxtframe;
2028 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2029 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
2030 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
2031 for (i = 0; i < 16; i++) {
2032 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2033 }
2034 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2035 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2036 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2037 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2038 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2039 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2040 return (abi_ulong*)(iwmmxtframe+1);
2041}
2042
pbrooka8c33202008-05-07 23:22:46 +00002043static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01002044 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002045{
pbrooka8c33202008-05-07 23:22:46 +00002046 struct target_sigaltstack stack;
2047 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00002048 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002049
2050 /* Clear all the bits of the ucontext we don't use. */
2051 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
2052
2053 memset(&stack, 0, sizeof(stack));
2054 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2055 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2056 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2057 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
2058
2059 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00002060 /* Save coprocessor signal frame. */
2061 regspace = uc->tuc_regspace;
2062 if (arm_feature(env, ARM_FEATURE_VFP)) {
2063 regspace = setup_sigframe_v2_vfp(regspace, env);
2064 }
Peter Maydell08e11252010-11-24 15:20:07 +00002065 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2066 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
2067 }
2068
Peter Maydell0d871bd2010-11-24 15:20:05 +00002069 /* Write terminating magic word */
2070 __put_user(0, regspace);
2071
pbrooka8c33202008-05-07 23:22:46 +00002072 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2073 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
2074 }
2075}
2076
2077/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002078static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002079 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002080{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002081 struct sigframe_v1 *frame;
2082 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2083 int i;
bellard43fff232003-07-09 19:31:39 +00002084
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002085 trace_user_setup_frame(regs, frame_addr);
2086 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002087 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002088 }
bellard579a97f2007-11-11 14:26:47 +00002089
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002090 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00002091
Riku Voipio0188fad2014-04-23 13:34:15 +03002092 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2093 __put_user(set->sig[i], &frame->extramask[i - 1]);
2094 }
bellard43fff232003-07-09 19:31:39 +00002095
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002096 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2097 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00002098
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002099 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002100 return;
2101sigsegv:
2102 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002103}
2104
pbrook624f7972008-05-31 16:11:38 +00002105static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002106 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002107{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002108 struct sigframe_v2 *frame;
2109 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00002110
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002111 trace_user_setup_frame(regs, frame_addr);
2112 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002113 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002114 }
pbrooka8c33202008-05-07 23:22:46 +00002115
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002116 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00002117
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002118 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
2119 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00002120
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002121 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002122 return;
2123sigsegv:
2124 force_sigsegv(usig);
pbrooka8c33202008-05-07 23:22:46 +00002125}
2126
pbrook624f7972008-05-31 16:11:38 +00002127static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002128 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00002129{
2130 if (get_osversion() >= 0x020612) {
2131 setup_frame_v2(usig, ka, set, regs);
2132 } else {
2133 setup_frame_v1(usig, ka, set, regs);
2134 }
bellard43fff232003-07-09 19:31:39 +00002135}
2136
bellard579a97f2007-11-11 14:26:47 +00002137/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00002138static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002139 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002140 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002141{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002142 struct rt_sigframe_v1 *frame;
2143 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2144 struct target_sigaltstack stack;
2145 int i;
2146 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00002147
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002148 trace_user_setup_rt_frame(env, frame_addr);
2149 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002150 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002151 }
bellardedf779f2004-02-22 13:40:13 +00002152
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002153 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
2154 __put_user(info_addr, &frame->pinfo);
2155 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
2156 __put_user(uc_addr, &frame->puc);
2157 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00002158
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002159 /* Clear all the bits of the ucontext we don't use. */
2160 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00002161
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002162 memset(&stack, 0, sizeof(stack));
2163 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
2164 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
2165 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
2166 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00002167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002168 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
2169 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2170 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
2171 }
bellard43fff232003-07-09 19:31:39 +00002172
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002173 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2174 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002175
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002176 env->regs[1] = info_addr;
2177 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002178
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002179 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002180 return;
2181sigsegv:
2182 force_sigsegv(usig);
pbrooka745ec62008-05-06 15:36:17 +00002183}
2184
pbrook624f7972008-05-31 16:11:38 +00002185static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002186 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002187 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002188{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002189 struct rt_sigframe_v2 *frame;
2190 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
2191 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002192
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002193 trace_user_setup_rt_frame(env, frame_addr);
2194 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Peter Maydell28298c92016-07-28 16:44:48 +01002195 goto sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002196 }
pbrooka745ec62008-05-06 15:36:17 +00002197
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002198 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
2199 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
2200 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00002201
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002202 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00002203
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002204 setup_return(env, ka, &frame->retcode, frame_addr, usig,
2205 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00002206
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002207 env->regs[1] = info_addr;
2208 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00002209
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002210 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell28298c92016-07-28 16:44:48 +01002211 return;
2212sigsegv:
2213 force_sigsegv(usig);
bellard43fff232003-07-09 19:31:39 +00002214}
2215
pbrook624f7972008-05-31 16:11:38 +00002216static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002217 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002218 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002219{
2220 if (get_osversion() >= 0x020612) {
2221 setup_rt_frame_v2(usig, ka, info, set, env);
2222 } else {
2223 setup_rt_frame_v1(usig, ka, info, set, env);
2224 }
2225}
2226
bellard43fff232003-07-09 19:31:39 +00002227static int
Andreas Färber05390242012-02-25 03:37:53 +01002228restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00002229{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002230 int err = 0;
2231 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00002232
Riku Voipio1d8b5122014-04-23 10:26:05 +03002233 __get_user(env->regs[0], &sc->arm_r0);
2234 __get_user(env->regs[1], &sc->arm_r1);
2235 __get_user(env->regs[2], &sc->arm_r2);
2236 __get_user(env->regs[3], &sc->arm_r3);
2237 __get_user(env->regs[4], &sc->arm_r4);
2238 __get_user(env->regs[5], &sc->arm_r5);
2239 __get_user(env->regs[6], &sc->arm_r6);
2240 __get_user(env->regs[7], &sc->arm_r7);
2241 __get_user(env->regs[8], &sc->arm_r8);
2242 __get_user(env->regs[9], &sc->arm_r9);
2243 __get_user(env->regs[10], &sc->arm_r10);
2244 __get_user(env->regs[11], &sc->arm_fp);
2245 __get_user(env->regs[12], &sc->arm_ip);
2246 __get_user(env->regs[13], &sc->arm_sp);
2247 __get_user(env->regs[14], &sc->arm_lr);
2248 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00002249#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03002250 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00002251 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00002252#endif
2253
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002254 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00002255
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002256 return err;
bellard43fff232003-07-09 19:31:39 +00002257}
2258
Andreas Färber05390242012-02-25 03:37:53 +01002259static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002260{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 abi_ulong frame_addr;
2262 struct sigframe_v1 *frame = NULL;
2263 target_sigset_t set;
2264 sigset_t host_set;
2265 int i;
bellard43fff232003-07-09 19:31:39 +00002266
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002267 /*
2268 * Since we stacked the signal on a 64-bit boundary,
2269 * then 'sp' should be word aligned here. If it's
2270 * not, then the user is trying to mess with us.
2271 */
2272 frame_addr = env->regs[13];
2273 trace_user_do_sigreturn(env, frame_addr);
2274 if (frame_addr & 7) {
2275 goto badframe;
2276 }
Peter Maydell978fae92013-07-29 12:00:32 +01002277
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002278 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2279 goto badframe;
2280 }
bellard43fff232003-07-09 19:31:39 +00002281
Riku Voipiof5f601a2014-04-23 13:00:17 +03002282 __get_user(set.sig[0], &frame->sc.oldmask);
2283 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2284 __get_user(set.sig[i], &frame->extramask[i - 1]);
2285 }
bellard43fff232003-07-09 19:31:39 +00002286
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002287 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002288 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002289
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002290 if (restore_sigcontext(env, &frame->sc)) {
2291 goto badframe;
2292 }
bellard43fff232003-07-09 19:31:39 +00002293
2294#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002295 /* Send SIGTRAP if we're single-stepping */
2296 if (ptrace_cancel_bpt(current))
2297 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002298#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002299 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002300 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002301
2302badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01002303 force_sig(TARGET_SIGSEGV);
2304 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002305}
2306
Andreas Färber05390242012-02-25 03:37:53 +01002307static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00002308{
2309 int i;
2310 abi_ulong magic, sz;
2311 uint32_t fpscr, fpexc;
2312 struct target_vfp_sigframe *vfpframe;
2313 vfpframe = (struct target_vfp_sigframe *)regspace;
2314
2315 __get_user(magic, &vfpframe->magic);
2316 __get_user(sz, &vfpframe->size);
2317 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
2318 return 0;
2319 }
2320 for (i = 0; i < 32; i++) {
Richard Henderson9a2b5252018-01-25 11:45:29 +00002321 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00002322 }
2323 __get_user(fpscr, &vfpframe->ufp.fpscr);
2324 vfp_set_fpscr(env, fpscr);
2325 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
2326 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
2327 * and the exception flag is cleared
2328 */
2329 fpexc |= (1 << 30);
2330 fpexc &= ~((1 << 31) | (1 << 28));
2331 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
2332 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
2333 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
2334 return (abi_ulong*)(vfpframe + 1);
2335}
2336
Andreas Färber05390242012-02-25 03:37:53 +01002337static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
2338 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00002339{
2340 int i;
2341 abi_ulong magic, sz;
2342 struct target_iwmmxt_sigframe *iwmmxtframe;
2343 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2344
2345 __get_user(magic, &iwmmxtframe->magic);
2346 __get_user(sz, &iwmmxtframe->size);
2347 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2348 return 0;
2349 }
2350 for (i = 0; i < 16; i++) {
2351 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2352 }
2353 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2354 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2355 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2356 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2357 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2358 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2359 return (abi_ulong*)(iwmmxtframe + 1);
2360}
2361
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002362static int do_sigframe_return_v2(CPUARMState *env,
2363 target_ulong context_addr,
pbrooka8c33202008-05-07 23:22:46 +00002364 struct target_ucontext_v2 *uc)
2365{
2366 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00002367 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00002368
2369 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002370 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00002371
2372 if (restore_sigcontext(env, &uc->tuc_mcontext))
2373 return 1;
2374
Peter Maydell5f9099d2010-11-24 15:20:06 +00002375 /* Restore coprocessor signal frame */
2376 regspace = uc->tuc_regspace;
2377 if (arm_feature(env, ARM_FEATURE_VFP)) {
2378 regspace = restore_sigframe_v2_vfp(env, regspace);
2379 if (!regspace) {
2380 return 1;
2381 }
2382 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002383 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2384 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2385 if (!regspace) {
2386 return 1;
2387 }
2388 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002389
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002390 if (do_sigaltstack(context_addr
2391 + offsetof(struct target_ucontext_v2, tuc_stack),
2392 0, get_sp_from_cpustate(env)) == -EFAULT) {
pbrooka8c33202008-05-07 23:22:46 +00002393 return 1;
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002394 }
pbrooka8c33202008-05-07 23:22:46 +00002395
2396#if 0
2397 /* Send SIGTRAP if we're single-stepping */
2398 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002399 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002400#endif
2401
2402 return 0;
2403}
2404
Andreas Färber05390242012-02-25 03:37:53 +01002405static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002406{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002407 abi_ulong frame_addr;
2408 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002409
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002410 /*
2411 * Since we stacked the signal on a 64-bit boundary,
2412 * then 'sp' should be word aligned here. If it's
2413 * not, then the user is trying to mess with us.
2414 */
2415 frame_addr = env->regs[13];
2416 trace_user_do_sigreturn(env, frame_addr);
2417 if (frame_addr & 7) {
2418 goto badframe;
2419 }
Peter Maydell978fae92013-07-29 12:00:32 +01002420
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002421 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2422 goto badframe;
2423 }
pbrooka8c33202008-05-07 23:22:46 +00002424
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002425 if (do_sigframe_return_v2(env,
2426 frame_addr
2427 + offsetof(struct sigframe_v2, uc),
2428 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002429 goto badframe;
2430 }
pbrooka8c33202008-05-07 23:22:46 +00002431
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002432 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002433 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002434
2435badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002436 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002437 force_sig(TARGET_SIGSEGV);
2438 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002439}
2440
Andreas Färber05390242012-02-25 03:37:53 +01002441long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002442{
2443 if (get_osversion() >= 0x020612) {
2444 return do_sigreturn_v2(env);
2445 } else {
2446 return do_sigreturn_v1(env);
2447 }
2448}
2449
Andreas Färber05390242012-02-25 03:37:53 +01002450static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002451{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002452 abi_ulong frame_addr;
2453 struct rt_sigframe_v1 *frame = NULL;
2454 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002455
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002456 /*
2457 * Since we stacked the signal on a 64-bit boundary,
2458 * then 'sp' should be word aligned here. If it's
2459 * not, then the user is trying to mess with us.
2460 */
2461 frame_addr = env->regs[13];
2462 trace_user_do_rt_sigreturn(env, frame_addr);
2463 if (frame_addr & 7) {
2464 goto badframe;
2465 }
Peter Maydell978fae92013-07-29 12:00:32 +01002466
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002467 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2468 goto badframe;
2469 }
bellard43fff232003-07-09 19:31:39 +00002470
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002471 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002472 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002473
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002474 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2475 goto badframe;
2476 }
bellard43fff232003-07-09 19:31:39 +00002477
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002478 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2479 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002480
bellard43fff232003-07-09 19:31:39 +00002481#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002482 /* Send SIGTRAP if we're single-stepping */
2483 if (ptrace_cancel_bpt(current))
2484 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002485#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002486 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002487 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002488
2489badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002490 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002491 force_sig(TARGET_SIGSEGV);
2492 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002493}
2494
Andreas Färber05390242012-02-25 03:37:53 +01002495static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002496{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002497 abi_ulong frame_addr;
2498 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002499
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002500 /*
2501 * Since we stacked the signal on a 64-bit boundary,
2502 * then 'sp' should be word aligned here. If it's
2503 * not, then the user is trying to mess with us.
2504 */
2505 frame_addr = env->regs[13];
2506 trace_user_do_rt_sigreturn(env, frame_addr);
2507 if (frame_addr & 7) {
2508 goto badframe;
2509 }
Peter Maydell978fae92013-07-29 12:00:32 +01002510
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002511 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2512 goto badframe;
2513 }
pbrooka745ec62008-05-06 15:36:17 +00002514
Timothy E Baldwin45eafb42016-09-09 19:35:58 +01002515 if (do_sigframe_return_v2(env,
2516 frame_addr
2517 + offsetof(struct rt_sigframe_v2, uc),
2518 &frame->uc)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002519 goto badframe;
2520 }
pbrooka745ec62008-05-06 15:36:17 +00002521
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002522 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002523 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002524
2525badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002526 unlock_user_struct(frame, frame_addr, 0);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002527 force_sig(TARGET_SIGSEGV);
2528 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002529}
2530
Andreas Färber05390242012-02-25 03:37:53 +01002531long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002532{
2533 if (get_osversion() >= 0x020612) {
2534 return do_rt_sigreturn_v2(env);
2535 } else {
2536 return do_rt_sigreturn_v1(env);
2537 }
2538}
2539
bellard6d5e2162004-09-30 22:04:13 +00002540#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002541
bellard6d5e2162004-09-30 22:04:13 +00002542#define __SUNOS_MAXWIN 31
2543
2544/* This is what SunOS does, so shall I. */
2545struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002546 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002547
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002548 abi_ulong sigc_mask; /* sigmask to restore */
2549 abi_ulong sigc_sp; /* stack pointer */
2550 abi_ulong sigc_pc; /* program counter */
2551 abi_ulong sigc_npc; /* next program counter */
2552 abi_ulong sigc_psr; /* for condition codes etc */
2553 abi_ulong sigc_g1; /* User uses these two registers */
2554 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002555
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002556 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002557 * at the time of the signal.
2558 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002559 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002560
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002561 /* stack ptrs for each regwin buf */
2562 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002563
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002564 /* Windows to restore after signal */
2565 struct {
2566 abi_ulong locals[8];
2567 abi_ulong ins[8];
2568 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002569};
2570/* A Sparc stack frame */
2571struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002572 abi_ulong locals[8];
2573 abi_ulong ins[8];
2574 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002575 * since we never need to access them ourselves.
2576 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002577 char *structptr;
2578 abi_ulong xargs[6];
2579 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002580};
2581
2582typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002583 struct {
2584 abi_ulong psr;
2585 abi_ulong pc;
2586 abi_ulong npc;
2587 abi_ulong y;
2588 abi_ulong u_regs[16]; /* globals and ins */
2589 } si_regs;
2590 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002591} __siginfo_t;
2592
2593typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002594 abi_ulong si_float_regs[32];
2595 unsigned long si_fsr;
2596 unsigned long si_fpqdepth;
2597 struct {
2598 unsigned long *insn_addr;
2599 unsigned long insn;
2600 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002601} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002602
2603
2604struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002605 struct sparc_stackf ss;
2606 __siginfo_t info;
2607 abi_ulong fpu_save;
2608 abi_ulong insns[2] __attribute__ ((aligned (8)));
2609 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2610 abi_ulong extra_size; /* Should be 0 */
2611 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002612};
2613struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002614 struct sparc_stackf ss;
2615 siginfo_t info;
2616 abi_ulong regs[20];
2617 sigset_t mask;
2618 abi_ulong fpu_save;
2619 unsigned int insns[2];
2620 stack_t stack;
2621 unsigned int extra_size; /* Should be 0 */
2622 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002623};
2624
bellarde80cfcf2004-12-19 23:18:01 +00002625#define UREG_O0 16
2626#define UREG_O6 22
2627#define UREG_I0 0
2628#define UREG_I1 1
2629#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002630#define UREG_I3 3
2631#define UREG_I4 4
2632#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002633#define UREG_I6 6
2634#define UREG_I7 7
2635#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002636#define UREG_FP UREG_I6
2637#define UREG_SP UREG_O6
2638
pbrook624f7972008-05-31 16:11:38 +00002639static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002640 CPUSPARCState *env,
2641 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002642{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002643 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002644
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002645 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002646
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002647 /* This is the X/Open sanctioned signal stack switching. */
2648 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2649 if (!on_sig_stack(sp)
2650 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2651 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2652 }
2653 }
2654 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002655}
2656
2657static int
Andreas Färber05390242012-02-25 03:37:53 +01002658setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002659{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002660 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002661
Riku Voipio1d8b5122014-04-23 10:26:05 +03002662 __put_user(env->psr, &si->si_regs.psr);
2663 __put_user(env->pc, &si->si_regs.pc);
2664 __put_user(env->npc, &si->si_regs.npc);
2665 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002666 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002667 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002668 }
2669 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002670 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002671 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002672 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002673 return err;
bellard6d5e2162004-09-30 22:04:13 +00002674}
bellarde80cfcf2004-12-19 23:18:01 +00002675
bellard80a9d032005-01-03 23:31:27 +00002676#if 0
bellard6d5e2162004-09-30 22:04:13 +00002677static int
2678setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002679 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002680{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002681 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002682
Riku Voipio1d8b5122014-04-23 10:26:05 +03002683 __put_user(mask, &sc->sigc_mask);
2684 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2685 __put_user(env->pc, &sc->sigc_pc);
2686 __put_user(env->npc, &sc->sigc_npc);
2687 __put_user(env->psr, &sc->sigc_psr);
2688 __put_user(env->gregs[1], &sc->sigc_g1);
2689 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002690
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002691 return err;
bellard6d5e2162004-09-30 22:04:13 +00002692}
bellard80a9d032005-01-03 23:31:27 +00002693#endif
bellard6d5e2162004-09-30 22:04:13 +00002694#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2695
pbrook624f7972008-05-31 16:11:38 +00002696static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002697 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002698{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002699 abi_ulong sf_addr;
2700 struct target_signal_frame *sf;
2701 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002702
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002703 /* 1. Make sure everything is clean */
2704 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002705
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002706 sigframe_size = NF_ALIGNEDSZ;
2707 sf_addr = get_sigframe(ka, env, sigframe_size);
2708 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002709
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002710 sf = lock_user(VERIFY_WRITE, sf_addr,
2711 sizeof(struct target_signal_frame), 0);
2712 if (!sf) {
2713 goto sigsegv;
2714 }
bellard6d5e2162004-09-30 22:04:13 +00002715#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002716 if (invalid_frame_pointer(sf, sigframe_size))
2717 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002718#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002719 /* 2. Save the current process state */
2720 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002721 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002722
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002723 //save_fpu_state(regs, &sf->fpu_state);
2724 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002725
Riku Voipio1d8b5122014-04-23 10:26:05 +03002726 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002727 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002728 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002729 }
bellard6d5e2162004-09-30 22:04:13 +00002730
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002731 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002732 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002733 }
2734 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002735 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002736 }
2737 if (err)
2738 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002739
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002740 /* 3. signal handler back-trampoline and parameters */
2741 env->regwptr[UREG_FP] = sf_addr;
2742 env->regwptr[UREG_I0] = sig;
2743 env->regwptr[UREG_I1] = sf_addr +
2744 offsetof(struct target_signal_frame, info);
2745 env->regwptr[UREG_I2] = sf_addr +
2746 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002747
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002748 /* 4. signal handler */
2749 env->pc = ka->_sa_handler;
2750 env->npc = (env->pc + 4);
2751 /* 5. return to kernel instructions */
2752 if (ka->sa_restorer) {
2753 env->regwptr[UREG_I7] = ka->sa_restorer;
2754 } else {
2755 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002756
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002757 env->regwptr[UREG_I7] = sf_addr +
2758 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002759
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002760 /* mov __NR_sigreturn, %g1 */
2761 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002762 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002763
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002764 /* t 0x10 */
2765 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002766 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002767 if (err)
2768 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002769
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002770 /* Flush instruction space. */
2771 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2772 // tb_flush(env);
2773 }
2774 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2775 return;
bellard459a4012007-11-11 19:45:10 +00002776#if 0
2777sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002778 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002779#endif
bellard6d5e2162004-09-30 22:04:13 +00002780sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002781 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
Peter Maydell09391662016-07-28 16:44:47 +01002782 force_sigsegv(sig);
bellard6d5e2162004-09-30 22:04:13 +00002783}
bellard6d5e2162004-09-30 22:04:13 +00002784
pbrook624f7972008-05-31 16:11:38 +00002785static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002786 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002787 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002788{
2789 fprintf(stderr, "setup_rt_frame: not implemented\n");
2790}
2791
Andreas Färber05390242012-02-25 03:37:53 +01002792long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002793{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002794 abi_ulong sf_addr;
2795 struct target_signal_frame *sf;
2796 uint32_t up_psr, pc, npc;
2797 target_sigset_t set;
2798 sigset_t host_set;
2799 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002800
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002801 sf_addr = env->regwptr[UREG_FP];
2802 trace_user_do_sigreturn(env, sf_addr);
2803 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2804 goto segv_and_exit;
2805 }
bellard6d5e2162004-09-30 22:04:13 +00002806
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002807 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002808
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002809 if (sf_addr & 3)
2810 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002811
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002812 __get_user(pc, &sf->info.si_regs.pc);
2813 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002814
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002815 if ((pc | npc) & 3) {
2816 goto segv_and_exit;
2817 }
bellard6d5e2162004-09-30 22:04:13 +00002818
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002819 /* 2. Restore the state */
2820 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002821
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002822 /* User can only change condition codes and FPU enabling in %psr. */
2823 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2824 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002825
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002826 env->pc = pc;
2827 env->npc = npc;
2828 __get_user(env->y, &sf->info.si_regs.y);
2829 for (i=0; i < 8; i++) {
2830 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2831 }
2832 for (i=0; i < 8; i++) {
2833 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2834 }
bellard6d5e2162004-09-30 22:04:13 +00002835
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002836 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002837 * __get_user(fpu_save, &sf->fpu_save);
2838 * if (fpu_save)
2839 * err |= restore_fpu_state(env, fpu_save);
2840 */
bellard6d5e2162004-09-30 22:04:13 +00002841
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002842 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002843 * the races which exist anyways.
2844 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002845 __get_user(set.sig[0], &sf->info.si_mask);
2846 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2847 __get_user(set.sig[i], &sf->extramask[i - 1]);
2848 }
bellarde80cfcf2004-12-19 23:18:01 +00002849
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002850 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002851 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002852
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002853 if (err) {
2854 goto segv_and_exit;
2855 }
2856 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002857 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002858
2859segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002860 unlock_user_struct(sf, sf_addr, 0);
2861 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01002862 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002863}
2864
Andreas Färber05390242012-02-25 03:37:53 +01002865long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002866{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002867 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002868 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002869 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002870}
2871
bellard459a4012007-11-11 19:45:10 +00002872#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
Peter Maydell8ebb3142018-01-30 13:17:19 +00002873#define SPARC_MC_TSTATE 0
2874#define SPARC_MC_PC 1
2875#define SPARC_MC_NPC 2
2876#define SPARC_MC_Y 3
2877#define SPARC_MC_G1 4
2878#define SPARC_MC_G2 5
2879#define SPARC_MC_G3 6
2880#define SPARC_MC_G4 7
2881#define SPARC_MC_G5 8
2882#define SPARC_MC_G6 9
2883#define SPARC_MC_G7 10
2884#define SPARC_MC_O0 11
2885#define SPARC_MC_O1 12
2886#define SPARC_MC_O2 13
2887#define SPARC_MC_O3 14
2888#define SPARC_MC_O4 15
2889#define SPARC_MC_O5 16
2890#define SPARC_MC_O6 17
2891#define SPARC_MC_O7 18
2892#define SPARC_MC_NGREG 19
blueswir15bfb56b2007-10-05 17:01:51 +00002893
Anthony Liguoric227f092009-10-01 16:12:16 -05002894typedef abi_ulong target_mc_greg_t;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002895typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002896
2897struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002898 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002899 uint32_t mcfq_insn;
2900};
2901
2902struct target_mc_fpu {
2903 union {
2904 uint32_t sregs[32];
2905 uint64_t dregs[32];
2906 //uint128_t qregs[16];
2907 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002908 abi_ulong mcfpu_fsr;
2909 abi_ulong mcfpu_fprs;
2910 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002911 struct target_mc_fq *mcfpu_fq;
2912 unsigned char mcfpu_qcnt;
2913 unsigned char mcfpu_qentsz;
2914 unsigned char mcfpu_enab;
2915};
Anthony Liguoric227f092009-10-01 16:12:16 -05002916typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002917
2918typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002919 target_mc_gregset_t mc_gregs;
2920 target_mc_greg_t mc_fp;
2921 target_mc_greg_t mc_i7;
2922 target_mc_fpu_t mc_fpregs;
2923} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002924
2925struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002926 struct target_ucontext *tuc_link;
2927 abi_ulong tuc_flags;
2928 target_sigset_t tuc_sigmask;
2929 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002930};
2931
2932/* A V9 register window */
2933struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002934 abi_ulong locals[8];
2935 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002936};
2937
2938#define TARGET_STACK_BIAS 2047
2939
2940/* {set, get}context() needed for 64-bit SparcLinux userland. */
2941void sparc64_set_context(CPUSPARCState *env)
2942{
bellard459a4012007-11-11 19:45:10 +00002943 abi_ulong ucp_addr;
2944 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002945 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002946 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002947 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002948 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002949
bellard459a4012007-11-11 19:45:10 +00002950 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002951 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002952 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002953 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002954 grp = &ucp->tuc_mcontext.mc_gregs;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002955 __get_user(pc, &((*grp)[SPARC_MC_PC]));
2956 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002957 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002958 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002959 }
blueswir15bfb56b2007-10-05 17:01:51 +00002960 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002961 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002962 sigset_t set;
2963
2964 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002965 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002966 } else {
bellard459a4012007-11-11 19:45:10 +00002967 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002968 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002969 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002970 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002971 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002972 }
blueswir15bfb56b2007-10-05 17:01:51 +00002973 }
2974 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002975 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002976 }
2977 env->pc = pc;
2978 env->npc = npc;
Peter Maydell8ebb3142018-01-30 13:17:19 +00002979 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
2980 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002981 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002982 cpu_put_ccr(env, tstate >> 32);
2983 cpu_put_cwp64(env, tstate & 0x1f);
Peter Maydell8ebb3142018-01-30 13:17:19 +00002984 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
2985 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
2986 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
2987 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
2988 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
2989 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
2990 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
2991 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
2992 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
2993 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
2994 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
2995 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
2996 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
2997 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
2998 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002999
Riku Voipio1d8b5122014-04-23 10:26:05 +03003000 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
3001 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003002
bellard459a4012007-11-11 19:45:10 +00003003 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003004 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3005 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003006 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003007 }
3008 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3009 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003010 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003011 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01003012 /* FIXME this does not match how the kernel handles the FPU in
3013 * its sparc64_set_context implementation. In particular the FPU
3014 * is only restored if fenab is non-zero in:
3015 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
3016 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03003017 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00003018 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003019 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3020 for (i = 0; i < 64; i++, src++) {
3021 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003022 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003023 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003024 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07003025 }
3026 }
bellard459a4012007-11-11 19:45:10 +00003027 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003028 __get_user(env->fsr,
3029 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
3030 __get_user(env->gsr,
3031 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00003032 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003033 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003034do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003035 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02003036 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003037}
3038
3039void sparc64_get_context(CPUSPARCState *env)
3040{
bellard459a4012007-11-11 19:45:10 +00003041 abi_ulong ucp_addr;
3042 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05003043 target_mc_gregset_t *grp;
3044 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00003045 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00003046 int err;
3047 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05003048 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00003049 sigset_t set;
3050
bellard459a4012007-11-11 19:45:10 +00003051 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003052 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00003053 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003054 }
bellard459a4012007-11-11 19:45:10 +00003055
Aurelien Jarno60e99242010-03-29 02:12:51 +02003056 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00003057 grp = &mcp->mc_gregs;
3058
3059 /* Skip over the trap instruction, first. */
3060 env->pc = env->npc;
3061 env->npc += 4;
3062
Peter Maydell3d3efba2016-05-27 15:51:49 +01003063 /* If we're only reading the signal mask then do_sigprocmask()
3064 * is guaranteed not to fail, which is important because we don't
3065 * have any way to signal a failure or restart this operation since
3066 * this is not a normal syscall.
3067 */
3068 err = do_sigprocmask(0, NULL, &set);
3069 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00003070 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00003071 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003072 __put_user(target_set.sig[0],
3073 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00003074 } else {
3075 abi_ulong *src, *dst;
3076 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003077 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003078 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003079 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01003080 }
blueswir15bfb56b2007-10-05 17:01:51 +00003081 if (err)
3082 goto do_sigsegv;
3083 }
3084
bellard459a4012007-11-11 19:45:10 +00003085 /* XXX: tstate must be saved properly */
Peter Maydell8ebb3142018-01-30 13:17:19 +00003086 // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
3087 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
3088 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
3089 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
3090 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
3091 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
3092 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
3093 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
3094 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
3095 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
3096 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
3097 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
3098 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
3099 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
3100 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
3101 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
3102 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
3103 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
3104 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00003105
bellard459a4012007-11-11 19:45:10 +00003106 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
3107 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003108 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
3109 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003110 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003111 }
3112 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
3113 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00003114 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003115 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003116 __put_user(fp, &(mcp->mc_fp));
3117 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00003118
bellard459a4012007-11-11 19:45:10 +00003119 {
Richard Henderson30038fd2011-10-17 10:42:49 -07003120 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
3121 for (i = 0; i < 64; i++, dst++) {
3122 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003123 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003124 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003125 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07003126 }
3127 }
bellard459a4012007-11-11 19:45:10 +00003128 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003129 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
3130 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
3131 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00003132
3133 if (err)
3134 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00003135 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00003136 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003137do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00003138 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003139 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00003140}
3141#endif
Richard Hendersonff970902013-02-10 10:30:42 -08003142#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00003143
Richard Hendersonff970902013-02-10 10:30:42 -08003144# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00003145struct target_sigcontext {
3146 uint32_t sc_regmask; /* Unused */
3147 uint32_t sc_status;
3148 uint64_t sc_pc;
3149 uint64_t sc_regs[32];
3150 uint64_t sc_fpregs[32];
3151 uint32_t sc_ownedfp; /* Unused */
3152 uint32_t sc_fpc_csr;
3153 uint32_t sc_fpc_eir; /* Unused */
3154 uint32_t sc_used_math;
3155 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01003156 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00003157 uint64_t sc_mdhi;
3158 uint64_t sc_mdlo;
3159 target_ulong sc_hi1; /* Was sc_cause */
3160 target_ulong sc_lo1; /* Was sc_badvaddr */
3161 target_ulong sc_hi2; /* Was sc_sigset[4] */
3162 target_ulong sc_lo2;
3163 target_ulong sc_hi3;
3164 target_ulong sc_lo3;
3165};
Richard Hendersonff970902013-02-10 10:30:42 -08003166# else /* N32 || N64 */
3167struct target_sigcontext {
3168 uint64_t sc_regs[32];
3169 uint64_t sc_fpregs[32];
3170 uint64_t sc_mdhi;
3171 uint64_t sc_hi1;
3172 uint64_t sc_hi2;
3173 uint64_t sc_hi3;
3174 uint64_t sc_mdlo;
3175 uint64_t sc_lo1;
3176 uint64_t sc_lo2;
3177 uint64_t sc_lo3;
3178 uint64_t sc_pc;
3179 uint32_t sc_fpc_csr;
3180 uint32_t sc_used_math;
3181 uint32_t sc_dsp;
3182 uint32_t sc_reserved;
3183};
3184# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003185
3186struct sigframe {
3187 uint32_t sf_ass[4]; /* argument save space for o32 */
3188 uint32_t sf_code[2]; /* signal trampoline */
3189 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05003190 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00003191};
3192
pbrook0b1bcb02009-04-21 01:41:10 +00003193struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003194 target_ulong tuc_flags;
3195 target_ulong tuc_link;
3196 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01003197 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02003198 struct target_sigcontext tuc_mcontext;
3199 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00003200};
3201
3202struct target_rt_sigframe {
3203 uint32_t rs_ass[4]; /* argument save space for o32 */
3204 uint32_t rs_code[2]; /* signal trampoline */
3205 struct target_siginfo rs_info;
3206 struct target_ucontext rs_uc;
3207};
3208
bellard106ec872006-06-27 21:08:10 +00003209/* Install trampoline to jump back from signal handler */
3210static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
3211{
Richard Henderson084d0492013-02-10 10:30:44 -08003212 int err = 0;
bellard106ec872006-06-27 21:08:10 +00003213
3214 /*
Richard Henderson084d0492013-02-10 10:30:44 -08003215 * Set up the return code ...
3216 *
3217 * li v0, __NR__foo_sigreturn
3218 * syscall
3219 */
bellard106ec872006-06-27 21:08:10 +00003220
Riku Voipio1d8b5122014-04-23 10:26:05 +03003221 __put_user(0x24020000 + syscall, tramp + 0);
3222 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00003223 return err;
3224}
3225
Riku Voipio41ecc722014-04-23 11:01:00 +03003226static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003227 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003228{
Richard Henderson084d0492013-02-10 10:30:44 -08003229 int i;
bellard106ec872006-06-27 21:08:10 +00003230
Riku Voipio1d8b5122014-04-23 10:26:05 +03003231 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07003232 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00003233
Richard Henderson084d0492013-02-10 10:30:44 -08003234 __put_user(0, &sc->sc_regs[0]);
3235 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003236 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003237 }
bellard106ec872006-06-27 21:08:10 +00003238
Riku Voipio1d8b5122014-04-23 10:26:05 +03003239 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3240 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003241
Richard Henderson084d0492013-02-10 10:30:44 -08003242 /* Rather than checking for dsp existence, always copy. The storage
3243 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003244 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
3245 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
3246 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
3247 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
3248 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
3249 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003250 {
3251 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003252 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00003253 }
Richard Henderson084d0492013-02-10 10:30:44 -08003254
Riku Voipio1d8b5122014-04-23 10:26:05 +03003255 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08003256
3257 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003258 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00003259 }
bellard106ec872006-06-27 21:08:10 +00003260}
3261
Riku Voipio016d2e12014-04-23 11:19:48 +03003262static inline void
Andreas Färber05390242012-02-25 03:37:53 +01003263restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00003264{
Richard Henderson084d0492013-02-10 10:30:44 -08003265 int i;
bellard106ec872006-06-27 21:08:10 +00003266
Riku Voipio1d8b5122014-04-23 10:26:05 +03003267 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00003268
Riku Voipio1d8b5122014-04-23 10:26:05 +03003269 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
3270 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00003271
Richard Henderson084d0492013-02-10 10:30:44 -08003272 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003273 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00003274 }
3275
Riku Voipio1d8b5122014-04-23 10:26:05 +03003276 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
3277 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
3278 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
3279 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
3280 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
3281 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08003282 {
3283 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003284 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08003285 cpu_wrdsp(dsp, 0x3ff, regs);
3286 }
3287
3288 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003289 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08003290 }
bellard106ec872006-06-27 21:08:10 +00003291}
Richard Hendersonff970902013-02-10 10:30:42 -08003292
bellard106ec872006-06-27 21:08:10 +00003293/*
3294 * Determine which stack to use..
3295 */
bellard579a97f2007-11-11 14:26:47 +00003296static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01003297get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00003298{
3299 unsigned long sp;
3300
3301 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00003302 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00003303
3304 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01003305 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00003306 * above the user stack, 16-bytes before the next lowest
3307 * 16 byte boundary. Try to avoid trashing it.
3308 */
3309 sp -= 32;
3310
bellard106ec872006-06-27 21:08:10 +00003311 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00003312 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00003313 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3314 }
bellard106ec872006-06-27 21:08:10 +00003315
bellard579a97f2007-11-11 14:26:47 +00003316 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00003317}
3318
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003319static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
3320{
3321 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
3322 env->hflags &= ~MIPS_HFLAG_M16;
3323 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
3324 env->active_tc.PC &= ~(target_ulong) 1;
3325 }
3326}
3327
Richard Hendersonff970902013-02-10 10:30:42 -08003328# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00003329/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00003330static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01003331 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003332{
3333 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003334 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00003335 int i;
3336
bellard579a97f2007-11-11 14:26:47 +00003337 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003338 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003339 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3340 goto give_sigsegv;
3341 }
bellard106ec872006-06-27 21:08:10 +00003342
3343 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
3344
Riku Voipio41ecc722014-04-23 11:01:00 +03003345 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003346
3347 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003348 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00003349 }
3350
3351 /*
3352 * Arguments to signal handler:
3353 *
3354 * a0 = signal number
3355 * a1 = 0 (should be cause)
3356 * a2 = pointer to struct sigcontext
3357 *
3358 * $25 and PC point to the signal handler, $29 points to the
3359 * struct sigframe.
3360 */
thsb5dc7732008-06-27 10:02:35 +00003361 regs->active_tc.gpr[ 4] = sig;
3362 regs->active_tc.gpr[ 5] = 0;
3363 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3364 regs->active_tc.gpr[29] = frame_addr;
3365 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00003366 /* The original kernel code sets CP0_EPC to the handler
3367 * since it returns to userland using eret
3368 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00003369 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003370 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00003371 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00003372 return;
3373
3374give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01003375 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003376}
3377
Andreas Färber05390242012-02-25 03:37:53 +01003378long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00003379{
ths388bb212007-05-13 13:58:00 +00003380 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00003381 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00003382 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003383 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00003384 int i;
bellard106ec872006-06-27 21:08:10 +00003385
thsb5dc7732008-06-27 10:02:35 +00003386 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003387 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00003388 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003389 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003390
ths388bb212007-05-13 13:58:00 +00003391 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003392 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003393 }
bellard106ec872006-06-27 21:08:10 +00003394
ths388bb212007-05-13 13:58:00 +00003395 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003396 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003397
Riku Voipio016d2e12014-04-23 11:19:48 +03003398 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003399
3400#if 0
ths388bb212007-05-13 13:58:00 +00003401 /*
3402 * Don't let your children do this ...
3403 */
3404 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003405 "move\t$29, %0\n\t"
3406 "j\tsyscall_exit"
3407 :/* no outputs */
3408 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003409 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003410#endif
ths3b46e622007-09-17 08:09:54 +00003411
thsb5dc7732008-06-27 10:02:35 +00003412 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003413 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003414 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003415 * maybe a problem with nested signals ? */
3416 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003417 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003418
3419badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003420 force_sig(TARGET_SIGSEGV);
3421 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003422}
Richard Hendersonff970902013-02-10 10:30:42 -08003423# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003424
pbrook624f7972008-05-31 16:11:38 +00003425static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003426 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003427 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003428{
pbrook0b1bcb02009-04-21 01:41:10 +00003429 struct target_rt_sigframe *frame;
3430 abi_ulong frame_addr;
3431 int i;
3432
3433 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003434 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003435 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3436 goto give_sigsegv;
3437 }
pbrook0b1bcb02009-04-21 01:41:10 +00003438
3439 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3440
Peter Maydellf6c7a052015-01-08 12:19:48 +00003441 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003442
Aurelien Jarno60e99242010-03-29 02:12:51 +02003443 __put_user(0, &frame->rs_uc.tuc_flags);
3444 __put_user(0, &frame->rs_uc.tuc_link);
3445 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3446 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003447 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003448 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003449
Aurelien Jarno60e99242010-03-29 02:12:51 +02003450 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003451
3452 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003453 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003454 }
3455
3456 /*
3457 * Arguments to signal handler:
3458 *
3459 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003460 * a1 = pointer to siginfo_t
Khem Raj04b33e22017-06-28 13:44:52 -07003461 * a2 = pointer to ucontext_t
pbrook0b1bcb02009-04-21 01:41:10 +00003462 *
3463 * $25 and PC point to the signal handler, $29 points to the
3464 * struct sigframe.
3465 */
3466 env->active_tc.gpr[ 4] = sig;
3467 env->active_tc.gpr[ 5] = frame_addr
3468 + offsetof(struct target_rt_sigframe, rs_info);
3469 env->active_tc.gpr[ 6] = frame_addr
3470 + offsetof(struct target_rt_sigframe, rs_uc);
3471 env->active_tc.gpr[29] = frame_addr;
3472 env->active_tc.gpr[31] = frame_addr
3473 + offsetof(struct target_rt_sigframe, rs_code);
3474 /* The original kernel code sets CP0_EPC to the handler
3475 * since it returns to userland using eret
3476 * we cannot do this here, and we must set PC directly */
3477 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003478 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003479 unlock_user_struct(frame, frame_addr, 1);
3480 return;
3481
3482give_sigsegv:
3483 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003484 force_sigsegv(sig);
bellard106ec872006-06-27 21:08:10 +00003485}
3486
Andreas Färber05390242012-02-25 03:37:53 +01003487long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003488{
pbrook0b1bcb02009-04-21 01:41:10 +00003489 struct target_rt_sigframe *frame;
3490 abi_ulong frame_addr;
3491 sigset_t blocked;
3492
pbrook0b1bcb02009-04-21 01:41:10 +00003493 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003494 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003495 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3496 goto badframe;
3497 }
pbrook0b1bcb02009-04-21 01:41:10 +00003498
Aurelien Jarno60e99242010-03-29 02:12:51 +02003499 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003500 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003501
Riku Voipio016d2e12014-04-23 11:19:48 +03003502 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003503
3504 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003505 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3506 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003507 goto badframe;
3508
3509 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003510 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003511 /* I am not sure this is right, but it seems to work
3512 * maybe a problem with nested signals ? */
3513 env->CP0_EPC = 0;
3514 return -TARGET_QEMU_ESIGRETURN;
3515
3516badframe:
Peter Maydellc599d4d2016-07-28 16:44:49 +01003517 force_sig(TARGET_SIGSEGV);
3518 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003519}
bellard6d5e2162004-09-30 22:04:13 +00003520
thsc3b5bc82007-12-02 06:31:25 +00003521#elif defined(TARGET_SH4)
3522
3523/*
3524 * code and data structures from linux kernel:
3525 * include/asm-sh/sigcontext.h
3526 * arch/sh/kernel/signal.c
3527 */
3528
3529struct target_sigcontext {
3530 target_ulong oldmask;
3531
3532 /* CPU registers */
3533 target_ulong sc_gregs[16];
3534 target_ulong sc_pc;
3535 target_ulong sc_pr;
3536 target_ulong sc_sr;
3537 target_ulong sc_gbr;
3538 target_ulong sc_mach;
3539 target_ulong sc_macl;
3540
3541 /* FPU registers */
3542 target_ulong sc_fpregs[16];
3543 target_ulong sc_xfpregs[16];
3544 unsigned int sc_fpscr;
3545 unsigned int sc_fpul;
3546 unsigned int sc_ownedfp;
3547};
3548
3549struct target_sigframe
3550{
3551 struct target_sigcontext sc;
3552 target_ulong extramask[TARGET_NSIG_WORDS-1];
3553 uint16_t retcode[3];
3554};
3555
3556
3557struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003558 target_ulong tuc_flags;
3559 struct target_ucontext *tuc_link;
3560 target_stack_t tuc_stack;
3561 struct target_sigcontext tuc_mcontext;
3562 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003563};
3564
3565struct target_rt_sigframe
3566{
3567 struct target_siginfo info;
3568 struct target_ucontext uc;
3569 uint16_t retcode[3];
3570};
3571
3572
3573#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3574#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3575
pbrook624f7972008-05-31 16:11:38 +00003576static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003577 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003578{
pbrook624f7972008-05-31 16:11:38 +00003579 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003580 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3581 }
3582
3583 return (sp - frame_size) & -8ul;
3584}
3585
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003586/* Notice when we're in the middle of a gUSA region and reset.
3587 Note that this will only occur for !parallel_cpus, as we will
3588 translate such sequences differently in a parallel context. */
3589static void unwind_gusa(CPUSH4State *regs)
3590{
3591 /* If the stack pointer is sufficiently negative, and we haven't
3592 completed the sequence, then reset to the entry to the region. */
3593 /* ??? The SH4 kernel checks for and address above 0xC0000000.
3594 However, the page mappings in qemu linux-user aren't as restricted
3595 and we wind up with the normal stack mapped above 0xF0000000.
3596 That said, there is no reason why the kernel should be allowing
3597 a gUSA region that spans 1GB. Use a tighter check here, for what
3598 can actually be enabled by the immediate move. */
3599 if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
3600 /* Reset the PC to before the gUSA region, as computed from
3601 R0 = region end, SP = -(region size), plus one more for the
3602 insn that actually initializes SP to the region size. */
3603 regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
3604
3605 /* Reset the SP to the saved version in R1. */
3606 regs->gregs[15] = regs->gregs[1];
3607 }
3608}
3609
Riku Voipio41ecc722014-04-23 11:01:00 +03003610static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003611 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003612{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003613 int i;
thsc3b5bc82007-12-02 06:31:25 +00003614
Riku Voipio1d8b5122014-04-23 10:26:05 +03003615#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003616 COPY(gregs[0]); COPY(gregs[1]);
3617 COPY(gregs[2]); COPY(gregs[3]);
3618 COPY(gregs[4]); COPY(gregs[5]);
3619 COPY(gregs[6]); COPY(gregs[7]);
3620 COPY(gregs[8]); COPY(gregs[9]);
3621 COPY(gregs[10]); COPY(gregs[11]);
3622 COPY(gregs[12]); COPY(gregs[13]);
3623 COPY(gregs[14]); COPY(gregs[15]);
3624 COPY(gbr); COPY(mach);
3625 COPY(macl); COPY(pr);
3626 COPY(sr); COPY(pc);
3627#undef COPY
3628
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003629 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003630 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003631 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003632 __put_user(regs->fpscr, &sc->sc_fpscr);
3633 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003634
3635 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003636 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003637}
3638
Timothy E Baldwinba412492016-05-12 18:47:35 +01003639static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003640{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003641 int i;
thsc3b5bc82007-12-02 06:31:25 +00003642
Riku Voipio1d8b5122014-04-23 10:26:05 +03003643#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003644 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003645 COPY(gregs[2]); COPY(gregs[3]);
3646 COPY(gregs[4]); COPY(gregs[5]);
3647 COPY(gregs[6]); COPY(gregs[7]);
3648 COPY(gregs[8]); COPY(gregs[9]);
3649 COPY(gregs[10]); COPY(gregs[11]);
3650 COPY(gregs[12]); COPY(gregs[13]);
3651 COPY(gregs[14]); COPY(gregs[15]);
3652 COPY(gbr); COPY(mach);
3653 COPY(macl); COPY(pr);
3654 COPY(sr); COPY(pc);
3655#undef COPY
3656
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003657 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003658 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003659 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003660 __get_user(regs->fpscr, &sc->sc_fpscr);
3661 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003662
3663 regs->tra = -1; /* disable syscall checks */
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003664 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003665}
3666
pbrook624f7972008-05-31 16:11:38 +00003667static void setup_frame(int sig, struct target_sigaction *ka,
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_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_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
Riku Voipio41ecc722014-04-23 11:01:00 +03003682 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003683
3684 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003685 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003686 }
3687
3688 /* Set up to return from userspace. If provided, use a stub
3689 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003690 if (ka->sa_flags & TARGET_SA_RESTORER) {
3691 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003692 } else {
3693 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003694 abi_ulong retcode_addr = frame_addr +
3695 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003696 __put_user(MOVW(2), &frame->retcode[0]);
3697 __put_user(TRAP_NOARG, &frame->retcode[1]);
3698 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003699 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003700 }
3701
thsc3b5bc82007-12-02 06:31:25 +00003702 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003703 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003704 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003705 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003706 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003707 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003708 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003709
3710 unlock_user_struct(frame, frame_addr, 1);
3711 return;
3712
3713give_sigsegv:
3714 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003715 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003716}
3717
pbrook624f7972008-05-31 16:11:38 +00003718static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003719 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003720 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003721{
3722 struct target_rt_sigframe *frame;
3723 abi_ulong frame_addr;
3724 int i;
thsc3b5bc82007-12-02 06:31:25 +00003725
Richard Hendersonb0e4f0e2017-07-18 10:02:33 -10003726 unwind_gusa(regs);
3727
thsc3b5bc82007-12-02 06:31:25 +00003728 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003729 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003730 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3731 goto give_sigsegv;
3732 }
thsc3b5bc82007-12-02 06:31:25 +00003733
Peter Maydellf6c7a052015-01-08 12:19:48 +00003734 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003735
3736 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003737 __put_user(0, &frame->uc.tuc_flags);
3738 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3739 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3740 &frame->uc.tuc_stack.ss_sp);
3741 __put_user(sas_ss_flags(regs->gregs[15]),
3742 &frame->uc.tuc_stack.ss_flags);
3743 __put_user(target_sigaltstack_used.ss_size,
3744 &frame->uc.tuc_stack.ss_size);
3745 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003746 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003747 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003748 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003749 }
3750
3751 /* Set up to return from userspace. If provided, use a stub
3752 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003753 if (ka->sa_flags & TARGET_SA_RESTORER) {
3754 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003755 } else {
3756 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003757 abi_ulong retcode_addr = frame_addr +
3758 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003759 __put_user(MOVW(2), &frame->retcode[0]);
3760 __put_user(TRAP_NOARG, &frame->retcode[1]);
3761 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003762 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003763 }
3764
thsc3b5bc82007-12-02 06:31:25 +00003765 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003766 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003767 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003768 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3769 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003770 regs->pc = (unsigned long) ka->_sa_handler;
Richard Hendersonb0e9c512017-07-18 10:02:34 -10003771 regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
thsc3b5bc82007-12-02 06:31:25 +00003772
3773 unlock_user_struct(frame, frame_addr, 1);
3774 return;
3775
3776give_sigsegv:
3777 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01003778 force_sigsegv(sig);
thsc3b5bc82007-12-02 06:31:25 +00003779}
3780
Andreas Färber05390242012-02-25 03:37:53 +01003781long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003782{
3783 struct target_sigframe *frame;
3784 abi_ulong frame_addr;
3785 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003786 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003787 int i;
3788 int err = 0;
3789
thsc3b5bc82007-12-02 06:31:25 +00003790 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003791 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003792 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3793 goto badframe;
3794 }
thsc3b5bc82007-12-02 06:31:25 +00003795
Riku Voipio1d8b5122014-04-23 10:26:05 +03003796 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003797 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003798 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003799 }
3800
3801 if (err)
3802 goto badframe;
3803
3804 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003805 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003806
Timothy E Baldwinba412492016-05-12 18:47:35 +01003807 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003808
3809 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003810 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003811
3812badframe:
3813 unlock_user_struct(frame, frame_addr, 0);
3814 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003815 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003816}
3817
Andreas Färber05390242012-02-25 03:37:53 +01003818long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003819{
3820 struct target_rt_sigframe *frame;
3821 abi_ulong frame_addr;
3822 sigset_t blocked;
3823
thsc3b5bc82007-12-02 06:31:25 +00003824 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003825 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003826 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3827 goto badframe;
3828 }
thsc3b5bc82007-12-02 06:31:25 +00003829
Aurelien Jarno60e99242010-03-29 02:12:51 +02003830 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003831 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003832
Timothy E Baldwinba412492016-05-12 18:47:35 +01003833 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003834
3835 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003836 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3837 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003838 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003839 }
thsc3b5bc82007-12-02 06:31:25 +00003840
3841 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003842 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003843
3844badframe:
3845 unlock_user_struct(frame, frame_addr, 0);
3846 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01003847 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003848}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003849#elif defined(TARGET_MICROBLAZE)
3850
3851struct target_sigcontext {
3852 struct target_pt_regs regs; /* needs to be first */
3853 uint32_t oldmask;
3854};
3855
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003856struct target_stack_t {
3857 abi_ulong ss_sp;
3858 int ss_flags;
3859 unsigned int ss_size;
3860};
3861
3862struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003863 abi_ulong tuc_flags;
3864 abi_ulong tuc_link;
3865 struct target_stack_t tuc_stack;
3866 struct target_sigcontext tuc_mcontext;
3867 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003868};
3869
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003870/* Signal frames. */
3871struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003872 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003873 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3874 uint32_t tramp[2];
3875};
3876
3877struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003878 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07003879 ucontext_t uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003880 uint32_t tramp[2];
3881};
3882
Andreas Färber05390242012-02-25 03:37:53 +01003883static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003884{
3885 __put_user(env->regs[0], &sc->regs.r0);
3886 __put_user(env->regs[1], &sc->regs.r1);
3887 __put_user(env->regs[2], &sc->regs.r2);
3888 __put_user(env->regs[3], &sc->regs.r3);
3889 __put_user(env->regs[4], &sc->regs.r4);
3890 __put_user(env->regs[5], &sc->regs.r5);
3891 __put_user(env->regs[6], &sc->regs.r6);
3892 __put_user(env->regs[7], &sc->regs.r7);
3893 __put_user(env->regs[8], &sc->regs.r8);
3894 __put_user(env->regs[9], &sc->regs.r9);
3895 __put_user(env->regs[10], &sc->regs.r10);
3896 __put_user(env->regs[11], &sc->regs.r11);
3897 __put_user(env->regs[12], &sc->regs.r12);
3898 __put_user(env->regs[13], &sc->regs.r13);
3899 __put_user(env->regs[14], &sc->regs.r14);
3900 __put_user(env->regs[15], &sc->regs.r15);
3901 __put_user(env->regs[16], &sc->regs.r16);
3902 __put_user(env->regs[17], &sc->regs.r17);
3903 __put_user(env->regs[18], &sc->regs.r18);
3904 __put_user(env->regs[19], &sc->regs.r19);
3905 __put_user(env->regs[20], &sc->regs.r20);
3906 __put_user(env->regs[21], &sc->regs.r21);
3907 __put_user(env->regs[22], &sc->regs.r22);
3908 __put_user(env->regs[23], &sc->regs.r23);
3909 __put_user(env->regs[24], &sc->regs.r24);
3910 __put_user(env->regs[25], &sc->regs.r25);
3911 __put_user(env->regs[26], &sc->regs.r26);
3912 __put_user(env->regs[27], &sc->regs.r27);
3913 __put_user(env->regs[28], &sc->regs.r28);
3914 __put_user(env->regs[29], &sc->regs.r29);
3915 __put_user(env->regs[30], &sc->regs.r30);
3916 __put_user(env->regs[31], &sc->regs.r31);
3917 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3918}
3919
Andreas Färber05390242012-02-25 03:37:53 +01003920static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003921{
3922 __get_user(env->regs[0], &sc->regs.r0);
3923 __get_user(env->regs[1], &sc->regs.r1);
3924 __get_user(env->regs[2], &sc->regs.r2);
3925 __get_user(env->regs[3], &sc->regs.r3);
3926 __get_user(env->regs[4], &sc->regs.r4);
3927 __get_user(env->regs[5], &sc->regs.r5);
3928 __get_user(env->regs[6], &sc->regs.r6);
3929 __get_user(env->regs[7], &sc->regs.r7);
3930 __get_user(env->regs[8], &sc->regs.r8);
3931 __get_user(env->regs[9], &sc->regs.r9);
3932 __get_user(env->regs[10], &sc->regs.r10);
3933 __get_user(env->regs[11], &sc->regs.r11);
3934 __get_user(env->regs[12], &sc->regs.r12);
3935 __get_user(env->regs[13], &sc->regs.r13);
3936 __get_user(env->regs[14], &sc->regs.r14);
3937 __get_user(env->regs[15], &sc->regs.r15);
3938 __get_user(env->regs[16], &sc->regs.r16);
3939 __get_user(env->regs[17], &sc->regs.r17);
3940 __get_user(env->regs[18], &sc->regs.r18);
3941 __get_user(env->regs[19], &sc->regs.r19);
3942 __get_user(env->regs[20], &sc->regs.r20);
3943 __get_user(env->regs[21], &sc->regs.r21);
3944 __get_user(env->regs[22], &sc->regs.r22);
3945 __get_user(env->regs[23], &sc->regs.r23);
3946 __get_user(env->regs[24], &sc->regs.r24);
3947 __get_user(env->regs[25], &sc->regs.r25);
3948 __get_user(env->regs[26], &sc->regs.r26);
3949 __get_user(env->regs[27], &sc->regs.r27);
3950 __get_user(env->regs[28], &sc->regs.r28);
3951 __get_user(env->regs[29], &sc->regs.r29);
3952 __get_user(env->regs[30], &sc->regs.r30);
3953 __get_user(env->regs[31], &sc->regs.r31);
3954 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3955}
3956
3957static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003958 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003959{
3960 abi_ulong sp = env->regs[1];
3961
Riku Voipiob545f632014-07-15 17:01:55 +03003962 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003963 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003964 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003965
3966 return ((sp - frame_size) & -8UL);
3967}
3968
3969static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003970 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003971{
3972 struct target_signal_frame *frame;
3973 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003974 int i;
3975
3976 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003977 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003978 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3979 goto badframe;
3980
3981 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003982 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003983
3984 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003985 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003986 }
3987
Richard Hendersonf711df62010-11-22 14:57:52 -08003988 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003989
3990 /* Set up to return from userspace. If provided, use a stub
3991 already in userspace. */
3992 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3993 if (ka->sa_flags & TARGET_SA_RESTORER) {
3994 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3995 } else {
3996 uint32_t t;
3997 /* Note, these encodings are _big endian_! */
3998 /* addi r12, r0, __NR_sigreturn */
3999 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004000 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004001 /* brki r14, 0x8 */
4002 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03004003 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004004
4005 /* Return from sighandler will jump to the tramp.
4006 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08004007 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
4008 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004009 }
4010
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004011 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004012 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004013 /* Signal handler args: */
4014 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02004015 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004016 /* arg 1: sigcontext */
4017 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004018
4019 /* Offset of 4 to handle microblaze rtid r14, 0 */
4020 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
4021
4022 unlock_user_struct(frame, frame_addr, 1);
4023 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004024badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004025 force_sigsegv(sig);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004026}
4027
4028static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004029 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004030 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004031{
4032 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
4033}
4034
Andreas Färber05390242012-02-25 03:37:53 +01004035long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004036{
4037 struct target_signal_frame *frame;
4038 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05004039 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004040 sigset_t set;
4041 int i;
4042
4043 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004044 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004045 /* Make sure the guest isn't playing games. */
4046 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4047 goto badframe;
4048
4049 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004050 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004051 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004052 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004053 }
4054 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004055 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004056
Richard Hendersonf711df62010-11-22 14:57:52 -08004057 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004058 /* We got here through a sigreturn syscall, our path back is via an
4059 rtb insn so setup r14 for that. */
4060 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004061
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004062 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01004063 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004064badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004065 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004066 return -TARGET_QEMU_ESIGRETURN;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004067}
4068
Andreas Färber05390242012-02-25 03:37:53 +01004069long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004070{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004071 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004072 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
4073 return -TARGET_ENOSYS;
4074}
4075
edgar_iglb6d3abd2008-02-28 11:29:27 +00004076#elif defined(TARGET_CRIS)
4077
4078struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004079 struct target_pt_regs regs; /* needs to be first */
4080 uint32_t oldmask;
4081 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004082};
4083
4084/* Signal frames. */
4085struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004086 struct target_sigcontext sc;
4087 uint32_t extramask[TARGET_NSIG_WORDS - 1];
4088 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004089};
4090
4091struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004092 siginfo_t *pinfo;
4093 void *puc;
4094 siginfo_t info;
Khem Raj04b33e22017-06-28 13:44:52 -07004095 ucontext_t uc;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004096 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00004097};
4098
Andreas Färber05390242012-02-25 03:37:53 +01004099static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004100{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004101 __put_user(env->regs[0], &sc->regs.r0);
4102 __put_user(env->regs[1], &sc->regs.r1);
4103 __put_user(env->regs[2], &sc->regs.r2);
4104 __put_user(env->regs[3], &sc->regs.r3);
4105 __put_user(env->regs[4], &sc->regs.r4);
4106 __put_user(env->regs[5], &sc->regs.r5);
4107 __put_user(env->regs[6], &sc->regs.r6);
4108 __put_user(env->regs[7], &sc->regs.r7);
4109 __put_user(env->regs[8], &sc->regs.r8);
4110 __put_user(env->regs[9], &sc->regs.r9);
4111 __put_user(env->regs[10], &sc->regs.r10);
4112 __put_user(env->regs[11], &sc->regs.r11);
4113 __put_user(env->regs[12], &sc->regs.r12);
4114 __put_user(env->regs[13], &sc->regs.r13);
4115 __put_user(env->regs[14], &sc->usp);
4116 __put_user(env->regs[15], &sc->regs.acr);
4117 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
4118 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
4119 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004120}
edgar_igl9664d922008-03-03 22:23:53 +00004121
Andreas Färber05390242012-02-25 03:37:53 +01004122static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004123{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004124 __get_user(env->regs[0], &sc->regs.r0);
4125 __get_user(env->regs[1], &sc->regs.r1);
4126 __get_user(env->regs[2], &sc->regs.r2);
4127 __get_user(env->regs[3], &sc->regs.r3);
4128 __get_user(env->regs[4], &sc->regs.r4);
4129 __get_user(env->regs[5], &sc->regs.r5);
4130 __get_user(env->regs[6], &sc->regs.r6);
4131 __get_user(env->regs[7], &sc->regs.r7);
4132 __get_user(env->regs[8], &sc->regs.r8);
4133 __get_user(env->regs[9], &sc->regs.r9);
4134 __get_user(env->regs[10], &sc->regs.r10);
4135 __get_user(env->regs[11], &sc->regs.r11);
4136 __get_user(env->regs[12], &sc->regs.r12);
4137 __get_user(env->regs[13], &sc->regs.r13);
4138 __get_user(env->regs[14], &sc->usp);
4139 __get_user(env->regs[15], &sc->regs.acr);
4140 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
4141 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
4142 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004143}
4144
Andreas Färber05390242012-02-25 03:37:53 +01004145static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004146{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004147 abi_ulong sp;
4148 /* Align the stack downwards to 4. */
4149 sp = (env->regs[R_SP] & ~3);
4150 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004151}
4152
pbrook624f7972008-05-31 16:11:38 +00004153static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004154 target_sigset_t *set, 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 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004159
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004160 frame_addr = get_sigframe(env, sizeof *frame);
4161 trace_user_setup_frame(env, frame_addr);
4162 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4163 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004164
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004165 /*
4166 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
4167 * use this trampoline anymore but it sets it up for GDB.
4168 * In QEMU, using the trampoline simplifies things a bit so we use it.
4169 *
4170 * This is movu.w __NR_sigreturn, r9; break 13;
4171 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004172 __put_user(0x9c5f, frame->retcode+0);
4173 __put_user(TARGET_NR_sigreturn,
4174 frame->retcode + 1);
4175 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004176
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004177 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004178 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004179
Riku Voipio0188fad2014-04-23 13:34:15 +03004180 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4181 __put_user(set->sig[i], &frame->extramask[i - 1]);
4182 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004183
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004184 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004185
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004186 /* Move the stack and setup the arguments for the handler. */
4187 env->regs[R_SP] = frame_addr;
4188 env->regs[10] = sig;
4189 env->pc = (unsigned long) ka->_sa_handler;
4190 /* Link SRP so the guest returns through the trampoline. */
4191 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004192
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004193 unlock_user_struct(frame, frame_addr, 1);
4194 return;
4195badframe:
Peter Maydell09391662016-07-28 16:44:47 +01004196 force_sigsegv(sig);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004197}
4198
pbrook624f7972008-05-31 16:11:38 +00004199static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004200 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004201 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004202{
4203 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
4204}
4205
Andreas Färber05390242012-02-25 03:37:53 +01004206long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004207{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004208 struct target_signal_frame *frame;
4209 abi_ulong frame_addr;
4210 target_sigset_t target_set;
4211 sigset_t set;
4212 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004213
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004214 frame_addr = env->regs[R_SP];
4215 trace_user_do_sigreturn(env, frame_addr);
4216 /* Make sure the guest isn't playing games. */
4217 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
4218 goto badframe;
4219 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00004220
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004221 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03004222 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004223 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03004224 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004225 }
4226 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004227 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004228
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004229 restore_sigcontext(&frame->sc, env);
4230 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01004231 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004232badframe:
4233 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004234 return -TARGET_QEMU_ESIGRETURN;
edgar_iglb6d3abd2008-02-28 11:29:27 +00004235}
4236
Andreas Färber05390242012-02-25 03:37:53 +01004237long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00004238{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004239 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00004240 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
4241 return -TARGET_ENOSYS;
4242}
thsc3b5bc82007-12-02 06:31:25 +00004243
Marek Vasuta0a839b2017-01-18 23:01:42 +01004244#elif defined(TARGET_NIOS2)
4245
4246#define MCONTEXT_VERSION 2
4247
4248struct target_sigcontext {
4249 int version;
4250 unsigned long gregs[32];
4251};
4252
4253struct target_ucontext {
4254 abi_ulong tuc_flags;
4255 abi_ulong tuc_link;
4256 target_stack_t tuc_stack;
4257 struct target_sigcontext tuc_mcontext;
4258 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4259};
4260
4261struct target_rt_sigframe {
4262 struct target_siginfo info;
4263 struct target_ucontext uc;
4264};
4265
4266static unsigned long sigsp(unsigned long sp, struct target_sigaction *ka)
4267{
4268 if (unlikely((ka->sa_flags & SA_ONSTACK)) && !sas_ss_flags(sp)) {
4269#ifdef CONFIG_STACK_GROWSUP
4270 return target_sigaltstack_used.ss_sp;
4271#else
4272 return target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4273#endif
4274 }
4275 return sp;
4276}
4277
4278static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
4279{
4280 unsigned long *gregs = uc->tuc_mcontext.gregs;
4281
4282 __put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4283 __put_user(env->regs[1], &gregs[0]);
4284 __put_user(env->regs[2], &gregs[1]);
4285 __put_user(env->regs[3], &gregs[2]);
4286 __put_user(env->regs[4], &gregs[3]);
4287 __put_user(env->regs[5], &gregs[4]);
4288 __put_user(env->regs[6], &gregs[5]);
4289 __put_user(env->regs[7], &gregs[6]);
4290 __put_user(env->regs[8], &gregs[7]);
4291 __put_user(env->regs[9], &gregs[8]);
4292 __put_user(env->regs[10], &gregs[9]);
4293 __put_user(env->regs[11], &gregs[10]);
4294 __put_user(env->regs[12], &gregs[11]);
4295 __put_user(env->regs[13], &gregs[12]);
4296 __put_user(env->regs[14], &gregs[13]);
4297 __put_user(env->regs[15], &gregs[14]);
4298 __put_user(env->regs[16], &gregs[15]);
4299 __put_user(env->regs[17], &gregs[16]);
4300 __put_user(env->regs[18], &gregs[17]);
4301 __put_user(env->regs[19], &gregs[18]);
4302 __put_user(env->regs[20], &gregs[19]);
4303 __put_user(env->regs[21], &gregs[20]);
4304 __put_user(env->regs[22], &gregs[21]);
4305 __put_user(env->regs[23], &gregs[22]);
4306 __put_user(env->regs[R_RA], &gregs[23]);
4307 __put_user(env->regs[R_FP], &gregs[24]);
4308 __put_user(env->regs[R_GP], &gregs[25]);
4309 __put_user(env->regs[R_EA], &gregs[27]);
4310 __put_user(env->regs[R_SP], &gregs[28]);
4311
4312 return 0;
4313}
4314
4315static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
4316 int *pr2)
4317{
4318 int temp;
4319 abi_ulong off, frame_addr = env->regs[R_SP];
4320 unsigned long *gregs = uc->tuc_mcontext.gregs;
4321 int err;
4322
4323 /* Always make any pending restarted system calls return -EINTR */
4324 /* current->restart_block.fn = do_no_restart_syscall; */
4325
4326 __get_user(temp, &uc->tuc_mcontext.version);
4327 if (temp != MCONTEXT_VERSION) {
4328 return 1;
4329 }
4330
4331 /* restore passed registers */
4332 __get_user(env->regs[1], &gregs[0]);
4333 __get_user(env->regs[2], &gregs[1]);
4334 __get_user(env->regs[3], &gregs[2]);
4335 __get_user(env->regs[4], &gregs[3]);
4336 __get_user(env->regs[5], &gregs[4]);
4337 __get_user(env->regs[6], &gregs[5]);
4338 __get_user(env->regs[7], &gregs[6]);
4339 __get_user(env->regs[8], &gregs[7]);
4340 __get_user(env->regs[9], &gregs[8]);
4341 __get_user(env->regs[10], &gregs[9]);
4342 __get_user(env->regs[11], &gregs[10]);
4343 __get_user(env->regs[12], &gregs[11]);
4344 __get_user(env->regs[13], &gregs[12]);
4345 __get_user(env->regs[14], &gregs[13]);
4346 __get_user(env->regs[15], &gregs[14]);
4347 __get_user(env->regs[16], &gregs[15]);
4348 __get_user(env->regs[17], &gregs[16]);
4349 __get_user(env->regs[18], &gregs[17]);
4350 __get_user(env->regs[19], &gregs[18]);
4351 __get_user(env->regs[20], &gregs[19]);
4352 __get_user(env->regs[21], &gregs[20]);
4353 __get_user(env->regs[22], &gregs[21]);
4354 __get_user(env->regs[23], &gregs[22]);
4355 /* gregs[23] is handled below */
4356 /* Verify, should this be settable */
4357 __get_user(env->regs[R_FP], &gregs[24]);
4358 /* Verify, should this be settable */
4359 __get_user(env->regs[R_GP], &gregs[25]);
4360 /* Not really necessary no user settable bits */
4361 __get_user(temp, &gregs[26]);
4362 __get_user(env->regs[R_EA], &gregs[27]);
4363
4364 __get_user(env->regs[R_RA], &gregs[23]);
4365 __get_user(env->regs[R_SP], &gregs[28]);
4366
4367 off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
4368 err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
4369 if (err == -EFAULT) {
4370 return 1;
4371 }
4372
4373 *pr2 = env->regs[2];
4374 return 0;
4375}
4376
4377static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
4378 size_t frame_size)
4379{
4380 unsigned long usp;
4381
4382 /* Default to using normal stack. */
4383 usp = env->regs[R_SP];
4384
4385 /* This is the X/Open sanctioned signal stack switching. */
4386 usp = sigsp(usp, ka);
4387
4388 /* Verify, is it 32 or 64 bit aligned */
4389 return (void *)((usp - frame_size) & -8UL);
4390}
4391
4392static void setup_rt_frame(int sig, struct target_sigaction *ka,
4393 target_siginfo_t *info,
4394 target_sigset_t *set,
4395 CPUNios2State *env)
4396{
4397 struct target_rt_sigframe *frame;
4398 int i, err = 0;
4399
4400 frame = get_sigframe(ka, env, sizeof(*frame));
4401
4402 if (ka->sa_flags & SA_SIGINFO) {
4403 tswap_siginfo(&frame->info, info);
4404 }
4405
4406 /* Create the ucontext. */
4407 __put_user(0, &frame->uc.tuc_flags);
4408 __put_user(0, &frame->uc.tuc_link);
4409 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4410 __put_user(sas_ss_flags(env->regs[R_SP]), &frame->uc.tuc_stack.ss_flags);
4411 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4412 err |= rt_setup_ucontext(&frame->uc, env);
4413 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4414 __put_user((abi_ulong)set->sig[i],
4415 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4416 }
4417
4418 if (err) {
4419 goto give_sigsegv;
4420 }
4421
4422 /* Set up to return from userspace; jump to fixed address sigreturn
4423 trampoline on kuser page. */
4424 env->regs[R_RA] = (unsigned long) (0x1044);
4425
4426 /* Set up registers for signal handler */
4427 env->regs[R_SP] = (unsigned long) frame;
4428 env->regs[4] = (unsigned long) sig;
4429 env->regs[5] = (unsigned long) &frame->info;
4430 env->regs[6] = (unsigned long) &frame->uc;
4431 env->regs[R_EA] = (unsigned long) ka->_sa_handler;
4432 return;
4433
4434give_sigsegv:
4435 if (sig == TARGET_SIGSEGV) {
4436 ka->_sa_handler = TARGET_SIG_DFL;
4437 }
4438 force_sigsegv(sig);
4439 return;
4440}
4441
4442long do_sigreturn(CPUNios2State *env)
4443{
4444 trace_user_do_sigreturn(env, 0);
4445 fprintf(stderr, "do_sigreturn: not implemented\n");
4446 return -TARGET_ENOSYS;
4447}
4448
4449long do_rt_sigreturn(CPUNios2State *env)
4450{
4451 /* Verify, can we follow the stack back */
4452 abi_ulong frame_addr = env->regs[R_SP];
4453 struct target_rt_sigframe *frame;
4454 sigset_t set;
4455 int rval;
4456
4457 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4458 goto badframe;
4459 }
4460
4461 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4462 do_sigprocmask(SIG_SETMASK, &set, NULL);
4463
4464 if (rt_restore_ucontext(env, &frame->uc, &rval)) {
4465 goto badframe;
4466 }
4467
4468 unlock_user_struct(frame, frame_addr, 0);
4469 return rval;
4470
4471badframe:
4472 unlock_user_struct(frame, frame_addr, 0);
4473 force_sig(TARGET_SIGSEGV);
4474 return 0;
4475}
4476/* TARGET_NIOS2 */
4477
Jia Liud9627832012-07-20 15:50:52 +08004478#elif defined(TARGET_OPENRISC)
4479
4480struct target_sigcontext {
4481 struct target_pt_regs regs;
4482 abi_ulong oldmask;
4483 abi_ulong usp;
4484};
4485
4486struct target_ucontext {
4487 abi_ulong tuc_flags;
4488 abi_ulong tuc_link;
4489 target_stack_t tuc_stack;
4490 struct target_sigcontext tuc_mcontext;
4491 target_sigset_t tuc_sigmask; /* mask last for extensibility */
4492};
4493
4494struct target_rt_sigframe {
4495 abi_ulong pinfo;
4496 uint64_t puc;
4497 struct target_siginfo info;
4498 struct target_sigcontext sc;
4499 struct target_ucontext uc;
4500 unsigned char retcode[16]; /* trampoline code */
4501};
4502
4503/* This is the asm-generic/ucontext.h version */
4504#if 0
4505static int restore_sigcontext(CPUOpenRISCState *regs,
4506 struct target_sigcontext *sc)
4507{
4508 unsigned int err = 0;
4509 unsigned long old_usp;
4510
4511 /* Alwys make any pending restarted system call return -EINTR */
4512 current_thread_info()->restart_block.fn = do_no_restart_syscall;
4513
4514 /* restore the regs from &sc->regs (same as sc, since regs is first)
4515 * (sc is already checked for VERIFY_READ since the sigframe was
4516 * checked in sys_sigreturn previously)
4517 */
4518
4519 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
4520 goto badframe;
4521 }
4522
4523 /* make sure the U-flag is set so user-mode cannot fool us */
4524
4525 regs->sr &= ~SR_SM;
4526
4527 /* restore the old USP as it was before we stacked the sc etc.
4528 * (we cannot just pop the sigcontext since we aligned the sp and
4529 * stuff after pushing it)
4530 */
4531
Riku Voipio1d8b5122014-04-23 10:26:05 +03004532 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004533 phx_signal("old_usp 0x%lx", old_usp);
4534
4535 __PHX__ REALLY /* ??? */
4536 wrusp(old_usp);
4537 regs->gpr[1] = old_usp;
4538
4539 /* TODO: the other ports use regs->orig_XX to disable syscall checks
4540 * after this completes, but we don't use that mechanism. maybe we can
4541 * use it now ?
4542 */
4543
4544 return err;
4545
4546badframe:
4547 return 1;
4548}
4549#endif
4550
4551/* Set up a signal frame. */
4552
Riku Voipio41ecc722014-04-23 11:01:00 +03004553static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004554 CPUOpenRISCState *regs,
4555 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08004556{
Stafford Horned89e71e2017-04-06 06:44:56 +09004557 unsigned long usp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004558
4559 /* copy the regs. they are first in sc so we can use sc directly */
4560
Riku Voipio1d8b5122014-04-23 10:26:05 +03004561 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08004562
4563 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
4564 the signal handler. The frametype will be restored to its previous
4565 value in restore_sigcontext. */
4566 /*regs->frametype = CRIS_FRAME_NORMAL;*/
4567
4568 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004569 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03004570 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08004571}
4572
4573static inline unsigned long align_sigframe(unsigned long sp)
4574{
Eduardo Habkost9be38592016-06-13 18:57:58 -03004575 return sp & ~3UL;
Jia Liud9627832012-07-20 15:50:52 +08004576}
4577
4578static inline abi_ulong get_sigframe(struct target_sigaction *ka,
4579 CPUOpenRISCState *regs,
4580 size_t frame_size)
4581{
Stafford Horned89e71e2017-04-06 06:44:56 +09004582 unsigned long sp = cpu_get_gpr(regs, 1);
Jia Liud9627832012-07-20 15:50:52 +08004583 int onsigstack = on_sig_stack(sp);
4584
4585 /* redzone */
4586 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03004587 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08004588 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4589 }
4590
4591 sp = align_sigframe(sp - frame_size);
4592
4593 /*
4594 * If we are on the alternate signal stack and would overflow it, don't.
4595 * Return an always-bogus address instead so we will die with SIGSEGV.
4596 */
4597
4598 if (onsigstack && !likely(on_sig_stack(sp))) {
4599 return -1L;
4600 }
4601
4602 return sp;
4603}
4604
Jia Liud9627832012-07-20 15:50:52 +08004605static void setup_rt_frame(int sig, struct target_sigaction *ka,
4606 target_siginfo_t *info,
4607 target_sigset_t *set, CPUOpenRISCState *env)
4608{
4609 int err = 0;
4610 abi_ulong frame_addr;
4611 unsigned long return_ip;
4612 struct target_rt_sigframe *frame;
4613 abi_ulong info_addr, uc_addr;
4614
Jia Liud9627832012-07-20 15:50:52 +08004615 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004616 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08004617 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4618 goto give_sigsegv;
4619 }
4620
4621 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004622 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08004623 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004624 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08004625
4626 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00004627 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08004628 }
4629
Khem Raj04b33e22017-06-28 13:44:52 -07004630 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03004631 __put_user(0, &frame->uc.tuc_flags);
4632 __put_user(0, &frame->uc.tuc_link);
4633 __put_user(target_sigaltstack_used.ss_sp,
4634 &frame->uc.tuc_stack.ss_sp);
Stafford Horned89e71e2017-04-06 06:44:56 +09004635 __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
4636 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004637 __put_user(target_sigaltstack_used.ss_size,
4638 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03004639 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08004640
4641 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4642
Jia Liud9627832012-07-20 15:50:52 +08004643 /* trampoline - the desired return ip is the retcode itself */
4644 return_ip = (unsigned long)&frame->retcode;
4645 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03004646 __put_user(0xa960, (short *)(frame->retcode + 0));
4647 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4648 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4649 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08004650
4651 if (err) {
4652 goto give_sigsegv;
4653 }
4654
4655 /* TODO what is the current->exec_domain stuff and invmap ? */
4656
4657 /* Set up registers for signal handler */
4658 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
Stafford Horned89e71e2017-04-06 06:44:56 +09004659 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
4660 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
4661 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
4662 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
Jia Liud9627832012-07-20 15:50:52 +08004663
4664 /* actually move the usp to reflect the stacked frame */
Stafford Horned89e71e2017-04-06 06:44:56 +09004665 cpu_set_gpr(env, 1, (unsigned long)frame);
Jia Liud9627832012-07-20 15:50:52 +08004666
4667 return;
4668
4669give_sigsegv:
4670 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01004671 force_sigsegv(sig);
Jia Liud9627832012-07-20 15:50:52 +08004672}
4673
4674long do_sigreturn(CPUOpenRISCState *env)
4675{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004676 trace_user_do_sigreturn(env, 0);
4677 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004678 return -TARGET_ENOSYS;
4679}
4680
4681long do_rt_sigreturn(CPUOpenRISCState *env)
4682{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004683 trace_user_do_rt_sigreturn(env, 0);
4684 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004685 return -TARGET_ENOSYS;
4686}
4687/* TARGET_OPENRISC */
4688
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004689#elif defined(TARGET_S390X)
4690
4691#define __NUM_GPRS 16
4692#define __NUM_FPRS 16
4693#define __NUM_ACRS 16
4694
4695#define S390_SYSCALL_SIZE 2
4696#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4697
4698#define _SIGCONTEXT_NSIG 64
4699#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4700#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4701#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4702#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4703#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4704
4705typedef struct {
4706 target_psw_t psw;
4707 target_ulong gprs[__NUM_GPRS];
4708 unsigned int acrs[__NUM_ACRS];
4709} target_s390_regs_common;
4710
4711typedef struct {
4712 unsigned int fpc;
4713 double fprs[__NUM_FPRS];
4714} target_s390_fp_regs;
4715
4716typedef struct {
4717 target_s390_regs_common regs;
4718 target_s390_fp_regs fpregs;
4719} target_sigregs;
4720
4721struct target_sigcontext {
4722 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4723 target_sigregs *sregs;
4724};
4725
4726typedef struct {
4727 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4728 struct target_sigcontext sc;
4729 target_sigregs sregs;
4730 int signo;
4731 uint8_t retcode[S390_SYSCALL_SIZE];
4732} sigframe;
4733
4734struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004735 target_ulong tuc_flags;
4736 struct target_ucontext *tuc_link;
4737 target_stack_t tuc_stack;
4738 target_sigregs tuc_mcontext;
4739 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004740};
4741
4742typedef struct {
4743 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4744 uint8_t retcode[S390_SYSCALL_SIZE];
4745 struct target_siginfo info;
4746 struct target_ucontext uc;
4747} rt_sigframe;
4748
4749static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004750get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004751{
4752 abi_ulong sp;
4753
4754 /* Default to using normal stack */
4755 sp = env->regs[15];
4756
4757 /* This is the X/Open sanctioned signal stack switching. */
4758 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4759 if (!sas_ss_flags(sp)) {
4760 sp = target_sigaltstack_used.ss_sp +
4761 target_sigaltstack_used.ss_size;
4762 }
4763 }
4764
4765 /* This is the legacy signal stack switching. */
4766 else if (/* FIXME !user_mode(regs) */ 0 &&
4767 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4768 ka->sa_restorer) {
4769 sp = (abi_ulong) ka->sa_restorer;
4770 }
4771
4772 return (sp - frame_size) & -8ul;
4773}
4774
Andreas Färber05390242012-02-25 03:37:53 +01004775static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004776{
4777 int i;
4778 //save_access_regs(current->thread.acrs); FIXME
4779
4780 /* Copy a 'clean' PSW mask to the user to avoid leaking
4781 information about whether PER is currently on. */
4782 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4783 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4784 for (i = 0; i < 16; i++) {
4785 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4786 }
4787 for (i = 0; i < 16; i++) {
4788 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4789 }
4790 /*
4791 * We have to store the fp registers to current->thread.fp_regs
4792 * to merge them with the emulated registers.
4793 */
4794 //save_fp_regs(&current->thread.fp_regs); FIXME
4795 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004796 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004797 }
4798}
4799
4800static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004801 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004802{
4803 sigframe *frame;
4804 abi_ulong frame_addr;
4805
4806 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004807 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004808 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004809 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004810 }
4811
Riku Voipio0188fad2014-04-23 13:34:15 +03004812 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004813
4814 save_sigregs(env, &frame->sregs);
4815
4816 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4817 (abi_ulong *)&frame->sc.sregs);
4818
4819 /* Set up to return from userspace. If provided, use a stub
4820 already in userspace. */
4821 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004822 env->regs[14] = (unsigned long)
4823 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004824 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004825 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4826 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004827 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4828 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004829 }
4830
4831 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004832 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004833
4834 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004835 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004836 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4837
4838 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004839 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004840
4841 /* We forgot to include these in the sigcontext.
4842 To avoid breaking binary compatibility, they are passed as args. */
4843 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4844 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4845
4846 /* Place signal number on stack to allow backtrace from handler. */
Laurent Vivierc1bc91c2016-06-15 18:14:32 +02004847 __put_user(env->regs[2], &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004848 unlock_user_struct(frame, frame_addr, 1);
4849 return;
4850
4851give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004852 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004853}
4854
4855static void setup_rt_frame(int sig, struct target_sigaction *ka,
4856 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004857 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004858{
4859 int i;
4860 rt_sigframe *frame;
4861 abi_ulong frame_addr;
4862
4863 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004864 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004865 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4866 goto give_sigsegv;
4867 }
4868
Peter Maydellf6c7a052015-01-08 12:19:48 +00004869 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004870
4871 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004872 __put_user(0, &frame->uc.tuc_flags);
4873 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4874 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004875 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004876 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004877 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4878 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004879 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4880 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004881 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004882 }
4883
4884 /* Set up to return from userspace. If provided, use a stub
4885 already in userspace. */
4886 if (ka->sa_flags & TARGET_SA_RESTORER) {
4887 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4888 } else {
4889 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004890 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4891 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004892 }
4893
4894 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004895 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004896
4897 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004898 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004899 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4900
4901 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004902 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4903 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004904 return;
4905
4906give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01004907 force_sigsegv(sig);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004908}
4909
4910static int
Andreas Färber05390242012-02-25 03:37:53 +01004911restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004912{
4913 int err = 0;
4914 int i;
4915
4916 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004917 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004918 }
4919
Riku Voipio1d8b5122014-04-23 10:26:05 +03004920 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004921 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4922 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004923 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004924 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4925
4926 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004927 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004928 }
4929 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004930 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004931 }
4932
4933 return err;
4934}
4935
Andreas Färber05390242012-02-25 03:37:53 +01004936long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004937{
4938 sigframe *frame;
4939 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004940 target_sigset_t target_set;
4941 sigset_t set;
4942
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004943 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004944 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4945 goto badframe;
4946 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004947 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004948
4949 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004950 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004951
4952 if (restore_sigregs(env, &frame->sregs)) {
4953 goto badframe;
4954 }
4955
4956 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004957 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004958
4959badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004960 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004961 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004962}
4963
Andreas Färber05390242012-02-25 03:37:53 +01004964long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004965{
4966 rt_sigframe *frame;
4967 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004968 sigset_t set;
4969
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004970 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004971 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4972 goto badframe;
4973 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004974 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004975
Peter Maydell9eede5b2016-05-27 15:51:46 +01004976 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004977
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004978 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004979 goto badframe;
4980 }
4981
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004982 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004983 get_sp_from_cpustate(env)) == -EFAULT) {
4984 goto badframe;
4985 }
4986 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004987 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004988
4989badframe:
4990 unlock_user_struct(frame, frame_addr, 0);
4991 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01004992 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004993}
4994
Tom Musta61e75fe2014-06-30 08:13:38 -05004995#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004996
4997/* Size of dummy stack frame allocated when calling signal handler.
4998 See arch/powerpc/include/asm/ptrace.h. */
4999#if defined(TARGET_PPC64)
5000#define SIGNAL_FRAMESIZE 128
5001#else
5002#define SIGNAL_FRAMESIZE 64
5003#endif
5004
Tom Musta61e75fe2014-06-30 08:13:38 -05005005/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
5006 on 64-bit PPC, sigcontext and mcontext are one and the same. */
5007struct target_mcontext {
5008 target_ulong mc_gregs[48];
5009 /* Includes fpscr. */
5010 uint64_t mc_fregs[33];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005011#if defined(TARGET_PPC64)
5012 /* Pointer to the vector regs */
5013 target_ulong v_regs;
5014#else
Tom Musta61e75fe2014-06-30 08:13:38 -05005015 target_ulong mc_pad[2];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005016#endif
Tom Musta61e75fe2014-06-30 08:13:38 -05005017 /* We need to handle Altivec and SPE at the same time, which no
5018 kernel needs to do. Fortunately, the kernel defines this bit to
5019 be Altivec-register-large all the time, rather than trying to
5020 twiddle it based on the specific platform. */
5021 union {
5022 /* SPE vector registers. One extra for SPEFSCR. */
5023 uint32_t spe[33];
5024 /* Altivec vector registers. The packing of VSCR and VRSAVE
5025 varies depending on whether we're PPC64 or not: PPC64 splits
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005026 them apart; PPC32 stuffs them together.
5027 We also need to account for the VSX registers on PPC64
5028 */
Tom Musta61e75fe2014-06-30 08:13:38 -05005029#if defined(TARGET_PPC64)
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005030#define QEMU_NVRREG (34 + 16)
5031 /* On ppc64, this mcontext structure is naturally *unaligned*,
5032 * or rather it is aligned on a 8 bytes boundary but not on
5033 * a 16 bytes one. This pad fixes it up. This is also why the
5034 * vector regs are referenced by the v_regs pointer above so
5035 * any amount of padding can be added here
5036 */
5037 target_ulong pad;
Tom Musta61e75fe2014-06-30 08:13:38 -05005038#else
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005039 /* On ppc32, we are already aligned to 16 bytes */
Tom Musta61e75fe2014-06-30 08:13:38 -05005040#define QEMU_NVRREG 33
5041#endif
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005042 /* We cannot use ppc_avr_t here as we do *not* want the implied
5043 * 16-bytes alignment that would result from it. This would have
5044 * the effect of making the whole struct target_mcontext aligned
5045 * which breaks the layout of struct target_ucontext on ppc64.
5046 */
5047 uint64_t altivec[QEMU_NVRREG][2];
Tom Musta61e75fe2014-06-30 08:13:38 -05005048#undef QEMU_NVRREG
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005049 } mc_vregs;
Tom Musta61e75fe2014-06-30 08:13:38 -05005050};
5051
Nathan Froydbcd49332009-05-12 19:13:18 -07005052/* See arch/powerpc/include/asm/sigcontext.h. */
5053struct target_sigcontext {
5054 target_ulong _unused[4];
5055 int32_t signal;
5056#if defined(TARGET_PPC64)
5057 int32_t pad0;
5058#endif
5059 target_ulong handler;
5060 target_ulong oldmask;
5061 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05005062#if defined(TARGET_PPC64)
5063 struct target_mcontext mcontext;
5064#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005065};
5066
5067/* Indices for target_mcontext.mc_gregs, below.
5068 See arch/powerpc/include/asm/ptrace.h for details. */
5069enum {
5070 TARGET_PT_R0 = 0,
5071 TARGET_PT_R1 = 1,
5072 TARGET_PT_R2 = 2,
5073 TARGET_PT_R3 = 3,
5074 TARGET_PT_R4 = 4,
5075 TARGET_PT_R5 = 5,
5076 TARGET_PT_R6 = 6,
5077 TARGET_PT_R7 = 7,
5078 TARGET_PT_R8 = 8,
5079 TARGET_PT_R9 = 9,
5080 TARGET_PT_R10 = 10,
5081 TARGET_PT_R11 = 11,
5082 TARGET_PT_R12 = 12,
5083 TARGET_PT_R13 = 13,
5084 TARGET_PT_R14 = 14,
5085 TARGET_PT_R15 = 15,
5086 TARGET_PT_R16 = 16,
5087 TARGET_PT_R17 = 17,
5088 TARGET_PT_R18 = 18,
5089 TARGET_PT_R19 = 19,
5090 TARGET_PT_R20 = 20,
5091 TARGET_PT_R21 = 21,
5092 TARGET_PT_R22 = 22,
5093 TARGET_PT_R23 = 23,
5094 TARGET_PT_R24 = 24,
5095 TARGET_PT_R25 = 25,
5096 TARGET_PT_R26 = 26,
5097 TARGET_PT_R27 = 27,
5098 TARGET_PT_R28 = 28,
5099 TARGET_PT_R29 = 29,
5100 TARGET_PT_R30 = 30,
5101 TARGET_PT_R31 = 31,
5102 TARGET_PT_NIP = 32,
5103 TARGET_PT_MSR = 33,
5104 TARGET_PT_ORIG_R3 = 34,
5105 TARGET_PT_CTR = 35,
5106 TARGET_PT_LNK = 36,
5107 TARGET_PT_XER = 37,
5108 TARGET_PT_CCR = 38,
5109 /* Yes, there are two registers with #39. One is 64-bit only. */
5110 TARGET_PT_MQ = 39,
5111 TARGET_PT_SOFTE = 39,
5112 TARGET_PT_TRAP = 40,
5113 TARGET_PT_DAR = 41,
5114 TARGET_PT_DSISR = 42,
5115 TARGET_PT_RESULT = 43,
5116 TARGET_PT_REGS_COUNT = 44
5117};
5118
Nathan Froydbcd49332009-05-12 19:13:18 -07005119
5120struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005121 target_ulong tuc_flags;
Khem Raj04b33e22017-06-28 13:44:52 -07005122 target_ulong tuc_link; /* ucontext_t __user * */
Aurelien Jarno60e99242010-03-29 02:12:51 +02005123 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07005124#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02005125 int32_t tuc_pad[7];
5126 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07005127 points to uc_mcontext field */
5128#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02005129 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07005130#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05005131 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05005132 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005133#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02005134 int32_t tuc_maskext[30];
5135 int32_t tuc_pad2[3];
5136 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07005137#endif
5138};
5139
5140/* See arch/powerpc/kernel/signal_32.c. */
5141struct target_sigframe {
5142 struct target_sigcontext sctx;
5143 struct target_mcontext mctx;
5144 int32_t abigap[56];
5145};
5146
Tom Musta61e75fe2014-06-30 08:13:38 -05005147#if defined(TARGET_PPC64)
5148
5149#define TARGET_TRAMP_SIZE 6
5150
5151struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005152 /* sys_rt_sigreturn requires the ucontext be the first field */
5153 struct target_ucontext uc;
5154 target_ulong _unused[2];
5155 uint32_t trampoline[TARGET_TRAMP_SIZE];
5156 target_ulong pinfo; /* struct siginfo __user * */
5157 target_ulong puc; /* void __user * */
5158 struct target_siginfo info;
5159 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
5160 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05005161} __attribute__((aligned(16)));
5162
5163#else
5164
Nathan Froydbcd49332009-05-12 19:13:18 -07005165struct target_rt_sigframe {
5166 struct target_siginfo info;
5167 struct target_ucontext uc;
5168 int32_t abigap[56];
5169};
5170
Tom Musta61e75fe2014-06-30 08:13:38 -05005171#endif
5172
Tom Musta8d6ab332014-06-30 08:13:39 -05005173#if defined(TARGET_PPC64)
5174
5175struct target_func_ptr {
5176 target_ulong entry;
5177 target_ulong toc;
5178};
5179
5180#endif
5181
Nathan Froydbcd49332009-05-12 19:13:18 -07005182/* We use the mc_pad field for the signal return trampoline. */
5183#define tramp mc_pad
5184
5185/* See arch/powerpc/kernel/signal.c. */
5186static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005187 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07005188 int frame_size)
5189{
Eduardo Habkost9be38592016-06-13 18:57:58 -03005190 target_ulong oldsp;
Nathan Froydbcd49332009-05-12 19:13:18 -07005191
5192 oldsp = env->gpr[1];
5193
5194 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005195 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07005196 oldsp = (target_sigaltstack_used.ss_sp
5197 + target_sigaltstack_used.ss_size);
5198 }
5199
Eduardo Habkost9be38592016-06-13 18:57:58 -03005200 return (oldsp - frame_size) & ~0xFUL;
Nathan Froydbcd49332009-05-12 19:13:18 -07005201}
5202
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005203#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
5204 (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
5205#define PPC_VEC_HI 0
5206#define PPC_VEC_LO 1
5207#else
5208#define PPC_VEC_HI 1
5209#define PPC_VEC_LO 0
5210#endif
5211
5212
Tom Musta76781082014-06-30 08:13:37 -05005213static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07005214{
5215 target_ulong msr = env->msr;
5216 int i;
5217 target_ulong ccr = 0;
5218
5219 /* In general, the kernel attempts to be intelligent about what it
5220 needs to save for Altivec/FP/SPE registers. We don't care that
5221 much, so we just go ahead and save everything. */
5222
5223 /* Save general registers. */
5224 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005225 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005226 }
Riku Voipioc650c002014-04-23 13:53:45 +03005227 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5228 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5229 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5230 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005231
5232 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5233 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
5234 }
Riku Voipioc650c002014-04-23 13:53:45 +03005235 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005236
5237 /* Save Altivec registers if necessary. */
5238 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005239 uint32_t *vrsave;
Nathan Froydbcd49332009-05-12 19:13:18 -07005240 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005241 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005242 ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005243
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005244 __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5245 __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005246 }
5247 /* Set MSR_VR in the saved MSR value to indicate that
5248 frame->mc_vregs contains valid data. */
5249 msr |= MSR_VR;
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005250#if defined(TARGET_PPC64)
5251 vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
5252 /* 64-bit needs to put a pointer to the vectors in the frame */
5253 __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
5254#else
5255 vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
5256#endif
5257 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
5258 }
5259
5260 /* Save VSX second halves */
5261 if (env->insns_flags2 & PPC2_VSX) {
5262 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5263 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5264 __put_user(env->vsr[i], &vsregs[i]);
5265 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005266 }
5267
5268 /* Save floating point registers. */
5269 if (env->insns_flags & PPC_FLOAT) {
5270 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005271 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005272 }
Riku Voipioc650c002014-04-23 13:53:45 +03005273 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005274 }
5275
5276 /* Save SPE registers. The kernel only saves the high half. */
5277 if (env->insns_flags & PPC_SPE) {
5278#if defined(TARGET_PPC64)
5279 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005280 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005281 }
5282#else
5283 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005284 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005285 }
5286#endif
5287 /* Set MSR_SPE in the saved MSR value to indicate that
5288 frame->mc_vregs contains valid data. */
5289 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03005290 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005291 }
5292
5293 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005294 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05005295}
Nathan Froydbcd49332009-05-12 19:13:18 -07005296
Tom Musta76781082014-06-30 08:13:37 -05005297static void encode_trampoline(int sigret, uint32_t *tramp)
5298{
Nathan Froydbcd49332009-05-12 19:13:18 -07005299 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
5300 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05005301 __put_user(0x38000000 | sigret, &tramp[0]);
5302 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005303 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005304}
5305
Riku Voipioc650c002014-04-23 13:53:45 +03005306static void restore_user_regs(CPUPPCState *env,
5307 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005308{
5309 target_ulong save_r2 = 0;
5310 target_ulong msr;
5311 target_ulong ccr;
5312
5313 int i;
5314
5315 if (!sig) {
5316 save_r2 = env->gpr[2];
5317 }
5318
5319 /* Restore general registers. */
5320 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005321 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005322 }
Riku Voipioc650c002014-04-23 13:53:45 +03005323 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
5324 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
5325 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
5326 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
5327 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005328
5329 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
5330 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
5331 }
5332
5333 if (!sig) {
5334 env->gpr[2] = save_r2;
5335 }
5336 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03005337 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005338
5339 /* If doing signal return, restore the previous little-endian mode. */
5340 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005341 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07005342
5343 /* Restore Altivec registers if necessary. */
5344 if (env->insns_flags & PPC_ALTIVEC) {
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005345 ppc_avr_t *v_regs;
5346 uint32_t *vrsave;
5347#if defined(TARGET_PPC64)
5348 uint64_t v_addr;
5349 /* 64-bit needs to recover the pointer to the vectors from the frame */
5350 __get_user(v_addr, &frame->v_regs);
5351 v_regs = g2h(v_addr);
5352#else
5353 v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
5354#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005355 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005356 ppc_avr_t *avr = &env->avr[i];
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005357 ppc_avr_t *vreg = &v_regs[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07005358
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005359 __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
5360 __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005361 }
5362 /* Set MSR_VEC in the saved MSR value to indicate that
5363 frame->mc_vregs contains valid data. */
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005364#if defined(TARGET_PPC64)
5365 vrsave = (uint32_t *)&v_regs[33];
5366#else
5367 vrsave = (uint32_t *)&v_regs[32];
5368#endif
5369 __get_user(env->spr[SPR_VRSAVE], vrsave);
5370 }
5371
5372 /* Restore VSX second halves */
5373 if (env->insns_flags2 & PPC2_VSX) {
5374 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
5375 for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
5376 __get_user(env->vsr[i], &vsregs[i]);
5377 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005378 }
5379
5380 /* Restore floating point registers. */
5381 if (env->insns_flags & PPC_FLOAT) {
5382 uint64_t fpscr;
5383 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005384 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005385 }
Riku Voipioc650c002014-04-23 13:53:45 +03005386 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005387 env->fpscr = (uint32_t) fpscr;
5388 }
5389
5390 /* Save SPE registers. The kernel only saves the high half. */
5391 if (env->insns_flags & PPC_SPE) {
5392#if defined(TARGET_PPC64)
5393 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
5394 uint32_t hi;
5395
Riku Voipioc650c002014-04-23 13:53:45 +03005396 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005397 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
5398 }
5399#else
5400 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03005401 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005402 }
5403#endif
Riku Voipioc650c002014-04-23 13:53:45 +03005404 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005405 }
Nathan Froydbcd49332009-05-12 19:13:18 -07005406}
5407
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005408#if !defined(TARGET_PPC64)
Nathan Froydbcd49332009-05-12 19:13:18 -07005409static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005410 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005411{
5412 struct target_sigframe *frame;
5413 struct target_sigcontext *sc;
5414 target_ulong frame_addr, newsp;
5415 int err = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005416
5417 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005418 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005419 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
5420 goto sigsegv;
5421 sc = &frame->sctx;
5422
Riku Voipio1d8b5122014-04-23 10:26:05 +03005423 __put_user(ka->_sa_handler, &sc->handler);
5424 __put_user(set->sig[0], &sc->oldmask);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005425 __put_user(set->sig[1], &sc->_unused[3]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005426 __put_user(h2g(&frame->mctx), &sc->regs);
5427 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07005428
5429 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05005430 save_user_regs(env, &frame->mctx);
5431
5432 /* Construct the trampoline code on the stack. */
5433 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07005434
5435 /* The kernel checks for the presence of a VDSO here. We don't
5436 emulate a vdso, so use a sigreturn system call. */
5437 env->lr = (target_ulong) h2g(frame->mctx.tramp);
5438
5439 /* Turn off all fp exceptions. */
5440 env->fpscr = 0;
5441
5442 /* Create a stack frame for the caller of the handler. */
5443 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00005444 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005445
5446 if (err)
5447 goto sigsegv;
5448
5449 /* Set up registers for signal handler. */
5450 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005451 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00005452 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05005453
Nathan Froydbcd49332009-05-12 19:13:18 -07005454 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005455
Nathan Froydbcd49332009-05-12 19:13:18 -07005456 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005457 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005458
5459 unlock_user_struct(frame, frame_addr, 1);
5460 return;
5461
5462sigsegv:
5463 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005464 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005465}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005466#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005467
5468static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005469 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005470 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005471{
5472 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05005473 uint32_t *trampptr = 0;
5474 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005475 target_ulong rt_sf_addr, newsp = 0;
5476 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05005477#if defined(TARGET_PPC64)
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005478 struct target_sigcontext *sc = 0;
Tom Musta14585582014-06-30 08:13:42 -05005479 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
5480#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005481
5482 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
5483 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
5484 goto sigsegv;
5485
Peter Maydellf6c7a052015-01-08 12:19:48 +00005486 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07005487
Riku Voipio1d8b5122014-04-23 10:26:05 +03005488 __put_user(0, &rt_sf->uc.tuc_flags);
5489 __put_user(0, &rt_sf->uc.tuc_link);
5490 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
5491 &rt_sf->uc.tuc_stack.ss_sp);
5492 __put_user(sas_ss_flags(env->gpr[1]),
5493 &rt_sf->uc.tuc_stack.ss_flags);
5494 __put_user(target_sigaltstack_used.ss_size,
5495 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05005496#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03005497 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
5498 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05005499#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005500 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005501 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005502 }
5503
Tom Musta61e75fe2014-06-30 08:13:38 -05005504#if defined(TARGET_PPC64)
5505 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
5506 trampptr = &rt_sf->trampoline[0];
Jose Ricardo Ziviani26920a22017-01-31 20:05:17 -02005507
5508 sc = &rt_sf->uc.tuc_sigcontext;
5509 __put_user(h2g(mctx), &sc->regs);
5510 __put_user(sig, &sc->signal);
Tom Musta61e75fe2014-06-30 08:13:38 -05005511#else
5512 mctx = &rt_sf->uc.tuc_mcontext;
5513 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
5514#endif
5515
5516 save_user_regs(env, mctx);
5517 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005518
5519 /* The kernel checks for the presence of a VDSO here. We don't
5520 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05005521 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07005522
5523 /* Turn off all fp exceptions. */
5524 env->fpscr = 0;
5525
5526 /* Create a stack frame for the caller of the handler. */
5527 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05005528 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07005529
5530 if (err)
5531 goto sigsegv;
5532
5533 /* Set up registers for signal handler. */
5534 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00005535 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07005536 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
5537 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
5538 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05005539
5540#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05005541 if (get_ppc64_abi(image) < 2) {
5542 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
5543 struct target_func_ptr *handler =
5544 (struct target_func_ptr *)g2h(ka->_sa_handler);
5545 env->nip = tswapl(handler->entry);
5546 env->gpr[2] = tswapl(handler->toc);
5547 } else {
5548 /* ELFv2 PPC64 function pointers are entry points, but R12
5549 * must also be set */
5550 env->nip = tswapl((target_ulong) ka->_sa_handler);
5551 env->gpr[12] = env->nip;
5552 }
Tom Musta8d6ab332014-06-30 08:13:39 -05005553#else
Nathan Froydbcd49332009-05-12 19:13:18 -07005554 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05005555#endif
5556
Nathan Froydbcd49332009-05-12 19:13:18 -07005557 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02005558 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07005559
5560 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5561 return;
5562
5563sigsegv:
5564 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01005565 force_sigsegv(sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005566
5567}
5568
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005569#if !defined(TARGET_PPC64)
Andreas Färber05390242012-02-25 03:37:53 +01005570long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005571{
5572 struct target_sigcontext *sc = NULL;
5573 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01005574 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07005575 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005576 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005577
5578 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
5579 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
5580 goto sigsegv;
5581
5582#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05005583 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07005584#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03005585 __get_user(set.sig[0], &sc->oldmask);
5586 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07005587#endif
5588 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005589 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07005590
Riku Voipiof5f601a2014-04-23 13:00:17 +03005591 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07005592 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
5593 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03005594 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07005595
5596 unlock_user_struct(sr, sr_addr, 1);
5597 unlock_user_struct(sc, sc_addr, 1);
5598 return -TARGET_QEMU_ESIGRETURN;
5599
5600sigsegv:
5601 unlock_user_struct(sr, sr_addr, 1);
5602 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005603 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005604 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005605}
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10005606#endif /* !defined(TARGET_PPC64) */
Nathan Froydbcd49332009-05-12 19:13:18 -07005607
5608/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01005609static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07005610{
5611 struct target_mcontext *mcp;
5612 target_ulong mcp_addr;
5613 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05005614 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07005615
Aurelien Jarno60e99242010-03-29 02:12:51 +02005616 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07005617 sizeof (set)))
5618 return 1;
5619
Tom Musta19774ec2014-06-30 08:13:40 -05005620#if defined(TARGET_PPC64)
5621 mcp_addr = h2g(ucp) +
5622 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
5623#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03005624 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05005625#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07005626
5627 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
5628 return 1;
5629
5630 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005631 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03005632 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07005633
5634 unlock_user_struct(mcp, mcp_addr, 1);
5635 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07005636}
5637
Andreas Färber05390242012-02-25 03:37:53 +01005638long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07005639{
5640 struct target_rt_sigframe *rt_sf = NULL;
5641 target_ulong rt_sf_addr;
5642
5643 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
5644 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
5645 goto sigsegv;
5646
5647 if (do_setcontext(&rt_sf->uc, env, 1))
5648 goto sigsegv;
5649
5650 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02005651 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07005652 0, env->gpr[1]);
5653
5654 unlock_user_struct(rt_sf, rt_sf_addr, 1);
5655 return -TARGET_QEMU_ESIGRETURN;
5656
5657sigsegv:
5658 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005659 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01005660 return -TARGET_QEMU_ESIGRETURN;
Nathan Froydbcd49332009-05-12 19:13:18 -07005661}
5662
Laurent Vivier492a8742009-08-03 16:12:17 +02005663#elif defined(TARGET_M68K)
5664
5665struct target_sigcontext {
5666 abi_ulong sc_mask;
5667 abi_ulong sc_usp;
5668 abi_ulong sc_d0;
5669 abi_ulong sc_d1;
5670 abi_ulong sc_a0;
5671 abi_ulong sc_a1;
5672 unsigned short sc_sr;
5673 abi_ulong sc_pc;
5674};
5675
5676struct target_sigframe
5677{
5678 abi_ulong pretcode;
5679 int sig;
5680 int code;
5681 abi_ulong psc;
5682 char retcode[8];
5683 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5684 struct target_sigcontext sc;
5685};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005686
Anthony Liguoric227f092009-10-01 16:12:16 -05005687typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005688#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05005689typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02005690
5691typedef struct target_fpregset {
5692 int f_fpcntl[3];
5693 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05005694} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02005695
5696struct target_mcontext {
5697 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05005698 target_gregset_t gregs;
5699 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005700};
5701
5702#define TARGET_MCONTEXT_VERSION 2
5703
5704struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005705 abi_ulong tuc_flags;
5706 abi_ulong tuc_link;
5707 target_stack_t tuc_stack;
5708 struct target_mcontext tuc_mcontext;
5709 abi_long tuc_filler[80];
5710 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005711};
5712
5713struct target_rt_sigframe
5714{
5715 abi_ulong pretcode;
5716 int sig;
5717 abi_ulong pinfo;
5718 abi_ulong puc;
5719 char retcode[8];
5720 struct target_siginfo info;
5721 struct target_ucontext uc;
5722};
Laurent Vivier492a8742009-08-03 16:12:17 +02005723
Riku Voipio41ecc722014-04-23 11:01:00 +03005724static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005725 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005726{
Laurent Vivieref597602018-01-04 02:28:59 +01005727 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005728 __put_user(mask, &sc->sc_mask);
5729 __put_user(env->aregs[7], &sc->sc_usp);
5730 __put_user(env->dregs[0], &sc->sc_d0);
5731 __put_user(env->dregs[1], &sc->sc_d1);
5732 __put_user(env->aregs[0], &sc->sc_a0);
5733 __put_user(env->aregs[1], &sc->sc_a1);
Laurent Vivieref597602018-01-04 02:28:59 +01005734 __put_user(sr, &sc->sc_sr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005735 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005736}
5737
Riku Voipio016d2e12014-04-23 11:19:48 +03005738static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005739restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005740{
Laurent Vivier492a8742009-08-03 16:12:17 +02005741 int temp;
5742
Riku Voipio1d8b5122014-04-23 10:26:05 +03005743 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005744 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005745 __get_user(env->dregs[1], &sc->sc_d1);
5746 __get_user(env->aregs[0], &sc->sc_a0);
5747 __get_user(env->aregs[1], &sc->sc_a1);
5748 __get_user(env->pc, &sc->sc_pc);
5749 __get_user(temp, &sc->sc_sr);
Laurent Vivieref597602018-01-04 02:28:59 +01005750 cpu_m68k_set_ccr(env, temp);
Laurent Vivier492a8742009-08-03 16:12:17 +02005751}
5752
5753/*
5754 * Determine which stack to use..
5755 */
5756static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005757get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5758 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005759{
5760 unsigned long sp;
5761
5762 sp = regs->aregs[7];
5763
5764 /* This is the X/Open sanctioned signal stack switching. */
5765 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5766 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5767 }
5768
5769 return ((sp - frame_size) & -8UL);
5770}
5771
5772static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005773 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005774{
5775 struct target_sigframe *frame;
5776 abi_ulong frame_addr;
5777 abi_ulong retcode_addr;
5778 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005779 int i;
5780
5781 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005782 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005783 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5784 goto give_sigsegv;
5785 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005786
Riku Voipio1d8b5122014-04-23 10:26:05 +03005787 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005788
5789 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005790 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005791
Riku Voipio41ecc722014-04-23 11:01:00 +03005792 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005793
5794 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005795 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005796 }
5797
5798 /* Set up to return from userspace. */
5799
5800 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005801 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005802
5803 /* moveq #,d0; trap #0 */
5804
Riku Voipio1d8b5122014-04-23 10:26:05 +03005805 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005806 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005807
Laurent Vivier492a8742009-08-03 16:12:17 +02005808 /* Set up to return from userspace */
5809
5810 env->aregs[7] = frame_addr;
5811 env->pc = ka->_sa_handler;
5812
5813 unlock_user_struct(frame, frame_addr, 1);
5814 return;
5815
5816give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01005817 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005818}
5819
Laurent Vivieree46a462017-09-14 18:35:05 +02005820static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
5821 CPUM68KState *env)
5822{
5823 int i;
5824 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5825
5826 __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
5827 __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
5828 /* fpiar is not emulated */
5829
5830 for (i = 0; i < 8; i++) {
5831 uint32_t high = env->fregs[i].d.high << 16;
5832 __put_user(high, &fpregs->f_fpregs[i * 3]);
5833 __put_user(env->fregs[i].d.low,
5834 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5835 }
5836}
5837
Laurent Vivier71811552009-08-03 16:12:18 +02005838static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005839 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005840{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005841 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivieref597602018-01-04 02:28:59 +01005842 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
Laurent Vivier71811552009-08-03 16:12:18 +02005843
Riku Voipio1d8b5122014-04-23 10:26:05 +03005844 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5845 __put_user(env->dregs[0], &gregs[0]);
5846 __put_user(env->dregs[1], &gregs[1]);
5847 __put_user(env->dregs[2], &gregs[2]);
5848 __put_user(env->dregs[3], &gregs[3]);
5849 __put_user(env->dregs[4], &gregs[4]);
5850 __put_user(env->dregs[5], &gregs[5]);
5851 __put_user(env->dregs[6], &gregs[6]);
5852 __put_user(env->dregs[7], &gregs[7]);
5853 __put_user(env->aregs[0], &gregs[8]);
5854 __put_user(env->aregs[1], &gregs[9]);
5855 __put_user(env->aregs[2], &gregs[10]);
5856 __put_user(env->aregs[3], &gregs[11]);
5857 __put_user(env->aregs[4], &gregs[12]);
5858 __put_user(env->aregs[5], &gregs[13]);
5859 __put_user(env->aregs[6], &gregs[14]);
5860 __put_user(env->aregs[7], &gregs[15]);
5861 __put_user(env->pc, &gregs[16]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005862 __put_user(sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005863
Laurent Vivieree46a462017-09-14 18:35:05 +02005864 target_rt_save_fpu_state(uc, env);
5865
Riku Voipio1d8b5122014-04-23 10:26:05 +03005866 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005867}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005868
Laurent Vivieree46a462017-09-14 18:35:05 +02005869static inline void target_rt_restore_fpu_state(CPUM68KState *env,
5870 struct target_ucontext *uc)
5871{
5872 int i;
5873 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
5874 uint32_t fpcr;
5875
5876 __get_user(fpcr, &fpregs->f_fpcntl[0]);
5877 cpu_m68k_set_fpcr(env, fpcr);
5878 __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
5879 /* fpiar is not emulated */
5880
5881 for (i = 0; i < 8; i++) {
5882 uint32_t high;
5883 __get_user(high, &fpregs->f_fpregs[i * 3]);
5884 env->fregs[i].d.high = high >> 16;
5885 __get_user(env->fregs[i].d.low,
5886 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
5887 }
5888}
5889
Andreas Färber05390242012-02-25 03:37:53 +01005890static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005891 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005892{
5893 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005894 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005895
Riku Voipio1d8b5122014-04-23 10:26:05 +03005896 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005897 if (temp != TARGET_MCONTEXT_VERSION)
5898 goto badframe;
5899
5900 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005901 __get_user(env->dregs[0], &gregs[0]);
5902 __get_user(env->dregs[1], &gregs[1]);
5903 __get_user(env->dregs[2], &gregs[2]);
5904 __get_user(env->dregs[3], &gregs[3]);
5905 __get_user(env->dregs[4], &gregs[4]);
5906 __get_user(env->dregs[5], &gregs[5]);
5907 __get_user(env->dregs[6], &gregs[6]);
5908 __get_user(env->dregs[7], &gregs[7]);
5909 __get_user(env->aregs[0], &gregs[8]);
5910 __get_user(env->aregs[1], &gregs[9]);
5911 __get_user(env->aregs[2], &gregs[10]);
5912 __get_user(env->aregs[3], &gregs[11]);
5913 __get_user(env->aregs[4], &gregs[12]);
5914 __get_user(env->aregs[5], &gregs[13]);
5915 __get_user(env->aregs[6], &gregs[14]);
5916 __get_user(env->aregs[7], &gregs[15]);
5917 __get_user(env->pc, &gregs[16]);
5918 __get_user(temp, &gregs[17]);
Laurent Vivier3219de42017-02-25 12:05:16 +01005919 cpu_m68k_set_ccr(env, temp);
Laurent Vivier71811552009-08-03 16:12:18 +02005920
Laurent Vivieree46a462017-09-14 18:35:05 +02005921 target_rt_restore_fpu_state(env, uc);
5922
Riku Voipio1d8b5122014-04-23 10:26:05 +03005923 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005924
5925badframe:
5926 return 1;
5927}
5928
Laurent Vivier492a8742009-08-03 16:12:17 +02005929static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005930 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005931 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005932{
Laurent Vivier71811552009-08-03 16:12:18 +02005933 struct target_rt_sigframe *frame;
5934 abi_ulong frame_addr;
5935 abi_ulong retcode_addr;
5936 abi_ulong info_addr;
5937 abi_ulong uc_addr;
5938 int err = 0;
5939 int i;
5940
5941 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005942 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005943 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5944 goto give_sigsegv;
5945 }
Laurent Vivier71811552009-08-03 16:12:18 +02005946
Riku Voipio1d8b5122014-04-23 10:26:05 +03005947 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005948
5949 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005950 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005951
5952 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005953 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005954
Peter Maydellf6c7a052015-01-08 12:19:48 +00005955 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005956
5957 /* Create the ucontext */
5958
Riku Voipio1d8b5122014-04-23 10:26:05 +03005959 __put_user(0, &frame->uc.tuc_flags);
5960 __put_user(0, &frame->uc.tuc_link);
5961 __put_user(target_sigaltstack_used.ss_sp,
5962 &frame->uc.tuc_stack.ss_sp);
5963 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005964 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005965 __put_user(target_sigaltstack_used.ss_size,
5966 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005967 err |= target_rt_setup_ucontext(&frame->uc, env);
5968
5969 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005970 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005971
5972 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005973 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005974 }
5975
5976 /* Set up to return from userspace. */
5977
5978 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005979 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005980
5981 /* moveq #,d0; notb d0; trap #0 */
5982
Riku Voipio1d8b5122014-04-23 10:26:05 +03005983 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005984 (uint32_t *)(frame->retcode + 0));
5985 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005986
5987 if (err)
5988 goto give_sigsegv;
5989
5990 /* Set up to return from userspace */
5991
5992 env->aregs[7] = frame_addr;
5993 env->pc = ka->_sa_handler;
5994
5995 unlock_user_struct(frame, frame_addr, 1);
5996 return;
5997
5998give_sigsegv:
5999 unlock_user_struct(frame, frame_addr, 1);
Peter Maydell09391662016-07-28 16:44:47 +01006000 force_sigsegv(sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02006001}
6002
Andreas Färber05390242012-02-25 03:37:53 +01006003long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006004{
6005 struct target_sigframe *frame;
6006 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05006007 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02006008 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006009 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02006010
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006011 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02006012 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6013 goto badframe;
6014
6015 /* set blocked signals */
6016
Riku Voipiof5f601a2014-04-23 13:00:17 +03006017 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02006018
6019 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03006020 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02006021 }
6022
6023 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006024 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02006025
6026 /* restore registers */
6027
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006028 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02006029
6030 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006031 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006032
6033badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02006034 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006035 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006036}
6037
Andreas Färber05390242012-02-25 03:37:53 +01006038long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02006039{
Laurent Vivier71811552009-08-03 16:12:18 +02006040 struct target_rt_sigframe *frame;
6041 abi_ulong frame_addr = env->aregs[7] - 4;
Laurent Vivier71811552009-08-03 16:12:18 +02006042 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02006043
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006044 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02006045 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
6046 goto badframe;
6047
Michael Karcher59ebb6e2017-02-25 12:05:17 +01006048 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006049 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02006050
6051 /* restore registers */
6052
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006053 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02006054 goto badframe;
6055
6056 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02006057 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02006058 0, get_sp_from_cpustate(env)) == -EFAULT)
6059 goto badframe;
6060
6061 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01006062 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02006063
6064badframe:
6065 unlock_user_struct(frame, frame_addr, 0);
6066 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006067 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02006068}
6069
Richard Henderson6049f4f2009-12-27 18:30:03 -08006070#elif defined(TARGET_ALPHA)
6071
6072struct target_sigcontext {
6073 abi_long sc_onstack;
6074 abi_long sc_mask;
6075 abi_long sc_pc;
6076 abi_long sc_ps;
6077 abi_long sc_regs[32];
6078 abi_long sc_ownedfp;
6079 abi_long sc_fpregs[32];
6080 abi_ulong sc_fpcr;
6081 abi_ulong sc_fp_control;
6082 abi_ulong sc_reserved1;
6083 abi_ulong sc_reserved2;
6084 abi_ulong sc_ssize;
6085 abi_ulong sc_sbase;
6086 abi_ulong sc_traparg_a0;
6087 abi_ulong sc_traparg_a1;
6088 abi_ulong sc_traparg_a2;
6089 abi_ulong sc_fp_trap_pc;
6090 abi_ulong sc_fp_trigger_sum;
6091 abi_ulong sc_fp_trigger_inst;
6092};
6093
6094struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02006095 abi_ulong tuc_flags;
6096 abi_ulong tuc_link;
6097 abi_ulong tuc_osf_sigmask;
6098 target_stack_t tuc_stack;
6099 struct target_sigcontext tuc_mcontext;
6100 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006101};
6102
6103struct target_sigframe {
6104 struct target_sigcontext sc;
6105 unsigned int retcode[3];
6106};
6107
6108struct target_rt_sigframe {
6109 target_siginfo_t info;
6110 struct target_ucontext uc;
6111 unsigned int retcode[3];
6112};
6113
6114#define INSN_MOV_R30_R16 0x47fe0410
6115#define INSN_LDI_R0 0x201f0000
6116#define INSN_CALLSYS 0x00000083
6117
Riku Voipio41ecc722014-04-23 11:01:00 +03006118static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006119 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006120{
Riku Voipio41ecc722014-04-23 11:01:00 +03006121 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006122
Riku Voipio1d8b5122014-04-23 10:26:05 +03006123 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
6124 __put_user(set->sig[0], &sc->sc_mask);
6125 __put_user(env->pc, &sc->sc_pc);
6126 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006127
6128 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006129 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006130 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006131 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006132
6133 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006134 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006135 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03006136 __put_user(0, &sc->sc_fpregs[31]);
6137 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006138
Riku Voipio1d8b5122014-04-23 10:26:05 +03006139 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
6140 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
6141 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08006142}
6143
Riku Voipio016d2e12014-04-23 11:19:48 +03006144static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006145 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006146{
6147 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03006148 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006149
Riku Voipio1d8b5122014-04-23 10:26:05 +03006150 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006151
6152 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006153 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006154 }
6155 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006156 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006157 }
6158
Riku Voipio1d8b5122014-04-23 10:26:05 +03006159 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006160 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006161}
6162
6163static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01006164 CPUAlphaState *env,
6165 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006166{
6167 abi_ulong sp = env->ir[IR_SP];
6168
6169 /* This is the X/Open sanctioned signal stack switching. */
6170 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
6171 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6172 }
6173 return (sp - framesize) & -32;
6174}
6175
6176static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01006177 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006178{
6179 abi_ulong frame_addr, r26;
6180 struct target_sigframe *frame;
6181 int err = 0;
6182
6183 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006184 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006185 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6186 goto give_sigsegv;
6187 }
6188
Riku Voipio41ecc722014-04-23 11:01:00 +03006189 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006190
6191 if (ka->sa_restorer) {
6192 r26 = ka->sa_restorer;
6193 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006194 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6195 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
6196 &frame->retcode[1]);
6197 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006198 /* imb() */
6199 r26 = frame_addr;
6200 }
6201
6202 unlock_user_struct(frame, frame_addr, 1);
6203
6204 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006205give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006206 force_sigsegv(sig);
6207 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006208 }
6209
6210 env->ir[IR_RA] = r26;
6211 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6212 env->ir[IR_A0] = sig;
6213 env->ir[IR_A1] = 0;
6214 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
6215 env->ir[IR_SP] = frame_addr;
6216}
6217
6218static void setup_rt_frame(int sig, struct target_sigaction *ka,
6219 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01006220 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006221{
6222 abi_ulong frame_addr, r26;
6223 struct target_rt_sigframe *frame;
6224 int i, err = 0;
6225
6226 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006227 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006228 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6229 goto give_sigsegv;
6230 }
6231
Peter Maydellf6c7a052015-01-08 12:19:48 +00006232 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006233
Riku Voipio1d8b5122014-04-23 10:26:05 +03006234 __put_user(0, &frame->uc.tuc_flags);
6235 __put_user(0, &frame->uc.tuc_link);
6236 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
6237 __put_user(target_sigaltstack_used.ss_sp,
6238 &frame->uc.tuc_stack.ss_sp);
6239 __put_user(sas_ss_flags(env->ir[IR_SP]),
6240 &frame->uc.tuc_stack.ss_flags);
6241 __put_user(target_sigaltstack_used.ss_size,
6242 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03006243 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006244 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006245 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006246 }
6247
6248 if (ka->sa_restorer) {
6249 r26 = ka->sa_restorer;
6250 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03006251 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
6252 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
6253 &frame->retcode[1]);
6254 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006255 /* imb(); */
6256 r26 = frame_addr;
6257 }
6258
6259 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006260give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006261 force_sigsegv(sig);
6262 return;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006263 }
6264
6265 env->ir[IR_RA] = r26;
6266 env->ir[IR_PV] = env->pc = ka->_sa_handler;
6267 env->ir[IR_A0] = sig;
6268 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6269 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6270 env->ir[IR_SP] = frame_addr;
6271}
6272
Andreas Färber05390242012-02-25 03:37:53 +01006273long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006274{
6275 struct target_sigcontext *sc;
6276 abi_ulong sc_addr = env->ir[IR_A0];
6277 target_sigset_t target_set;
6278 sigset_t set;
6279
6280 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
6281 goto badframe;
6282 }
6283
6284 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03006285 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006286
6287 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006288 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006289
Riku Voipio016d2e12014-04-23 11:19:48 +03006290 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006291 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006292 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006293
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006294badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006295 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006296 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006297}
6298
Andreas Färber05390242012-02-25 03:37:53 +01006299long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08006300{
6301 abi_ulong frame_addr = env->ir[IR_A0];
6302 struct target_rt_sigframe *frame;
6303 sigset_t set;
6304
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006305 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006306 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6307 goto badframe;
6308 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02006309 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006310 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006311
Riku Voipio016d2e12014-04-23 11:19:48 +03006312 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08006313 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02006314 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08006315 0, env->ir[IR_SP]) == -EFAULT) {
6316 goto badframe;
6317 }
6318
6319 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01006320 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006321
6322
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006323badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08006324 unlock_user_struct(frame, frame_addr, 0);
6325 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006326 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08006327}
6328
Chen Gangbf0f60a2015-09-27 08:10:18 +08006329#elif defined(TARGET_TILEGX)
6330
6331struct target_sigcontext {
6332 union {
6333 /* General-purpose registers. */
6334 abi_ulong gregs[56];
6335 struct {
6336 abi_ulong __gregs[53];
6337 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
6338 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
6339 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
6340 };
6341 };
6342 abi_ulong pc; /* Program counter. */
6343 abi_ulong ics; /* In Interrupt Critical Section? */
6344 abi_ulong faultnum; /* Fault number. */
6345 abi_ulong pad[5];
6346};
6347
6348struct target_ucontext {
6349 abi_ulong tuc_flags;
6350 abi_ulong tuc_link;
6351 target_stack_t tuc_stack;
6352 struct target_sigcontext tuc_mcontext;
6353 target_sigset_t tuc_sigmask; /* mask last for extensibility */
6354};
6355
6356struct target_rt_sigframe {
6357 unsigned char save_area[16]; /* caller save area */
6358 struct target_siginfo info;
6359 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08006360 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08006361};
6362
Chen Gangf1d9d102016-03-29 21:53:49 +08006363#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
6364#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
6365
6366
Chen Gangbf0f60a2015-09-27 08:10:18 +08006367static void setup_sigcontext(struct target_sigcontext *sc,
6368 CPUArchState *env, int signo)
6369{
6370 int i;
6371
6372 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6373 __put_user(env->regs[i], &sc->gregs[i]);
6374 }
6375
6376 __put_user(env->pc, &sc->pc);
6377 __put_user(0, &sc->ics);
6378 __put_user(signo, &sc->faultnum);
6379}
6380
6381static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
6382{
6383 int i;
6384
6385 for (i = 0; i < TILEGX_R_COUNT; ++i) {
6386 __get_user(env->regs[i], &sc->gregs[i]);
6387 }
6388
6389 __get_user(env->pc, &sc->pc);
6390}
6391
6392static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
6393 size_t frame_size)
6394{
6395 unsigned long sp = env->regs[TILEGX_R_SP];
6396
6397 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
6398 return -1UL;
6399 }
6400
6401 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
6402 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6403 }
6404
6405 sp -= frame_size;
6406 sp &= -16UL;
6407 return sp;
6408}
6409
6410static void setup_rt_frame(int sig, struct target_sigaction *ka,
6411 target_siginfo_t *info,
6412 target_sigset_t *set, CPUArchState *env)
6413{
6414 abi_ulong frame_addr;
6415 struct target_rt_sigframe *frame;
6416 unsigned long restorer;
6417
6418 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006419 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006420 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6421 goto give_sigsegv;
6422 }
6423
6424 /* Always write at least the signal number for the stack backtracer. */
6425 if (ka->sa_flags & TARGET_SA_SIGINFO) {
6426 /* At sigreturn time, restore the callee-save registers too. */
6427 tswap_siginfo(&frame->info, info);
6428 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
6429 } else {
6430 __put_user(info->si_signo, &frame->info.si_signo);
6431 }
6432
6433 /* Create the ucontext. */
6434 __put_user(0, &frame->uc.tuc_flags);
6435 __put_user(0, &frame->uc.tuc_link);
6436 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6437 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
6438 &frame->uc.tuc_stack.ss_flags);
6439 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
6440 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
6441
Chen Gangbf0f60a2015-09-27 08:10:18 +08006442 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08006443 restorer = (unsigned long) ka->sa_restorer;
6444 } else {
6445 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
6446 __put_user(INSN_SWINT1, &frame->retcode[1]);
6447 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006448 }
6449 env->pc = (unsigned long) ka->_sa_handler;
6450 env->regs[TILEGX_R_SP] = (unsigned long) frame;
6451 env->regs[TILEGX_R_LR] = restorer;
6452 env->regs[0] = (unsigned long) sig;
6453 env->regs[1] = (unsigned long) &frame->info;
6454 env->regs[2] = (unsigned long) &frame->uc;
6455 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
6456
6457 unlock_user_struct(frame, frame_addr, 1);
6458 return;
6459
6460give_sigsegv:
Peter Maydell09391662016-07-28 16:44:47 +01006461 force_sigsegv(sig);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006462}
6463
6464long do_rt_sigreturn(CPUTLGState *env)
6465{
6466 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
6467 struct target_rt_sigframe *frame;
6468 sigset_t set;
6469
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006470 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006471 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6472 goto badframe;
6473 }
6474 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01006475 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08006476
6477 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6478 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6479 uc.tuc_stack),
6480 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
6481 goto badframe;
6482 }
6483
6484 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01006485 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006486
6487
6488 badframe:
6489 unlock_user_struct(frame, frame_addr, 0);
6490 force_sig(TARGET_SIGSEGV);
Peter Maydellc599d4d2016-07-28 16:44:49 +01006491 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08006492}
6493
Michael Clark47ae93c2018-03-03 01:31:11 +13006494#elif defined(TARGET_RISCV)
6495
6496/* Signal handler invocation must be transparent for the code being
6497 interrupted. Complete CPU (hart) state is saved on entry and restored
6498 before returning from the handler. Process sigmask is also saved to block
6499 signals while the handler is running. The handler gets its own stack,
6500 which also doubles as storage for the CPU state and sigmask.
6501
6502 The code below is qemu re-implementation of arch/riscv/kernel/signal.c */
6503
6504struct target_sigcontext {
6505 abi_long pc;
6506 abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
6507 uint64_t fpr[32];
6508 uint32_t fcsr;
6509}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
6510
6511struct target_ucontext {
6512 unsigned long uc_flags;
6513 struct target_ucontext *uc_link;
6514 target_stack_t uc_stack;
6515 struct target_sigcontext uc_mcontext;
6516 target_sigset_t uc_sigmask;
6517};
6518
6519struct target_rt_sigframe {
6520 uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
6521 struct target_siginfo info;
6522 struct target_ucontext uc;
6523};
6524
6525static abi_ulong get_sigframe(struct target_sigaction *ka,
6526 CPURISCVState *regs, size_t framesize)
6527{
6528 abi_ulong sp = regs->gpr[xSP];
6529 int onsigstack = on_sig_stack(sp);
6530
6531 /* redzone */
6532 /* This is the X/Open sanctioned signal stack switching. */
6533 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
6534 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6535 }
6536
6537 sp -= framesize;
6538 sp &= ~3UL; /* align sp on 4-byte boundary */
6539
6540 /* If we are on the alternate signal stack and would overflow it, don't.
6541 Return an always-bogus address instead so we will die with SIGSEGV. */
6542 if (onsigstack && !likely(on_sig_stack(sp))) {
6543 return -1L;
6544 }
6545
6546 return sp;
6547}
6548
6549static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
6550{
6551 int i;
6552
6553 __put_user(env->pc, &sc->pc);
6554
6555 for (i = 1; i < 32; i++) {
6556 __put_user(env->gpr[i], &sc->gpr[i - 1]);
6557 }
6558 for (i = 0; i < 32; i++) {
6559 __put_user(env->fpr[i], &sc->fpr[i]);
6560 }
6561
6562 uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
6563 __put_user(fcsr, &sc->fcsr);
6564}
6565
6566static void setup_ucontext(struct target_ucontext *uc,
6567 CPURISCVState *env, target_sigset_t *set)
6568{
6569 abi_ulong ss_sp = (target_ulong)target_sigaltstack_used.ss_sp;
6570 abi_ulong ss_flags = sas_ss_flags(env->gpr[xSP]);
6571 abi_ulong ss_size = target_sigaltstack_used.ss_size;
6572
6573 __put_user(0, &(uc->uc_flags));
6574 __put_user(0, &(uc->uc_link));
6575
6576 __put_user(ss_sp, &(uc->uc_stack.ss_sp));
6577 __put_user(ss_flags, &(uc->uc_stack.ss_flags));
6578 __put_user(ss_size, &(uc->uc_stack.ss_size));
6579
6580 int i;
6581 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6582 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
6583 }
6584
6585 setup_sigcontext(&uc->uc_mcontext, env);
6586}
6587
6588static inline void install_sigtramp(uint32_t *tramp)
6589{
6590 __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */
6591 __put_user(0x00000073, tramp + 1); /* ecall */
6592}
6593
6594static void setup_rt_frame(int sig, struct target_sigaction *ka,
6595 target_siginfo_t *info,
6596 target_sigset_t *set, CPURISCVState *env)
6597{
6598 abi_ulong frame_addr;
6599 struct target_rt_sigframe *frame;
6600
6601 frame_addr = get_sigframe(ka, env, sizeof(*frame));
6602 trace_user_setup_rt_frame(env, frame_addr);
6603
6604 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6605 goto badframe;
6606 }
6607
6608 setup_ucontext(&frame->uc, env, set);
6609 tswap_siginfo(&frame->info, info);
6610 install_sigtramp(frame->tramp);
6611
6612 env->pc = ka->_sa_handler;
6613 env->gpr[xSP] = frame_addr;
6614 env->gpr[xA0] = sig;
6615 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
6616 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
6617 env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
6618
6619 return;
6620
6621badframe:
6622 unlock_user_struct(frame, frame_addr, 1);
6623 if (sig == TARGET_SIGSEGV) {
6624 ka->_sa_handler = TARGET_SIG_DFL;
6625 }
6626 force_sig(TARGET_SIGSEGV);
6627}
6628
6629static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
6630{
6631 int i;
6632
6633 __get_user(env->pc, &sc->pc);
6634
6635 for (i = 1; i < 32; ++i) {
6636 __get_user(env->gpr[i], &sc->gpr[i - 1]);
6637 }
6638 for (i = 0; i < 32; ++i) {
6639 __get_user(env->fpr[i], &sc->fpr[i]);
6640 }
6641
6642 uint32_t fcsr;
6643 __get_user(fcsr, &sc->fcsr);
6644 csr_write_helper(env, fcsr, CSR_FCSR);
6645}
6646
6647static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
6648{
6649 sigset_t blocked;
6650 target_sigset_t target_set;
6651 int i;
6652
6653 target_sigemptyset(&target_set);
6654 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6655 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
6656 }
6657
6658 target_to_host_sigset_internal(&blocked, &target_set);
6659 set_sigmask(&blocked);
6660
6661 restore_sigcontext(env, &uc->uc_mcontext);
6662}
6663
6664long do_rt_sigreturn(CPURISCVState *env)
6665{
6666 struct target_rt_sigframe *frame;
6667 abi_ulong frame_addr;
6668
6669 frame_addr = env->gpr[xSP];
6670 trace_user_do_sigreturn(env, frame_addr);
6671 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6672 goto badframe;
6673 }
6674
6675 restore_ucontext(env, &frame->uc);
6676
6677 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6678 uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
6679 goto badframe;
6680 }
6681
6682 unlock_user_struct(frame, frame_addr, 0);
6683 return -TARGET_QEMU_ESIGRETURN;
6684
6685badframe:
6686 unlock_user_struct(frame, frame_addr, 0);
6687 force_sig(TARGET_SIGSEGV);
6688 return 0;
6689}
6690
Richard Henderson1659e382016-12-15 09:59:01 -08006691#elif defined(TARGET_HPPA)
6692
6693struct target_sigcontext {
6694 abi_ulong sc_flags;
6695 abi_ulong sc_gr[32];
6696 uint64_t sc_fr[32];
6697 abi_ulong sc_iasq[2];
6698 abi_ulong sc_iaoq[2];
6699 abi_ulong sc_sar;
6700};
6701
6702struct target_ucontext {
6703 abi_uint tuc_flags;
6704 abi_ulong tuc_link;
6705 target_stack_t tuc_stack;
6706 abi_uint pad[1];
6707 struct target_sigcontext tuc_mcontext;
6708 target_sigset_t tuc_sigmask;
6709};
6710
6711struct target_rt_sigframe {
6712 abi_uint tramp[9];
6713 target_siginfo_t info;
6714 struct target_ucontext uc;
6715 /* hidden location of upper halves of pa2.0 64-bit gregs */
6716};
6717
6718static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
6719{
6720 int flags = 0;
6721 int i;
6722
6723 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
6724
6725 if (env->iaoq_f < TARGET_PAGE_SIZE) {
6726 /* In the gateway page, executing a syscall. */
6727 flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
6728 __put_user(env->gr[31], &sc->sc_iaoq[0]);
6729 __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
6730 } else {
6731 __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
6732 __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
6733 }
6734 __put_user(0, &sc->sc_iasq[0]);
6735 __put_user(0, &sc->sc_iasq[1]);
6736 __put_user(flags, &sc->sc_flags);
6737
6738 __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
6739 for (i = 1; i < 32; ++i) {
6740 __put_user(env->gr[i], &sc->sc_gr[i]);
6741 }
6742
6743 __put_user((uint64_t)env->fr0_shadow << 32, &sc->sc_fr[0]);
6744 for (i = 1; i < 32; ++i) {
6745 __put_user(env->fr[i], &sc->sc_fr[i]);
6746 }
6747
Richard Henderson35136a72017-10-10 21:19:34 -07006748 __put_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006749}
6750
6751static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
6752{
6753 target_ulong psw;
6754 int i;
6755
6756 __get_user(psw, &sc->sc_gr[0]);
6757 cpu_hppa_put_psw(env, psw);
6758
6759 for (i = 1; i < 32; ++i) {
6760 __get_user(env->gr[i], &sc->sc_gr[i]);
6761 }
6762 for (i = 0; i < 32; ++i) {
6763 __get_user(env->fr[i], &sc->sc_fr[i]);
6764 }
6765 cpu_hppa_loaded_fr0(env);
6766
6767 __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
6768 __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
Richard Henderson35136a72017-10-10 21:19:34 -07006769 __get_user(env->cr[CR_SAR], &sc->sc_sar);
Richard Henderson1659e382016-12-15 09:59:01 -08006770}
6771
6772/* No, this doesn't look right, but it's copied straight from the kernel. */
6773#define PARISC_RT_SIGFRAME_SIZE32 \
6774 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
6775
6776static void setup_rt_frame(int sig, struct target_sigaction *ka,
6777 target_siginfo_t *info,
6778 target_sigset_t *set, CPUArchState *env)
6779{
6780 abi_ulong frame_addr, sp, haddr;
6781 struct target_rt_sigframe *frame;
6782 int i;
6783
6784 sp = env->gr[30];
6785 if (ka->sa_flags & TARGET_SA_ONSTACK) {
6786 if (sas_ss_flags(sp) == 0) {
6787 sp = (target_sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
6788 }
6789 }
6790 frame_addr = QEMU_ALIGN_UP(sp, 64);
6791 sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
6792
6793 trace_user_setup_rt_frame(env, frame_addr);
6794
6795 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
6796 goto give_sigsegv;
6797 }
6798
6799 tswap_siginfo(&frame->info, info);
6800 frame->uc.tuc_flags = 0;
6801 frame->uc.tuc_link = 0;
6802
6803 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
6804 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6805 &frame->uc.tuc_stack.ss_flags);
6806 __put_user(target_sigaltstack_used.ss_size,
6807 &frame->uc.tuc_stack.ss_size);
6808
6809 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
6810 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6811 }
6812
6813 setup_sigcontext(&frame->uc.tuc_mcontext, env);
6814
6815 __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
6816 __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
6817 __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
6818 __put_user(0x08000240, frame->tramp + 3); /* nop */
6819
6820 unlock_user_struct(frame, frame_addr, 1);
6821
6822 env->gr[2] = h2g(frame->tramp);
6823 env->gr[30] = sp;
6824 env->gr[26] = sig;
6825 env->gr[25] = h2g(&frame->info);
6826 env->gr[24] = h2g(&frame->uc);
6827
6828 haddr = ka->_sa_handler;
6829 if (haddr & 2) {
6830 /* Function descriptor. */
6831 target_ulong *fdesc, dest;
6832
6833 haddr &= -4;
6834 if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
6835 goto give_sigsegv;
6836 }
6837 __get_user(dest, fdesc);
6838 __get_user(env->gr[19], fdesc + 1);
6839 unlock_user_struct(fdesc, haddr, 1);
6840 haddr = dest;
6841 }
6842 env->iaoq_f = haddr;
Ladi Prosek3c254ab2017-10-17 16:40:51 +02006843 env->iaoq_b = haddr + 4;
Richard Henderson1659e382016-12-15 09:59:01 -08006844 return;
6845
6846 give_sigsegv:
6847 force_sigsegv(sig);
6848}
6849
6850long do_rt_sigreturn(CPUArchState *env)
6851{
6852 abi_ulong frame_addr = env->gr[30] - PARISC_RT_SIGFRAME_SIZE32;
6853 struct target_rt_sigframe *frame;
6854 sigset_t set;
6855
6856 trace_user_do_rt_sigreturn(env, frame_addr);
6857 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
6858 goto badframe;
6859 }
6860 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
6861 set_sigmask(&set);
6862
6863 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6864 unlock_user_struct(frame, frame_addr, 0);
6865
6866 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
6867 uc.tuc_stack),
6868 0, env->gr[30]) == -EFAULT) {
6869 goto badframe;
6870 }
6871
6872 unlock_user_struct(frame, frame_addr, 0);
6873 return -TARGET_QEMU_ESIGRETURN;
6874
6875 badframe:
6876 force_sig(TARGET_SIGSEGV);
6877 return -TARGET_QEMU_ESIGRETURN;
6878}
6879
bellardb346ff42003-06-15 20:05:50 +00006880#else
6881
pbrook624f7972008-05-31 16:11:38 +00006882static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006883 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006884{
6885 fprintf(stderr, "setup_frame: not implemented\n");
6886}
6887
pbrook624f7972008-05-31 16:11:38 +00006888static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05006889 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01006890 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006891{
6892 fprintf(stderr, "setup_rt_frame: not implemented\n");
6893}
6894
Andreas Färber9349b4f2012-03-14 01:38:32 +01006895long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006896{
6897 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006898 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006899}
6900
Andreas Färber9349b4f2012-03-14 01:38:32 +01006901long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00006902{
6903 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00006904 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00006905}
6906
bellard66fb9762003-03-23 01:06:05 +00006907#endif
6908
Peter Maydell31efaef2016-07-06 15:09:29 +01006909static void handle_pending_signal(CPUArchState *cpu_env, int sig,
6910 struct emulated_sigtable *k)
Peter Maydelleb552502016-05-27 15:51:43 +01006911{
6912 CPUState *cpu = ENV_GET_CPU(cpu_env);
6913 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006914 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01006915 target_sigset_t target_old_set;
6916 struct target_sigaction *sa;
Peter Maydelleb552502016-05-27 15:51:43 +01006917 TaskState *ts = cpu->opaque;
Peter Maydelleb552502016-05-27 15:51:43 +01006918
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01006919 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00006920 /* dequeue signal */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006921 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00006922
Andreas Färberdb6b81d2013-06-27 19:49:31 +02006923 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00006924 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00006925 sa = NULL;
6926 handler = TARGET_SIG_IGN;
6927 } else {
6928 sa = &sigact_table[sig - 1];
6929 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00006930 }
bellard66fb9762003-03-23 01:06:05 +00006931
Peter Maydell0cb581d2016-07-18 18:12:24 +01006932 if (do_strace) {
6933 print_taken_signal(sig, &k->info);
6934 }
6935
bellard66fb9762003-03-23 01:06:05 +00006936 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00006937 /* default handler : ignore some signal. The other are job control or fatal */
6938 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
6939 kill(getpid(),SIGSTOP);
6940 } else if (sig != TARGET_SIGCHLD &&
6941 sig != TARGET_SIGURG &&
6942 sig != TARGET_SIGWINCH &&
6943 sig != TARGET_SIGCONT) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006944 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006945 }
6946 } else if (handler == TARGET_SIG_IGN) {
6947 /* ignore sig */
6948 } else if (handler == TARGET_SIG_ERR) {
Peter Maydellc599d4d2016-07-28 16:44:49 +01006949 dump_core_and_abort(sig);
bellard66fb9762003-03-23 01:06:05 +00006950 } else {
bellard9de5e442003-03-23 16:49:39 +00006951 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006952 sigset_t *blocked_set;
6953
pbrook624f7972008-05-31 16:11:38 +00006954 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00006955 /* SA_NODEFER indicates that the current signal should not be
6956 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00006957 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00006958 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00006959
bellard9de5e442003-03-23 16:49:39 +00006960 /* save the previous blocked signal state to restore it at the
6961 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01006962 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
6963
6964 /* block signals in the handler */
6965 blocked_set = ts->in_sigsuspend ?
6966 &ts->sigsuspend_mask : &ts->signal_mask;
6967 sigorset(&ts->signal_mask, blocked_set, &set);
6968 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00006969
bellardbc8a22c2003-03-30 21:02:40 +00006970 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00006971#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00006972 {
6973 CPUX86State *env = cpu_env;
6974 if (env->eflags & VM_MASK)
6975 save_v86_state(env);
6976 }
6977#endif
bellard9de5e442003-03-23 16:49:39 +00006978 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08006979#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Benjamin Herrenschmidt95cda4c2016-08-03 22:38:51 +10006980 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
Marek Vasuta0a839b2017-01-18 23:01:42 +01006981 || defined(TARGET_PPC64) || defined(TARGET_HPPA) \
Michael Clark47ae93c2018-03-03 01:31:11 +13006982 || defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
6983 || defined(TARGET_RISCV)
Richard Hendersonff970902013-02-10 10:30:42 -08006984 /* These targets do not have traditional signals. */
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006985 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006986#else
pbrook624f7972008-05-31 16:11:38 +00006987 if (sa->sa_flags & TARGET_SA_SIGINFO)
Timothy E Baldwin907f5fd2016-05-27 15:51:52 +01006988 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00006989 else
pbrook624f7972008-05-31 16:11:38 +00006990 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08006991#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01006992 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00006993 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01006994 }
bellard31e31b82003-02-18 22:55:36 +00006995 }
bellard31e31b82003-02-18 22:55:36 +00006996}
Peter Maydelle902d582016-05-27 15:51:44 +01006997
6998void process_pending_signals(CPUArchState *cpu_env)
6999{
7000 CPUState *cpu = ENV_GET_CPU(cpu_env);
7001 int sig;
7002 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007003 sigset_t set;
7004 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01007005
Peter Maydell3d3efba2016-05-27 15:51:49 +01007006 while (atomic_read(&ts->signal_pending)) {
7007 /* FIXME: This is not threadsafe. */
7008 sigfillset(&set);
7009 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007010
Peter Maydell8bd37732016-07-28 16:44:45 +01007011 restart_scan:
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007012 sig = ts->sync_signal.pending;
7013 if (sig) {
7014 /* Synchronous signals are forced,
7015 * see force_sig_info() and callers in Linux
7016 * Note that not all of our queue_signal() calls in QEMU correspond
7017 * to force_sig_info() calls in Linux (some are send_sig_info()).
7018 * However it seems like a kernel bug to me to allow the process
7019 * to block a synchronous signal since it could then just end up
7020 * looping round and round indefinitely.
7021 */
7022 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
7023 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
7024 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
7025 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
7026 }
7027
Peter Maydell31efaef2016-07-06 15:09:29 +01007028 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007029 }
7030
Peter Maydell3d3efba2016-05-27 15:51:49 +01007031 for (sig = 1; sig <= TARGET_NSIG; sig++) {
7032 blocked_set = ts->in_sigsuspend ?
7033 &ts->sigsuspend_mask : &ts->signal_mask;
7034
7035 if (ts->sigtab[sig - 1].pending &&
7036 (!sigismember(blocked_set,
Timothy E Baldwin655ed672016-05-27 15:51:53 +01007037 target_to_host_signal_table[sig]))) {
Peter Maydell31efaef2016-07-06 15:09:29 +01007038 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
Peter Maydell8bd37732016-07-28 16:44:45 +01007039 /* Restart scan from the beginning, as handle_pending_signal
7040 * might have resulted in a new synchronous signal (eg SIGSEGV).
7041 */
7042 goto restart_scan;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007043 }
Peter Maydelle902d582016-05-27 15:51:44 +01007044 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007045
7046 /* if no signal is pending, unblock signals and recheck (the act
7047 * of unblocking might cause us to take another host signal which
7048 * will set signal_pending again).
7049 */
7050 atomic_set(&ts->signal_pending, 0);
7051 ts->in_sigsuspend = 0;
7052 set = ts->signal_mask;
7053 sigdelset(&set, SIGSEGV);
7054 sigdelset(&set, SIGBUS);
7055 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01007056 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007057 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01007058}