]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/signal.c
linux-user: Implement do_setcontext for PPC64
[mirror_qemu.git] / linux-user / signal.c
CommitLineData
31e31b8a 1/*
66fb9763 2 * Emulation of Linux signals
5fafdf24 3 *
31e31b8a
FB
4 * 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
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a
FB
18 */
19#include <stdlib.h>
20#include <stdio.h>
66fb9763 21#include <string.h>
31e31b8a 22#include <stdarg.h>
2677e107 23#include <unistd.h>
66fb9763 24#include <errno.h>
603e4fd7 25#include <assert.h>
31e31b8a 26#include <sys/ucontext.h>
edf8e2af 27#include <sys/resource.h>
31e31b8a 28
3ef693a0 29#include "qemu.h"
7d99a001 30#include "qemu-common.h"
992f48a0 31#include "target_signal.h"
66fb9763
FB
32
33//#define DEBUG_SIGNAL
34
249c4c32 35static struct target_sigaltstack target_sigaltstack_used = {
a04e134a
TS
36 .ss_sp = 0,
37 .ss_size = 0,
38 .ss_flags = TARGET_SS_DISABLE,
39};
40
624f7979 41static struct target_sigaction sigact_table[TARGET_NSIG];
31e31b8a 42
5fafdf24 43static void host_signal_handler(int host_signum, siginfo_t *info,
66fb9763
FB
44 void *puc);
45
3ca05588 46static uint8_t host_to_target_signal_table[_NSIG] = {
9e5f5284
FB
47 [SIGHUP] = TARGET_SIGHUP,
48 [SIGINT] = TARGET_SIGINT,
49 [SIGQUIT] = TARGET_SIGQUIT,
50 [SIGILL] = TARGET_SIGILL,
51 [SIGTRAP] = TARGET_SIGTRAP,
52 [SIGABRT] = TARGET_SIGABRT,
01e3b763 53/* [SIGIOT] = TARGET_SIGIOT,*/
9e5f5284
FB
54 [SIGBUS] = TARGET_SIGBUS,
55 [SIGFPE] = TARGET_SIGFPE,
56 [SIGKILL] = TARGET_SIGKILL,
57 [SIGUSR1] = TARGET_SIGUSR1,
58 [SIGSEGV] = TARGET_SIGSEGV,
59 [SIGUSR2] = TARGET_SIGUSR2,
60 [SIGPIPE] = TARGET_SIGPIPE,
61 [SIGALRM] = TARGET_SIGALRM,
62 [SIGTERM] = TARGET_SIGTERM,
63#ifdef SIGSTKFLT
64 [SIGSTKFLT] = TARGET_SIGSTKFLT,
65#endif
66 [SIGCHLD] = TARGET_SIGCHLD,
67 [SIGCONT] = TARGET_SIGCONT,
68 [SIGSTOP] = TARGET_SIGSTOP,
69 [SIGTSTP] = TARGET_SIGTSTP,
70 [SIGTTIN] = TARGET_SIGTTIN,
71 [SIGTTOU] = TARGET_SIGTTOU,
72 [SIGURG] = TARGET_SIGURG,
73 [SIGXCPU] = TARGET_SIGXCPU,
74 [SIGXFSZ] = TARGET_SIGXFSZ,
75 [SIGVTALRM] = TARGET_SIGVTALRM,
76 [SIGPROF] = TARGET_SIGPROF,
77 [SIGWINCH] = TARGET_SIGWINCH,
78 [SIGIO] = TARGET_SIGIO,
79 [SIGPWR] = TARGET_SIGPWR,
80 [SIGSYS] = TARGET_SIGSYS,
81 /* next signals stay the same */
624f7979 82 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
b4916d7b 83 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
624f7979
PB
84 To fix this properly we need to do manual signal delivery multiplexed
85 over a single host signal. */
86 [__SIGRTMIN] = __SIGRTMAX,
87 [__SIGRTMAX] = __SIGRTMIN,
9e5f5284 88};
3ca05588 89static uint8_t target_to_host_signal_table[_NSIG];
9e5f5284 90
a04e134a
TS
91static inline int on_sig_stack(unsigned long sp)
92{
93 return (sp - target_sigaltstack_used.ss_sp
94 < target_sigaltstack_used.ss_size);
95}
96
97static inline int sas_ss_flags(unsigned long sp)
98{
99 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
100 : on_sig_stack(sp) ? SS_ONSTACK : 0);
101}
102
1d9d8b55 103int host_to_target_signal(int sig)
31e31b8a 104{
167c50d8 105 if (sig < 0 || sig >= _NSIG)
4cb05961 106 return sig;
9e5f5284 107 return host_to_target_signal_table[sig];
31e31b8a
FB
108}
109
4cb05961 110int target_to_host_signal(int sig)
31e31b8a 111{
167c50d8 112 if (sig < 0 || sig >= _NSIG)
4cb05961 113 return sig;
9e5f5284 114 return target_to_host_signal_table[sig];
31e31b8a
FB
115}
116
c227f099 117static inline void target_sigemptyset(target_sigset_t *set)
f5545b5c
PB
118{
119 memset(set, 0, sizeof(*set));
120}
121
c227f099 122static inline void target_sigaddset(target_sigset_t *set, int signum)
f5545b5c
PB
123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 set->sig[signum / TARGET_NSIG_BPW] |= mask;
127}
128
c227f099 129static inline int target_sigismember(const target_sigset_t *set, int signum)
f5545b5c
PB
130{
131 signum--;
132 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
133 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
134}
135
c227f099 136static void host_to_target_sigset_internal(target_sigset_t *d,
9231944d 137 const sigset_t *s)
66fb9763
FB
138{
139 int i;
f5545b5c
PB
140 target_sigemptyset(d);
141 for (i = 1; i <= TARGET_NSIG; i++) {
142 if (sigismember(s, i)) {
143 target_sigaddset(d, host_to_target_signal(i));
144 }
66fb9763
FB
145 }
146}
147
c227f099 148void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
9231944d 149{
c227f099 150 target_sigset_t d1;
9231944d
FB
151 int i;
152
153 host_to_target_sigset_internal(&d1, s);
154 for(i = 0;i < TARGET_NSIG_WORDS; i++)
cbb21eed 155 d->sig[i] = tswapal(d1.sig[i]);
9231944d
FB
156}
157
8fcd3692 158static void target_to_host_sigset_internal(sigset_t *d,
c227f099 159 const target_sigset_t *s)
66fb9763
FB
160{
161 int i;
f5545b5c
PB
162 sigemptyset(d);
163 for (i = 1; i <= TARGET_NSIG; i++) {
164 if (target_sigismember(s, i)) {
165 sigaddset(d, target_to_host_signal(i));
166 }
167 }
66fb9763
FB
168}
169
c227f099 170void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
9231944d 171{
c227f099 172 target_sigset_t s1;
9231944d
FB
173 int i;
174
175 for(i = 0;i < TARGET_NSIG_WORDS; i++)
cbb21eed 176 s1.sig[i] = tswapal(s->sig[i]);
9231944d
FB
177 target_to_host_sigset_internal(d, &s1);
178}
3b46e624 179
992f48a0 180void host_to_target_old_sigset(abi_ulong *old_sigset,
66fb9763
FB
181 const sigset_t *sigset)
182{
c227f099 183 target_sigset_t d;
9e5f5284
FB
184 host_to_target_sigset(&d, sigset);
185 *old_sigset = d.sig[0];
66fb9763
FB
186}
187
5fafdf24 188void target_to_host_old_sigset(sigset_t *sigset,
992f48a0 189 const abi_ulong *old_sigset)
66fb9763 190{
c227f099 191 target_sigset_t d;
9e5f5284
FB
192 int i;
193
194 d.sig[0] = *old_sigset;
195 for(i = 1;i < TARGET_NSIG_WORDS; i++)
196 d.sig[i] = 0;
197 target_to_host_sigset(sigset, &d);
66fb9763
FB
198}
199
1c275925
AB
200/* Wrapper for sigprocmask function
201 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
202 * are host signal set, not guest ones. This wraps the sigprocmask host calls
203 * that should be protected (calls originated from guest)
204 */
205int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
206{
a7ec0f98
PM
207 int ret;
208 sigset_t val;
209 sigset_t *temp = NULL;
210 CPUState *cpu = thread_cpu;
211 TaskState *ts = (TaskState *)cpu->opaque;
212 bool segv_was_blocked = ts->sigsegv_blocked;
213
214 if (set) {
215 bool has_sigsegv = sigismember(set, SIGSEGV);
216 val = *set;
217 temp = &val;
218
219 sigdelset(temp, SIGSEGV);
220
221 switch (how) {
222 case SIG_BLOCK:
223 if (has_sigsegv) {
224 ts->sigsegv_blocked = true;
225 }
226 break;
227 case SIG_UNBLOCK:
228 if (has_sigsegv) {
229 ts->sigsegv_blocked = false;
230 }
231 break;
232 case SIG_SETMASK:
233 ts->sigsegv_blocked = has_sigsegv;
234 break;
235 default:
236 g_assert_not_reached();
237 }
238 }
239
240 ret = sigprocmask(how, temp, oldset);
241
242 if (oldset && segv_was_blocked) {
243 sigaddset(oldset, SIGSEGV);
244 }
245
246 return ret;
1c275925
AB
247}
248
9de5e440
FB
249/* siginfo conversion */
250
c227f099 251static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
9de5e440 252 const siginfo_t *info)
66fb9763 253{
a05c6409 254 int sig = host_to_target_signal(info->si_signo);
9de5e440
FB
255 tinfo->si_signo = sig;
256 tinfo->si_errno = 0;
afd7cd92 257 tinfo->si_code = info->si_code;
a05c6409
RH
258
259 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
260 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
261 /* Should never come here, but who knows. The information for
262 the target is irrelevant. */
9de5e440 263 tinfo->_sifields._sigfault._addr = 0;
a05c6409
RH
264 } else if (sig == TARGET_SIGIO) {
265 tinfo->_sifields._sigpoll._band = info->si_band;
7f7f7c84 266 tinfo->_sifields._sigpoll._fd = info->si_fd;
a05c6409
RH
267 } else if (sig == TARGET_SIGCHLD) {
268 tinfo->_sifields._sigchld._pid = info->si_pid;
269 tinfo->_sifields._sigchld._uid = info->si_uid;
270 tinfo->_sifields._sigchld._status
271 = host_to_target_waitstatus(info->si_status);
272 tinfo->_sifields._sigchld._utime = info->si_utime;
273 tinfo->_sifields._sigchld._stime = info->si_stime;
9de5e440
FB
274 } else if (sig >= TARGET_SIGRTMIN) {
275 tinfo->_sifields._rt._pid = info->si_pid;
276 tinfo->_sifields._rt._uid = info->si_uid;
277 /* XXX: potential problem if 64 bit */
a05c6409
RH
278 tinfo->_sifields._rt._sigval.sival_ptr
279 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
9de5e440
FB
280 }
281}
282
c227f099
AL
283static void tswap_siginfo(target_siginfo_t *tinfo,
284 const target_siginfo_t *info)
9de5e440 285{
a05c6409 286 int sig = info->si_signo;
9de5e440 287 tinfo->si_signo = tswap32(sig);
66fb9763
FB
288 tinfo->si_errno = tswap32(info->si_errno);
289 tinfo->si_code = tswap32(info->si_code);
a05c6409
RH
290
291 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
292 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
293 tinfo->_sifields._sigfault._addr
294 = tswapal(info->_sifields._sigfault._addr);
295 } else if (sig == TARGET_SIGIO) {
296 tinfo->_sifields._sigpoll._band
297 = tswap32(info->_sifields._sigpoll._band);
298 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
299 } else if (sig == TARGET_SIGCHLD) {
300 tinfo->_sifields._sigchld._pid
301 = tswap32(info->_sifields._sigchld._pid);
302 tinfo->_sifields._sigchld._uid
303 = tswap32(info->_sifields._sigchld._uid);
304 tinfo->_sifields._sigchld._status
305 = tswap32(info->_sifields._sigchld._status);
306 tinfo->_sifields._sigchld._utime
307 = tswapal(info->_sifields._sigchld._utime);
308 tinfo->_sifields._sigchld._stime
309 = tswapal(info->_sifields._sigchld._stime);
9de5e440
FB
310 } else if (sig >= TARGET_SIGRTMIN) {
311 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
312 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
a05c6409
RH
313 tinfo->_sifields._rt._sigval.sival_ptr
314 = tswapal(info->_sifields._rt._sigval.sival_ptr);
9de5e440
FB
315 }
316}
317
318
c227f099 319void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
9de5e440
FB
320{
321 host_to_target_siginfo_noswap(tinfo, info);
322 tswap_siginfo(tinfo, tinfo);
66fb9763
FB
323}
324
9de5e440 325/* XXX: we support only POSIX RT signals are used. */
aa1f17c1 326/* XXX: find a solution for 64 bit (additional malloced data is needed) */
c227f099 327void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
66fb9763
FB
328{
329 info->si_signo = tswap32(tinfo->si_signo);
330 info->si_errno = tswap32(tinfo->si_errno);
331 info->si_code = tswap32(tinfo->si_code);
9de5e440
FB
332 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
333 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
5fafdf24 334 info->si_value.sival_ptr =
cbb21eed 335 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
66fb9763
FB
336}
337
ca587a8e
AJ
338static int fatal_signal (int sig)
339{
340 switch (sig) {
341 case TARGET_SIGCHLD:
342 case TARGET_SIGURG:
343 case TARGET_SIGWINCH:
344 /* Ignored by default. */
345 return 0;
346 case TARGET_SIGCONT:
347 case TARGET_SIGSTOP:
348 case TARGET_SIGTSTP:
349 case TARGET_SIGTTIN:
350 case TARGET_SIGTTOU:
351 /* Job control signals. */
352 return 0;
353 default:
354 return 1;
355 }
356}
357
edf8e2af
MW
358/* returns 1 if given signal should dump core if not handled */
359static int core_dump_signal(int sig)
360{
361 switch (sig) {
362 case TARGET_SIGABRT:
363 case TARGET_SIGFPE:
364 case TARGET_SIGILL:
365 case TARGET_SIGQUIT:
366 case TARGET_SIGSEGV:
367 case TARGET_SIGTRAP:
368 case TARGET_SIGBUS:
369 return (1);
370 default:
371 return (0);
372 }
373}
374
31e31b8a
FB
375void signal_init(void)
376{
377 struct sigaction act;
624f7979 378 struct sigaction oact;
9e5f5284 379 int i, j;
624f7979 380 int host_sig;
31e31b8a 381
9e5f5284 382 /* generate signal conversion tables */
3ca05588 383 for(i = 1; i < _NSIG; i++) {
9e5f5284
FB
384 if (host_to_target_signal_table[i] == 0)
385 host_to_target_signal_table[i] = i;
386 }
3ca05588 387 for(i = 1; i < _NSIG; i++) {
9e5f5284
FB
388 j = host_to_target_signal_table[i];
389 target_to_host_signal_table[j] = i;
390 }
3b46e624 391
9de5e440
FB
392 /* set all host signal handlers. ALL signals are blocked during
393 the handlers to serialize them. */
624f7979
PB
394 memset(sigact_table, 0, sizeof(sigact_table));
395
9de5e440 396 sigfillset(&act.sa_mask);
31e31b8a
FB
397 act.sa_flags = SA_SIGINFO;
398 act.sa_sigaction = host_signal_handler;
624f7979
PB
399 for(i = 1; i <= TARGET_NSIG; i++) {
400 host_sig = target_to_host_signal(i);
401 sigaction(host_sig, NULL, &oact);
402 if (oact.sa_sigaction == (void *)SIG_IGN) {
403 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
404 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
405 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
406 }
407 /* If there's already a handler installed then something has
408 gone horribly wrong, so don't even try to handle that case. */
ca587a8e
AJ
409 /* Install some handlers for our own use. We need at least
410 SIGSEGV and SIGBUS, to detect exceptions. We can not just
411 trap all signals because it affects syscall interrupt
412 behavior. But do trap all default-fatal signals. */
413 if (fatal_signal (i))
624f7979 414 sigaction(host_sig, &act, NULL);
31e31b8a 415 }
66fb9763
FB
416}
417
418/* signal queue handling */
419
9349b4f9 420static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
66fb9763 421{
0429a971
AF
422 CPUState *cpu = ENV_GET_CPU(env);
423 TaskState *ts = cpu->opaque;
624f7979 424 struct sigqueue *q = ts->first_free;
66fb9763
FB
425 if (!q)
426 return NULL;
624f7979 427 ts->first_free = q->next;
66fb9763 428 return q;
31e31b8a
FB
429}
430
9349b4f9 431static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
66fb9763 432{
0429a971
AF
433 CPUState *cpu = ENV_GET_CPU(env);
434 TaskState *ts = cpu->opaque;
435
624f7979
PB
436 q->next = ts->first_free;
437 ts->first_free = q;
66fb9763
FB
438}
439
9de5e440 440/* abort execution with signal */
66393fb9 441static void QEMU_NORETURN force_sig(int target_sig)
66fb9763 442{
0429a971
AF
443 CPUState *cpu = thread_cpu;
444 CPUArchState *env = cpu->env_ptr;
445 TaskState *ts = (TaskState *)cpu->opaque;
edf8e2af 446 int host_sig, core_dumped = 0;
603e4fd7 447 struct sigaction act;
66393fb9 448 host_sig = target_to_host_signal(target_sig);
a2247f8e 449 gdb_signalled(env, target_sig);
603e4fd7 450
edf8e2af 451 /* dump core if supported by target binary format */
66393fb9 452 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
edf8e2af
MW
453 stop_all_tasks();
454 core_dumped =
a2247f8e 455 ((*ts->bprm->core_dump)(target_sig, env) == 0);
edf8e2af
MW
456 }
457 if (core_dumped) {
458 /* we already dumped the core of target process, we don't want
459 * a coredump of qemu itself */
460 struct rlimit nodump;
461 getrlimit(RLIMIT_CORE, &nodump);
462 nodump.rlim_cur=0;
463 setrlimit(RLIMIT_CORE, &nodump);
464 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
66393fb9 465 target_sig, strsignal(host_sig), "core dumped" );
edf8e2af
MW
466 }
467
0c58751c 468 /* The proper exit code for dying from an uncaught signal is
603e4fd7
AJ
469 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
470 * a negative value. To get the proper exit code we need to
471 * actually die from an uncaught signal. Here the default signal
472 * handler is installed, we send ourself a signal and we wait for
473 * it to arrive. */
474 sigfillset(&act.sa_mask);
475 act.sa_handler = SIG_DFL;
3a5d30bf 476 act.sa_flags = 0;
603e4fd7
AJ
477 sigaction(host_sig, &act, NULL);
478
479 /* For some reason raise(host_sig) doesn't send the signal when
480 * statically linked on x86-64. */
481 kill(getpid(), host_sig);
482
483 /* Make sure the signal isn't masked (just reuse the mask inside
484 of act) */
485 sigdelset(&act.sa_mask, host_sig);
486 sigsuspend(&act.sa_mask);
487
488 /* unreachable */
a6c6f76c 489 abort();
66fb9763
FB
490}
491
9de5e440
FB
492/* queue a signal so that it will be send to the virtual CPU as soon
493 as possible */
9349b4f9 494int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
31e31b8a 495{
0429a971
AF
496 CPUState *cpu = ENV_GET_CPU(env);
497 TaskState *ts = cpu->opaque;
624f7979 498 struct emulated_sigtable *k;
9de5e440 499 struct sigqueue *q, **pq;
992f48a0 500 abi_ulong handler;
ca587a8e 501 int queue;
66fb9763 502
9de5e440 503#if defined(DEBUG_SIGNAL)
5fafdf24 504 fprintf(stderr, "queue_signal: sig=%d\n",
9de5e440 505 sig);
66fb9763 506#endif
624f7979 507 k = &ts->sigtab[sig - 1];
ca587a8e 508 queue = gdb_queuesig ();
624f7979 509 handler = sigact_table[sig - 1]._sa_handler;
a7ec0f98
PM
510
511 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
512 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
513 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
514 * because it got a real MMU fault). A blocked SIGSEGV in that
515 * situation is treated as if using the default handler. This is
516 * not correct if some other process has randomly sent us a SIGSEGV
517 * via kill(), but that is not easy to distinguish at this point,
518 * so we assume it doesn't happen.
519 */
520 handler = TARGET_SIG_DFL;
521 }
522
ca587a8e 523 if (!queue && handler == TARGET_SIG_DFL) {
60b19691
TS
524 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
525 kill(getpid(),SIGSTOP);
526 return 0;
527 } else
66fb9763 528 /* default handler : ignore some signal. The other are fatal */
5fafdf24
TS
529 if (sig != TARGET_SIGCHLD &&
530 sig != TARGET_SIGURG &&
60b19691
TS
531 sig != TARGET_SIGWINCH &&
532 sig != TARGET_SIGCONT) {
66fb9763 533 force_sig(sig);
9de5e440
FB
534 } else {
535 return 0; /* indicate ignored */
66fb9763 536 }
ca587a8e 537 } else if (!queue && handler == TARGET_SIG_IGN) {
66fb9763 538 /* ignore signal */
9de5e440 539 return 0;
ca587a8e 540 } else if (!queue && handler == TARGET_SIG_ERR) {
66fb9763
FB
541 force_sig(sig);
542 } else {
9de5e440
FB
543 pq = &k->first;
544 if (sig < TARGET_SIGRTMIN) {
545 /* if non real time signal, we queue exactly one signal */
546 if (!k->pending)
547 q = &k->info;
548 else
549 return 0;
550 } else {
551 if (!k->pending) {
552 /* first signal */
553 q = &k->info;
554 } else {
624f7979 555 q = alloc_sigqueue(env);
9de5e440
FB
556 if (!q)
557 return -EAGAIN;
558 while (*pq != NULL)
559 pq = &(*pq)->next;
560 }
561 }
562 *pq = q;
563 q->info = *info;
564 q->next = NULL;
565 k->pending = 1;
566 /* signal that a new signal is pending */
624f7979 567 ts->signal_pending = 1;
9de5e440
FB
568 return 1; /* indicates that the signal was queued */
569 }
570}
571
5fafdf24 572static void host_signal_handler(int host_signum, siginfo_t *info,
9de5e440
FB
573 void *puc)
574{
a2247f8e 575 CPUArchState *env = thread_cpu->env_ptr;
9de5e440 576 int sig;
c227f099 577 target_siginfo_t tinfo;
9de5e440
FB
578
579 /* the CPU emulator uses some host signals to detect exceptions,
eaa449b9 580 we forward to it some signals */
ca587a8e 581 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
eaa449b9 582 && info->si_code > 0) {
b346ff46 583 if (cpu_signal_handler(host_signum, info, puc))
9de5e440
FB
584 return;
585 }
586
587 /* get target signal number */
588 sig = host_to_target_signal(host_signum);
589 if (sig < 1 || sig > TARGET_NSIG)
590 return;
591#if defined(DEBUG_SIGNAL)
bc8a22cc 592 fprintf(stderr, "qemu: got signal %d\n", sig);
9de5e440
FB
593#endif
594 host_to_target_siginfo_noswap(&tinfo, info);
a2247f8e 595 if (queue_signal(env, sig, &tinfo) == 1) {
9de5e440 596 /* interrupt the virtual CPU as soon as possible */
a2247f8e 597 cpu_exit(thread_cpu);
66fb9763
FB
598 }
599}
600
0da46a6e 601/* do_sigaltstack() returns target values and errnos. */
579a97f7
FB
602/* compare linux/kernel/signal.c:do_sigaltstack() */
603abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
a04e134a
TS
604{
605 int ret;
606 struct target_sigaltstack oss;
607
608 /* XXX: test errors */
579a97f7 609 if(uoss_addr)
a04e134a
TS
610 {
611 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
612 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
613 __put_user(sas_ss_flags(sp), &oss.ss_flags);
614 }
615
579a97f7 616 if(uss_addr)
a04e134a 617 {
579a97f7
FB
618 struct target_sigaltstack *uss;
619 struct target_sigaltstack ss;
0903c8be
TM
620 size_t minstacksize = TARGET_MINSIGSTKSZ;
621
622#if defined(TARGET_PPC64)
623 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
624 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
625 if (get_ppc64_abi(image) > 1) {
626 minstacksize = 4096;
627 }
628#endif
a04e134a 629
0da46a6e 630 ret = -TARGET_EFAULT;
9eeb8306 631 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
a04e134a 632 goto out;
9eeb8306
RV
633 }
634 __get_user(ss.ss_sp, &uss->ss_sp);
635 __get_user(ss.ss_size, &uss->ss_size);
636 __get_user(ss.ss_flags, &uss->ss_flags);
579a97f7 637 unlock_user_struct(uss, uss_addr, 0);
a04e134a 638
0da46a6e 639 ret = -TARGET_EPERM;
a04e134a
TS
640 if (on_sig_stack(sp))
641 goto out;
642
0da46a6e 643 ret = -TARGET_EINVAL;
a04e134a
TS
644 if (ss.ss_flags != TARGET_SS_DISABLE
645 && ss.ss_flags != TARGET_SS_ONSTACK
646 && ss.ss_flags != 0)
647 goto out;
648
649 if (ss.ss_flags == TARGET_SS_DISABLE) {
650 ss.ss_size = 0;
651 ss.ss_sp = 0;
652 } else {
0da46a6e 653 ret = -TARGET_ENOMEM;
0903c8be 654 if (ss.ss_size < minstacksize) {
a04e134a 655 goto out;
0903c8be 656 }
a04e134a
TS
657 }
658
659 target_sigaltstack_used.ss_sp = ss.ss_sp;
660 target_sigaltstack_used.ss_size = ss.ss_size;
661 }
662
579a97f7 663 if (uoss_addr) {
0da46a6e 664 ret = -TARGET_EFAULT;
579a97f7 665 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
a04e134a 666 goto out;
a04e134a
TS
667 }
668
669 ret = 0;
670out:
671 return ret;
672}
673
0da46a6e 674/* do_sigaction() return host values and errnos */
66fb9763
FB
675int do_sigaction(int sig, const struct target_sigaction *act,
676 struct target_sigaction *oact)
677{
624f7979 678 struct target_sigaction *k;
773b93ee
FB
679 struct sigaction act1;
680 int host_sig;
0da46a6e 681 int ret = 0;
66fb9763 682
2a913eb1 683 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
66fb9763
FB
684 return -EINVAL;
685 k = &sigact_table[sig - 1];
773b93ee 686#if defined(DEBUG_SIGNAL)
0bf9e31a
BS
687 fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
688 sig, act, oact);
66fb9763
FB
689#endif
690 if (oact) {
d2565875
RH
691 __put_user(k->_sa_handler, &oact->_sa_handler);
692 __put_user(k->sa_flags, &oact->sa_flags);
388bb21a 693#if !defined(TARGET_MIPS)
d2565875 694 __put_user(k->sa_restorer, &oact->sa_restorer);
388bb21a 695#endif
d2565875 696 /* Not swapped. */
624f7979 697 oact->sa_mask = k->sa_mask;
66fb9763
FB
698 }
699 if (act) {
624f7979 700 /* FIXME: This is not threadsafe. */
d2565875
RH
701 __get_user(k->_sa_handler, &act->_sa_handler);
702 __get_user(k->sa_flags, &act->sa_flags);
388bb21a 703#if !defined(TARGET_MIPS)
d2565875 704 __get_user(k->sa_restorer, &act->sa_restorer);
388bb21a 705#endif
d2565875 706 /* To be swapped in target_to_host_sigset. */
624f7979 707 k->sa_mask = act->sa_mask;
773b93ee
FB
708
709 /* we update the host linux signal state */
710 host_sig = target_to_host_signal(sig);
711 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
712 sigfillset(&act1.sa_mask);
713 act1.sa_flags = SA_SIGINFO;
624f7979 714 if (k->sa_flags & TARGET_SA_RESTART)
773b93ee
FB
715 act1.sa_flags |= SA_RESTART;
716 /* NOTE: it is important to update the host kernel signal
717 ignore state to avoid getting unexpected interrupted
718 syscalls */
624f7979 719 if (k->_sa_handler == TARGET_SIG_IGN) {
773b93ee 720 act1.sa_sigaction = (void *)SIG_IGN;
624f7979 721 } else if (k->_sa_handler == TARGET_SIG_DFL) {
ca587a8e
AJ
722 if (fatal_signal (sig))
723 act1.sa_sigaction = host_signal_handler;
724 else
725 act1.sa_sigaction = (void *)SIG_DFL;
773b93ee
FB
726 } else {
727 act1.sa_sigaction = host_signal_handler;
728 }
0da46a6e 729 ret = sigaction(host_sig, &act1, NULL);
773b93ee 730 }
66fb9763 731 }
0da46a6e 732 return ret;
66fb9763
FB
733}
734
b0fd8d18 735static inline void copy_siginfo_to_user(target_siginfo_t *tinfo,
c227f099 736 const target_siginfo_t *info)
43fff238
FB
737{
738 tswap_siginfo(tinfo, info);
43fff238
FB
739}
740
c3b5bc8a
TS
741static inline int current_exec_domain_sig(int sig)
742{
743 return /* current->exec_domain && current->exec_domain->signal_invmap
744 && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
745}
746
459a4017 747#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
66fb9763
FB
748
749/* from the Linux kernel */
750
751struct target_fpreg {
752 uint16_t significand[4];
753 uint16_t exponent;
754};
755
756struct target_fpxreg {
757 uint16_t significand[4];
758 uint16_t exponent;
759 uint16_t padding[3];
760};
761
762struct target_xmmreg {
992f48a0 763 abi_ulong element[4];
66fb9763
FB
764};
765
766struct target_fpstate {
767 /* Regular FPU environment */
992f48a0
BS
768 abi_ulong cw;
769 abi_ulong sw;
770 abi_ulong tag;
771 abi_ulong ipoff;
772 abi_ulong cssel;
773 abi_ulong dataoff;
774 abi_ulong datasel;
66fb9763
FB
775 struct target_fpreg _st[8];
776 uint16_t status;
777 uint16_t magic; /* 0xffff = regular FPU data only */
778
779 /* FXSR FPU environment */
992f48a0
BS
780 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
781 abi_ulong mxcsr;
782 abi_ulong reserved;
66fb9763
FB
783 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
784 struct target_xmmreg _xmm[8];
992f48a0 785 abi_ulong padding[56];
66fb9763
FB
786};
787
788#define X86_FXSR_MAGIC 0x0000
789
790struct target_sigcontext {
791 uint16_t gs, __gsh;
792 uint16_t fs, __fsh;
793 uint16_t es, __esh;
794 uint16_t ds, __dsh;
992f48a0
BS
795 abi_ulong edi;
796 abi_ulong esi;
797 abi_ulong ebp;
798 abi_ulong esp;
799 abi_ulong ebx;
800 abi_ulong edx;
801 abi_ulong ecx;
802 abi_ulong eax;
803 abi_ulong trapno;
804 abi_ulong err;
805 abi_ulong eip;
66fb9763 806 uint16_t cs, __csh;
992f48a0
BS
807 abi_ulong eflags;
808 abi_ulong esp_at_signal;
66fb9763 809 uint16_t ss, __ssh;
992f48a0
BS
810 abi_ulong fpstate; /* pointer */
811 abi_ulong oldmask;
812 abi_ulong cr2;
66fb9763
FB
813};
814
66fb9763 815struct target_ucontext {
992f48a0
BS
816 abi_ulong tuc_flags;
817 abi_ulong tuc_link;
c227f099 818 target_stack_t tuc_stack;
b8076a74 819 struct target_sigcontext tuc_mcontext;
c227f099 820 target_sigset_t tuc_sigmask; /* mask last for extensibility */
66fb9763
FB
821};
822
823struct sigframe
824{
992f48a0 825 abi_ulong pretcode;
66fb9763
FB
826 int sig;
827 struct target_sigcontext sc;
828 struct target_fpstate fpstate;
992f48a0 829 abi_ulong extramask[TARGET_NSIG_WORDS-1];
66fb9763
FB
830 char retcode[8];
831};
832
833struct rt_sigframe
834{
992f48a0 835 abi_ulong pretcode;
66fb9763 836 int sig;
992f48a0
BS
837 abi_ulong pinfo;
838 abi_ulong puc;
66fb9763
FB
839 struct target_siginfo info;
840 struct target_ucontext uc;
841 struct target_fpstate fpstate;
842 char retcode[8];
843};
844
845/*
846 * Set up a signal frame.
847 */
848
66fb9763 849/* XXX: save x87 state */
41ecc72b
RV
850static void setup_sigcontext(struct target_sigcontext *sc,
851 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
852 abi_ulong fpstate_addr)
66fb9763 853{
27103424 854 CPUState *cs = CPU(x86_env_get_cpu(env));
27103424 855 uint16_t magic;
66fb9763 856
579a97f7 857 /* already locked in setup_frame() */
1d8b512b
RV
858 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
859 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
860 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
861 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
862 __put_user(env->regs[R_EDI], &sc->edi);
863 __put_user(env->regs[R_ESI], &sc->esi);
864 __put_user(env->regs[R_EBP], &sc->ebp);
865 __put_user(env->regs[R_ESP], &sc->esp);
866 __put_user(env->regs[R_EBX], &sc->ebx);
867 __put_user(env->regs[R_EDX], &sc->edx);
868 __put_user(env->regs[R_ECX], &sc->ecx);
869 __put_user(env->regs[R_EAX], &sc->eax);
870 __put_user(cs->exception_index, &sc->trapno);
871 __put_user(env->error_code, &sc->err);
872 __put_user(env->eip, &sc->eip);
873 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
874 __put_user(env->eflags, &sc->eflags);
875 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
876 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
ed2dcdf6 877
28be6234 878 cpu_x86_fsave(env, fpstate_addr, 1);
ed2dcdf6 879 fpstate->status = fpstate->sw;
775b58d8 880 magic = 0xffff;
1d8b512b
RV
881 __put_user(magic, &fpstate->magic);
882 __put_user(fpstate_addr, &sc->fpstate);
ed2dcdf6 883
66fb9763 884 /* non-iBCS2 extensions.. */
1d8b512b
RV
885 __put_user(mask, &sc->oldmask);
886 __put_user(env->cr[2], &sc->cr2);
31e31b8a
FB
887}
888
66fb9763
FB
889/*
890 * Determine which stack to use..
891 */
31e31b8a 892
579a97f7 893static inline abi_ulong
624f7979 894get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
31e31b8a 895{
66fb9763
FB
896 unsigned long esp;
897
898 /* Default to using normal stack */
899 esp = env->regs[R_ESP];
66fb9763 900 /* This is the X/Open sanctioned signal stack switching. */
624f7979 901 if (ka->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
902 if (sas_ss_flags(esp) == 0)
903 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
904 }
66fb9763
FB
905
906 /* This is the legacy signal stack switching. */
5fafdf24 907 else
a52c757c 908 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
624f7979
PB
909 !(ka->sa_flags & TARGET_SA_RESTORER) &&
910 ka->sa_restorer) {
911 esp = (unsigned long) ka->sa_restorer;
a52c757c 912 }
579a97f7 913 return (esp - frame_size) & -8ul;
66fb9763
FB
914}
915
579a97f7 916/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
624f7979 917static void setup_frame(int sig, struct target_sigaction *ka,
c227f099 918 target_sigset_t *set, CPUX86State *env)
66fb9763 919{
579a97f7 920 abi_ulong frame_addr;
66fb9763 921 struct sigframe *frame;
7df2fa36 922 int i;
66fb9763 923
579a97f7 924 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 925
579a97f7 926 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 927 goto give_sigsegv;
579a97f7 928
1d8b512b
RV
929 __put_user(current_exec_domain_sig(sig),
930 &frame->sig);
66fb9763 931
28be6234
FB
932 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
933 frame_addr + offsetof(struct sigframe, fpstate));
66fb9763 934
7df2fa36
RV
935 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
936 __put_user(set->sig[i], &frame->extramask[i - 1]);
937 }
66fb9763
FB
938
939 /* Set up to return from userspace. If provided, use a stub
940 already in userspace. */
624f7979 941 if (ka->sa_flags & TARGET_SA_RESTORER) {
1d8b512b 942 __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 943 } else {
775b58d8 944 uint16_t val16;
28be6234
FB
945 abi_ulong retcode_addr;
946 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
1d8b512b 947 __put_user(retcode_addr, &frame->pretcode);
66fb9763 948 /* This is popl %eax ; movl $,%eax ; int $0x80 */
775b58d8 949 val16 = 0xb858;
1d8b512b
RV
950 __put_user(val16, (uint16_t *)(frame->retcode+0));
951 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
775b58d8 952 val16 = 0x80cd;
1d8b512b 953 __put_user(val16, (uint16_t *)(frame->retcode+6));
66fb9763
FB
954 }
955
66fb9763
FB
956
957 /* Set up registers for signal handler */
28be6234 958 env->regs[R_ESP] = frame_addr;
624f7979 959 env->eip = ka->_sa_handler;
66fb9763
FB
960
961 cpu_x86_load_seg(env, R_DS, __USER_DS);
962 cpu_x86_load_seg(env, R_ES, __USER_DS);
963 cpu_x86_load_seg(env, R_SS, __USER_DS);
964 cpu_x86_load_seg(env, R_CS, __USER_CS);
965 env->eflags &= ~TF_MASK;
966
579a97f7
FB
967 unlock_user_struct(frame, frame_addr, 1);
968
66fb9763
FB
969 return;
970
971give_sigsegv:
972 if (sig == TARGET_SIGSEGV)
624f7979 973 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
974 force_sig(TARGET_SIGSEGV /* , current */);
975}
976
579a97f7 977/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
624f7979 978static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099
AL
979 target_siginfo_t *info,
980 target_sigset_t *set, CPUX86State *env)
66fb9763 981{
28be6234 982 abi_ulong frame_addr, addr;
66fb9763 983 struct rt_sigframe *frame;
0188fadb 984 int i;
66fb9763 985
579a97f7 986 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 987
579a97f7 988 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 989 goto give_sigsegv;
66fb9763 990
1d8b512b 991 __put_user(current_exec_domain_sig(sig), &frame->sig);
28be6234 992 addr = frame_addr + offsetof(struct rt_sigframe, info);
1d8b512b 993 __put_user(addr, &frame->pinfo);
28be6234 994 addr = frame_addr + offsetof(struct rt_sigframe, uc);
1d8b512b 995 __put_user(addr, &frame->puc);
b0fd8d18 996 copy_siginfo_to_user(&frame->info, info);
31e31b8a 997
66fb9763 998 /* Create the ucontext. */
1d8b512b
RV
999 __put_user(0, &frame->uc.tuc_flags);
1000 __put_user(0, &frame->uc.tuc_link);
1001 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1002 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1003 &frame->uc.tuc_stack.ss_flags);
1004 __put_user(target_sigaltstack_used.ss_size,
1005 &frame->uc.tuc_stack.ss_size);
41ecc72b
RV
1006 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1007 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1008
0188fadb
RV
1009 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1010 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1011 }
31e31b8a 1012
66fb9763
FB
1013 /* Set up to return from userspace. If provided, use a stub
1014 already in userspace. */
624f7979 1015 if (ka->sa_flags & TARGET_SA_RESTORER) {
1d8b512b 1016 __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 1017 } else {
775b58d8 1018 uint16_t val16;
28be6234 1019 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
1d8b512b 1020 __put_user(addr, &frame->pretcode);
66fb9763 1021 /* This is movl $,%eax ; int $0x80 */
1d8b512b
RV
1022 __put_user(0xb8, (char *)(frame->retcode+0));
1023 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
775b58d8 1024 val16 = 0x80cd;
1d8b512b 1025 __put_user(val16, (uint16_t *)(frame->retcode+5));
66fb9763
FB
1026 }
1027
66fb9763 1028 /* Set up registers for signal handler */
28be6234 1029 env->regs[R_ESP] = frame_addr;
624f7979 1030 env->eip = ka->_sa_handler;
66fb9763
FB
1031
1032 cpu_x86_load_seg(env, R_DS, __USER_DS);
1033 cpu_x86_load_seg(env, R_ES, __USER_DS);
1034 cpu_x86_load_seg(env, R_SS, __USER_DS);
1035 cpu_x86_load_seg(env, R_CS, __USER_CS);
1036 env->eflags &= ~TF_MASK;
1037
579a97f7
FB
1038 unlock_user_struct(frame, frame_addr, 1);
1039
66fb9763
FB
1040 return;
1041
1042give_sigsegv:
1043 if (sig == TARGET_SIGSEGV)
624f7979 1044 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
1045 force_sig(TARGET_SIGSEGV /* , current */);
1046}
1047
1048static int
1049restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
1050{
1051 unsigned int err = 0;
28be6234
FB
1052 abi_ulong fpstate_addr;
1053 unsigned int tmpflags;
1054
1055 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1056 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1057 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1058 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
1059
1060 env->regs[R_EDI] = tswapl(sc->edi);
1061 env->regs[R_ESI] = tswapl(sc->esi);
1062 env->regs[R_EBP] = tswapl(sc->ebp);
1063 env->regs[R_ESP] = tswapl(sc->esp);
1064 env->regs[R_EBX] = tswapl(sc->ebx);
1065 env->regs[R_EDX] = tswapl(sc->edx);
1066 env->regs[R_ECX] = tswapl(sc->ecx);
1067 env->eip = tswapl(sc->eip);
66fb9763 1068
9a826d78
MM
1069 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1070 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
5fafdf24 1071
28be6234
FB
1072 tmpflags = tswapl(sc->eflags);
1073 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1074 // regs->orig_eax = -1; /* disable syscall checks */
66fb9763 1075
28be6234
FB
1076 fpstate_addr = tswapl(sc->fpstate);
1077 if (fpstate_addr != 0) {
1078 if (!access_ok(VERIFY_READ, fpstate_addr,
1079 sizeof(struct target_fpstate)))
1080 goto badframe;
1081 cpu_x86_frstor(env, fpstate_addr, 1);
66fb9763 1082 }
ed2dcdf6 1083
28be6234 1084 *peax = tswapl(sc->eax);
66fb9763 1085 return err;
66fb9763
FB
1086badframe:
1087 return 1;
66fb9763
FB
1088}
1089
1090long do_sigreturn(CPUX86State *env)
1091{
579a97f7
FB
1092 struct sigframe *frame;
1093 abi_ulong frame_addr = env->regs[R_ESP] - 8;
c227f099 1094 target_sigset_t target_set;
66fb9763
FB
1095 sigset_t set;
1096 int eax, i;
1097
447db213
FB
1098#if defined(DEBUG_SIGNAL)
1099 fprintf(stderr, "do_sigreturn\n");
1100#endif
579a97f7
FB
1101 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1102 goto badframe;
66fb9763 1103 /* set blocked signals */
f5f601af 1104 __get_user(target_set.sig[0], &frame->sc.oldmask);
9231944d 1105 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 1106 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
9231944d 1107 }
66fb9763 1108
9231944d 1109 target_to_host_sigset_internal(&set, &target_set);
1c275925 1110 do_sigprocmask(SIG_SETMASK, &set, NULL);
3b46e624 1111
66fb9763
FB
1112 /* restore registers */
1113 if (restore_sigcontext(env, &frame->sc, &eax))
1114 goto badframe;
579a97f7 1115 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1116 return eax;
1117
1118badframe:
579a97f7 1119 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1120 force_sig(TARGET_SIGSEGV);
1121 return 0;
1122}
1123
1124long do_rt_sigreturn(CPUX86State *env)
1125{
28be6234
FB
1126 abi_ulong frame_addr;
1127 struct rt_sigframe *frame;
66fb9763 1128 sigset_t set;
66fb9763
FB
1129 int eax;
1130
28be6234
FB
1131 frame_addr = env->regs[R_ESP] - 4;
1132 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1133 goto badframe;
b8076a74 1134 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1c275925 1135 do_sigprocmask(SIG_SETMASK, &set, NULL);
5fafdf24 1136
b8076a74 1137 if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
66fb9763
FB
1138 goto badframe;
1139
28be6234
FB
1140 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1141 get_sp_from_cpustate(env)) == -EFAULT)
66fb9763 1142 goto badframe;
a04e134a 1143
28be6234 1144 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1145 return eax;
1146
1147badframe:
28be6234
FB
1148 unlock_user_struct(frame, frame_addr, 0);
1149 force_sig(TARGET_SIGSEGV);
66fb9763
FB
1150 return 0;
1151}
1152
1744aea1
AS
1153#elif defined(TARGET_AARCH64)
1154
1155struct target_sigcontext {
1156 uint64_t fault_address;
1157 /* AArch64 registers */
1158 uint64_t regs[31];
1159 uint64_t sp;
1160 uint64_t pc;
1161 uint64_t pstate;
1162 /* 4K reserved for FP/SIMD state and future expansion */
1163 char __reserved[4096] __attribute__((__aligned__(16)));
1164};
1165
1166struct target_ucontext {
1167 abi_ulong tuc_flags;
1168 abi_ulong tuc_link;
1169 target_stack_t tuc_stack;
1170 target_sigset_t tuc_sigmask;
1171 /* glibc uses a 1024-bit sigset_t */
1172 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1173 /* last for future expansion */
1174 struct target_sigcontext tuc_mcontext;
1175};
1176
1177/*
1178 * Header to be used at the beginning of structures extending the user
1179 * context. Such structures must be placed after the rt_sigframe on the stack
1180 * and be 16-byte aligned. The last structure must be a dummy one with the
1181 * magic and size set to 0.
1182 */
1183struct target_aarch64_ctx {
1184 uint32_t magic;
1185 uint32_t size;
1186};
1187
1188#define TARGET_FPSIMD_MAGIC 0x46508001
1189
1190struct target_fpsimd_context {
1191 struct target_aarch64_ctx head;
1192 uint32_t fpsr;
1193 uint32_t fpcr;
1194 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1195};
1196
1197/*
1198 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1199 * user space as it will change with the addition of new context. User space
1200 * should check the magic/size information.
1201 */
1202struct target_aux_context {
1203 struct target_fpsimd_context fpsimd;
1204 /* additional context to be added before "end" */
1205 struct target_aarch64_ctx end;
1206};
1207
1208struct target_rt_sigframe {
1209 struct target_siginfo info;
1210 struct target_ucontext uc;
1211 uint64_t fp;
1212 uint64_t lr;
1213 uint32_t tramp[2];
1214};
1215
1216static int target_setup_sigframe(struct target_rt_sigframe *sf,
1217 CPUARMState *env, target_sigset_t *set)
1218{
1219 int i;
1220 struct target_aux_context *aux =
1221 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1222
1223 /* set up the stack frame for unwinding */
1224 __put_user(env->xregs[29], &sf->fp);
1225 __put_user(env->xregs[30], &sf->lr);
1226
1227 for (i = 0; i < 31; i++) {
1228 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1229 }
1230 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1231 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
d356312f 1232 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
1744aea1 1233
7af03928 1234 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
1744aea1
AS
1235
1236 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1237 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1238 }
1239
1240 for (i = 0; i < 32; i++) {
1241#ifdef TARGET_WORDS_BIGENDIAN
1242 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1243 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1244#else
1245 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1246 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1247#endif
1248 }
e0ee138b
WN
1249 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1250 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
1744aea1
AS
1251 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1252 __put_user(sizeof(struct target_fpsimd_context),
1253 &aux->fpsimd.head.size);
1254
1255 /* set the "end" magic */
1256 __put_user(0, &aux->end.magic);
1257 __put_user(0, &aux->end.size);
1258
1259 return 0;
1260}
1261
1262static int target_restore_sigframe(CPUARMState *env,
1263 struct target_rt_sigframe *sf)
1264{
1265 sigset_t set;
1266 int i;
1267 struct target_aux_context *aux =
1268 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
e0ee138b 1269 uint32_t magic, size, fpsr, fpcr;
d356312f 1270 uint64_t pstate;
1744aea1
AS
1271
1272 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
1c275925 1273 do_sigprocmask(SIG_SETMASK, &set, NULL);
1744aea1
AS
1274
1275 for (i = 0; i < 31; i++) {
1276 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1277 }
1278
1279 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1280 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
d356312f
PM
1281 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1282 pstate_write(env, pstate);
1744aea1
AS
1283
1284 __get_user(magic, &aux->fpsimd.head.magic);
1285 __get_user(size, &aux->fpsimd.head.size);
1286
1287 if (magic != TARGET_FPSIMD_MAGIC
1288 || size != sizeof(struct target_fpsimd_context)) {
1289 return 1;
1290 }
1291
4cf23480
PM
1292 for (i = 0; i < 32; i++) {
1293#ifdef TARGET_WORDS_BIGENDIAN
1294 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1295 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1296#else
1297 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1298 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1299#endif
1744aea1 1300 }
e0ee138b
WN
1301 __get_user(fpsr, &aux->fpsimd.fpsr);
1302 vfp_set_fpsr(env, fpsr);
1303 __get_user(fpcr, &aux->fpsimd.fpcr);
1304 vfp_set_fpcr(env, fpcr);
1744aea1
AS
1305
1306 return 0;
1307}
1308
1309static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1310{
1311 abi_ulong sp;
1312
1313 sp = env->xregs[31];
1314
1315 /*
1316 * This is the X/Open sanctioned signal stack switching.
1317 */
b545f63f 1318 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1744aea1
AS
1319 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1320 }
1321
1322 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1323
1324 return sp;
1325}
1326
1327static void target_setup_frame(int usig, struct target_sigaction *ka,
1328 target_siginfo_t *info, target_sigset_t *set,
1329 CPUARMState *env)
1330{
1331 struct target_rt_sigframe *frame;
8a3ae910 1332 abi_ulong frame_addr, return_addr;
1744aea1
AS
1333
1334 frame_addr = get_sigframe(ka, env);
1335 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1336 goto give_sigsegv;
1337 }
1338
1339 __put_user(0, &frame->uc.tuc_flags);
1340 __put_user(0, &frame->uc.tuc_link);
1341
1342 __put_user(target_sigaltstack_used.ss_sp,
1343 &frame->uc.tuc_stack.ss_sp);
1344 __put_user(sas_ss_flags(env->xregs[31]),
1345 &frame->uc.tuc_stack.ss_flags);
1346 __put_user(target_sigaltstack_used.ss_size,
1347 &frame->uc.tuc_stack.ss_size);
1348 target_setup_sigframe(frame, env, set);
8a3ae910
MM
1349 if (ka->sa_flags & TARGET_SA_RESTORER) {
1350 return_addr = ka->sa_restorer;
1351 } else {
1352 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1353 __put_user(0xd2801168, &frame->tramp[0]);
1354 __put_user(0xd4000001, &frame->tramp[1]);
1355 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1356 }
1744aea1
AS
1357 env->xregs[0] = usig;
1358 env->xregs[31] = frame_addr;
1359 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1360 env->pc = ka->_sa_handler;
8a3ae910 1361 env->xregs[30] = return_addr;
1744aea1 1362 if (info) {
b0fd8d18 1363 copy_siginfo_to_user(&frame->info, info);
1744aea1
AS
1364 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1365 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1366 }
1367
1368 unlock_user_struct(frame, frame_addr, 1);
1369 return;
1370
1371 give_sigsegv:
1372 unlock_user_struct(frame, frame_addr, 1);
1373 force_sig(TARGET_SIGSEGV);
1374}
1375
1376static void setup_rt_frame(int sig, struct target_sigaction *ka,
1377 target_siginfo_t *info, target_sigset_t *set,
1378 CPUARMState *env)
1379{
1380 target_setup_frame(sig, ka, info, set, env);
1381}
1382
1383static void setup_frame(int sig, struct target_sigaction *ka,
1384 target_sigset_t *set, CPUARMState *env)
1385{
1386 target_setup_frame(sig, ka, 0, set, env);
1387}
1388
1389long do_rt_sigreturn(CPUARMState *env)
1390{
7f72cd23 1391 struct target_rt_sigframe *frame = NULL;
1744aea1
AS
1392 abi_ulong frame_addr = env->xregs[31];
1393
1394 if (frame_addr & 15) {
1395 goto badframe;
1396 }
1397
1398 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1399 goto badframe;
1400 }
1401
1402 if (target_restore_sigframe(env, frame)) {
1403 goto badframe;
1404 }
1405
1406 if (do_sigaltstack(frame_addr +
1407 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1408 0, get_sp_from_cpustate(env)) == -EFAULT) {
1409 goto badframe;
1410 }
1411
1412 unlock_user_struct(frame, frame_addr, 0);
1413 return env->xregs[0];
1414
1415 badframe:
1416 unlock_user_struct(frame, frame_addr, 0);
1417 force_sig(TARGET_SIGSEGV);
1418 return 0;
1419}
1420
1421long do_sigreturn(CPUARMState *env)
1422{
1423 return do_rt_sigreturn(env);
1424}
1425
43fff238
FB
1426#elif defined(TARGET_ARM)
1427
1428struct target_sigcontext {
992f48a0
BS
1429 abi_ulong trap_no;
1430 abi_ulong error_code;
1431 abi_ulong oldmask;
1432 abi_ulong arm_r0;
1433 abi_ulong arm_r1;
1434 abi_ulong arm_r2;
1435 abi_ulong arm_r3;
1436 abi_ulong arm_r4;
1437 abi_ulong arm_r5;
1438 abi_ulong arm_r6;
1439 abi_ulong arm_r7;
1440 abi_ulong arm_r8;
1441 abi_ulong arm_r9;
1442 abi_ulong arm_r10;
1443 abi_ulong arm_fp;
1444 abi_ulong arm_ip;
1445 abi_ulong arm_sp;
1446 abi_ulong arm_lr;
1447 abi_ulong arm_pc;
1448 abi_ulong arm_cpsr;
1449 abi_ulong fault_address;
43fff238
FB
1450};
1451
a745ec6d
PB
1452struct target_ucontext_v1 {
1453 abi_ulong tuc_flags;
1454 abi_ulong tuc_link;
c227f099 1455 target_stack_t tuc_stack;
a745ec6d 1456 struct target_sigcontext tuc_mcontext;
c227f099 1457 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a745ec6d
PB
1458};
1459
1460struct target_ucontext_v2 {
992f48a0
BS
1461 abi_ulong tuc_flags;
1462 abi_ulong tuc_link;
c227f099 1463 target_stack_t tuc_stack;
b8076a74 1464 struct target_sigcontext tuc_mcontext;
c227f099 1465 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5f0b7c88 1466 char __unused[128 - sizeof(target_sigset_t)];
a745ec6d 1467 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
43fff238
FB
1468};
1469
0d871bdb
PM
1470struct target_user_vfp {
1471 uint64_t fpregs[32];
1472 abi_ulong fpscr;
1473};
1474
1475struct target_user_vfp_exc {
1476 abi_ulong fpexc;
1477 abi_ulong fpinst;
1478 abi_ulong fpinst2;
1479};
1480
1481struct target_vfp_sigframe {
1482 abi_ulong magic;
1483 abi_ulong size;
1484 struct target_user_vfp ufp;
1485 struct target_user_vfp_exc ufp_exc;
1486} __attribute__((__aligned__(8)));
1487
08e11256
PM
1488struct target_iwmmxt_sigframe {
1489 abi_ulong magic;
1490 abi_ulong size;
1491 uint64_t regs[16];
1492 /* Note that not all the coprocessor control registers are stored here */
1493 uint32_t wcssf;
1494 uint32_t wcasf;
1495 uint32_t wcgr0;
1496 uint32_t wcgr1;
1497 uint32_t wcgr2;
1498 uint32_t wcgr3;
1499} __attribute__((__aligned__(8)));
1500
0d871bdb 1501#define TARGET_VFP_MAGIC 0x56465001
08e11256 1502#define TARGET_IWMMXT_MAGIC 0x12ef842a
0d871bdb 1503
a8c33204 1504struct sigframe_v1
43fff238
FB
1505{
1506 struct target_sigcontext sc;
992f48a0
BS
1507 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1508 abi_ulong retcode;
43fff238
FB
1509};
1510
a8c33204
PB
1511struct sigframe_v2
1512{
1513 struct target_ucontext_v2 uc;
1514 abi_ulong retcode;
1515};
1516
a745ec6d 1517struct rt_sigframe_v1
43fff238 1518{
f8b0aa25
FB
1519 abi_ulong pinfo;
1520 abi_ulong puc;
43fff238 1521 struct target_siginfo info;
a745ec6d
PB
1522 struct target_ucontext_v1 uc;
1523 abi_ulong retcode;
1524};
1525
1526struct rt_sigframe_v2
1527{
1528 struct target_siginfo info;
1529 struct target_ucontext_v2 uc;
992f48a0 1530 abi_ulong retcode;
43fff238
FB
1531};
1532
1533#define TARGET_CONFIG_CPU_32 1
1534
1535/*
1536 * For ARM syscalls, we encode the syscall number into the instruction.
1537 */
1538#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1539#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1540
1541/*
1542 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1543 * need two 16-bit instructions.
1544 */
1545#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1546#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1547
992f48a0 1548static const abi_ulong retcodes[4] = {
43fff238
FB
1549 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1550 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1551};
1552
1553
05390248 1554static inline int valid_user_regs(CPUARMState *regs)
43fff238
FB
1555{
1556 return 1;
1557}
1558
a8c33204 1559static void
43fff238 1560setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
05390248 1561 CPUARMState *env, abi_ulong mask)
43fff238 1562{
a8c33204
PB
1563 __put_user(env->regs[0], &sc->arm_r0);
1564 __put_user(env->regs[1], &sc->arm_r1);
1565 __put_user(env->regs[2], &sc->arm_r2);
1566 __put_user(env->regs[3], &sc->arm_r3);
1567 __put_user(env->regs[4], &sc->arm_r4);
1568 __put_user(env->regs[5], &sc->arm_r5);
1569 __put_user(env->regs[6], &sc->arm_r6);
1570 __put_user(env->regs[7], &sc->arm_r7);
1571 __put_user(env->regs[8], &sc->arm_r8);
1572 __put_user(env->regs[9], &sc->arm_r9);
1573 __put_user(env->regs[10], &sc->arm_r10);
1574 __put_user(env->regs[11], &sc->arm_fp);
1575 __put_user(env->regs[12], &sc->arm_ip);
1576 __put_user(env->regs[13], &sc->arm_sp);
1577 __put_user(env->regs[14], &sc->arm_lr);
1578 __put_user(env->regs[15], &sc->arm_pc);
43fff238 1579#ifdef TARGET_CONFIG_CPU_32
a8c33204 1580 __put_user(cpsr_read(env), &sc->arm_cpsr);
43fff238
FB
1581#endif
1582
a8c33204
PB
1583 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1584 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1585 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1586 __put_user(mask, &sc->oldmask);
43fff238
FB
1587}
1588
579a97f7 1589static inline abi_ulong
05390248 1590get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
43fff238
FB
1591{
1592 unsigned long sp = regs->regs[13];
1593
43fff238
FB
1594 /*
1595 * This is the X/Open sanctioned signal stack switching.
1596 */
624f7979 1597 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
a04e134a 1598 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
43fff238
FB
1599 /*
1600 * ATPCS B01 mandates 8-byte alignment
1601 */
579a97f7 1602 return (sp - framesize) & ~7;
43fff238
FB
1603}
1604
0188fadb 1605static void
05390248 1606setup_return(CPUARMState *env, struct target_sigaction *ka,
f8b0aa25 1607 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
43fff238 1608{
624f7979 1609 abi_ulong handler = ka->_sa_handler;
992f48a0 1610 abi_ulong retcode;
75b680e5 1611 int thumb = handler & 1;
964413d9
PM
1612 uint32_t cpsr = cpsr_read(env);
1613
1614 cpsr &= ~CPSR_IT;
1615 if (thumb) {
1616 cpsr |= CPSR_T;
1617 } else {
1618 cpsr &= ~CPSR_T;
1619 }
43fff238 1620
624f7979
PB
1621 if (ka->sa_flags & TARGET_SA_RESTORER) {
1622 retcode = ka->sa_restorer;
43fff238
FB
1623 } else {
1624 unsigned int idx = thumb;
1625
624f7979 1626 if (ka->sa_flags & TARGET_SA_SIGINFO)
43fff238
FB
1627 idx += 2;
1628
0188fadb 1629 __put_user(retcodes[idx], rc);
ca8a277c 1630
f8b0aa25 1631 retcode = rc_addr + thumb;
43fff238
FB
1632 }
1633
1634 env->regs[0] = usig;
f8b0aa25 1635 env->regs[13] = frame_addr;
43fff238
FB
1636 env->regs[14] = retcode;
1637 env->regs[15] = handler & (thumb ? ~1 : ~3);
964413d9 1638 cpsr_write(env, cpsr, 0xffffffff);
43fff238
FB
1639}
1640
05390248 1641static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
0d871bdb
PM
1642{
1643 int i;
1644 struct target_vfp_sigframe *vfpframe;
1645 vfpframe = (struct target_vfp_sigframe *)regspace;
1646 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1647 __put_user(sizeof(*vfpframe), &vfpframe->size);
1648 for (i = 0; i < 32; i++) {
005e1a0a 1649 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
0d871bdb
PM
1650 }
1651 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1652 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1653 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1654 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1655 return (abi_ulong*)(vfpframe+1);
1656}
1657
05390248
AF
1658static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1659 CPUARMState *env)
08e11256
PM
1660{
1661 int i;
1662 struct target_iwmmxt_sigframe *iwmmxtframe;
1663 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1664 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1665 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1666 for (i = 0; i < 16; i++) {
1667 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1668 }
1669 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1670 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1671 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1672 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1673 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1674 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1675 return (abi_ulong*)(iwmmxtframe+1);
1676}
1677
a8c33204 1678static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
05390248 1679 target_sigset_t *set, CPUARMState *env)
a8c33204
PB
1680{
1681 struct target_sigaltstack stack;
1682 int i;
0d871bdb 1683 abi_ulong *regspace;
a8c33204
PB
1684
1685 /* Clear all the bits of the ucontext we don't use. */
1686 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1687
1688 memset(&stack, 0, sizeof(stack));
1689 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1690 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1691 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1692 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1693
1694 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
0d871bdb
PM
1695 /* Save coprocessor signal frame. */
1696 regspace = uc->tuc_regspace;
1697 if (arm_feature(env, ARM_FEATURE_VFP)) {
1698 regspace = setup_sigframe_v2_vfp(regspace, env);
1699 }
08e11256
PM
1700 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1701 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1702 }
1703
0d871bdb
PM
1704 /* Write terminating magic word */
1705 __put_user(0, regspace);
1706
a8c33204
PB
1707 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1708 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1709 }
1710}
1711
579a97f7 1712/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
624f7979 1713static void setup_frame_v1(int usig, struct target_sigaction *ka,
05390248 1714 target_sigset_t *set, CPUARMState *regs)
43fff238 1715{
a8c33204 1716 struct sigframe_v1 *frame;
579a97f7 1717 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
a8c33204 1718 int i;
43fff238 1719
579a97f7
FB
1720 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1721 return;
1722
a8c33204 1723 setup_sigcontext(&frame->sc, regs, set->sig[0]);
43fff238 1724
0188fadb
RV
1725 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1726 __put_user(set->sig[i], &frame->extramask[i - 1]);
1727 }
43fff238 1728
a8c33204
PB
1729 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1730 frame_addr + offsetof(struct sigframe_v1, retcode));
579a97f7 1731
579a97f7 1732 unlock_user_struct(frame, frame_addr, 1);
a8c33204
PB
1733}
1734
624f7979 1735static void setup_frame_v2(int usig, struct target_sigaction *ka,
05390248 1736 target_sigset_t *set, CPUARMState *regs)
a8c33204
PB
1737{
1738 struct sigframe_v2 *frame;
1739 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1740
1741 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1742 return;
1743
1744 setup_sigframe_v2(&frame->uc, set, regs);
1745
1746 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1747 frame_addr + offsetof(struct sigframe_v2, retcode));
1748
1749 unlock_user_struct(frame, frame_addr, 1);
1750}
1751
624f7979 1752static void setup_frame(int usig, struct target_sigaction *ka,
05390248 1753 target_sigset_t *set, CPUARMState *regs)
a8c33204
PB
1754{
1755 if (get_osversion() >= 0x020612) {
1756 setup_frame_v2(usig, ka, set, regs);
1757 } else {
1758 setup_frame_v1(usig, ka, set, regs);
1759 }
43fff238
FB
1760}
1761
579a97f7 1762/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
624f7979 1763static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
c227f099 1764 target_siginfo_t *info,
05390248 1765 target_sigset_t *set, CPUARMState *env)
43fff238 1766{
a745ec6d 1767 struct rt_sigframe_v1 *frame;
579a97f7 1768 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a04e134a 1769 struct target_sigaltstack stack;
a8c33204 1770 int i;
f8b0aa25 1771 abi_ulong info_addr, uc_addr;
43fff238 1772
579a97f7 1773 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
edf779ff
FB
1774 return /* 1 */;
1775
a745ec6d 1776 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
a8c33204 1777 __put_user(info_addr, &frame->pinfo);
a745ec6d 1778 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
a8c33204
PB
1779 __put_user(uc_addr, &frame->puc);
1780 copy_siginfo_to_user(&frame->info, info);
43fff238
FB
1781
1782 /* Clear all the bits of the ucontext we don't use. */
a745ec6d 1783 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
43fff238 1784
a04e134a
TS
1785 memset(&stack, 0, sizeof(stack));
1786 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1787 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1788 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
775b58d8 1789 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
a04e134a 1790
a8c33204 1791 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
9231944d 1792 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
0188fadb 1793 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
9231944d 1794 }
43fff238 1795
a8c33204
PB
1796 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1797 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
a745ec6d 1798
a8c33204
PB
1799 env->regs[1] = info_addr;
1800 env->regs[2] = uc_addr;
a745ec6d 1801
a745ec6d 1802 unlock_user_struct(frame, frame_addr, 1);
a745ec6d
PB
1803}
1804
624f7979 1805static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
c227f099 1806 target_siginfo_t *info,
05390248 1807 target_sigset_t *set, CPUARMState *env)
a745ec6d
PB
1808{
1809 struct rt_sigframe_v2 *frame;
1810 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a745ec6d
PB
1811 abi_ulong info_addr, uc_addr;
1812
1813 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1814 return /* 1 */;
1815
1816 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1817 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
a8c33204 1818 copy_siginfo_to_user(&frame->info, info);
a745ec6d 1819
a8c33204 1820 setup_sigframe_v2(&frame->uc, set, env);
a745ec6d 1821
a8c33204
PB
1822 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1823 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
a745ec6d 1824
a8c33204
PB
1825 env->regs[1] = info_addr;
1826 env->regs[2] = uc_addr;
43fff238 1827
579a97f7 1828 unlock_user_struct(frame, frame_addr, 1);
43fff238
FB
1829}
1830
624f7979 1831static void setup_rt_frame(int usig, struct target_sigaction *ka,
c227f099 1832 target_siginfo_t *info,
05390248 1833 target_sigset_t *set, CPUARMState *env)
a745ec6d
PB
1834{
1835 if (get_osversion() >= 0x020612) {
1836 setup_rt_frame_v2(usig, ka, info, set, env);
1837 } else {
1838 setup_rt_frame_v1(usig, ka, info, set, env);
1839 }
1840}
1841
43fff238 1842static int
05390248 1843restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
43fff238
FB
1844{
1845 int err = 0;
b5ff1b31 1846 uint32_t cpsr;
43fff238 1847
1d8b512b
RV
1848 __get_user(env->regs[0], &sc->arm_r0);
1849 __get_user(env->regs[1], &sc->arm_r1);
1850 __get_user(env->regs[2], &sc->arm_r2);
1851 __get_user(env->regs[3], &sc->arm_r3);
1852 __get_user(env->regs[4], &sc->arm_r4);
1853 __get_user(env->regs[5], &sc->arm_r5);
1854 __get_user(env->regs[6], &sc->arm_r6);
1855 __get_user(env->regs[7], &sc->arm_r7);
1856 __get_user(env->regs[8], &sc->arm_r8);
1857 __get_user(env->regs[9], &sc->arm_r9);
1858 __get_user(env->regs[10], &sc->arm_r10);
1859 __get_user(env->regs[11], &sc->arm_fp);
1860 __get_user(env->regs[12], &sc->arm_ip);
1861 __get_user(env->regs[13], &sc->arm_sp);
1862 __get_user(env->regs[14], &sc->arm_lr);
1863 __get_user(env->regs[15], &sc->arm_pc);
43fff238 1864#ifdef TARGET_CONFIG_CPU_32
1d8b512b 1865 __get_user(cpsr, &sc->arm_cpsr);
75b680e5 1866 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
43fff238
FB
1867#endif
1868
1869 err |= !valid_user_regs(env);
1870
1871 return err;
1872}
1873
05390248 1874static long do_sigreturn_v1(CPUARMState *env)
43fff238 1875{
f8b0aa25 1876 abi_ulong frame_addr;
978fae9f 1877 struct sigframe_v1 *frame = NULL;
c227f099 1878 target_sigset_t set;
43fff238 1879 sigset_t host_set;
9231944d 1880 int i;
43fff238
FB
1881
1882 /*
1883 * Since we stacked the signal on a 64-bit boundary,
1884 * then 'sp' should be word aligned here. If it's
1885 * not, then the user is trying to mess with us.
1886 */
f8b0aa25 1887 frame_addr = env->regs[13];
978fae9f
PM
1888 if (frame_addr & 7) {
1889 goto badframe;
1890 }
1891
f8b0aa25
FB
1892 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1893 goto badframe;
43fff238 1894
f5f601af
RV
1895 __get_user(set.sig[0], &frame->sc.oldmask);
1896 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1897 __get_user(set.sig[i], &frame->extramask[i - 1]);
1898 }
43fff238 1899
9231944d 1900 target_to_host_sigset_internal(&host_set, &set);
1c275925 1901 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
43fff238
FB
1902
1903 if (restore_sigcontext(env, &frame->sc))
1904 goto badframe;
1905
1906#if 0
1907 /* Send SIGTRAP if we're single-stepping */
1908 if (ptrace_cancel_bpt(current))
1909 send_sig(SIGTRAP, current, 1);
1910#endif
f8b0aa25
FB
1911 unlock_user_struct(frame, frame_addr, 0);
1912 return env->regs[0];
43fff238
FB
1913
1914badframe:
66393fb9 1915 force_sig(TARGET_SIGSEGV /* , current */);
43fff238
FB
1916 return 0;
1917}
1918
05390248 1919static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
5f9099d9
PM
1920{
1921 int i;
1922 abi_ulong magic, sz;
1923 uint32_t fpscr, fpexc;
1924 struct target_vfp_sigframe *vfpframe;
1925 vfpframe = (struct target_vfp_sigframe *)regspace;
1926
1927 __get_user(magic, &vfpframe->magic);
1928 __get_user(sz, &vfpframe->size);
1929 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1930 return 0;
1931 }
1932 for (i = 0; i < 32; i++) {
005e1a0a 1933 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
5f9099d9
PM
1934 }
1935 __get_user(fpscr, &vfpframe->ufp.fpscr);
1936 vfp_set_fpscr(env, fpscr);
1937 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1938 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1939 * and the exception flag is cleared
1940 */
1941 fpexc |= (1 << 30);
1942 fpexc &= ~((1 << 31) | (1 << 28));
1943 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1944 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1945 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1946 return (abi_ulong*)(vfpframe + 1);
1947}
1948
05390248
AF
1949static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1950 abi_ulong *regspace)
a59d69da
PM
1951{
1952 int i;
1953 abi_ulong magic, sz;
1954 struct target_iwmmxt_sigframe *iwmmxtframe;
1955 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1956
1957 __get_user(magic, &iwmmxtframe->magic);
1958 __get_user(sz, &iwmmxtframe->size);
1959 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1960 return 0;
1961 }
1962 for (i = 0; i < 16; i++) {
1963 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1964 }
1965 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1966 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1967 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1968 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1969 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1970 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1971 return (abi_ulong*)(iwmmxtframe + 1);
1972}
1973
05390248 1974static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
a8c33204
PB
1975 struct target_ucontext_v2 *uc)
1976{
1977 sigset_t host_set;
5f9099d9 1978 abi_ulong *regspace;
a8c33204
PB
1979
1980 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
1c275925 1981 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
a8c33204
PB
1982
1983 if (restore_sigcontext(env, &uc->tuc_mcontext))
1984 return 1;
1985
5f9099d9
PM
1986 /* Restore coprocessor signal frame */
1987 regspace = uc->tuc_regspace;
1988 if (arm_feature(env, ARM_FEATURE_VFP)) {
1989 regspace = restore_sigframe_v2_vfp(env, regspace);
1990 if (!regspace) {
1991 return 1;
1992 }
1993 }
a59d69da
PM
1994 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1995 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1996 if (!regspace) {
1997 return 1;
1998 }
1999 }
5f9099d9 2000
a8c33204
PB
2001 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2002 return 1;
2003
2004#if 0
2005 /* Send SIGTRAP if we're single-stepping */
2006 if (ptrace_cancel_bpt(current))
2007 send_sig(SIGTRAP, current, 1);
2008#endif
2009
2010 return 0;
2011}
2012
05390248 2013static long do_sigreturn_v2(CPUARMState *env)
a8c33204
PB
2014{
2015 abi_ulong frame_addr;
978fae9f 2016 struct sigframe_v2 *frame = NULL;
a8c33204
PB
2017
2018 /*
2019 * Since we stacked the signal on a 64-bit boundary,
2020 * then 'sp' should be word aligned here. If it's
2021 * not, then the user is trying to mess with us.
2022 */
a8c33204 2023 frame_addr = env->regs[13];
978fae9f
PM
2024 if (frame_addr & 7) {
2025 goto badframe;
2026 }
2027
a8c33204
PB
2028 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2029 goto badframe;
2030
2031 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2032 goto badframe;
2033
2034 unlock_user_struct(frame, frame_addr, 0);
2035 return env->regs[0];
2036
2037badframe:
2038 unlock_user_struct(frame, frame_addr, 0);
66393fb9 2039 force_sig(TARGET_SIGSEGV /* , current */);
a8c33204
PB
2040 return 0;
2041}
2042
05390248 2043long do_sigreturn(CPUARMState *env)
a8c33204
PB
2044{
2045 if (get_osversion() >= 0x020612) {
2046 return do_sigreturn_v2(env);
2047 } else {
2048 return do_sigreturn_v1(env);
2049 }
2050}
2051
05390248 2052static long do_rt_sigreturn_v1(CPUARMState *env)
43fff238 2053{
f8b0aa25 2054 abi_ulong frame_addr;
978fae9f 2055 struct rt_sigframe_v1 *frame = NULL;
a745ec6d
PB
2056 sigset_t host_set;
2057
2058 /*
2059 * Since we stacked the signal on a 64-bit boundary,
2060 * then 'sp' should be word aligned here. If it's
2061 * not, then the user is trying to mess with us.
2062 */
a745ec6d 2063 frame_addr = env->regs[13];
978fae9f
PM
2064 if (frame_addr & 7) {
2065 goto badframe;
2066 }
2067
a745ec6d
PB
2068 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2069 goto badframe;
2070
2071 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1c275925 2072 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
a745ec6d
PB
2073
2074 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
2075 goto badframe;
2076
2077 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2078 goto badframe;
2079
2080#if 0
2081 /* Send SIGTRAP if we're single-stepping */
2082 if (ptrace_cancel_bpt(current))
2083 send_sig(SIGTRAP, current, 1);
2084#endif
2085 unlock_user_struct(frame, frame_addr, 0);
2086 return env->regs[0];
2087
2088badframe:
2089 unlock_user_struct(frame, frame_addr, 0);
66393fb9 2090 force_sig(TARGET_SIGSEGV /* , current */);
a745ec6d
PB
2091 return 0;
2092}
2093
05390248 2094static long do_rt_sigreturn_v2(CPUARMState *env)
a745ec6d
PB
2095{
2096 abi_ulong frame_addr;
978fae9f 2097 struct rt_sigframe_v2 *frame = NULL;
43fff238
FB
2098
2099 /*
2100 * Since we stacked the signal on a 64-bit boundary,
2101 * then 'sp' should be word aligned here. If it's
2102 * not, then the user is trying to mess with us.
2103 */
f8b0aa25 2104 frame_addr = env->regs[13];
978fae9f
PM
2105 if (frame_addr & 7) {
2106 goto badframe;
2107 }
2108
f8b0aa25
FB
2109 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2110 goto badframe;
43fff238 2111
a8c33204
PB
2112 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2113 goto badframe;
a04e134a 2114
f8b0aa25 2115 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
2116 return env->regs[0];
2117
2118badframe:
f8b0aa25 2119 unlock_user_struct(frame, frame_addr, 0);
66393fb9 2120 force_sig(TARGET_SIGSEGV /* , current */);
43fff238
FB
2121 return 0;
2122}
2123
05390248 2124long do_rt_sigreturn(CPUARMState *env)
a745ec6d
PB
2125{
2126 if (get_osversion() >= 0x020612) {
2127 return do_rt_sigreturn_v2(env);
2128 } else {
2129 return do_rt_sigreturn_v1(env);
2130 }
2131}
2132
6d5e216d 2133#elif defined(TARGET_SPARC)
80a9d035 2134
6d5e216d
FB
2135#define __SUNOS_MAXWIN 31
2136
2137/* This is what SunOS does, so shall I. */
2138struct target_sigcontext {
992f48a0 2139 abi_ulong sigc_onstack; /* state to restore */
6d5e216d 2140
992f48a0
BS
2141 abi_ulong sigc_mask; /* sigmask to restore */
2142 abi_ulong sigc_sp; /* stack pointer */
2143 abi_ulong sigc_pc; /* program counter */
2144 abi_ulong sigc_npc; /* next program counter */
2145 abi_ulong sigc_psr; /* for condition codes etc */
2146 abi_ulong sigc_g1; /* User uses these two registers */
2147 abi_ulong sigc_o0; /* within the trampoline code. */
6d5e216d
FB
2148
2149 /* Now comes information regarding the users window set
2150 * at the time of the signal.
2151 */
992f48a0 2152 abi_ulong sigc_oswins; /* outstanding windows */
6d5e216d
FB
2153
2154 /* stack ptrs for each regwin buf */
2155 char *sigc_spbuf[__SUNOS_MAXWIN];
2156
2157 /* Windows to restore after signal */
2158 struct {
992f48a0
BS
2159 abi_ulong locals[8];
2160 abi_ulong ins[8];
6d5e216d
FB
2161 } sigc_wbuf[__SUNOS_MAXWIN];
2162};
2163/* A Sparc stack frame */
2164struct sparc_stackf {
992f48a0 2165 abi_ulong locals[8];
e321c34a
PM
2166 abi_ulong ins[8];
2167 /* It's simpler to treat fp and callers_pc as elements of ins[]
2168 * since we never need to access them ourselves.
2169 */
6d5e216d 2170 char *structptr;
992f48a0
BS
2171 abi_ulong xargs[6];
2172 abi_ulong xxargs[1];
6d5e216d
FB
2173};
2174
2175typedef struct {
2176 struct {
992f48a0
BS
2177 abi_ulong psr;
2178 abi_ulong pc;
2179 abi_ulong npc;
2180 abi_ulong y;
2181 abi_ulong u_regs[16]; /* globals and ins */
6d5e216d
FB
2182 } si_regs;
2183 int si_mask;
2184} __siginfo_t;
2185
2186typedef struct {
8954bae3 2187 abi_ulong si_float_regs[32];
6d5e216d
FB
2188 unsigned long si_fsr;
2189 unsigned long si_fpqdepth;
2190 struct {
2191 unsigned long *insn_addr;
2192 unsigned long insn;
2193 } si_fpqueue [16];
c227f099 2194} qemu_siginfo_fpu_t;
6d5e216d
FB
2195
2196
2197struct target_signal_frame {
2198 struct sparc_stackf ss;
2199 __siginfo_t info;
f8b0aa25 2200 abi_ulong fpu_save;
992f48a0
BS
2201 abi_ulong insns[2] __attribute__ ((aligned (8)));
2202 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2203 abi_ulong extra_size; /* Should be 0 */
c227f099 2204 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
2205};
2206struct target_rt_signal_frame {
2207 struct sparc_stackf ss;
2208 siginfo_t info;
992f48a0 2209 abi_ulong regs[20];
6d5e216d 2210 sigset_t mask;
f8b0aa25 2211 abi_ulong fpu_save;
6d5e216d
FB
2212 unsigned int insns[2];
2213 stack_t stack;
2214 unsigned int extra_size; /* Should be 0 */
c227f099 2215 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
2216};
2217
e80cfcfc
FB
2218#define UREG_O0 16
2219#define UREG_O6 22
2220#define UREG_I0 0
2221#define UREG_I1 1
2222#define UREG_I2 2
5bfb56b2
BS
2223#define UREG_I3 3
2224#define UREG_I4 4
2225#define UREG_I5 5
e80cfcfc
FB
2226#define UREG_I6 6
2227#define UREG_I7 7
2228#define UREG_L0 8
6d5e216d
FB
2229#define UREG_FP UREG_I6
2230#define UREG_SP UREG_O6
2231
624f7979 2232static inline abi_ulong get_sigframe(struct target_sigaction *sa,
05390248
AF
2233 CPUSPARCState *env,
2234 unsigned long framesize)
6d5e216d 2235{
459a4017 2236 abi_ulong sp;
6d5e216d
FB
2237
2238 sp = env->regwptr[UREG_FP];
6d5e216d
FB
2239
2240 /* This is the X/Open sanctioned signal stack switching. */
624f7979 2241 if (sa->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
2242 if (!on_sig_stack(sp)
2243 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
2244 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6d5e216d 2245 }
459a4017 2246 return sp - framesize;
6d5e216d
FB
2247}
2248
2249static int
05390248 2250setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
6d5e216d
FB
2251{
2252 int err = 0, i;
2253
1d8b512b
RV
2254 __put_user(env->psr, &si->si_regs.psr);
2255 __put_user(env->pc, &si->si_regs.pc);
2256 __put_user(env->npc, &si->si_regs.npc);
2257 __put_user(env->y, &si->si_regs.y);
a315a145 2258 for (i=0; i < 8; i++) {
1d8b512b 2259 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
6d5e216d 2260 }
a315a145 2261 for (i=0; i < 8; i++) {
1d8b512b 2262 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
6d5e216d 2263 }
1d8b512b 2264 __put_user(mask, &si->si_mask);
6d5e216d
FB
2265 return err;
2266}
e80cfcfc 2267
80a9d035 2268#if 0
6d5e216d
FB
2269static int
2270setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
05390248 2271 CPUSPARCState *env, unsigned long mask)
6d5e216d
FB
2272{
2273 int err = 0;
2274
1d8b512b
RV
2275 __put_user(mask, &sc->sigc_mask);
2276 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2277 __put_user(env->pc, &sc->sigc_pc);
2278 __put_user(env->npc, &sc->sigc_npc);
2279 __put_user(env->psr, &sc->sigc_psr);
2280 __put_user(env->gregs[1], &sc->sigc_g1);
2281 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
6d5e216d
FB
2282
2283 return err;
2284}
80a9d035 2285#endif
6d5e216d
FB
2286#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2287
624f7979 2288static void setup_frame(int sig, struct target_sigaction *ka,
05390248 2289 target_sigset_t *set, CPUSPARCState *env)
6d5e216d 2290{
459a4017 2291 abi_ulong sf_addr;
6d5e216d
FB
2292 struct target_signal_frame *sf;
2293 int sigframe_size, err, i;
2294
2295 /* 1. Make sure everything is clean */
2296 //synchronize_user_stack();
2297
2298 sigframe_size = NF_ALIGNEDSZ;
459a4017 2299 sf_addr = get_sigframe(ka, env, sigframe_size);
6d5e216d 2300
459a4017
FB
2301 sf = lock_user(VERIFY_WRITE, sf_addr,
2302 sizeof(struct target_signal_frame), 0);
2303 if (!sf)
2304 goto sigsegv;
2305
e80cfcfc 2306 //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
6d5e216d
FB
2307#if 0
2308 if (invalid_frame_pointer(sf, sigframe_size))
2309 goto sigill_and_return;
2310#endif
2311 /* 2. Save the current process state */
2312 err = setup___siginfo(&sf->info, env, set->sig[0]);
1d8b512b 2313 __put_user(0, &sf->extra_size);
6d5e216d 2314
1d8b512b
RV
2315 //save_fpu_state(regs, &sf->fpu_state);
2316 //__put_user(&sf->fpu_state, &sf->fpu_save);
6d5e216d 2317
1d8b512b 2318 __put_user(set->sig[0], &sf->info.si_mask);
6d5e216d 2319 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1d8b512b 2320 __put_user(set->sig[i + 1], &sf->extramask[i]);
6d5e216d
FB
2321 }
2322
a315a145 2323 for (i = 0; i < 8; i++) {
1d8b512b 2324 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
6d5e216d 2325 }
a315a145 2326 for (i = 0; i < 8; i++) {
1d8b512b 2327 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
6d5e216d 2328 }
6d5e216d
FB
2329 if (err)
2330 goto sigsegv;
2331
2332 /* 3. signal handler back-trampoline and parameters */
459a4017 2333 env->regwptr[UREG_FP] = sf_addr;
6d5e216d 2334 env->regwptr[UREG_I0] = sig;
459a4017
FB
2335 env->regwptr[UREG_I1] = sf_addr +
2336 offsetof(struct target_signal_frame, info);
2337 env->regwptr[UREG_I2] = sf_addr +
2338 offsetof(struct target_signal_frame, info);
6d5e216d
FB
2339
2340 /* 4. signal handler */
624f7979 2341 env->pc = ka->_sa_handler;
6d5e216d
FB
2342 env->npc = (env->pc + 4);
2343 /* 5. return to kernel instructions */
624f7979
PB
2344 if (ka->sa_restorer)
2345 env->regwptr[UREG_I7] = ka->sa_restorer;
6d5e216d 2346 else {
775b58d8 2347 uint32_t val32;
459a4017
FB
2348
2349 env->regwptr[UREG_I7] = sf_addr +
2350 offsetof(struct target_signal_frame, insns) - 2 * 4;
6d5e216d
FB
2351
2352 /* mov __NR_sigreturn, %g1 */
775b58d8 2353 val32 = 0x821020d8;
1d8b512b 2354 __put_user(val32, &sf->insns[0]);
6d5e216d
FB
2355
2356 /* t 0x10 */
775b58d8 2357 val32 = 0x91d02010;
1d8b512b 2358 __put_user(val32, &sf->insns[1]);
6d5e216d
FB
2359 if (err)
2360 goto sigsegv;
2361
2362 /* Flush instruction space. */
2363 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
80a9d035 2364 // tb_flush(env);
6d5e216d 2365 }
459a4017 2366 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d 2367 return;
459a4017
FB
2368#if 0
2369sigill_and_return:
6d5e216d 2370 force_sig(TARGET_SIGILL);
459a4017 2371#endif
6d5e216d 2372sigsegv:
e80cfcfc 2373 //fprintf(stderr, "force_sig\n");
459a4017 2374 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d
FB
2375 force_sig(TARGET_SIGSEGV);
2376}
6d5e216d 2377
624f7979 2378static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 2379 target_siginfo_t *info,
05390248 2380 target_sigset_t *set, CPUSPARCState *env)
6d5e216d
FB
2381{
2382 fprintf(stderr, "setup_rt_frame: not implemented\n");
2383}
2384
05390248 2385long do_sigreturn(CPUSPARCState *env)
6d5e216d 2386{
f8b0aa25 2387 abi_ulong sf_addr;
6d5e216d 2388 struct target_signal_frame *sf;
e80cfcfc 2389 uint32_t up_psr, pc, npc;
c227f099 2390 target_sigset_t set;
e80cfcfc 2391 sigset_t host_set;
1d8b512b 2392 int err=0, i;
6d5e216d 2393
f8b0aa25
FB
2394 sf_addr = env->regwptr[UREG_FP];
2395 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
2396 goto segv_and_exit;
80a9d035 2397#if 0
e80cfcfc
FB
2398 fprintf(stderr, "sigreturn\n");
2399 fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
80a9d035 2400#endif
e80cfcfc 2401 //cpu_dump_state(env, stderr, fprintf, 0);
6d5e216d
FB
2402
2403 /* 1. Make sure we are not getting garbage from the user */
6d5e216d 2404
f8b0aa25 2405 if (sf_addr & 3)
6d5e216d
FB
2406 goto segv_and_exit;
2407
1d8b512b
RV
2408 __get_user(pc, &sf->info.si_regs.pc);
2409 __get_user(npc, &sf->info.si_regs.npc);
6d5e216d 2410
6d5e216d
FB
2411 if ((pc | npc) & 3)
2412 goto segv_and_exit;
2413
2414 /* 2. Restore the state */
1d8b512b 2415 __get_user(up_psr, &sf->info.si_regs.psr);
e80cfcfc 2416
6d5e216d 2417 /* User can only change condition codes and FPU enabling in %psr. */
a315a145
FB
2418 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2419 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
2420
2421 env->pc = pc;
2422 env->npc = npc;
1d8b512b 2423 __get_user(env->y, &sf->info.si_regs.y);
a315a145 2424 for (i=0; i < 8; i++) {
1d8b512b 2425 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
e80cfcfc 2426 }
a315a145 2427 for (i=0; i < 8; i++) {
1d8b512b 2428 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
e80cfcfc 2429 }
6d5e216d 2430
2aec3a27
PM
2431 /* FIXME: implement FPU save/restore:
2432 * __get_user(fpu_save, &sf->fpu_save);
2433 * if (fpu_save)
2434 * err |= restore_fpu_state(env, fpu_save);
2435 */
6d5e216d
FB
2436
2437 /* This is pretty much atomic, no amount locking would prevent
2438 * the races which exist anyways.
2439 */
1d8b512b 2440 __get_user(set.sig[0], &sf->info.si_mask);
e80cfcfc 2441 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 2442 __get_user(set.sig[i], &sf->extramask[i - 1]);
e80cfcfc
FB
2443 }
2444
2445 target_to_host_sigset_internal(&host_set, &set);
1c275925 2446 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
6d5e216d
FB
2447
2448 if (err)
2449 goto segv_and_exit;
f8b0aa25 2450 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
2451 return env->regwptr[0];
2452
2453segv_and_exit:
f8b0aa25 2454 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
2455 force_sig(TARGET_SIGSEGV);
2456}
2457
05390248 2458long do_rt_sigreturn(CPUSPARCState *env)
6d5e216d
FB
2459{
2460 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2461 return -TARGET_ENOSYS;
6d5e216d
FB
2462}
2463
459a4017 2464#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
5bfb56b2
BS
2465#define MC_TSTATE 0
2466#define MC_PC 1
2467#define MC_NPC 2
2468#define MC_Y 3
2469#define MC_G1 4
2470#define MC_G2 5
2471#define MC_G3 6
2472#define MC_G4 7
2473#define MC_G5 8
2474#define MC_G6 9
2475#define MC_G7 10
2476#define MC_O0 11
2477#define MC_O1 12
2478#define MC_O2 13
2479#define MC_O3 14
2480#define MC_O4 15
2481#define MC_O5 16
2482#define MC_O6 17
2483#define MC_O7 18
2484#define MC_NGREG 19
2485
c227f099
AL
2486typedef abi_ulong target_mc_greg_t;
2487typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
5bfb56b2
BS
2488
2489struct target_mc_fq {
992f48a0 2490 abi_ulong *mcfq_addr;
5bfb56b2
BS
2491 uint32_t mcfq_insn;
2492};
2493
2494struct target_mc_fpu {
2495 union {
2496 uint32_t sregs[32];
2497 uint64_t dregs[32];
2498 //uint128_t qregs[16];
2499 } mcfpu_fregs;
992f48a0
BS
2500 abi_ulong mcfpu_fsr;
2501 abi_ulong mcfpu_fprs;
2502 abi_ulong mcfpu_gsr;
5bfb56b2
BS
2503 struct target_mc_fq *mcfpu_fq;
2504 unsigned char mcfpu_qcnt;
2505 unsigned char mcfpu_qentsz;
2506 unsigned char mcfpu_enab;
2507};
c227f099 2508typedef struct target_mc_fpu target_mc_fpu_t;
5bfb56b2
BS
2509
2510typedef struct {
c227f099
AL
2511 target_mc_gregset_t mc_gregs;
2512 target_mc_greg_t mc_fp;
2513 target_mc_greg_t mc_i7;
2514 target_mc_fpu_t mc_fpregs;
2515} target_mcontext_t;
5bfb56b2
BS
2516
2517struct target_ucontext {
60e99246
AJ
2518 struct target_ucontext *tuc_link;
2519 abi_ulong tuc_flags;
2520 target_sigset_t tuc_sigmask;
2521 target_mcontext_t tuc_mcontext;
5bfb56b2
BS
2522};
2523
2524/* A V9 register window */
2525struct target_reg_window {
992f48a0
BS
2526 abi_ulong locals[8];
2527 abi_ulong ins[8];
5bfb56b2
BS
2528};
2529
2530#define TARGET_STACK_BIAS 2047
2531
2532/* {set, get}context() needed for 64-bit SparcLinux userland. */
2533void sparc64_set_context(CPUSPARCState *env)
2534{
459a4017
FB
2535 abi_ulong ucp_addr;
2536 struct target_ucontext *ucp;
c227f099 2537 target_mc_gregset_t *grp;
992f48a0 2538 abi_ulong pc, npc, tstate;
459a4017 2539 abi_ulong fp, i7, w_addr;
5bfb56b2 2540 unsigned int i;
5bfb56b2 2541
459a4017
FB
2542 ucp_addr = env->regwptr[UREG_I0];
2543 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2544 goto do_sigsegv;
60e99246 2545 grp = &ucp->tuc_mcontext.mc_gregs;
1d8b512b
RV
2546 __get_user(pc, &((*grp)[MC_PC]));
2547 __get_user(npc, &((*grp)[MC_NPC]));
be3ef5c7 2548 if ((pc | npc) & 3)
5bfb56b2
BS
2549 goto do_sigsegv;
2550 if (env->regwptr[UREG_I1]) {
c227f099 2551 target_sigset_t target_set;
5bfb56b2
BS
2552 sigset_t set;
2553
2554 if (TARGET_NSIG_WORDS == 1) {
be3ef5c7 2555 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
5bfb56b2 2556 } else {
459a4017 2557 abi_ulong *src, *dst;
60e99246 2558 src = ucp->tuc_sigmask.sig;
459a4017 2559 dst = target_set.sig;
0d9e61c2 2560 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
1d8b512b 2561 __get_user(*dst, src);
0d9e61c2 2562 }
5bfb56b2
BS
2563 }
2564 target_to_host_sigset_internal(&set, &target_set);
1c275925 2565 do_sigprocmask(SIG_SETMASK, &set, NULL);
5bfb56b2
BS
2566 }
2567 env->pc = pc;
2568 env->npc = npc;
1d8b512b
RV
2569 __get_user(env->y, &((*grp)[MC_Y]));
2570 __get_user(tstate, &((*grp)[MC_TSTATE]));
5bfb56b2 2571 env->asi = (tstate >> 24) & 0xff;
5a834bb4
BS
2572 cpu_put_ccr(env, tstate >> 32);
2573 cpu_put_cwp64(env, tstate & 0x1f);
1d8b512b
RV
2574 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2575 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2576 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2577 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2578 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2579 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2580 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2581 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2582 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2583 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2584 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2585 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2586 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2587 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2588 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2589
2590 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2591 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
579a97f7 2592
459a4017
FB
2593 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2594 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2595 abi_ulong) != 0)
2596 goto do_sigsegv;
2597 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2598 abi_ulong) != 0)
2599 goto do_sigsegv;
c7b016ba
PM
2600 /* FIXME this does not match how the kernel handles the FPU in
2601 * its sparc64_set_context implementation. In particular the FPU
2602 * is only restored if fenab is non-zero in:
2603 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2604 */
be3ef5c7 2605 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
459a4017 2606 {
30038fd8
RH
2607 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2608 for (i = 0; i < 64; i++, src++) {
2609 if (i & 1) {
1d8b512b 2610 __get_user(env->fpr[i/2].l.lower, src);
30038fd8 2611 } else {
1d8b512b 2612 __get_user(env->fpr[i/2].l.upper, src);
30038fd8
RH
2613 }
2614 }
459a4017 2615 }
1d8b512b
RV
2616 __get_user(env->fsr,
2617 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2618 __get_user(env->gsr,
2619 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
459a4017 2620 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2
BS
2621 return;
2622 do_sigsegv:
459a4017 2623 unlock_user_struct(ucp, ucp_addr, 0);
66393fb9 2624 force_sig(TARGET_SIGSEGV);
5bfb56b2
BS
2625}
2626
2627void sparc64_get_context(CPUSPARCState *env)
2628{
459a4017
FB
2629 abi_ulong ucp_addr;
2630 struct target_ucontext *ucp;
c227f099
AL
2631 target_mc_gregset_t *grp;
2632 target_mcontext_t *mcp;
459a4017 2633 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2634 int err;
2635 unsigned int i;
c227f099 2636 target_sigset_t target_set;
5bfb56b2
BS
2637 sigset_t set;
2638
459a4017
FB
2639 ucp_addr = env->regwptr[UREG_I0];
2640 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2641 goto do_sigsegv;
2642
60e99246 2643 mcp = &ucp->tuc_mcontext;
5bfb56b2
BS
2644 grp = &mcp->mc_gregs;
2645
2646 /* Skip over the trap instruction, first. */
2647 env->pc = env->npc;
2648 env->npc += 4;
2649
2650 err = 0;
2651
1c275925 2652 do_sigprocmask(0, NULL, &set);
5bfb56b2 2653 host_to_target_sigset_internal(&target_set, &set);
459a4017 2654 if (TARGET_NSIG_WORDS == 1) {
1d8b512b
RV
2655 __put_user(target_set.sig[0],
2656 (abi_ulong *)&ucp->tuc_sigmask);
459a4017
FB
2657 } else {
2658 abi_ulong *src, *dst;
2659 src = target_set.sig;
60e99246 2660 dst = ucp->tuc_sigmask.sig;
0d9e61c2 2661 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
1d8b512b 2662 __put_user(*src, dst);
0d9e61c2 2663 }
5bfb56b2
BS
2664 if (err)
2665 goto do_sigsegv;
2666 }
2667
459a4017 2668 /* XXX: tstate must be saved properly */
1d8b512b
RV
2669 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2670 __put_user(env->pc, &((*grp)[MC_PC]));
2671 __put_user(env->npc, &((*grp)[MC_NPC]));
2672 __put_user(env->y, &((*grp)[MC_Y]));
2673 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2674 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2675 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2676 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2677 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2678 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2679 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2680 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2681 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2682 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2683 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2684 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2685 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2686 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2687 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
579a97f7 2688
459a4017
FB
2689 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2690 fp = i7 = 0;
2691 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2692 abi_ulong) != 0)
2693 goto do_sigsegv;
2694 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2695 abi_ulong) != 0)
2696 goto do_sigsegv;
1d8b512b
RV
2697 __put_user(fp, &(mcp->mc_fp));
2698 __put_user(i7, &(mcp->mc_i7));
5bfb56b2 2699
459a4017 2700 {
30038fd8
RH
2701 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2702 for (i = 0; i < 64; i++, dst++) {
2703 if (i & 1) {
1d8b512b 2704 __put_user(env->fpr[i/2].l.lower, dst);
30038fd8 2705 } else {
1d8b512b 2706 __put_user(env->fpr[i/2].l.upper, dst);
30038fd8
RH
2707 }
2708 }
459a4017 2709 }
1d8b512b
RV
2710 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2711 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2712 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
5bfb56b2
BS
2713
2714 if (err)
2715 goto do_sigsegv;
459a4017 2716 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2
BS
2717 return;
2718 do_sigsegv:
459a4017 2719 unlock_user_struct(ucp, ucp_addr, 1);
66393fb9 2720 force_sig(TARGET_SIGSEGV);
5bfb56b2
BS
2721}
2722#endif
ff970904 2723#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
106ec879 2724
ff970904 2725# if defined(TARGET_ABI_MIPSO32)
106ec879
FB
2726struct target_sigcontext {
2727 uint32_t sc_regmask; /* Unused */
2728 uint32_t sc_status;
2729 uint64_t sc_pc;
2730 uint64_t sc_regs[32];
2731 uint64_t sc_fpregs[32];
2732 uint32_t sc_ownedfp; /* Unused */
2733 uint32_t sc_fpc_csr;
2734 uint32_t sc_fpc_eir; /* Unused */
2735 uint32_t sc_used_math;
2736 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
94c5495d 2737 uint32_t pad0;
106ec879
FB
2738 uint64_t sc_mdhi;
2739 uint64_t sc_mdlo;
2740 target_ulong sc_hi1; /* Was sc_cause */
2741 target_ulong sc_lo1; /* Was sc_badvaddr */
2742 target_ulong sc_hi2; /* Was sc_sigset[4] */
2743 target_ulong sc_lo2;
2744 target_ulong sc_hi3;
2745 target_ulong sc_lo3;
2746};
ff970904
RH
2747# else /* N32 || N64 */
2748struct target_sigcontext {
2749 uint64_t sc_regs[32];
2750 uint64_t sc_fpregs[32];
2751 uint64_t sc_mdhi;
2752 uint64_t sc_hi1;
2753 uint64_t sc_hi2;
2754 uint64_t sc_hi3;
2755 uint64_t sc_mdlo;
2756 uint64_t sc_lo1;
2757 uint64_t sc_lo2;
2758 uint64_t sc_lo3;
2759 uint64_t sc_pc;
2760 uint32_t sc_fpc_csr;
2761 uint32_t sc_used_math;
2762 uint32_t sc_dsp;
2763 uint32_t sc_reserved;
2764};
2765# endif /* O32 */
106ec879
FB
2766
2767struct sigframe {
2768 uint32_t sf_ass[4]; /* argument save space for o32 */
2769 uint32_t sf_code[2]; /* signal trampoline */
2770 struct target_sigcontext sf_sc;
c227f099 2771 target_sigset_t sf_mask;
106ec879
FB
2772};
2773
0b1bcb00 2774struct target_ucontext {
60e99246
AJ
2775 target_ulong tuc_flags;
2776 target_ulong tuc_link;
2777 target_stack_t tuc_stack;
94c5495d 2778 target_ulong pad0;
60e99246
AJ
2779 struct target_sigcontext tuc_mcontext;
2780 target_sigset_t tuc_sigmask;
0b1bcb00
PB
2781};
2782
2783struct target_rt_sigframe {
2784 uint32_t rs_ass[4]; /* argument save space for o32 */
2785 uint32_t rs_code[2]; /* signal trampoline */
2786 struct target_siginfo rs_info;
2787 struct target_ucontext rs_uc;
2788};
2789
106ec879
FB
2790/* Install trampoline to jump back from signal handler */
2791static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2792{
084d0497 2793 int err = 0;
106ec879
FB
2794
2795 /*
084d0497
RH
2796 * Set up the return code ...
2797 *
2798 * li v0, __NR__foo_sigreturn
2799 * syscall
2800 */
106ec879 2801
1d8b512b
RV
2802 __put_user(0x24020000 + syscall, tramp + 0);
2803 __put_user(0x0000000c , tramp + 1);
106ec879
FB
2804 return err;
2805}
2806
41ecc72b
RV
2807static inline void setup_sigcontext(CPUMIPSState *regs,
2808 struct target_sigcontext *sc)
106ec879 2809{
084d0497 2810 int i;
106ec879 2811
1d8b512b 2812 __put_user(exception_resume_pc(regs), &sc->sc_pc);
1239b472 2813 regs->hflags &= ~MIPS_HFLAG_BMASK;
106ec879 2814
084d0497
RH
2815 __put_user(0, &sc->sc_regs[0]);
2816 for (i = 1; i < 32; ++i) {
1d8b512b 2817 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
084d0497 2818 }
106ec879 2819
1d8b512b
RV
2820 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2821 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2822
084d0497
RH
2823 /* Rather than checking for dsp existence, always copy. The storage
2824 would just be garbage otherwise. */
1d8b512b
RV
2825 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2826 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2827 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2828 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2829 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2830 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
084d0497
RH
2831 {
2832 uint32_t dsp = cpu_rddsp(0x3ff, regs);
1d8b512b 2833 __put_user(dsp, &sc->sc_dsp);
106ec879 2834 }
106ec879 2835
1d8b512b 2836 __put_user(1, &sc->sc_used_math);
106ec879 2837
084d0497 2838 for (i = 0; i < 32; ++i) {
1d8b512b 2839 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
106ec879 2840 }
106ec879
FB
2841}
2842
016d2e1d 2843static inline void
05390248 2844restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
106ec879 2845{
084d0497 2846 int i;
106ec879 2847
1d8b512b 2848 __get_user(regs->CP0_EPC, &sc->sc_pc);
106ec879 2849
1d8b512b
RV
2850 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2851 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2852
084d0497 2853 for (i = 1; i < 32; ++i) {
1d8b512b 2854 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
106ec879 2855 }
106ec879 2856
1d8b512b
RV
2857 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2858 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2859 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2860 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2861 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2862 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
084d0497
RH
2863 {
2864 uint32_t dsp;
1d8b512b 2865 __get_user(dsp, &sc->sc_dsp);
084d0497
RH
2866 cpu_wrdsp(dsp, 0x3ff, regs);
2867 }
106ec879 2868
084d0497 2869 for (i = 0; i < 32; ++i) {
1d8b512b 2870 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
106ec879 2871 }
106ec879 2872}
ff970904 2873
106ec879
FB
2874/*
2875 * Determine which stack to use..
2876 */
579a97f7 2877static inline abi_ulong
05390248 2878get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
106ec879
FB
2879{
2880 unsigned long sp;
2881
2882 /* Default to using normal stack */
b5dc7732 2883 sp = regs->active_tc.gpr[29];
106ec879
FB
2884
2885 /*
93148aa5 2886 * FPU emulator may have its own trampoline active just
106ec879
FB
2887 * above the user stack, 16-bytes before the next lowest
2888 * 16 byte boundary. Try to avoid trashing it.
2889 */
2890 sp -= 32;
2891
106ec879 2892 /* This is the X/Open sanctioned signal stack switching. */
624f7979 2893 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
a04e134a
TS
2894 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2895 }
106ec879 2896
579a97f7 2897 return (sp - frame_size) & ~7;
106ec879
FB
2898}
2899
ea3164aa
KCY
2900static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2901{
2902 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2903 env->hflags &= ~MIPS_HFLAG_M16;
2904 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2905 env->active_tc.PC &= ~(target_ulong) 1;
2906 }
2907}
2908
ff970904 2909# if defined(TARGET_ABI_MIPSO32)
579a97f7 2910/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
624f7979 2911static void setup_frame(int sig, struct target_sigaction * ka,
05390248 2912 target_sigset_t *set, CPUMIPSState *regs)
106ec879
FB
2913{
2914 struct sigframe *frame;
579a97f7 2915 abi_ulong frame_addr;
106ec879
FB
2916 int i;
2917
579a97f7
FB
2918 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2919 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
106ec879
FB
2920 goto give_sigsegv;
2921
2922 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2923
41ecc72b 2924 setup_sigcontext(regs, &frame->sf_sc);
106ec879
FB
2925
2926 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
0188fadb 2927 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
106ec879
FB
2928 }
2929
2930 /*
2931 * Arguments to signal handler:
2932 *
2933 * a0 = signal number
2934 * a1 = 0 (should be cause)
2935 * a2 = pointer to struct sigcontext
2936 *
2937 * $25 and PC point to the signal handler, $29 points to the
2938 * struct sigframe.
2939 */
b5dc7732
TS
2940 regs->active_tc.gpr[ 4] = sig;
2941 regs->active_tc.gpr[ 5] = 0;
2942 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2943 regs->active_tc.gpr[29] = frame_addr;
2944 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
106ec879
FB
2945 /* The original kernel code sets CP0_EPC to the handler
2946 * since it returns to userland using eret
2947 * we cannot do this here, and we must set PC directly */
b5dc7732 2948 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
ea3164aa 2949 mips_set_hflags_isa_mode_from_pc(regs);
579a97f7 2950 unlock_user_struct(frame, frame_addr, 1);
106ec879
FB
2951 return;
2952
2953give_sigsegv:
2954 force_sig(TARGET_SIGSEGV/*, current*/);
106ec879
FB
2955}
2956
05390248 2957long do_sigreturn(CPUMIPSState *regs)
106ec879 2958{
388bb21a 2959 struct sigframe *frame;
579a97f7 2960 abi_ulong frame_addr;
388bb21a 2961 sigset_t blocked;
c227f099 2962 target_sigset_t target_set;
388bb21a 2963 int i;
106ec879
FB
2964
2965#if defined(DEBUG_SIGNAL)
388bb21a 2966 fprintf(stderr, "do_sigreturn\n");
106ec879 2967#endif
b5dc7732 2968 frame_addr = regs->active_tc.gpr[29];
579a97f7 2969 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
106ec879
FB
2970 goto badframe;
2971
388bb21a 2972 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
f5f601af 2973 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
388bb21a 2974 }
106ec879 2975
388bb21a 2976 target_to_host_sigset_internal(&blocked, &target_set);
1c275925 2977 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
106ec879 2978
016d2e1d 2979 restore_sigcontext(regs, &frame->sf_sc);
106ec879
FB
2980
2981#if 0
388bb21a
TS
2982 /*
2983 * Don't let your children do this ...
2984 */
2985 __asm__ __volatile__(
106ec879
FB
2986 "move\t$29, %0\n\t"
2987 "j\tsyscall_exit"
2988 :/* no outputs */
2989 :"r" (&regs));
388bb21a 2990 /* Unreached */
106ec879 2991#endif
3b46e624 2992
b5dc7732 2993 regs->active_tc.PC = regs->CP0_EPC;
ea3164aa 2994 mips_set_hflags_isa_mode_from_pc(regs);
388bb21a 2995 /* I am not sure this is right, but it seems to work
106ec879
FB
2996 * maybe a problem with nested signals ? */
2997 regs->CP0_EPC = 0;
0b1bcb00 2998 return -TARGET_QEMU_ESIGRETURN;
106ec879
FB
2999
3000badframe:
388bb21a
TS
3001 force_sig(TARGET_SIGSEGV/*, current*/);
3002 return 0;
106ec879 3003}
ff970904 3004# endif /* O32 */
106ec879 3005
624f7979 3006static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3007 target_siginfo_t *info,
05390248 3008 target_sigset_t *set, CPUMIPSState *env)
106ec879 3009{
0b1bcb00
PB
3010 struct target_rt_sigframe *frame;
3011 abi_ulong frame_addr;
3012 int i;
3013
3014 frame_addr = get_sigframe(ka, env, sizeof(*frame));
3015 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3016 goto give_sigsegv;
3017
3018 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3019
3020 copy_siginfo_to_user(&frame->rs_info, info);
3021
60e99246
AJ
3022 __put_user(0, &frame->rs_uc.tuc_flags);
3023 __put_user(0, &frame->rs_uc.tuc_link);
3024 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3025 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
0b1bcb00 3026 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
60e99246 3027 &frame->rs_uc.tuc_stack.ss_flags);
0b1bcb00 3028
60e99246 3029 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
0b1bcb00
PB
3030
3031 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
60e99246 3032 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
0b1bcb00
PB
3033 }
3034
3035 /*
3036 * Arguments to signal handler:
3037 *
3038 * a0 = signal number
02d2bd5d 3039 * a1 = pointer to siginfo_t
0b1bcb00
PB
3040 * a2 = pointer to struct ucontext
3041 *
3042 * $25 and PC point to the signal handler, $29 points to the
3043 * struct sigframe.
3044 */
3045 env->active_tc.gpr[ 4] = sig;
3046 env->active_tc.gpr[ 5] = frame_addr
3047 + offsetof(struct target_rt_sigframe, rs_info);
3048 env->active_tc.gpr[ 6] = frame_addr
3049 + offsetof(struct target_rt_sigframe, rs_uc);
3050 env->active_tc.gpr[29] = frame_addr;
3051 env->active_tc.gpr[31] = frame_addr
3052 + offsetof(struct target_rt_sigframe, rs_code);
3053 /* The original kernel code sets CP0_EPC to the handler
3054 * since it returns to userland using eret
3055 * we cannot do this here, and we must set PC directly */
3056 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
ea3164aa 3057 mips_set_hflags_isa_mode_from_pc(env);
0b1bcb00
PB
3058 unlock_user_struct(frame, frame_addr, 1);
3059 return;
3060
3061give_sigsegv:
3062 unlock_user_struct(frame, frame_addr, 1);
3063 force_sig(TARGET_SIGSEGV/*, current*/);
106ec879
FB
3064}
3065
05390248 3066long do_rt_sigreturn(CPUMIPSState *env)
106ec879 3067{
0b1bcb00
PB
3068 struct target_rt_sigframe *frame;
3069 abi_ulong frame_addr;
3070 sigset_t blocked;
3071
3072#if defined(DEBUG_SIGNAL)
3073 fprintf(stderr, "do_rt_sigreturn\n");
3074#endif
3075 frame_addr = env->active_tc.gpr[29];
3076 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3077 goto badframe;
3078
60e99246 3079 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
1c275925 3080 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
0b1bcb00 3081
016d2e1d 3082 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
0b1bcb00
PB
3083
3084 if (do_sigaltstack(frame_addr +
60e99246 3085 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
0b1bcb00
PB
3086 0, get_sp_from_cpustate(env)) == -EFAULT)
3087 goto badframe;
3088
3089 env->active_tc.PC = env->CP0_EPC;
ea3164aa 3090 mips_set_hflags_isa_mode_from_pc(env);
0b1bcb00
PB
3091 /* I am not sure this is right, but it seems to work
3092 * maybe a problem with nested signals ? */
3093 env->CP0_EPC = 0;
3094 return -TARGET_QEMU_ESIGRETURN;
3095
3096badframe:
3097 force_sig(TARGET_SIGSEGV/*, current*/);
3098 return 0;
106ec879 3099}
6d5e216d 3100
c3b5bc8a
TS
3101#elif defined(TARGET_SH4)
3102
3103/*
3104 * code and data structures from linux kernel:
3105 * include/asm-sh/sigcontext.h
3106 * arch/sh/kernel/signal.c
3107 */
3108
3109struct target_sigcontext {
3110 target_ulong oldmask;
3111
3112 /* CPU registers */
3113 target_ulong sc_gregs[16];
3114 target_ulong sc_pc;
3115 target_ulong sc_pr;
3116 target_ulong sc_sr;
3117 target_ulong sc_gbr;
3118 target_ulong sc_mach;
3119 target_ulong sc_macl;
3120
3121 /* FPU registers */
3122 target_ulong sc_fpregs[16];
3123 target_ulong sc_xfpregs[16];
3124 unsigned int sc_fpscr;
3125 unsigned int sc_fpul;
3126 unsigned int sc_ownedfp;
3127};
3128
3129struct target_sigframe
3130{
3131 struct target_sigcontext sc;
3132 target_ulong extramask[TARGET_NSIG_WORDS-1];
3133 uint16_t retcode[3];
3134};
3135
3136
3137struct target_ucontext {
60e99246
AJ
3138 target_ulong tuc_flags;
3139 struct target_ucontext *tuc_link;
3140 target_stack_t tuc_stack;
3141 struct target_sigcontext tuc_mcontext;
3142 target_sigset_t tuc_sigmask; /* mask last for extensibility */
c3b5bc8a
TS
3143};
3144
3145struct target_rt_sigframe
3146{
3147 struct target_siginfo info;
3148 struct target_ucontext uc;
3149 uint16_t retcode[3];
3150};
3151
3152
3153#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3154#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3155
624f7979 3156static abi_ulong get_sigframe(struct target_sigaction *ka,
c3b5bc8a
TS
3157 unsigned long sp, size_t frame_size)
3158{
624f7979 3159 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
c3b5bc8a
TS
3160 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3161 }
3162
3163 return (sp - frame_size) & -8ul;
3164}
3165
41ecc72b 3166static void setup_sigcontext(struct target_sigcontext *sc,
05390248 3167 CPUSH4State *regs, unsigned long mask)
c3b5bc8a 3168{
d8714436 3169 int i;
c3b5bc8a 3170
1d8b512b 3171#define COPY(x) __put_user(regs->x, &sc->sc_##x)
c3b5bc8a
TS
3172 COPY(gregs[0]); COPY(gregs[1]);
3173 COPY(gregs[2]); COPY(gregs[3]);
3174 COPY(gregs[4]); COPY(gregs[5]);
3175 COPY(gregs[6]); COPY(gregs[7]);
3176 COPY(gregs[8]); COPY(gregs[9]);
3177 COPY(gregs[10]); COPY(gregs[11]);
3178 COPY(gregs[12]); COPY(gregs[13]);
3179 COPY(gregs[14]); COPY(gregs[15]);
3180 COPY(gbr); COPY(mach);
3181 COPY(macl); COPY(pr);
3182 COPY(sr); COPY(pc);
3183#undef COPY
3184
d8714436 3185 for (i=0; i<16; i++) {
1d8b512b 3186 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
d8714436 3187 }
1d8b512b
RV
3188 __put_user(regs->fpscr, &sc->sc_fpscr);
3189 __put_user(regs->fpul, &sc->sc_fpul);
c3b5bc8a
TS
3190
3191 /* non-iBCS2 extensions.. */
1d8b512b 3192 __put_user(mask, &sc->oldmask);
c3b5bc8a
TS
3193}
3194
016d2e1d 3195static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
d8714436 3196 target_ulong *r0_p)
c3b5bc8a 3197{
d8714436 3198 int i;
c3b5bc8a 3199
1d8b512b 3200#define COPY(x) __get_user(regs->x, &sc->sc_##x)
c3b5bc8a
TS
3201 COPY(gregs[1]);
3202 COPY(gregs[2]); COPY(gregs[3]);
3203 COPY(gregs[4]); COPY(gregs[5]);
3204 COPY(gregs[6]); COPY(gregs[7]);
3205 COPY(gregs[8]); COPY(gregs[9]);
3206 COPY(gregs[10]); COPY(gregs[11]);
3207 COPY(gregs[12]); COPY(gregs[13]);
3208 COPY(gregs[14]); COPY(gregs[15]);
3209 COPY(gbr); COPY(mach);
3210 COPY(macl); COPY(pr);
3211 COPY(sr); COPY(pc);
3212#undef COPY
3213
d8714436 3214 for (i=0; i<16; i++) {
1d8b512b 3215 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
d8714436 3216 }
1d8b512b
RV
3217 __get_user(regs->fpscr, &sc->sc_fpscr);
3218 __get_user(regs->fpul, &sc->sc_fpul);
c3b5bc8a
TS
3219
3220 regs->tra = -1; /* disable syscall checks */
1d8b512b 3221 __get_user(*r0_p, &sc->sc_gregs[0]);
c3b5bc8a
TS
3222}
3223
624f7979 3224static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3225 target_sigset_t *set, CPUSH4State *regs)
c3b5bc8a
TS
3226{
3227 struct target_sigframe *frame;
3228 abi_ulong frame_addr;
3229 int i;
3230 int err = 0;
3231 int signal;
3232
3233 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3234 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3235 goto give_sigsegv;
3236
3237 signal = current_exec_domain_sig(sig);
3238
41ecc72b 3239 setup_sigcontext(&frame->sc, regs, set->sig[0]);
c3b5bc8a
TS
3240
3241 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1d8b512b 3242 __put_user(set->sig[i + 1], &frame->extramask[i]);
c3b5bc8a
TS
3243 }
3244
3245 /* Set up to return from userspace. If provided, use a stub
3246 already in userspace. */
624f7979
PB
3247 if (ka->sa_flags & TARGET_SA_RESTORER) {
3248 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
3249 } else {
3250 /* Generate return code (system call to sigreturn) */
1d8b512b
RV
3251 __put_user(MOVW(2), &frame->retcode[0]);
3252 __put_user(TRAP_NOARG, &frame->retcode[1]);
3253 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
c3b5bc8a
TS
3254 regs->pr = (unsigned long) frame->retcode;
3255 }
3256
3257 if (err)
3258 goto give_sigsegv;
3259
3260 /* Set up registers for signal handler */
cb9c6268 3261 regs->gregs[15] = frame_addr;
c3b5bc8a
TS
3262 regs->gregs[4] = signal; /* Arg for signal handler */
3263 regs->gregs[5] = 0;
cb9c6268 3264 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
624f7979 3265 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
3266
3267 unlock_user_struct(frame, frame_addr, 1);
3268 return;
3269
3270give_sigsegv:
3271 unlock_user_struct(frame, frame_addr, 1);
66393fb9 3272 force_sig(TARGET_SIGSEGV);
c3b5bc8a
TS
3273}
3274
624f7979 3275static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3276 target_siginfo_t *info,
05390248 3277 target_sigset_t *set, CPUSH4State *regs)
c3b5bc8a
TS
3278{
3279 struct target_rt_sigframe *frame;
3280 abi_ulong frame_addr;
3281 int i;
3282 int err = 0;
3283 int signal;
3284
3285 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3286 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3287 goto give_sigsegv;
3288
3289 signal = current_exec_domain_sig(sig);
3290
b0fd8d18 3291 copy_siginfo_to_user(&frame->info, info);
c3b5bc8a
TS
3292
3293 /* Create the ucontext. */
1d8b512b
RV
3294 __put_user(0, &frame->uc.tuc_flags);
3295 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3296 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3297 &frame->uc.tuc_stack.ss_sp);
3298 __put_user(sas_ss_flags(regs->gregs[15]),
3299 &frame->uc.tuc_stack.ss_flags);
3300 __put_user(target_sigaltstack_used.ss_size,
3301 &frame->uc.tuc_stack.ss_size);
3302 setup_sigcontext(&frame->uc.tuc_mcontext,
c3b5bc8a
TS
3303 regs, set->sig[0]);
3304 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 3305 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
c3b5bc8a
TS
3306 }
3307
3308 /* Set up to return from userspace. If provided, use a stub
3309 already in userspace. */
624f7979
PB
3310 if (ka->sa_flags & TARGET_SA_RESTORER) {
3311 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
3312 } else {
3313 /* Generate return code (system call to sigreturn) */
1d8b512b
RV
3314 __put_user(MOVW(2), &frame->retcode[0]);
3315 __put_user(TRAP_NOARG, &frame->retcode[1]);
3316 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
c3b5bc8a
TS
3317 regs->pr = (unsigned long) frame->retcode;
3318 }
3319
3320 if (err)
3321 goto give_sigsegv;
3322
3323 /* Set up registers for signal handler */
cb9c6268 3324 regs->gregs[15] = frame_addr;
c3b5bc8a 3325 regs->gregs[4] = signal; /* Arg for signal handler */
cb9c6268
EI
3326 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3327 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
624f7979 3328 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
3329
3330 unlock_user_struct(frame, frame_addr, 1);
3331 return;
3332
3333give_sigsegv:
3334 unlock_user_struct(frame, frame_addr, 1);
66393fb9 3335 force_sig(TARGET_SIGSEGV);
c3b5bc8a
TS
3336}
3337
05390248 3338long do_sigreturn(CPUSH4State *regs)
c3b5bc8a
TS
3339{
3340 struct target_sigframe *frame;
3341 abi_ulong frame_addr;
3342 sigset_t blocked;
c227f099 3343 target_sigset_t target_set;
d8714436 3344 target_ulong r0;
c3b5bc8a
TS
3345 int i;
3346 int err = 0;
3347
3348#if defined(DEBUG_SIGNAL)
3349 fprintf(stderr, "do_sigreturn\n");
3350#endif
3351 frame_addr = regs->gregs[15];
3352 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3353 goto badframe;
3354
1d8b512b 3355 __get_user(target_set.sig[0], &frame->sc.oldmask);
c3b5bc8a 3356 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 3357 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
c3b5bc8a
TS
3358 }
3359
3360 if (err)
3361 goto badframe;
3362
3363 target_to_host_sigset_internal(&blocked, &target_set);
1c275925 3364 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
c3b5bc8a 3365
016d2e1d 3366 restore_sigcontext(regs, &frame->sc, &r0);
c3b5bc8a
TS
3367
3368 unlock_user_struct(frame, frame_addr, 0);
d8714436 3369 return r0;
c3b5bc8a
TS
3370
3371badframe:
3372 unlock_user_struct(frame, frame_addr, 0);
3373 force_sig(TARGET_SIGSEGV);
3374 return 0;
3375}
3376
05390248 3377long do_rt_sigreturn(CPUSH4State *regs)
c3b5bc8a
TS
3378{
3379 struct target_rt_sigframe *frame;
3380 abi_ulong frame_addr;
3381 sigset_t blocked;
d8714436 3382 target_ulong r0;
c3b5bc8a
TS
3383
3384#if defined(DEBUG_SIGNAL)
3385 fprintf(stderr, "do_rt_sigreturn\n");
3386#endif
3387 frame_addr = regs->gregs[15];
3388 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3389 goto badframe;
3390
60e99246 3391 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
1c275925 3392 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
c3b5bc8a 3393
016d2e1d 3394 restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
c3b5bc8a
TS
3395
3396 if (do_sigaltstack(frame_addr +
60e99246 3397 offsetof(struct target_rt_sigframe, uc.tuc_stack),
c3b5bc8a
TS
3398 0, get_sp_from_cpustate(regs)) == -EFAULT)
3399 goto badframe;
3400
3401 unlock_user_struct(frame, frame_addr, 0);
d8714436 3402 return r0;
c3b5bc8a
TS
3403
3404badframe:
3405 unlock_user_struct(frame, frame_addr, 0);
3406 force_sig(TARGET_SIGSEGV);
3407 return 0;
3408}
b779e29e
EI
3409#elif defined(TARGET_MICROBLAZE)
3410
3411struct target_sigcontext {
3412 struct target_pt_regs regs; /* needs to be first */
3413 uint32_t oldmask;
3414};
3415
b2178704
EI
3416struct target_stack_t {
3417 abi_ulong ss_sp;
3418 int ss_flags;
3419 unsigned int ss_size;
3420};
3421
3422struct target_ucontext {
f711df67
RH
3423 abi_ulong tuc_flags;
3424 abi_ulong tuc_link;
3425 struct target_stack_t tuc_stack;
3426 struct target_sigcontext tuc_mcontext;
3427 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
b2178704
EI
3428};
3429
b779e29e
EI
3430/* Signal frames. */
3431struct target_signal_frame {
b2178704 3432 struct target_ucontext uc;
b779e29e
EI
3433 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3434 uint32_t tramp[2];
3435};
3436
3437struct rt_signal_frame {
02d2bd5d 3438 siginfo_t info;
b779e29e
EI
3439 struct ucontext uc;
3440 uint32_t tramp[2];
3441};
3442
05390248 3443static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
b779e29e
EI
3444{
3445 __put_user(env->regs[0], &sc->regs.r0);
3446 __put_user(env->regs[1], &sc->regs.r1);
3447 __put_user(env->regs[2], &sc->regs.r2);
3448 __put_user(env->regs[3], &sc->regs.r3);
3449 __put_user(env->regs[4], &sc->regs.r4);
3450 __put_user(env->regs[5], &sc->regs.r5);
3451 __put_user(env->regs[6], &sc->regs.r6);
3452 __put_user(env->regs[7], &sc->regs.r7);
3453 __put_user(env->regs[8], &sc->regs.r8);
3454 __put_user(env->regs[9], &sc->regs.r9);
3455 __put_user(env->regs[10], &sc->regs.r10);
3456 __put_user(env->regs[11], &sc->regs.r11);
3457 __put_user(env->regs[12], &sc->regs.r12);
3458 __put_user(env->regs[13], &sc->regs.r13);
3459 __put_user(env->regs[14], &sc->regs.r14);
3460 __put_user(env->regs[15], &sc->regs.r15);
3461 __put_user(env->regs[16], &sc->regs.r16);
3462 __put_user(env->regs[17], &sc->regs.r17);
3463 __put_user(env->regs[18], &sc->regs.r18);
3464 __put_user(env->regs[19], &sc->regs.r19);
3465 __put_user(env->regs[20], &sc->regs.r20);
3466 __put_user(env->regs[21], &sc->regs.r21);
3467 __put_user(env->regs[22], &sc->regs.r22);
3468 __put_user(env->regs[23], &sc->regs.r23);
3469 __put_user(env->regs[24], &sc->regs.r24);
3470 __put_user(env->regs[25], &sc->regs.r25);
3471 __put_user(env->regs[26], &sc->regs.r26);
3472 __put_user(env->regs[27], &sc->regs.r27);
3473 __put_user(env->regs[28], &sc->regs.r28);
3474 __put_user(env->regs[29], &sc->regs.r29);
3475 __put_user(env->regs[30], &sc->regs.r30);
3476 __put_user(env->regs[31], &sc->regs.r31);
3477 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3478}
3479
05390248 3480static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
b779e29e
EI
3481{
3482 __get_user(env->regs[0], &sc->regs.r0);
3483 __get_user(env->regs[1], &sc->regs.r1);
3484 __get_user(env->regs[2], &sc->regs.r2);
3485 __get_user(env->regs[3], &sc->regs.r3);
3486 __get_user(env->regs[4], &sc->regs.r4);
3487 __get_user(env->regs[5], &sc->regs.r5);
3488 __get_user(env->regs[6], &sc->regs.r6);
3489 __get_user(env->regs[7], &sc->regs.r7);
3490 __get_user(env->regs[8], &sc->regs.r8);
3491 __get_user(env->regs[9], &sc->regs.r9);
3492 __get_user(env->regs[10], &sc->regs.r10);
3493 __get_user(env->regs[11], &sc->regs.r11);
3494 __get_user(env->regs[12], &sc->regs.r12);
3495 __get_user(env->regs[13], &sc->regs.r13);
3496 __get_user(env->regs[14], &sc->regs.r14);
3497 __get_user(env->regs[15], &sc->regs.r15);
3498 __get_user(env->regs[16], &sc->regs.r16);
3499 __get_user(env->regs[17], &sc->regs.r17);
3500 __get_user(env->regs[18], &sc->regs.r18);
3501 __get_user(env->regs[19], &sc->regs.r19);
3502 __get_user(env->regs[20], &sc->regs.r20);
3503 __get_user(env->regs[21], &sc->regs.r21);
3504 __get_user(env->regs[22], &sc->regs.r22);
3505 __get_user(env->regs[23], &sc->regs.r23);
3506 __get_user(env->regs[24], &sc->regs.r24);
3507 __get_user(env->regs[25], &sc->regs.r25);
3508 __get_user(env->regs[26], &sc->regs.r26);
3509 __get_user(env->regs[27], &sc->regs.r27);
3510 __get_user(env->regs[28], &sc->regs.r28);
3511 __get_user(env->regs[29], &sc->regs.r29);
3512 __get_user(env->regs[30], &sc->regs.r30);
3513 __get_user(env->regs[31], &sc->regs.r31);
3514 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3515}
3516
3517static abi_ulong get_sigframe(struct target_sigaction *ka,
05390248 3518 CPUMBState *env, int frame_size)
b779e29e
EI
3519{
3520 abi_ulong sp = env->regs[1];
3521
b545f63f 3522 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
b779e29e 3523 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
b545f63f 3524 }
b779e29e
EI
3525
3526 return ((sp - frame_size) & -8UL);
3527}
3528
3529static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3530 target_sigset_t *set, CPUMBState *env)
b779e29e
EI
3531{
3532 struct target_signal_frame *frame;
3533 abi_ulong frame_addr;
b779e29e
EI
3534 int i;
3535
3536 frame_addr = get_sigframe(ka, env, sizeof *frame);
3537 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3538 goto badframe;
3539
3540 /* Save the mask. */
1d8b512b 3541 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
b779e29e
EI
3542
3543 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
0188fadb 3544 __put_user(set->sig[i], &frame->extramask[i - 1]);
b779e29e
EI
3545 }
3546
f711df67 3547 setup_sigcontext(&frame->uc.tuc_mcontext, env);
b779e29e
EI
3548
3549 /* Set up to return from userspace. If provided, use a stub
3550 already in userspace. */
3551 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3552 if (ka->sa_flags & TARGET_SA_RESTORER) {
3553 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3554 } else {
3555 uint32_t t;
3556 /* Note, these encodings are _big endian_! */
3557 /* addi r12, r0, __NR_sigreturn */
3558 t = 0x31800000UL | TARGET_NR_sigreturn;
1d8b512b 3559 __put_user(t, frame->tramp + 0);
b779e29e
EI
3560 /* brki r14, 0x8 */
3561 t = 0xb9cc0008UL;
1d8b512b 3562 __put_user(t, frame->tramp + 1);
b779e29e
EI
3563
3564 /* Return from sighandler will jump to the tramp.
3565 Negative 8 offset because return is rtsd r15, 8 */
3566 env->regs[15] = ((unsigned long)frame->tramp) - 8;
3567 }
3568
b779e29e 3569 /* Set up registers for signal handler */
cb9c6268 3570 env->regs[1] = frame_addr;
b779e29e
EI
3571 /* Signal handler args: */
3572 env->regs[5] = sig; /* Arg 0: signum */
187b4e08 3573 env->regs[6] = 0;
cb9c6268
EI
3574 /* arg 1: sigcontext */
3575 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
b779e29e
EI
3576
3577 /* Offset of 4 to handle microblaze rtid r14, 0 */
3578 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3579
3580 unlock_user_struct(frame, frame_addr, 1);
3581 return;
3582 badframe:
b779e29e
EI
3583 force_sig(TARGET_SIGSEGV);
3584}
3585
3586static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3587 target_siginfo_t *info,
05390248 3588 target_sigset_t *set, CPUMBState *env)
b779e29e
EI
3589{
3590 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3591}
3592
05390248 3593long do_sigreturn(CPUMBState *env)
b779e29e
EI
3594{
3595 struct target_signal_frame *frame;
3596 abi_ulong frame_addr;
c227f099 3597 target_sigset_t target_set;
b779e29e
EI
3598 sigset_t set;
3599 int i;
3600
3601 frame_addr = env->regs[R_SP];
3602 /* Make sure the guest isn't playing games. */
3603 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3604 goto badframe;
3605
3606 /* Restore blocked signals */
f5f601af 3607 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
b779e29e 3608 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 3609 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
b779e29e
EI
3610 }
3611 target_to_host_sigset_internal(&set, &target_set);
1c275925 3612 do_sigprocmask(SIG_SETMASK, &set, NULL);
b779e29e 3613
f711df67 3614 restore_sigcontext(&frame->uc.tuc_mcontext, env);
b779e29e
EI
3615 /* We got here through a sigreturn syscall, our path back is via an
3616 rtb insn so setup r14 for that. */
3617 env->regs[14] = env->sregs[SR_PC];
3618
3619 unlock_user_struct(frame, frame_addr, 0);
3620 return env->regs[10];
3621 badframe:
b779e29e
EI
3622 force_sig(TARGET_SIGSEGV);
3623}
3624
05390248 3625long do_rt_sigreturn(CPUMBState *env)
b779e29e
EI
3626{
3627 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3628 return -TARGET_ENOSYS;
3629}
3630
b6d3abda
EI
3631#elif defined(TARGET_CRIS)
3632
3633struct target_sigcontext {
3634 struct target_pt_regs regs; /* needs to be first */
3635 uint32_t oldmask;
3636 uint32_t usp; /* usp before stacking this gunk on it */
3637};
3638
3639/* Signal frames. */
3640struct target_signal_frame {
3641 struct target_sigcontext sc;
3642 uint32_t extramask[TARGET_NSIG_WORDS - 1];
8cfc114a 3643 uint16_t retcode[4]; /* Trampoline code. */
b6d3abda
EI
3644};
3645
3646struct rt_signal_frame {
02d2bd5d 3647 siginfo_t *pinfo;
b6d3abda 3648 void *puc;
02d2bd5d 3649 siginfo_t info;
b6d3abda 3650 struct ucontext uc;
8cfc114a 3651 uint16_t retcode[4]; /* Trampoline code. */
b6d3abda
EI
3652};
3653
05390248 3654static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
b6d3abda 3655{
9664d928
EI
3656 __put_user(env->regs[0], &sc->regs.r0);
3657 __put_user(env->regs[1], &sc->regs.r1);
3658 __put_user(env->regs[2], &sc->regs.r2);
3659 __put_user(env->regs[3], &sc->regs.r3);
3660 __put_user(env->regs[4], &sc->regs.r4);
3661 __put_user(env->regs[5], &sc->regs.r5);
3662 __put_user(env->regs[6], &sc->regs.r6);
3663 __put_user(env->regs[7], &sc->regs.r7);
3664 __put_user(env->regs[8], &sc->regs.r8);
3665 __put_user(env->regs[9], &sc->regs.r9);
3666 __put_user(env->regs[10], &sc->regs.r10);
3667 __put_user(env->regs[11], &sc->regs.r11);
3668 __put_user(env->regs[12], &sc->regs.r12);
3669 __put_user(env->regs[13], &sc->regs.r13);
3670 __put_user(env->regs[14], &sc->usp);
3671 __put_user(env->regs[15], &sc->regs.acr);
3672 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3673 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3674 __put_user(env->pc, &sc->regs.erp);
b6d3abda 3675}
9664d928 3676
05390248 3677static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
b6d3abda 3678{
9664d928
EI
3679 __get_user(env->regs[0], &sc->regs.r0);
3680 __get_user(env->regs[1], &sc->regs.r1);
3681 __get_user(env->regs[2], &sc->regs.r2);
3682 __get_user(env->regs[3], &sc->regs.r3);
3683 __get_user(env->regs[4], &sc->regs.r4);
3684 __get_user(env->regs[5], &sc->regs.r5);
3685 __get_user(env->regs[6], &sc->regs.r6);
3686 __get_user(env->regs[7], &sc->regs.r7);
3687 __get_user(env->regs[8], &sc->regs.r8);
3688 __get_user(env->regs[9], &sc->regs.r9);
3689 __get_user(env->regs[10], &sc->regs.r10);
3690 __get_user(env->regs[11], &sc->regs.r11);
3691 __get_user(env->regs[12], &sc->regs.r12);
3692 __get_user(env->regs[13], &sc->regs.r13);
3693 __get_user(env->regs[14], &sc->usp);
3694 __get_user(env->regs[15], &sc->regs.acr);
3695 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3696 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3697 __get_user(env->pc, &sc->regs.erp);
3698}
3699
05390248 3700static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
9664d928
EI
3701{
3702 abi_ulong sp;
b6d3abda 3703 /* Align the stack downwards to 4. */
9664d928
EI
3704 sp = (env->regs[R_SP] & ~3);
3705 return sp - framesize;
b6d3abda
EI
3706}
3707
624f7979 3708static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3709 target_sigset_t *set, CPUCRISState *env)
b6d3abda
EI
3710{
3711 struct target_signal_frame *frame;
9664d928 3712 abi_ulong frame_addr;
b6d3abda 3713 int i;
b6d3abda 3714
9664d928
EI
3715 frame_addr = get_sigframe(env, sizeof *frame);
3716 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
b6d3abda
EI
3717 goto badframe;
3718
3719 /*
3720 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3721 * use this trampoline anymore but it sets it up for GDB.
3722 * In QEMU, using the trampoline simplifies things a bit so we use it.
3723 *
3724 * This is movu.w __NR_sigreturn, r9; break 13;
3725 */
1d8b512b
RV
3726 __put_user(0x9c5f, frame->retcode+0);
3727 __put_user(TARGET_NR_sigreturn,
3728 frame->retcode + 1);
3729 __put_user(0xe93d, frame->retcode + 2);
b6d3abda
EI
3730
3731 /* Save the mask. */
1d8b512b 3732 __put_user(set->sig[0], &frame->sc.oldmask);
b6d3abda 3733
0188fadb
RV
3734 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3735 __put_user(set->sig[i], &frame->extramask[i - 1]);
3736 }
b6d3abda
EI
3737
3738 setup_sigcontext(&frame->sc, env);
3739
3740 /* Move the stack and setup the arguments for the handler. */
cb9c6268 3741 env->regs[R_SP] = frame_addr;
b6d3abda 3742 env->regs[10] = sig;
624f7979 3743 env->pc = (unsigned long) ka->_sa_handler;
b6d3abda 3744 /* Link SRP so the guest returns through the trampoline. */
cb9c6268 3745 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
b6d3abda 3746
9664d928 3747 unlock_user_struct(frame, frame_addr, 1);
b6d3abda
EI
3748 return;
3749 badframe:
b6d3abda
EI
3750 force_sig(TARGET_SIGSEGV);
3751}
3752
624f7979 3753static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3754 target_siginfo_t *info,
05390248 3755 target_sigset_t *set, CPUCRISState *env)
b6d3abda
EI
3756{
3757 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3758}
3759
05390248 3760long do_sigreturn(CPUCRISState *env)
b6d3abda
EI
3761{
3762 struct target_signal_frame *frame;
9664d928 3763 abi_ulong frame_addr;
c227f099 3764 target_sigset_t target_set;
b6d3abda
EI
3765 sigset_t set;
3766 int i;
3767
9664d928 3768 frame_addr = env->regs[R_SP];
b6d3abda 3769 /* Make sure the guest isn't playing games. */
9664d928 3770 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
b6d3abda
EI
3771 goto badframe;
3772
3773 /* Restore blocked signals */
f5f601af 3774 __get_user(target_set.sig[0], &frame->sc.oldmask);
b6d3abda 3775 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 3776 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
b6d3abda
EI
3777 }
3778 target_to_host_sigset_internal(&set, &target_set);
1c275925 3779 do_sigprocmask(SIG_SETMASK, &set, NULL);
b6d3abda
EI
3780
3781 restore_sigcontext(&frame->sc, env);
9664d928 3782 unlock_user_struct(frame, frame_addr, 0);
b6d3abda
EI
3783 return env->regs[10];
3784 badframe:
b6d3abda
EI
3785 force_sig(TARGET_SIGSEGV);
3786}
3787
05390248 3788long do_rt_sigreturn(CPUCRISState *env)
b6d3abda
EI
3789{
3790 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3791 return -TARGET_ENOSYS;
3792}
c3b5bc8a 3793
d962783e
JL
3794#elif defined(TARGET_OPENRISC)
3795
3796struct target_sigcontext {
3797 struct target_pt_regs regs;
3798 abi_ulong oldmask;
3799 abi_ulong usp;
3800};
3801
3802struct target_ucontext {
3803 abi_ulong tuc_flags;
3804 abi_ulong tuc_link;
3805 target_stack_t tuc_stack;
3806 struct target_sigcontext tuc_mcontext;
3807 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3808};
3809
3810struct target_rt_sigframe {
3811 abi_ulong pinfo;
3812 uint64_t puc;
3813 struct target_siginfo info;
3814 struct target_sigcontext sc;
3815 struct target_ucontext uc;
3816 unsigned char retcode[16]; /* trampoline code */
3817};
3818
3819/* This is the asm-generic/ucontext.h version */
3820#if 0
3821static int restore_sigcontext(CPUOpenRISCState *regs,
3822 struct target_sigcontext *sc)
3823{
3824 unsigned int err = 0;
3825 unsigned long old_usp;
3826
3827 /* Alwys make any pending restarted system call return -EINTR */
3828 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3829
3830 /* restore the regs from &sc->regs (same as sc, since regs is first)
3831 * (sc is already checked for VERIFY_READ since the sigframe was
3832 * checked in sys_sigreturn previously)
3833 */
3834
3835 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3836 goto badframe;
3837 }
3838
3839 /* make sure the U-flag is set so user-mode cannot fool us */
3840
3841 regs->sr &= ~SR_SM;
3842
3843 /* restore the old USP as it was before we stacked the sc etc.
3844 * (we cannot just pop the sigcontext since we aligned the sp and
3845 * stuff after pushing it)
3846 */
3847
1d8b512b 3848 __get_user(old_usp, &sc->usp);
d962783e
JL
3849 phx_signal("old_usp 0x%lx", old_usp);
3850
3851 __PHX__ REALLY /* ??? */
3852 wrusp(old_usp);
3853 regs->gpr[1] = old_usp;
3854
3855 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3856 * after this completes, but we don't use that mechanism. maybe we can
3857 * use it now ?
3858 */
3859
3860 return err;
3861
3862badframe:
3863 return 1;
3864}
3865#endif
3866
3867/* Set up a signal frame. */
3868
41ecc72b 3869static void setup_sigcontext(struct target_sigcontext *sc,
d962783e
JL
3870 CPUOpenRISCState *regs,
3871 unsigned long mask)
3872{
d962783e
JL
3873 unsigned long usp = regs->gpr[1];
3874
3875 /* copy the regs. they are first in sc so we can use sc directly */
3876
1d8b512b 3877 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
d962783e
JL
3878
3879 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3880 the signal handler. The frametype will be restored to its previous
3881 value in restore_sigcontext. */
3882 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3883
3884 /* then some other stuff */
1d8b512b 3885 __put_user(mask, &sc->oldmask);
41ecc72b 3886 __put_user(usp, &sc->usp);
d962783e
JL
3887}
3888
3889static inline unsigned long align_sigframe(unsigned long sp)
3890{
3891 unsigned long i;
3892 i = sp & ~3UL;
3893 return i;
3894}
3895
3896static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3897 CPUOpenRISCState *regs,
3898 size_t frame_size)
3899{
3900 unsigned long sp = regs->gpr[1];
3901 int onsigstack = on_sig_stack(sp);
3902
3903 /* redzone */
3904 /* This is the X/Open sanctioned signal stack switching. */
b545f63f 3905 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
d962783e
JL
3906 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3907 }
3908
3909 sp = align_sigframe(sp - frame_size);
3910
3911 /*
3912 * If we are on the alternate signal stack and would overflow it, don't.
3913 * Return an always-bogus address instead so we will die with SIGSEGV.
3914 */
3915
3916 if (onsigstack && !likely(on_sig_stack(sp))) {
3917 return -1L;
3918 }
3919
3920 return sp;
3921}
3922
3923static void setup_frame(int sig, struct target_sigaction *ka,
3924 target_sigset_t *set, CPUOpenRISCState *env)
3925{
3926 qemu_log("Not implement.\n");
3927}
3928
3929static void setup_rt_frame(int sig, struct target_sigaction *ka,
3930 target_siginfo_t *info,
3931 target_sigset_t *set, CPUOpenRISCState *env)
3932{
3933 int err = 0;
3934 abi_ulong frame_addr;
3935 unsigned long return_ip;
3936 struct target_rt_sigframe *frame;
3937 abi_ulong info_addr, uc_addr;
3938
d962783e
JL
3939 frame_addr = get_sigframe(ka, env, sizeof(*frame));
3940 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3941 goto give_sigsegv;
3942 }
3943
3944 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
1d8b512b 3945 __put_user(info_addr, &frame->pinfo);
d962783e 3946 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
1d8b512b 3947 __put_user(uc_addr, &frame->puc);
d962783e
JL
3948
3949 if (ka->sa_flags & SA_SIGINFO) {
b0fd8d18 3950 copy_siginfo_to_user(&frame->info, info);
d962783e
JL
3951 }
3952
3953 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
1d8b512b
RV
3954 __put_user(0, &frame->uc.tuc_flags);
3955 __put_user(0, &frame->uc.tuc_link);
3956 __put_user(target_sigaltstack_used.ss_sp,
3957 &frame->uc.tuc_stack.ss_sp);
3958 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3959 __put_user(target_sigaltstack_used.ss_size,
3960 &frame->uc.tuc_stack.ss_size);
41ecc72b 3961 setup_sigcontext(&frame->sc, env, set->sig[0]);
d962783e
JL
3962
3963 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3964
d962783e
JL
3965 /* trampoline - the desired return ip is the retcode itself */
3966 return_ip = (unsigned long)&frame->retcode;
3967 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
1d8b512b
RV
3968 __put_user(0xa960, (short *)(frame->retcode + 0));
3969 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3970 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3971 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
d962783e
JL
3972
3973 if (err) {
3974 goto give_sigsegv;
3975 }
3976
3977 /* TODO what is the current->exec_domain stuff and invmap ? */
3978
3979 /* Set up registers for signal handler */
3980 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3981 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
3982 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
3983 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
3984 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
3985
3986 /* actually move the usp to reflect the stacked frame */
3987 env->gpr[1] = (unsigned long)frame;
3988
3989 return;
3990
3991give_sigsegv:
3992 unlock_user_struct(frame, frame_addr, 1);
3993 if (sig == TARGET_SIGSEGV) {
3994 ka->_sa_handler = TARGET_SIG_DFL;
3995 }
3996 force_sig(TARGET_SIGSEGV);
3997}
3998
3999long do_sigreturn(CPUOpenRISCState *env)
4000{
4001
4002 qemu_log("do_sigreturn: not implemented\n");
4003 return -TARGET_ENOSYS;
4004}
4005
4006long do_rt_sigreturn(CPUOpenRISCState *env)
4007{
4008 qemu_log("do_rt_sigreturn: not implemented\n");
4009 return -TARGET_ENOSYS;
4010}
4011/* TARGET_OPENRISC */
4012
a4c075f1
UH
4013#elif defined(TARGET_S390X)
4014
4015#define __NUM_GPRS 16
4016#define __NUM_FPRS 16
4017#define __NUM_ACRS 16
4018
4019#define S390_SYSCALL_SIZE 2
4020#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4021
4022#define _SIGCONTEXT_NSIG 64
4023#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4024#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4025#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4026#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4027#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4028
4029typedef struct {
4030 target_psw_t psw;
4031 target_ulong gprs[__NUM_GPRS];
4032 unsigned int acrs[__NUM_ACRS];
4033} target_s390_regs_common;
4034
4035typedef struct {
4036 unsigned int fpc;
4037 double fprs[__NUM_FPRS];
4038} target_s390_fp_regs;
4039
4040typedef struct {
4041 target_s390_regs_common regs;
4042 target_s390_fp_regs fpregs;
4043} target_sigregs;
4044
4045struct target_sigcontext {
4046 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4047 target_sigregs *sregs;
4048};
4049
4050typedef struct {
4051 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4052 struct target_sigcontext sc;
4053 target_sigregs sregs;
4054 int signo;
4055 uint8_t retcode[S390_SYSCALL_SIZE];
4056} sigframe;
4057
4058struct target_ucontext {
6fea2ea4
PM
4059 target_ulong tuc_flags;
4060 struct target_ucontext *tuc_link;
4061 target_stack_t tuc_stack;
4062 target_sigregs tuc_mcontext;
4063 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a4c075f1
UH
4064};
4065
4066typedef struct {
4067 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4068 uint8_t retcode[S390_SYSCALL_SIZE];
4069 struct target_siginfo info;
4070 struct target_ucontext uc;
4071} rt_sigframe;
4072
4073static inline abi_ulong
05390248 4074get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
a4c075f1
UH
4075{
4076 abi_ulong sp;
4077
4078 /* Default to using normal stack */
4079 sp = env->regs[15];
4080
4081 /* This is the X/Open sanctioned signal stack switching. */
4082 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4083 if (!sas_ss_flags(sp)) {
4084 sp = target_sigaltstack_used.ss_sp +
4085 target_sigaltstack_used.ss_size;
4086 }
4087 }
4088
4089 /* This is the legacy signal stack switching. */
4090 else if (/* FIXME !user_mode(regs) */ 0 &&
4091 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4092 ka->sa_restorer) {
4093 sp = (abi_ulong) ka->sa_restorer;
4094 }
4095
4096 return (sp - frame_size) & -8ul;
4097}
4098
05390248 4099static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
a4c075f1
UH
4100{
4101 int i;
4102 //save_access_regs(current->thread.acrs); FIXME
4103
4104 /* Copy a 'clean' PSW mask to the user to avoid leaking
4105 information about whether PER is currently on. */
4106 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4107 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4108 for (i = 0; i < 16; i++) {
4109 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4110 }
4111 for (i = 0; i < 16; i++) {
4112 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4113 }
4114 /*
4115 * We have to store the fp registers to current->thread.fp_regs
4116 * to merge them with the emulated registers.
4117 */
4118 //save_fp_regs(&current->thread.fp_regs); FIXME
4119 for (i = 0; i < 16; i++) {
4120 __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]);
4121 }
4122}
4123
4124static void setup_frame(int sig, struct target_sigaction *ka,
05390248 4125 target_sigset_t *set, CPUS390XState *env)
a4c075f1
UH
4126{
4127 sigframe *frame;
4128 abi_ulong frame_addr;
4129
4130 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4131 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4132 (unsigned long long)frame_addr);
4133 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4134 goto give_sigsegv;
4135 }
4136
4137 qemu_log("%s: 1\n", __FUNCTION__);
0188fadb 4138 __put_user(set->sig[0], &frame->sc.oldmask[0]);
a4c075f1
UH
4139
4140 save_sigregs(env, &frame->sregs);
4141
4142 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4143 (abi_ulong *)&frame->sc.sregs);
4144
4145 /* Set up to return from userspace. If provided, use a stub
4146 already in userspace. */
4147 if (ka->sa_flags & TARGET_SA_RESTORER) {
4148 env->regs[14] = (unsigned long)
4149 ka->sa_restorer | PSW_ADDR_AMODE;
4150 } else {
4151 env->regs[14] = (unsigned long)
4152 frame->retcode | PSW_ADDR_AMODE;
0188fadb
RV
4153 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4154 (uint16_t *)(frame->retcode));
a4c075f1
UH
4155 }
4156
4157 /* Set up backchain. */
0188fadb 4158 __put_user(env->regs[15], (abi_ulong *) frame);
a4c075f1
UH
4159
4160 /* Set up registers for signal handler */
cb9c6268 4161 env->regs[15] = frame_addr;
a4c075f1
UH
4162 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4163
4164 env->regs[2] = sig; //map_signal(sig);
cb9c6268 4165 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
a4c075f1
UH
4166
4167 /* We forgot to include these in the sigcontext.
4168 To avoid breaking binary compatibility, they are passed as args. */
4169 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4170 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4171
4172 /* Place signal number on stack to allow backtrace from handler. */
0188fadb 4173 __put_user(env->regs[2], (int *) &frame->signo);
a4c075f1
UH
4174 unlock_user_struct(frame, frame_addr, 1);
4175 return;
4176
4177give_sigsegv:
4178 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
a4c075f1
UH
4179 force_sig(TARGET_SIGSEGV);
4180}
4181
4182static void setup_rt_frame(int sig, struct target_sigaction *ka,
4183 target_siginfo_t *info,
05390248 4184 target_sigset_t *set, CPUS390XState *env)
a4c075f1
UH
4185{
4186 int i;
4187 rt_sigframe *frame;
4188 abi_ulong frame_addr;
4189
4190 frame_addr = get_sigframe(ka, env, sizeof *frame);
4191 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4192 (unsigned long long)frame_addr);
4193 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4194 goto give_sigsegv;
4195 }
4196
4197 qemu_log("%s: 1\n", __FUNCTION__);
b0fd8d18 4198 copy_siginfo_to_user(&frame->info, info);
a4c075f1
UH
4199
4200 /* Create the ucontext. */
6fea2ea4
PM
4201 __put_user(0, &frame->uc.tuc_flags);
4202 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4203 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
a4c075f1 4204 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
6fea2ea4
PM
4205 &frame->uc.tuc_stack.ss_flags);
4206 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4207 save_sigregs(env, &frame->uc.tuc_mcontext);
a4c075f1
UH
4208 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4209 __put_user((abi_ulong)set->sig[i],
6fea2ea4 4210 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
a4c075f1
UH
4211 }
4212
4213 /* Set up to return from userspace. If provided, use a stub
4214 already in userspace. */
4215 if (ka->sa_flags & TARGET_SA_RESTORER) {
4216 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4217 } else {
4218 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
0188fadb
RV
4219 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4220 (uint16_t *)(frame->retcode));
a4c075f1
UH
4221 }
4222
4223 /* Set up backchain. */
0188fadb 4224 __put_user(env->regs[15], (abi_ulong *) frame);
a4c075f1
UH
4225
4226 /* Set up registers for signal handler */
cb9c6268 4227 env->regs[15] = frame_addr;
a4c075f1
UH
4228 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4229
4230 env->regs[2] = sig; //map_signal(sig);
cb9c6268
EI
4231 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4232 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
a4c075f1
UH
4233 return;
4234
4235give_sigsegv:
4236 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
a4c075f1
UH
4237 force_sig(TARGET_SIGSEGV);
4238}
4239
4240static int
05390248 4241restore_sigregs(CPUS390XState *env, target_sigregs *sc)
a4c075f1
UH
4242{
4243 int err = 0;
4244 int i;
4245
4246 for (i = 0; i < 16; i++) {
1d8b512b 4247 __get_user(env->regs[i], &sc->regs.gprs[i]);
a4c075f1
UH
4248 }
4249
1d8b512b 4250 __get_user(env->psw.mask, &sc->regs.psw.mask);
a4c075f1
UH
4251 qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
4252 __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
4253 (unsigned long long)env->psw.addr);
1d8b512b 4254 __get_user(env->psw.addr, &sc->regs.psw.addr);
a4c075f1
UH
4255 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4256
4257 for (i = 0; i < 16; i++) {
1d8b512b 4258 __get_user(env->aregs[i], &sc->regs.acrs[i]);
a4c075f1
UH
4259 }
4260 for (i = 0; i < 16; i++) {
1d8b512b 4261 __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]);
a4c075f1
UH
4262 }
4263
4264 return err;
4265}
4266
05390248 4267long do_sigreturn(CPUS390XState *env)
a4c075f1
UH
4268{
4269 sigframe *frame;
4270 abi_ulong frame_addr = env->regs[15];
4271 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4272 (unsigned long long)frame_addr);
4273 target_sigset_t target_set;
4274 sigset_t set;
4275
4276 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4277 goto badframe;
4278 }
f5f601af 4279 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
a4c075f1
UH
4280
4281 target_to_host_sigset_internal(&set, &target_set);
1c275925 4282 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
a4c075f1
UH
4283
4284 if (restore_sigregs(env, &frame->sregs)) {
4285 goto badframe;
4286 }
4287
4288 unlock_user_struct(frame, frame_addr, 0);
4289 return env->regs[2];
4290
4291badframe:
a4c075f1
UH
4292 force_sig(TARGET_SIGSEGV);
4293 return 0;
4294}
4295
05390248 4296long do_rt_sigreturn(CPUS390XState *env)
a4c075f1
UH
4297{
4298 rt_sigframe *frame;
4299 abi_ulong frame_addr = env->regs[15];
4300 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4301 (unsigned long long)frame_addr);
4302 sigset_t set;
4303
4304 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4305 goto badframe;
4306 }
6fea2ea4 4307 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
a4c075f1 4308
1c275925 4309 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
a4c075f1 4310
6fea2ea4 4311 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
a4c075f1
UH
4312 goto badframe;
4313 }
4314
6fea2ea4 4315 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
a4c075f1
UH
4316 get_sp_from_cpustate(env)) == -EFAULT) {
4317 goto badframe;
4318 }
4319 unlock_user_struct(frame, frame_addr, 0);
4320 return env->regs[2];
4321
4322badframe:
4323 unlock_user_struct(frame, frame_addr, 0);
4324 force_sig(TARGET_SIGSEGV);
4325 return 0;
4326}
4327
61e75fec 4328#elif defined(TARGET_PPC)
bcd4933a
NF
4329
4330/* Size of dummy stack frame allocated when calling signal handler.
4331 See arch/powerpc/include/asm/ptrace.h. */
4332#if defined(TARGET_PPC64)
4333#define SIGNAL_FRAMESIZE 128
4334#else
4335#define SIGNAL_FRAMESIZE 64
4336#endif
4337
61e75fec
TM
4338/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4339 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4340struct target_mcontext {
4341 target_ulong mc_gregs[48];
4342 /* Includes fpscr. */
4343 uint64_t mc_fregs[33];
4344 target_ulong mc_pad[2];
4345 /* We need to handle Altivec and SPE at the same time, which no
4346 kernel needs to do. Fortunately, the kernel defines this bit to
4347 be Altivec-register-large all the time, rather than trying to
4348 twiddle it based on the specific platform. */
4349 union {
4350 /* SPE vector registers. One extra for SPEFSCR. */
4351 uint32_t spe[33];
4352 /* Altivec vector registers. The packing of VSCR and VRSAVE
4353 varies depending on whether we're PPC64 or not: PPC64 splits
4354 them apart; PPC32 stuffs them together. */
4355#if defined(TARGET_PPC64)
4356#define QEMU_NVRREG 34
4357#else
4358#define QEMU_NVRREG 33
4359#endif
4360 ppc_avr_t altivec[QEMU_NVRREG];
4361#undef QEMU_NVRREG
4362 } mc_vregs __attribute__((__aligned__(16)));
4363};
4364
bcd4933a
NF
4365/* See arch/powerpc/include/asm/sigcontext.h. */
4366struct target_sigcontext {
4367 target_ulong _unused[4];
4368 int32_t signal;
4369#if defined(TARGET_PPC64)
4370 int32_t pad0;
4371#endif
4372 target_ulong handler;
4373 target_ulong oldmask;
4374 target_ulong regs; /* struct pt_regs __user * */
61e75fec
TM
4375#if defined(TARGET_PPC64)
4376 struct target_mcontext mcontext;
4377#endif
bcd4933a
NF
4378};
4379
4380/* Indices for target_mcontext.mc_gregs, below.
4381 See arch/powerpc/include/asm/ptrace.h for details. */
4382enum {
4383 TARGET_PT_R0 = 0,
4384 TARGET_PT_R1 = 1,
4385 TARGET_PT_R2 = 2,
4386 TARGET_PT_R3 = 3,
4387 TARGET_PT_R4 = 4,
4388 TARGET_PT_R5 = 5,
4389 TARGET_PT_R6 = 6,
4390 TARGET_PT_R7 = 7,
4391 TARGET_PT_R8 = 8,
4392 TARGET_PT_R9 = 9,
4393 TARGET_PT_R10 = 10,
4394 TARGET_PT_R11 = 11,
4395 TARGET_PT_R12 = 12,
4396 TARGET_PT_R13 = 13,
4397 TARGET_PT_R14 = 14,
4398 TARGET_PT_R15 = 15,
4399 TARGET_PT_R16 = 16,
4400 TARGET_PT_R17 = 17,
4401 TARGET_PT_R18 = 18,
4402 TARGET_PT_R19 = 19,
4403 TARGET_PT_R20 = 20,
4404 TARGET_PT_R21 = 21,
4405 TARGET_PT_R22 = 22,
4406 TARGET_PT_R23 = 23,
4407 TARGET_PT_R24 = 24,
4408 TARGET_PT_R25 = 25,
4409 TARGET_PT_R26 = 26,
4410 TARGET_PT_R27 = 27,
4411 TARGET_PT_R28 = 28,
4412 TARGET_PT_R29 = 29,
4413 TARGET_PT_R30 = 30,
4414 TARGET_PT_R31 = 31,
4415 TARGET_PT_NIP = 32,
4416 TARGET_PT_MSR = 33,
4417 TARGET_PT_ORIG_R3 = 34,
4418 TARGET_PT_CTR = 35,
4419 TARGET_PT_LNK = 36,
4420 TARGET_PT_XER = 37,
4421 TARGET_PT_CCR = 38,
4422 /* Yes, there are two registers with #39. One is 64-bit only. */
4423 TARGET_PT_MQ = 39,
4424 TARGET_PT_SOFTE = 39,
4425 TARGET_PT_TRAP = 40,
4426 TARGET_PT_DAR = 41,
4427 TARGET_PT_DSISR = 42,
4428 TARGET_PT_RESULT = 43,
4429 TARGET_PT_REGS_COUNT = 44
4430};
4431
bcd4933a
NF
4432
4433struct target_ucontext {
60e99246
AJ
4434 target_ulong tuc_flags;
4435 target_ulong tuc_link; /* struct ucontext __user * */
4436 struct target_sigaltstack tuc_stack;
bcd4933a 4437#if !defined(TARGET_PPC64)
60e99246
AJ
4438 int32_t tuc_pad[7];
4439 target_ulong tuc_regs; /* struct mcontext __user *
bcd4933a
NF
4440 points to uc_mcontext field */
4441#endif
60e99246 4442 target_sigset_t tuc_sigmask;
bcd4933a 4443#if defined(TARGET_PPC64)
c227f099 4444 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
61e75fec 4445 struct target_sigcontext tuc_sigcontext;
bcd4933a 4446#else
60e99246
AJ
4447 int32_t tuc_maskext[30];
4448 int32_t tuc_pad2[3];
4449 struct target_mcontext tuc_mcontext;
bcd4933a
NF
4450#endif
4451};
4452
4453/* See arch/powerpc/kernel/signal_32.c. */
4454struct target_sigframe {
4455 struct target_sigcontext sctx;
4456 struct target_mcontext mctx;
4457 int32_t abigap[56];
4458};
4459
61e75fec
TM
4460#if defined(TARGET_PPC64)
4461
4462#define TARGET_TRAMP_SIZE 6
4463
4464struct target_rt_sigframe {
4465 /* sys_rt_sigreturn requires the ucontext be the first field */
4466 struct target_ucontext uc;
4467 target_ulong _unused[2];
4468 uint32_t trampoline[TARGET_TRAMP_SIZE];
4469 target_ulong pinfo; /* struct siginfo __user * */
4470 target_ulong puc; /* void __user * */
4471 struct target_siginfo info;
4472 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4473 char abigap[288];
4474} __attribute__((aligned(16)));
4475
4476#else
4477
bcd4933a
NF
4478struct target_rt_sigframe {
4479 struct target_siginfo info;
4480 struct target_ucontext uc;
4481 int32_t abigap[56];
4482};
4483
61e75fec
TM
4484#endif
4485
8d6ab333
TM
4486#if defined(TARGET_PPC64)
4487
4488struct target_func_ptr {
4489 target_ulong entry;
4490 target_ulong toc;
4491};
4492
4493#endif
4494
bcd4933a
NF
4495/* We use the mc_pad field for the signal return trampoline. */
4496#define tramp mc_pad
4497
4498/* See arch/powerpc/kernel/signal.c. */
4499static target_ulong get_sigframe(struct target_sigaction *ka,
05390248 4500 CPUPPCState *env,
bcd4933a
NF
4501 int frame_size)
4502{
4503 target_ulong oldsp, newsp;
4504
4505 oldsp = env->gpr[1];
4506
4507 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
32a2003a 4508 (sas_ss_flags(oldsp) == 0)) {
bcd4933a
NF
4509 oldsp = (target_sigaltstack_used.ss_sp
4510 + target_sigaltstack_used.ss_size);
4511 }
4512
4513 newsp = (oldsp - frame_size) & ~0xFUL;
4514
4515 return newsp;
4516}
4517
7678108b 4518static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
bcd4933a
NF
4519{
4520 target_ulong msr = env->msr;
4521 int i;
4522 target_ulong ccr = 0;
4523
4524 /* In general, the kernel attempts to be intelligent about what it
4525 needs to save for Altivec/FP/SPE registers. We don't care that
4526 much, so we just go ahead and save everything. */
4527
4528 /* Save general registers. */
4529 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
c650c008 4530 __put_user(env->gpr[i], &frame->mc_gregs[i]);
bcd4933a 4531 }
c650c008
RV
4532 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4533 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4534 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4535 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
bcd4933a
NF
4536
4537 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4538 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4539 }
c650c008 4540 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
bcd4933a
NF
4541
4542 /* Save Altivec registers if necessary. */
4543 if (env->insns_flags & PPC_ALTIVEC) {
4544 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
c227f099
AL
4545 ppc_avr_t *avr = &env->avr[i];
4546 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
bcd4933a 4547
c650c008
RV
4548 __put_user(avr->u64[0], &vreg->u64[0]);
4549 __put_user(avr->u64[1], &vreg->u64[1]);
bcd4933a
NF
4550 }
4551 /* Set MSR_VR in the saved MSR value to indicate that
4552 frame->mc_vregs contains valid data. */
4553 msr |= MSR_VR;
c650c008
RV
4554 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4555 &frame->mc_vregs.altivec[32].u32[3]);
bcd4933a
NF
4556 }
4557
4558 /* Save floating point registers. */
4559 if (env->insns_flags & PPC_FLOAT) {
4560 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
c650c008 4561 __put_user(env->fpr[i], &frame->mc_fregs[i]);
bcd4933a 4562 }
c650c008 4563 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
bcd4933a
NF
4564 }
4565
4566 /* Save SPE registers. The kernel only saves the high half. */
4567 if (env->insns_flags & PPC_SPE) {
4568#if defined(TARGET_PPC64)
4569 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
c650c008 4570 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
bcd4933a
NF
4571 }
4572#else
4573 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
c650c008 4574 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
bcd4933a
NF
4575 }
4576#endif
4577 /* Set MSR_SPE in the saved MSR value to indicate that
4578 frame->mc_vregs contains valid data. */
4579 msr |= MSR_SPE;
c650c008 4580 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
bcd4933a
NF
4581 }
4582
4583 /* Store MSR. */
c650c008 4584 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
7678108b 4585}
bcd4933a 4586
7678108b
TM
4587static void encode_trampoline(int sigret, uint32_t *tramp)
4588{
bcd4933a
NF
4589 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4590 if (sigret) {
7678108b
TM
4591 __put_user(0x38000000 | sigret, &tramp[0]);
4592 __put_user(0x44000002, &tramp[1]);
bcd4933a 4593 }
bcd4933a
NF
4594}
4595
c650c008
RV
4596static void restore_user_regs(CPUPPCState *env,
4597 struct target_mcontext *frame, int sig)
bcd4933a
NF
4598{
4599 target_ulong save_r2 = 0;
4600 target_ulong msr;
4601 target_ulong ccr;
4602
4603 int i;
4604
4605 if (!sig) {
4606 save_r2 = env->gpr[2];
4607 }
4608
4609 /* Restore general registers. */
4610 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
c650c008 4611 __get_user(env->gpr[i], &frame->mc_gregs[i]);
bcd4933a 4612 }
c650c008
RV
4613 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4614 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4615 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4616 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4617 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
bcd4933a
NF
4618
4619 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4620 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4621 }
4622
4623 if (!sig) {
4624 env->gpr[2] = save_r2;
4625 }
4626 /* Restore MSR. */
c650c008 4627 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
bcd4933a
NF
4628
4629 /* If doing signal return, restore the previous little-endian mode. */
4630 if (sig)
4631 env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4632
4633 /* Restore Altivec registers if necessary. */
4634 if (env->insns_flags & PPC_ALTIVEC) {
4635 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
c227f099
AL
4636 ppc_avr_t *avr = &env->avr[i];
4637 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
bcd4933a 4638
c650c008
RV
4639 __get_user(avr->u64[0], &vreg->u64[0]);
4640 __get_user(avr->u64[1], &vreg->u64[1]);
bcd4933a
NF
4641 }
4642 /* Set MSR_VEC in the saved MSR value to indicate that
4643 frame->mc_vregs contains valid data. */
c650c008
RV
4644 __get_user(env->spr[SPR_VRSAVE],
4645 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
bcd4933a
NF
4646 }
4647
4648 /* Restore floating point registers. */
4649 if (env->insns_flags & PPC_FLOAT) {
4650 uint64_t fpscr;
4651 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
c650c008 4652 __get_user(env->fpr[i], &frame->mc_fregs[i]);
bcd4933a 4653 }
c650c008 4654 __get_user(fpscr, &frame->mc_fregs[32]);
bcd4933a
NF
4655 env->fpscr = (uint32_t) fpscr;
4656 }
4657
4658 /* Save SPE registers. The kernel only saves the high half. */
4659 if (env->insns_flags & PPC_SPE) {
4660#if defined(TARGET_PPC64)
4661 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4662 uint32_t hi;
4663
c650c008 4664 __get_user(hi, &frame->mc_vregs.spe[i]);
bcd4933a
NF
4665 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4666 }
4667#else
4668 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
c650c008 4669 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
bcd4933a
NF
4670 }
4671#endif
c650c008 4672 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
bcd4933a 4673 }
bcd4933a
NF
4674}
4675
4676static void setup_frame(int sig, struct target_sigaction *ka,
05390248 4677 target_sigset_t *set, CPUPPCState *env)
bcd4933a
NF
4678{
4679 struct target_sigframe *frame;
4680 struct target_sigcontext *sc;
4681 target_ulong frame_addr, newsp;
4682 int err = 0;
4683 int signal;
4684
4685 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4686 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4687 goto sigsegv;
4688 sc = &frame->sctx;
4689
4690 signal = current_exec_domain_sig(sig);
4691
1d8b512b
RV
4692 __put_user(ka->_sa_handler, &sc->handler);
4693 __put_user(set->sig[0], &sc->oldmask);
61e75fec 4694#if TARGET_ABI_BITS == 64
1d8b512b 4695 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
bcd4933a 4696#else
1d8b512b 4697 __put_user(set->sig[1], &sc->_unused[3]);
bcd4933a 4698#endif
1d8b512b
RV
4699 __put_user(h2g(&frame->mctx), &sc->regs);
4700 __put_user(sig, &sc->signal);
bcd4933a
NF
4701
4702 /* Save user regs. */
7678108b
TM
4703 save_user_regs(env, &frame->mctx);
4704
4705 /* Construct the trampoline code on the stack. */
4706 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
bcd4933a
NF
4707
4708 /* The kernel checks for the presence of a VDSO here. We don't
4709 emulate a vdso, so use a sigreturn system call. */
4710 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4711
4712 /* Turn off all fp exceptions. */
4713 env->fpscr = 0;
4714
4715 /* Create a stack frame for the caller of the handler. */
4716 newsp = frame_addr - SIGNAL_FRAMESIZE;
beb526b1 4717 err |= put_user(env->gpr[1], newsp, target_ulong);
bcd4933a
NF
4718
4719 if (err)
4720 goto sigsegv;
4721
4722 /* Set up registers for signal handler. */
4723 env->gpr[1] = newsp;
4724 env->gpr[3] = signal;
61993a67 4725 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
8d6ab333
TM
4726
4727#if defined(TARGET_PPC64)
4728 /* PPC64 function pointers are pointers to OPD entries. */
4729 struct target_func_ptr *handler =
4730 (struct target_func_ptr *)g2h(ka->_sa_handler);
4731 env->nip = tswapl(handler->entry);
4732 env->gpr[2] = tswapl(handler->toc);
4733#else
bcd4933a 4734 env->nip = (target_ulong) ka->_sa_handler;
8d6ab333
TM
4735#endif
4736
bcd4933a
NF
4737 /* Signal handlers are entered in big-endian mode. */
4738 env->msr &= ~MSR_LE;
4739
4740 unlock_user_struct(frame, frame_addr, 1);
4741 return;
4742
4743sigsegv:
4744 unlock_user_struct(frame, frame_addr, 1);
eeacee4d 4745 qemu_log("segfaulting from setup_frame\n");
66393fb9 4746 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4747}
4748
4749static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 4750 target_siginfo_t *info,
05390248 4751 target_sigset_t *set, CPUPPCState *env)
bcd4933a
NF
4752{
4753 struct target_rt_sigframe *rt_sf;
61e75fec
TM
4754 uint32_t *trampptr = 0;
4755 struct target_mcontext *mctx = 0;
bcd4933a
NF
4756 target_ulong rt_sf_addr, newsp = 0;
4757 int i, err = 0;
4758 int signal;
4759
4760 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4761 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4762 goto sigsegv;
4763
4764 signal = current_exec_domain_sig(sig);
4765
b0fd8d18 4766 copy_siginfo_to_user(&rt_sf->info, info);
bcd4933a 4767
1d8b512b
RV
4768 __put_user(0, &rt_sf->uc.tuc_flags);
4769 __put_user(0, &rt_sf->uc.tuc_link);
4770 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4771 &rt_sf->uc.tuc_stack.ss_sp);
4772 __put_user(sas_ss_flags(env->gpr[1]),
4773 &rt_sf->uc.tuc_stack.ss_flags);
4774 __put_user(target_sigaltstack_used.ss_size,
4775 &rt_sf->uc.tuc_stack.ss_size);
61e75fec 4776#if !defined(TARGET_PPC64)
1d8b512b
RV
4777 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4778 &rt_sf->uc.tuc_regs);
61e75fec 4779#endif
bcd4933a 4780 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 4781 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
bcd4933a
NF
4782 }
4783
61e75fec
TM
4784#if defined(TARGET_PPC64)
4785 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4786 trampptr = &rt_sf->trampoline[0];
4787#else
4788 mctx = &rt_sf->uc.tuc_mcontext;
4789 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4790#endif
4791
4792 save_user_regs(env, mctx);
4793 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
bcd4933a
NF
4794
4795 /* The kernel checks for the presence of a VDSO here. We don't
4796 emulate a vdso, so use a sigreturn system call. */
61e75fec 4797 env->lr = (target_ulong) h2g(trampptr);
bcd4933a
NF
4798
4799 /* Turn off all fp exceptions. */
4800 env->fpscr = 0;
4801
4802 /* Create a stack frame for the caller of the handler. */
4803 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
fbdc200a 4804 err |= put_user(env->gpr[1], newsp, target_ulong);
bcd4933a
NF
4805
4806 if (err)
4807 goto sigsegv;
4808
4809 /* Set up registers for signal handler. */
4810 env->gpr[1] = newsp;
4811 env->gpr[3] = (target_ulong) signal;
4812 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4813 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4814 env->gpr[6] = (target_ulong) h2g(rt_sf);
8d6ab333
TM
4815
4816#if defined(TARGET_PPC64)
4817 /* PPC64 function pointers are pointers to OPD entries. */
4818 struct target_func_ptr *handler =
4819 (struct target_func_ptr *)g2h(ka->_sa_handler);
4820 env->nip = tswapl(handler->entry);
4821 env->gpr[2] = tswapl(handler->toc);
4822#else
bcd4933a 4823 env->nip = (target_ulong) ka->_sa_handler;
8d6ab333
TM
4824#endif
4825
bcd4933a
NF
4826 /* Signal handlers are entered in big-endian mode. */
4827 env->msr &= ~MSR_LE;
4828
4829 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4830 return;
4831
4832sigsegv:
4833 unlock_user_struct(rt_sf, rt_sf_addr, 1);
eeacee4d 4834 qemu_log("segfaulting from setup_rt_frame\n");
66393fb9 4835 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4836
4837}
4838
05390248 4839long do_sigreturn(CPUPPCState *env)
bcd4933a
NF
4840{
4841 struct target_sigcontext *sc = NULL;
4842 struct target_mcontext *sr = NULL;
b04636f8 4843 target_ulong sr_addr = 0, sc_addr;
bcd4933a 4844 sigset_t blocked;
c227f099 4845 target_sigset_t set;
bcd4933a
NF
4846
4847 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4848 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4849 goto sigsegv;
4850
4851#if defined(TARGET_PPC64)
61e75fec 4852 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
bcd4933a 4853#else
f5f601af
RV
4854 __get_user(set.sig[0], &sc->oldmask);
4855 __get_user(set.sig[1], &sc->_unused[3]);
bcd4933a
NF
4856#endif
4857 target_to_host_sigset_internal(&blocked, &set);
1c275925 4858 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
bcd4933a 4859
f5f601af 4860 __get_user(sr_addr, &sc->regs);
bcd4933a
NF
4861 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4862 goto sigsegv;
c650c008 4863 restore_user_regs(env, sr, 1);
bcd4933a
NF
4864
4865 unlock_user_struct(sr, sr_addr, 1);
4866 unlock_user_struct(sc, sc_addr, 1);
4867 return -TARGET_QEMU_ESIGRETURN;
4868
4869sigsegv:
4870 unlock_user_struct(sr, sr_addr, 1);
4871 unlock_user_struct(sc, sc_addr, 1);
eeacee4d 4872 qemu_log("segfaulting from do_sigreturn\n");
66393fb9 4873 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4874 return 0;
4875}
4876
4877/* See arch/powerpc/kernel/signal_32.c. */
05390248 4878static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
bcd4933a
NF
4879{
4880 struct target_mcontext *mcp;
4881 target_ulong mcp_addr;
4882 sigset_t blocked;
c227f099 4883 target_sigset_t set;
bcd4933a 4884
60e99246 4885 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
bcd4933a
NF
4886 sizeof (set)))
4887 return 1;
4888
19774ec5
TM
4889#if defined(TARGET_PPC64)
4890 mcp_addr = h2g(ucp) +
4891 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4892#else
9e918dc9 4893 __get_user(mcp_addr, &ucp->tuc_regs);
19774ec5 4894#endif
bcd4933a
NF
4895
4896 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4897 return 1;
4898
4899 target_to_host_sigset_internal(&blocked, &set);
1c275925 4900 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
c650c008 4901 restore_user_regs(env, mcp, sig);
bcd4933a
NF
4902
4903 unlock_user_struct(mcp, mcp_addr, 1);
4904 return 0;
bcd4933a
NF
4905}
4906
05390248 4907long do_rt_sigreturn(CPUPPCState *env)
bcd4933a
NF
4908{
4909 struct target_rt_sigframe *rt_sf = NULL;
4910 target_ulong rt_sf_addr;
4911
4912 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4913 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4914 goto sigsegv;
4915
4916 if (do_setcontext(&rt_sf->uc, env, 1))
4917 goto sigsegv;
4918
4919 do_sigaltstack(rt_sf_addr
60e99246 4920 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
bcd4933a
NF
4921 0, env->gpr[1]);
4922
4923 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4924 return -TARGET_QEMU_ESIGRETURN;
4925
4926sigsegv:
4927 unlock_user_struct(rt_sf, rt_sf_addr, 1);
eeacee4d 4928 qemu_log("segfaulting from do_rt_sigreturn\n");
66393fb9 4929 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4930 return 0;
4931}
4932
492a8744
LV
4933#elif defined(TARGET_M68K)
4934
4935struct target_sigcontext {
4936 abi_ulong sc_mask;
4937 abi_ulong sc_usp;
4938 abi_ulong sc_d0;
4939 abi_ulong sc_d1;
4940 abi_ulong sc_a0;
4941 abi_ulong sc_a1;
4942 unsigned short sc_sr;
4943 abi_ulong sc_pc;
4944};
4945
4946struct target_sigframe
4947{
4948 abi_ulong pretcode;
4949 int sig;
4950 int code;
4951 abi_ulong psc;
4952 char retcode[8];
4953 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4954 struct target_sigcontext sc;
4955};
7181155d 4956
c227f099 4957typedef int target_greg_t;
7181155d 4958#define TARGET_NGREG 18
c227f099 4959typedef target_greg_t target_gregset_t[TARGET_NGREG];
7181155d
LV
4960
4961typedef struct target_fpregset {
4962 int f_fpcntl[3];
4963 int f_fpregs[8*3];
c227f099 4964} target_fpregset_t;
7181155d
LV
4965
4966struct target_mcontext {
4967 int version;
c227f099
AL
4968 target_gregset_t gregs;
4969 target_fpregset_t fpregs;
7181155d
LV
4970};
4971
4972#define TARGET_MCONTEXT_VERSION 2
4973
4974struct target_ucontext {
60e99246
AJ
4975 abi_ulong tuc_flags;
4976 abi_ulong tuc_link;
4977 target_stack_t tuc_stack;
4978 struct target_mcontext tuc_mcontext;
4979 abi_long tuc_filler[80];
4980 target_sigset_t tuc_sigmask;
7181155d
LV
4981};
4982
4983struct target_rt_sigframe
4984{
4985 abi_ulong pretcode;
4986 int sig;
4987 abi_ulong pinfo;
4988 abi_ulong puc;
4989 char retcode[8];
4990 struct target_siginfo info;
4991 struct target_ucontext uc;
4992};
492a8744 4993
41ecc72b
RV
4994static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
4995 abi_ulong mask)
492a8744 4996{
1d8b512b
RV
4997 __put_user(mask, &sc->sc_mask);
4998 __put_user(env->aregs[7], &sc->sc_usp);
4999 __put_user(env->dregs[0], &sc->sc_d0);
5000 __put_user(env->dregs[1], &sc->sc_d1);
5001 __put_user(env->aregs[0], &sc->sc_a0);
5002 __put_user(env->aregs[1], &sc->sc_a1);
5003 __put_user(env->sr, &sc->sc_sr);
5004 __put_user(env->pc, &sc->sc_pc);
492a8744
LV
5005}
5006
016d2e1d 5007static void
05390248 5008restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
492a8744 5009{
492a8744
LV
5010 int temp;
5011
1d8b512b
RV
5012 __get_user(env->aregs[7], &sc->sc_usp);
5013 __get_user(env->dregs[1], &sc->sc_d1);
5014 __get_user(env->aregs[0], &sc->sc_a0);
5015 __get_user(env->aregs[1], &sc->sc_a1);
5016 __get_user(env->pc, &sc->sc_pc);
5017 __get_user(temp, &sc->sc_sr);
492a8744
LV
5018 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5019
5020 *pd0 = tswapl(sc->sc_d0);
492a8744
LV
5021}
5022
5023/*
5024 * Determine which stack to use..
5025 */
5026static inline abi_ulong
05390248
AF
5027get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5028 size_t frame_size)
492a8744
LV
5029{
5030 unsigned long sp;
5031
5032 sp = regs->aregs[7];
5033
5034 /* This is the X/Open sanctioned signal stack switching. */
5035 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5036 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5037 }
5038
5039 return ((sp - frame_size) & -8UL);
5040}
5041
5042static void setup_frame(int sig, struct target_sigaction *ka,
05390248 5043 target_sigset_t *set, CPUM68KState *env)
492a8744
LV
5044{
5045 struct target_sigframe *frame;
5046 abi_ulong frame_addr;
5047 abi_ulong retcode_addr;
5048 abi_ulong sc_addr;
492a8744
LV
5049 int i;
5050
5051 frame_addr = get_sigframe(ka, env, sizeof *frame);
5052 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5053 goto give_sigsegv;
5054
1d8b512b 5055 __put_user(sig, &frame->sig);
492a8744
LV
5056
5057 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
1d8b512b 5058 __put_user(sc_addr, &frame->psc);
492a8744 5059
41ecc72b 5060 setup_sigcontext(&frame->sc, env, set->sig[0]);
492a8744
LV
5061
5062 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
0188fadb 5063 __put_user(set->sig[i], &frame->extramask[i - 1]);
492a8744
LV
5064 }
5065
5066 /* Set up to return from userspace. */
5067
5068 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
1d8b512b 5069 __put_user(retcode_addr, &frame->pretcode);
492a8744
LV
5070
5071 /* moveq #,d0; trap #0 */
5072
1d8b512b 5073 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
492a8744
LV
5074 (long *)(frame->retcode));
5075
492a8744
LV
5076 /* Set up to return from userspace */
5077
5078 env->aregs[7] = frame_addr;
5079 env->pc = ka->_sa_handler;
5080
5081 unlock_user_struct(frame, frame_addr, 1);
5082 return;
5083
5084give_sigsegv:
66393fb9 5085 force_sig(TARGET_SIGSEGV);
492a8744
LV
5086}
5087
7181155d 5088static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
05390248 5089 CPUM68KState *env)
7181155d 5090{
60e99246 5091 target_greg_t *gregs = uc->tuc_mcontext.gregs;
7181155d 5092
1d8b512b
RV
5093 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5094 __put_user(env->dregs[0], &gregs[0]);
5095 __put_user(env->dregs[1], &gregs[1]);
5096 __put_user(env->dregs[2], &gregs[2]);
5097 __put_user(env->dregs[3], &gregs[3]);
5098 __put_user(env->dregs[4], &gregs[4]);
5099 __put_user(env->dregs[5], &gregs[5]);
5100 __put_user(env->dregs[6], &gregs[6]);
5101 __put_user(env->dregs[7], &gregs[7]);
5102 __put_user(env->aregs[0], &gregs[8]);
5103 __put_user(env->aregs[1], &gregs[9]);
5104 __put_user(env->aregs[2], &gregs[10]);
5105 __put_user(env->aregs[3], &gregs[11]);
5106 __put_user(env->aregs[4], &gregs[12]);
5107 __put_user(env->aregs[5], &gregs[13]);
5108 __put_user(env->aregs[6], &gregs[14]);
5109 __put_user(env->aregs[7], &gregs[15]);
5110 __put_user(env->pc, &gregs[16]);
5111 __put_user(env->sr, &gregs[17]);
7181155d 5112
1d8b512b 5113 return 0;
7181155d
LV
5114}
5115
05390248 5116static inline int target_rt_restore_ucontext(CPUM68KState *env,
7181155d
LV
5117 struct target_ucontext *uc,
5118 int *pd0)
5119{
5120 int temp;
60e99246 5121 target_greg_t *gregs = uc->tuc_mcontext.gregs;
7181155d 5122
1d8b512b 5123 __get_user(temp, &uc->tuc_mcontext.version);
7181155d
LV
5124 if (temp != TARGET_MCONTEXT_VERSION)
5125 goto badframe;
5126
5127 /* restore passed registers */
1d8b512b
RV
5128 __get_user(env->dregs[0], &gregs[0]);
5129 __get_user(env->dregs[1], &gregs[1]);
5130 __get_user(env->dregs[2], &gregs[2]);
5131 __get_user(env->dregs[3], &gregs[3]);
5132 __get_user(env->dregs[4], &gregs[4]);
5133 __get_user(env->dregs[5], &gregs[5]);
5134 __get_user(env->dregs[6], &gregs[6]);
5135 __get_user(env->dregs[7], &gregs[7]);
5136 __get_user(env->aregs[0], &gregs[8]);
5137 __get_user(env->aregs[1], &gregs[9]);
5138 __get_user(env->aregs[2], &gregs[10]);
5139 __get_user(env->aregs[3], &gregs[11]);
5140 __get_user(env->aregs[4], &gregs[12]);
5141 __get_user(env->aregs[5], &gregs[13]);
5142 __get_user(env->aregs[6], &gregs[14]);
5143 __get_user(env->aregs[7], &gregs[15]);
5144 __get_user(env->pc, &gregs[16]);
5145 __get_user(temp, &gregs[17]);
7181155d
LV
5146 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5147
5148 *pd0 = env->dregs[0];
1d8b512b 5149 return 0;
7181155d
LV
5150
5151badframe:
5152 return 1;
5153}
5154
492a8744 5155static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 5156 target_siginfo_t *info,
05390248 5157 target_sigset_t *set, CPUM68KState *env)
492a8744 5158{
7181155d
LV
5159 struct target_rt_sigframe *frame;
5160 abi_ulong frame_addr;
5161 abi_ulong retcode_addr;
5162 abi_ulong info_addr;
5163 abi_ulong uc_addr;
5164 int err = 0;
5165 int i;
5166
5167 frame_addr = get_sigframe(ka, env, sizeof *frame);
5168 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5169 goto give_sigsegv;
5170
1d8b512b 5171 __put_user(sig, &frame->sig);
7181155d
LV
5172
5173 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
1d8b512b 5174 __put_user(info_addr, &frame->pinfo);
7181155d
LV
5175
5176 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
1d8b512b 5177 __put_user(uc_addr, &frame->puc);
7181155d 5178
b0fd8d18 5179 copy_siginfo_to_user(&frame->info, info);
7181155d
LV
5180
5181 /* Create the ucontext */
5182
1d8b512b
RV
5183 __put_user(0, &frame->uc.tuc_flags);
5184 __put_user(0, &frame->uc.tuc_link);
5185 __put_user(target_sigaltstack_used.ss_sp,
5186 &frame->uc.tuc_stack.ss_sp);
5187 __put_user(sas_ss_flags(env->aregs[7]),
5188 &frame->uc.tuc_stack.ss_flags);
5189 __put_user(target_sigaltstack_used.ss_size,
5190 &frame->uc.tuc_stack.ss_size);
7181155d
LV
5191 err |= target_rt_setup_ucontext(&frame->uc, env);
5192
5193 if (err)
5194 goto give_sigsegv;
5195
5196 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
0188fadb 5197 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7181155d
LV
5198 }
5199
5200 /* Set up to return from userspace. */
5201
5202 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
1d8b512b 5203 __put_user(retcode_addr, &frame->pretcode);
7181155d
LV
5204
5205 /* moveq #,d0; notb d0; trap #0 */
5206
1d8b512b
RV
5207 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
5208 (long *)(frame->retcode + 0));
5209 __put_user(0x4e40, (short *)(frame->retcode + 4));
7181155d
LV
5210
5211 if (err)
5212 goto give_sigsegv;
5213
5214 /* Set up to return from userspace */
5215
5216 env->aregs[7] = frame_addr;
5217 env->pc = ka->_sa_handler;
5218
5219 unlock_user_struct(frame, frame_addr, 1);
5220 return;
5221
5222give_sigsegv:
5223 unlock_user_struct(frame, frame_addr, 1);
66393fb9 5224 force_sig(TARGET_SIGSEGV);
492a8744
LV
5225}
5226
05390248 5227long do_sigreturn(CPUM68KState *env)
492a8744
LV
5228{
5229 struct target_sigframe *frame;
5230 abi_ulong frame_addr = env->aregs[7] - 4;
c227f099 5231 target_sigset_t target_set;
492a8744
LV
5232 sigset_t set;
5233 int d0, i;
5234
5235 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5236 goto badframe;
5237
5238 /* set blocked signals */
5239
f5f601af 5240 __get_user(target_set.sig[0], &frame->sc.sc_mask);
492a8744
LV
5241
5242 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 5243 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
492a8744
LV
5244 }
5245
5246 target_to_host_sigset_internal(&set, &target_set);
1c275925 5247 do_sigprocmask(SIG_SETMASK, &set, NULL);
492a8744
LV
5248
5249 /* restore registers */
5250
016d2e1d 5251 restore_sigcontext(env, &frame->sc, &d0);
492a8744
LV
5252
5253 unlock_user_struct(frame, frame_addr, 0);
5254 return d0;
5255
5256badframe:
492a8744
LV
5257 force_sig(TARGET_SIGSEGV);
5258 return 0;
5259}
5260
05390248 5261long do_rt_sigreturn(CPUM68KState *env)
492a8744 5262{
7181155d
LV
5263 struct target_rt_sigframe *frame;
5264 abi_ulong frame_addr = env->aregs[7] - 4;
c227f099 5265 target_sigset_t target_set;
7181155d
LV
5266 sigset_t set;
5267 int d0;
5268
5269 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5270 goto badframe;
5271
5272 target_to_host_sigset_internal(&set, &target_set);
1c275925 5273 do_sigprocmask(SIG_SETMASK, &set, NULL);
7181155d
LV
5274
5275 /* restore registers */
5276
5277 if (target_rt_restore_ucontext(env, &frame->uc, &d0))
5278 goto badframe;
5279
5280 if (do_sigaltstack(frame_addr +
60e99246 5281 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7181155d
LV
5282 0, get_sp_from_cpustate(env)) == -EFAULT)
5283 goto badframe;
5284
5285 unlock_user_struct(frame, frame_addr, 0);
5286 return d0;
5287
5288badframe:
5289 unlock_user_struct(frame, frame_addr, 0);
5290 force_sig(TARGET_SIGSEGV);
5291 return 0;
492a8744
LV
5292}
5293
6049f4f8
RH
5294#elif defined(TARGET_ALPHA)
5295
5296struct target_sigcontext {
5297 abi_long sc_onstack;
5298 abi_long sc_mask;
5299 abi_long sc_pc;
5300 abi_long sc_ps;
5301 abi_long sc_regs[32];
5302 abi_long sc_ownedfp;
5303 abi_long sc_fpregs[32];
5304 abi_ulong sc_fpcr;
5305 abi_ulong sc_fp_control;
5306 abi_ulong sc_reserved1;
5307 abi_ulong sc_reserved2;
5308 abi_ulong sc_ssize;
5309 abi_ulong sc_sbase;
5310 abi_ulong sc_traparg_a0;
5311 abi_ulong sc_traparg_a1;
5312 abi_ulong sc_traparg_a2;
5313 abi_ulong sc_fp_trap_pc;
5314 abi_ulong sc_fp_trigger_sum;
5315 abi_ulong sc_fp_trigger_inst;
5316};
5317
5318struct target_ucontext {
60e99246
AJ
5319 abi_ulong tuc_flags;
5320 abi_ulong tuc_link;
5321 abi_ulong tuc_osf_sigmask;
5322 target_stack_t tuc_stack;
5323 struct target_sigcontext tuc_mcontext;
5324 target_sigset_t tuc_sigmask;
6049f4f8
RH
5325};
5326
5327struct target_sigframe {
5328 struct target_sigcontext sc;
5329 unsigned int retcode[3];
5330};
5331
5332struct target_rt_sigframe {
5333 target_siginfo_t info;
5334 struct target_ucontext uc;
5335 unsigned int retcode[3];
5336};
5337
5338#define INSN_MOV_R30_R16 0x47fe0410
5339#define INSN_LDI_R0 0x201f0000
5340#define INSN_CALLSYS 0x00000083
5341
41ecc72b 5342static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
6049f4f8
RH
5343 abi_ulong frame_addr, target_sigset_t *set)
5344{
41ecc72b 5345 int i;
6049f4f8 5346
1d8b512b
RV
5347 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5348 __put_user(set->sig[0], &sc->sc_mask);
5349 __put_user(env->pc, &sc->sc_pc);
5350 __put_user(8, &sc->sc_ps);
6049f4f8
RH
5351
5352 for (i = 0; i < 31; ++i) {
1d8b512b 5353 __put_user(env->ir[i], &sc->sc_regs[i]);
6049f4f8 5354 }
1d8b512b 5355 __put_user(0, &sc->sc_regs[31]);
6049f4f8
RH
5356
5357 for (i = 0; i < 31; ++i) {
1d8b512b 5358 __put_user(env->fir[i], &sc->sc_fpregs[i]);
6049f4f8 5359 }
1d8b512b
RV
5360 __put_user(0, &sc->sc_fpregs[31]);
5361 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
6049f4f8 5362
1d8b512b
RV
5363 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5364 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5365 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
6049f4f8
RH
5366}
5367
016d2e1d 5368static void restore_sigcontext(CPUAlphaState *env,
05390248 5369 struct target_sigcontext *sc)
6049f4f8
RH
5370{
5371 uint64_t fpcr;
016d2e1d 5372 int i;
6049f4f8 5373
1d8b512b 5374 __get_user(env->pc, &sc->sc_pc);
6049f4f8
RH
5375
5376 for (i = 0; i < 31; ++i) {
1d8b512b 5377 __get_user(env->ir[i], &sc->sc_regs[i]);
6049f4f8
RH
5378 }
5379 for (i = 0; i < 31; ++i) {
1d8b512b 5380 __get_user(env->fir[i], &sc->sc_fpregs[i]);
6049f4f8
RH
5381 }
5382
1d8b512b 5383 __get_user(fpcr, &sc->sc_fpcr);
6049f4f8 5384 cpu_alpha_store_fpcr(env, fpcr);
6049f4f8
RH
5385}
5386
5387static inline abi_ulong get_sigframe(struct target_sigaction *sa,
05390248
AF
5388 CPUAlphaState *env,
5389 unsigned long framesize)
6049f4f8
RH
5390{
5391 abi_ulong sp = env->ir[IR_SP];
5392
5393 /* This is the X/Open sanctioned signal stack switching. */
5394 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5395 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5396 }
5397 return (sp - framesize) & -32;
5398}
5399
5400static void setup_frame(int sig, struct target_sigaction *ka,
05390248 5401 target_sigset_t *set, CPUAlphaState *env)
6049f4f8
RH
5402{
5403 abi_ulong frame_addr, r26;
5404 struct target_sigframe *frame;
5405 int err = 0;
5406
5407 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5408 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5409 goto give_sigsegv;
5410 }
5411
41ecc72b 5412 setup_sigcontext(&frame->sc, env, frame_addr, set);
6049f4f8
RH
5413
5414 if (ka->sa_restorer) {
5415 r26 = ka->sa_restorer;
5416 } else {
1d8b512b
RV
5417 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5418 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5419 &frame->retcode[1]);
5420 __put_user(INSN_CALLSYS, &frame->retcode[2]);
6049f4f8
RH
5421 /* imb() */
5422 r26 = frame_addr;
5423 }
5424
5425 unlock_user_struct(frame, frame_addr, 1);
5426
5427 if (err) {
5428 give_sigsegv:
5429 if (sig == TARGET_SIGSEGV) {
5430 ka->_sa_handler = TARGET_SIG_DFL;
5431 }
5432 force_sig(TARGET_SIGSEGV);
5433 }
5434
5435 env->ir[IR_RA] = r26;
5436 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5437 env->ir[IR_A0] = sig;
5438 env->ir[IR_A1] = 0;
5439 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5440 env->ir[IR_SP] = frame_addr;
5441}
5442
5443static void setup_rt_frame(int sig, struct target_sigaction *ka,
5444 target_siginfo_t *info,
05390248 5445 target_sigset_t *set, CPUAlphaState *env)
6049f4f8
RH
5446{
5447 abi_ulong frame_addr, r26;
5448 struct target_rt_sigframe *frame;
5449 int i, err = 0;
5450
5451 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5452 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5453 goto give_sigsegv;
5454 }
5455
b0fd8d18 5456 copy_siginfo_to_user(&frame->info, info);
6049f4f8 5457
1d8b512b
RV
5458 __put_user(0, &frame->uc.tuc_flags);
5459 __put_user(0, &frame->uc.tuc_link);
5460 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5461 __put_user(target_sigaltstack_used.ss_sp,
5462 &frame->uc.tuc_stack.ss_sp);
5463 __put_user(sas_ss_flags(env->ir[IR_SP]),
5464 &frame->uc.tuc_stack.ss_flags);
5465 __put_user(target_sigaltstack_used.ss_size,
5466 &frame->uc.tuc_stack.ss_size);
41ecc72b 5467 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
6049f4f8 5468 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
1d8b512b 5469 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6049f4f8
RH
5470 }
5471
5472 if (ka->sa_restorer) {
5473 r26 = ka->sa_restorer;
5474 } else {
1d8b512b
RV
5475 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5476 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5477 &frame->retcode[1]);
5478 __put_user(INSN_CALLSYS, &frame->retcode[2]);
6049f4f8
RH
5479 /* imb(); */
5480 r26 = frame_addr;
5481 }
5482
5483 if (err) {
5484 give_sigsegv:
5485 if (sig == TARGET_SIGSEGV) {
5486 ka->_sa_handler = TARGET_SIG_DFL;
5487 }
5488 force_sig(TARGET_SIGSEGV);
5489 }
5490
5491 env->ir[IR_RA] = r26;
5492 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5493 env->ir[IR_A0] = sig;
5494 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5495 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5496 env->ir[IR_SP] = frame_addr;
5497}
5498
05390248 5499long do_sigreturn(CPUAlphaState *env)
6049f4f8
RH
5500{
5501 struct target_sigcontext *sc;
5502 abi_ulong sc_addr = env->ir[IR_A0];
5503 target_sigset_t target_set;
5504 sigset_t set;
5505
5506 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5507 goto badframe;
5508 }
5509
5510 target_sigemptyset(&target_set);
f5f601af 5511 __get_user(target_set.sig[0], &sc->sc_mask);
6049f4f8
RH
5512
5513 target_to_host_sigset_internal(&set, &target_set);
1c275925 5514 do_sigprocmask(SIG_SETMASK, &set, NULL);
6049f4f8 5515
016d2e1d 5516 restore_sigcontext(env, sc);
6049f4f8
RH
5517 unlock_user_struct(sc, sc_addr, 0);
5518 return env->ir[IR_V0];
5519
5520 badframe:
6049f4f8
RH
5521 force_sig(TARGET_SIGSEGV);
5522}
5523
05390248 5524long do_rt_sigreturn(CPUAlphaState *env)
6049f4f8
RH
5525{
5526 abi_ulong frame_addr = env->ir[IR_A0];
5527 struct target_rt_sigframe *frame;
5528 sigset_t set;
5529
5530 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5531 goto badframe;
5532 }
60e99246 5533 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1c275925 5534 do_sigprocmask(SIG_SETMASK, &set, NULL);
6049f4f8 5535
016d2e1d 5536 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6049f4f8 5537 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
60e99246 5538 uc.tuc_stack),
6049f4f8
RH
5539 0, env->ir[IR_SP]) == -EFAULT) {
5540 goto badframe;
5541 }
5542
5543 unlock_user_struct(frame, frame_addr, 0);
5544 return env->ir[IR_V0];
5545
5546
5547 badframe:
5548 unlock_user_struct(frame, frame_addr, 0);
5549 force_sig(TARGET_SIGSEGV);
5550}
5551
b346ff46
FB
5552#else
5553
624f7979 5554static void setup_frame(int sig, struct target_sigaction *ka,
9349b4f9 5555 target_sigset_t *set, CPUArchState *env)
b346ff46
FB
5556{
5557 fprintf(stderr, "setup_frame: not implemented\n");
5558}
5559
624f7979 5560static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 5561 target_siginfo_t *info,
9349b4f9 5562 target_sigset_t *set, CPUArchState *env)
b346ff46
FB
5563{
5564 fprintf(stderr, "setup_rt_frame: not implemented\n");
5565}
5566
9349b4f9 5567long do_sigreturn(CPUArchState *env)
b346ff46
FB
5568{
5569 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 5570 return -TARGET_ENOSYS;
b346ff46
FB
5571}
5572
9349b4f9 5573long do_rt_sigreturn(CPUArchState *env)
b346ff46
FB
5574{
5575 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 5576 return -TARGET_ENOSYS;
b346ff46
FB
5577}
5578
66fb9763
FB
5579#endif
5580
9349b4f9 5581void process_pending_signals(CPUArchState *cpu_env)
66fb9763 5582{
db6b81d4 5583 CPUState *cpu = ENV_GET_CPU(cpu_env);
66fb9763 5584 int sig;
992f48a0 5585 abi_ulong handler;
9de5e440 5586 sigset_t set, old_set;
c227f099 5587 target_sigset_t target_old_set;
624f7979
PB
5588 struct emulated_sigtable *k;
5589 struct target_sigaction *sa;
66fb9763 5590 struct sigqueue *q;
0429a971 5591 TaskState *ts = cpu->opaque;
3b46e624 5592
624f7979 5593 if (!ts->signal_pending)
31e31b8a
FB
5594 return;
5595
624f7979
PB
5596 /* FIXME: This is not threadsafe. */
5597 k = ts->sigtab;
66fb9763
FB
5598 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5599 if (k->pending)
31e31b8a 5600 goto handle_signal;
66fb9763 5601 k++;
31e31b8a
FB
5602 }
5603 /* if no signal is pending, just return */
624f7979 5604 ts->signal_pending = 0;
31e31b8a 5605 return;
66fb9763 5606
31e31b8a 5607 handle_signal:
66fb9763 5608#ifdef DEBUG_SIGNAL
bc8a22cc 5609 fprintf(stderr, "qemu: process signal %d\n", sig);
66fb9763
FB
5610#endif
5611 /* dequeue signal */
5612 q = k->first;
5613 k->first = q->next;
5614 if (!k->first)
5615 k->pending = 0;
3b46e624 5616
db6b81d4 5617 sig = gdb_handlesig(cpu, sig);
1fddef4b 5618 if (!sig) {
ca587a8e
AJ
5619 sa = NULL;
5620 handler = TARGET_SIG_IGN;
5621 } else {
5622 sa = &sigact_table[sig - 1];
5623 handler = sa->_sa_handler;
1fddef4b 5624 }
66fb9763 5625
a7ec0f98
PM
5626 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5627 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5628 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5629 * because it got a real MMU fault), and treat as if default handler.
5630 */
5631 handler = TARGET_SIG_DFL;
5632 }
5633
66fb9763 5634 if (handler == TARGET_SIG_DFL) {
ca587a8e
AJ
5635 /* default handler : ignore some signal. The other are job control or fatal */
5636 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5637 kill(getpid(),SIGSTOP);
5638 } else if (sig != TARGET_SIGCHLD &&
5639 sig != TARGET_SIGURG &&
5640 sig != TARGET_SIGWINCH &&
5641 sig != TARGET_SIGCONT) {
66fb9763
FB
5642 force_sig(sig);
5643 }
5644 } else if (handler == TARGET_SIG_IGN) {
5645 /* ignore sig */
5646 } else if (handler == TARGET_SIG_ERR) {
5647 force_sig(sig);
5648 } else {
9de5e440 5649 /* compute the blocked signals during the handler execution */
624f7979 5650 target_to_host_sigset(&set, &sa->sa_mask);
9de5e440
FB
5651 /* SA_NODEFER indicates that the current signal should not be
5652 blocked during the handler */
624f7979 5653 if (!(sa->sa_flags & TARGET_SA_NODEFER))
9de5e440 5654 sigaddset(&set, target_to_host_signal(sig));
3b46e624 5655
9de5e440 5656 /* block signals in the handler using Linux */
1c275925 5657 do_sigprocmask(SIG_BLOCK, &set, &old_set);
9de5e440
FB
5658 /* save the previous blocked signal state to restore it at the
5659 end of the signal execution (see do_sigreturn) */
9231944d 5660 host_to_target_sigset_internal(&target_old_set, &old_set);
9de5e440 5661
bc8a22cc 5662 /* if the CPU is in VM86 mode, we restore the 32 bit values */
84409ddb 5663#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bc8a22cc
FB
5664 {
5665 CPUX86State *env = cpu_env;
5666 if (env->eflags & VM_MASK)
5667 save_v86_state(env);
5668 }
5669#endif
9de5e440 5670 /* prepare the stack frame of the virtual CPU */
ff970904
RH
5671#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
5672 /* These targets do not have traditional signals. */
5673 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5674#else
624f7979
PB
5675 if (sa->sa_flags & TARGET_SA_SIGINFO)
5676 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
66fb9763 5677 else
624f7979 5678 setup_frame(sig, sa, &target_old_set, cpu_env);
ff970904 5679#endif
624f7979
PB
5680 if (sa->sa_flags & TARGET_SA_RESETHAND)
5681 sa->_sa_handler = TARGET_SIG_DFL;
31e31b8a 5682 }
66fb9763 5683 if (q != &k->info)
624f7979 5684 free_sigqueue(cpu_env, q);
66fb9763 5685}