]> git.proxmox.com Git - qemu.git/blame - linux-user/signal.c
Migrate to check_define
[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
17 * along with this program; if not, write to the Free Software
530e7615
BS
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
31e31b8a
FB
20 */
21#include <stdlib.h>
22#include <stdio.h>
66fb9763 23#include <string.h>
31e31b8a 24#include <stdarg.h>
2677e107 25#include <unistd.h>
31e31b8a 26#include <signal.h>
66fb9763 27#include <errno.h>
31e31b8a
FB
28#include <sys/ucontext.h>
29
3ef693a0 30#include "qemu.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
9e5f5284
FB
46static uint8_t host_to_target_signal_table[65] = {
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
PB
82 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
83 host libpthread signals. This assumes noone actually uses SIGRTMAX :-/
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
FB
88};
89static uint8_t target_to_host_signal_table[65];
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
31e31b8a
FB
103static inline int host_to_target_signal(int sig)
104{
4cb05961
PB
105 if (sig > 64)
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{
4cb05961
PB
112 if (sig > 64)
113 return sig;
9e5f5284 114 return target_to_host_signal_table[sig];
31e31b8a
FB
115}
116
f5545b5c
PB
117static inline void target_sigemptyset(target_sigset_t *set)
118{
119 memset(set, 0, sizeof(*set));
120}
121
122static inline void target_sigaddset(target_sigset_t *set, int signum)
123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 set->sig[signum / TARGET_NSIG_BPW] |= mask;
127}
128
129static inline int target_sigismember(const target_sigset_t *set, int signum)
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
5fafdf24 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
9231944d
FB
148void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
149{
150 target_sigset_t d1;
151 int i;
152
153 host_to_target_sigset_internal(&d1, s);
154 for(i = 0;i < TARGET_NSIG_WORDS; i++)
53a5960a 155 d->sig[i] = tswapl(d1.sig[i]);
9231944d
FB
156}
157
8fcd3692
BS
158static void target_to_host_sigset_internal(sigset_t *d,
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
9231944d
FB
170void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
171{
172 target_sigset_t s1;
173 int i;
174
175 for(i = 0;i < TARGET_NSIG_WORDS; i++)
53a5960a 176 s1.sig[i] = tswapl(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{
9e5f5284
FB
183 target_sigset_t d;
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{
9e5f5284
FB
191 target_sigset_t d;
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
9de5e440
FB
200/* siginfo conversion */
201
5fafdf24 202static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
9de5e440 203 const siginfo_t *info)
66fb9763 204{
9de5e440
FB
205 int sig;
206 sig = host_to_target_signal(info->si_signo);
207 tinfo->si_signo = sig;
208 tinfo->si_errno = 0;
afd7cd92 209 tinfo->si_code = info->si_code;
5fafdf24 210 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
447db213 211 sig == SIGBUS || sig == SIGTRAP) {
9de5e440
FB
212 /* should never come here, but who knows. The information for
213 the target is irrelevant */
214 tinfo->_sifields._sigfault._addr = 0;
7f7f7c84
TS
215 } else if (sig == SIGIO) {
216 tinfo->_sifields._sigpoll._fd = info->si_fd;
9de5e440
FB
217 } else if (sig >= TARGET_SIGRTMIN) {
218 tinfo->_sifields._rt._pid = info->si_pid;
219 tinfo->_sifields._rt._uid = info->si_uid;
220 /* XXX: potential problem if 64 bit */
5fafdf24 221 tinfo->_sifields._rt._sigval.sival_ptr =
459a4017 222 (abi_ulong)(unsigned long)info->si_value.sival_ptr;
9de5e440
FB
223 }
224}
225
5fafdf24 226static void tswap_siginfo(target_siginfo_t *tinfo,
9de5e440
FB
227 const target_siginfo_t *info)
228{
229 int sig;
230 sig = info->si_signo;
231 tinfo->si_signo = tswap32(sig);
66fb9763
FB
232 tinfo->si_errno = tswap32(info->si_errno);
233 tinfo->si_code = tswap32(info->si_code);
5fafdf24 234 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
447db213 235 sig == SIGBUS || sig == SIGTRAP) {
5fafdf24 236 tinfo->_sifields._sigfault._addr =
9de5e440 237 tswapl(info->_sifields._sigfault._addr);
7f7f7c84
TS
238 } else if (sig == SIGIO) {
239 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
9de5e440
FB
240 } else if (sig >= TARGET_SIGRTMIN) {
241 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
242 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
5fafdf24 243 tinfo->_sifields._rt._sigval.sival_ptr =
9de5e440
FB
244 tswapl(info->_sifields._rt._sigval.sival_ptr);
245 }
246}
247
248
249void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
250{
251 host_to_target_siginfo_noswap(tinfo, info);
252 tswap_siginfo(tinfo, tinfo);
66fb9763
FB
253}
254
9de5e440 255/* XXX: we support only POSIX RT signals are used. */
aa1f17c1 256/* XXX: find a solution for 64 bit (additional malloced data is needed) */
9de5e440 257void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
66fb9763
FB
258{
259 info->si_signo = tswap32(tinfo->si_signo);
260 info->si_errno = tswap32(tinfo->si_errno);
261 info->si_code = tswap32(tinfo->si_code);
9de5e440
FB
262 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
263 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
5fafdf24 264 info->si_value.sival_ptr =
459a4017 265 (void *)(long)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
66fb9763
FB
266}
267
ca587a8e
AJ
268static int fatal_signal (int sig)
269{
270 switch (sig) {
271 case TARGET_SIGCHLD:
272 case TARGET_SIGURG:
273 case TARGET_SIGWINCH:
274 /* Ignored by default. */
275 return 0;
276 case TARGET_SIGCONT:
277 case TARGET_SIGSTOP:
278 case TARGET_SIGTSTP:
279 case TARGET_SIGTTIN:
280 case TARGET_SIGTTOU:
281 /* Job control signals. */
282 return 0;
283 default:
284 return 1;
285 }
286}
287
31e31b8a
FB
288void signal_init(void)
289{
290 struct sigaction act;
624f7979 291 struct sigaction oact;
9e5f5284 292 int i, j;
624f7979 293 int host_sig;
31e31b8a 294
9e5f5284
FB
295 /* generate signal conversion tables */
296 for(i = 1; i <= 64; i++) {
297 if (host_to_target_signal_table[i] == 0)
298 host_to_target_signal_table[i] = i;
299 }
300 for(i = 1; i <= 64; i++) {
301 j = host_to_target_signal_table[i];
302 target_to_host_signal_table[j] = i;
303 }
3b46e624 304
9de5e440
FB
305 /* set all host signal handlers. ALL signals are blocked during
306 the handlers to serialize them. */
624f7979
PB
307 memset(sigact_table, 0, sizeof(sigact_table));
308
9de5e440 309 sigfillset(&act.sa_mask);
31e31b8a
FB
310 act.sa_flags = SA_SIGINFO;
311 act.sa_sigaction = host_signal_handler;
624f7979
PB
312 for(i = 1; i <= TARGET_NSIG; i++) {
313 host_sig = target_to_host_signal(i);
314 sigaction(host_sig, NULL, &oact);
315 if (oact.sa_sigaction == (void *)SIG_IGN) {
316 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
317 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
318 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
319 }
320 /* If there's already a handler installed then something has
321 gone horribly wrong, so don't even try to handle that case. */
ca587a8e
AJ
322 /* Install some handlers for our own use. We need at least
323 SIGSEGV and SIGBUS, to detect exceptions. We can not just
324 trap all signals because it affects syscall interrupt
325 behavior. But do trap all default-fatal signals. */
326 if (fatal_signal (i))
624f7979 327 sigaction(host_sig, &act, NULL);
31e31b8a 328 }
66fb9763
FB
329}
330
331/* signal queue handling */
332
624f7979 333static inline struct sigqueue *alloc_sigqueue(CPUState *env)
66fb9763 334{
624f7979
PB
335 TaskState *ts = env->opaque;
336 struct sigqueue *q = ts->first_free;
66fb9763
FB
337 if (!q)
338 return NULL;
624f7979 339 ts->first_free = q->next;
66fb9763 340 return q;
31e31b8a
FB
341}
342
624f7979 343static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
66fb9763 344{
624f7979
PB
345 TaskState *ts = env->opaque;
346 q->next = ts->first_free;
347 ts->first_free = q;
66fb9763
FB
348}
349
9de5e440 350/* abort execution with signal */
8fcd3692 351static void __attribute((noreturn)) force_sig(int sig)
66fb9763
FB
352{
353 int host_sig;
66fb9763 354 host_sig = target_to_host_signal(sig);
5fafdf24 355 fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
66fb9763 356 sig, strsignal(host_sig));
9de5e440 357#if 1
ca587a8e 358 gdb_signalled(thread_env, sig);
66fb9763 359 _exit(-host_sig);
9de5e440
FB
360#else
361 {
362 struct sigaction act;
363 sigemptyset(&act.sa_mask);
364 act.sa_flags = SA_SIGINFO;
365 act.sa_sigaction = SIG_DFL;
366 sigaction(SIGABRT, &act, NULL);
367 abort();
368 }
369#endif
66fb9763
FB
370}
371
9de5e440
FB
372/* queue a signal so that it will be send to the virtual CPU as soon
373 as possible */
624f7979 374int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
31e31b8a 375{
624f7979
PB
376 TaskState *ts = env->opaque;
377 struct emulated_sigtable *k;
9de5e440 378 struct sigqueue *q, **pq;
992f48a0 379 abi_ulong handler;
ca587a8e 380 int queue;
66fb9763 381
9de5e440 382#if defined(DEBUG_SIGNAL)
5fafdf24 383 fprintf(stderr, "queue_signal: sig=%d\n",
9de5e440 384 sig);
66fb9763 385#endif
624f7979 386 k = &ts->sigtab[sig - 1];
ca587a8e 387 queue = gdb_queuesig ();
624f7979 388 handler = sigact_table[sig - 1]._sa_handler;
ca587a8e 389 if (!queue && handler == TARGET_SIG_DFL) {
60b19691
TS
390 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
391 kill(getpid(),SIGSTOP);
392 return 0;
393 } else
66fb9763 394 /* default handler : ignore some signal. The other are fatal */
5fafdf24
TS
395 if (sig != TARGET_SIGCHLD &&
396 sig != TARGET_SIGURG &&
60b19691
TS
397 sig != TARGET_SIGWINCH &&
398 sig != TARGET_SIGCONT) {
66fb9763 399 force_sig(sig);
9de5e440
FB
400 } else {
401 return 0; /* indicate ignored */
66fb9763 402 }
ca587a8e 403 } else if (!queue && handler == TARGET_SIG_IGN) {
66fb9763 404 /* ignore signal */
9de5e440 405 return 0;
ca587a8e 406 } else if (!queue && handler == TARGET_SIG_ERR) {
66fb9763
FB
407 force_sig(sig);
408 } else {
9de5e440
FB
409 pq = &k->first;
410 if (sig < TARGET_SIGRTMIN) {
411 /* if non real time signal, we queue exactly one signal */
412 if (!k->pending)
413 q = &k->info;
414 else
415 return 0;
416 } else {
417 if (!k->pending) {
418 /* first signal */
419 q = &k->info;
420 } else {
624f7979 421 q = alloc_sigqueue(env);
9de5e440
FB
422 if (!q)
423 return -EAGAIN;
424 while (*pq != NULL)
425 pq = &(*pq)->next;
426 }
427 }
428 *pq = q;
429 q->info = *info;
430 q->next = NULL;
431 k->pending = 1;
432 /* signal that a new signal is pending */
624f7979 433 ts->signal_pending = 1;
9de5e440
FB
434 return 1; /* indicates that the signal was queued */
435 }
436}
437
5fafdf24 438static void host_signal_handler(int host_signum, siginfo_t *info,
9de5e440
FB
439 void *puc)
440{
441 int sig;
442 target_siginfo_t tinfo;
443
444 /* the CPU emulator uses some host signals to detect exceptions,
eaa449b9 445 we forward to it some signals */
ca587a8e 446 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
eaa449b9 447 && info->si_code > 0) {
b346ff46 448 if (cpu_signal_handler(host_signum, info, puc))
9de5e440
FB
449 return;
450 }
451
452 /* get target signal number */
453 sig = host_to_target_signal(host_signum);
454 if (sig < 1 || sig > TARGET_NSIG)
455 return;
456#if defined(DEBUG_SIGNAL)
bc8a22cc 457 fprintf(stderr, "qemu: got signal %d\n", sig);
9de5e440
FB
458#endif
459 host_to_target_siginfo_noswap(&tinfo, info);
d5975363 460 if (queue_signal(thread_env, sig, &tinfo) == 1) {
9de5e440 461 /* interrupt the virtual CPU as soon as possible */
d5975363 462 cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT);
66fb9763
FB
463 }
464}
465
0da46a6e 466/* do_sigaltstack() returns target values and errnos. */
579a97f7
FB
467/* compare linux/kernel/signal.c:do_sigaltstack() */
468abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
a04e134a
TS
469{
470 int ret;
471 struct target_sigaltstack oss;
472
473 /* XXX: test errors */
579a97f7 474 if(uoss_addr)
a04e134a
TS
475 {
476 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
477 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
478 __put_user(sas_ss_flags(sp), &oss.ss_flags);
479 }
480
579a97f7 481 if(uss_addr)
a04e134a 482 {
579a97f7
FB
483 struct target_sigaltstack *uss;
484 struct target_sigaltstack ss;
a04e134a 485
0da46a6e 486 ret = -TARGET_EFAULT;
579a97f7 487 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
a04e134a
TS
488 || __get_user(ss.ss_sp, &uss->ss_sp)
489 || __get_user(ss.ss_size, &uss->ss_size)
490 || __get_user(ss.ss_flags, &uss->ss_flags))
491 goto out;
579a97f7 492 unlock_user_struct(uss, uss_addr, 0);
a04e134a 493
0da46a6e 494 ret = -TARGET_EPERM;
a04e134a
TS
495 if (on_sig_stack(sp))
496 goto out;
497
0da46a6e 498 ret = -TARGET_EINVAL;
a04e134a
TS
499 if (ss.ss_flags != TARGET_SS_DISABLE
500 && ss.ss_flags != TARGET_SS_ONSTACK
501 && ss.ss_flags != 0)
502 goto out;
503
504 if (ss.ss_flags == TARGET_SS_DISABLE) {
505 ss.ss_size = 0;
506 ss.ss_sp = 0;
507 } else {
0da46a6e 508 ret = -TARGET_ENOMEM;
a04e134a
TS
509 if (ss.ss_size < MINSIGSTKSZ)
510 goto out;
511 }
512
513 target_sigaltstack_used.ss_sp = ss.ss_sp;
514 target_sigaltstack_used.ss_size = ss.ss_size;
515 }
516
579a97f7 517 if (uoss_addr) {
0da46a6e 518 ret = -TARGET_EFAULT;
579a97f7 519 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
a04e134a 520 goto out;
a04e134a
TS
521 }
522
523 ret = 0;
524out:
525 return ret;
526}
527
0da46a6e 528/* do_sigaction() return host values and errnos */
66fb9763
FB
529int do_sigaction(int sig, const struct target_sigaction *act,
530 struct target_sigaction *oact)
531{
624f7979 532 struct target_sigaction *k;
773b93ee
FB
533 struct sigaction act1;
534 int host_sig;
0da46a6e 535 int ret = 0;
66fb9763 536
2a913eb1 537 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
66fb9763
FB
538 return -EINVAL;
539 k = &sigact_table[sig - 1];
773b93ee 540#if defined(DEBUG_SIGNAL)
5fafdf24 541 fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
66fb9763
FB
542 sig, (int)act, (int)oact);
543#endif
544 if (oact) {
624f7979
PB
545 oact->_sa_handler = tswapl(k->_sa_handler);
546 oact->sa_flags = tswapl(k->sa_flags);
388bb21a 547#if !defined(TARGET_MIPS)
624f7979 548 oact->sa_restorer = tswapl(k->sa_restorer);
388bb21a 549#endif
624f7979 550 oact->sa_mask = k->sa_mask;
66fb9763
FB
551 }
552 if (act) {
624f7979
PB
553 /* FIXME: This is not threadsafe. */
554 k->_sa_handler = tswapl(act->_sa_handler);
555 k->sa_flags = tswapl(act->sa_flags);
388bb21a 556#if !defined(TARGET_MIPS)
624f7979 557 k->sa_restorer = tswapl(act->sa_restorer);
388bb21a 558#endif
624f7979 559 k->sa_mask = act->sa_mask;
773b93ee
FB
560
561 /* we update the host linux signal state */
562 host_sig = target_to_host_signal(sig);
563 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
564 sigfillset(&act1.sa_mask);
565 act1.sa_flags = SA_SIGINFO;
624f7979 566 if (k->sa_flags & TARGET_SA_RESTART)
773b93ee
FB
567 act1.sa_flags |= SA_RESTART;
568 /* NOTE: it is important to update the host kernel signal
569 ignore state to avoid getting unexpected interrupted
570 syscalls */
624f7979 571 if (k->_sa_handler == TARGET_SIG_IGN) {
773b93ee 572 act1.sa_sigaction = (void *)SIG_IGN;
624f7979 573 } else if (k->_sa_handler == TARGET_SIG_DFL) {
ca587a8e
AJ
574 if (fatal_signal (sig))
575 act1.sa_sigaction = host_signal_handler;
576 else
577 act1.sa_sigaction = (void *)SIG_DFL;
773b93ee
FB
578 } else {
579 act1.sa_sigaction = host_signal_handler;
580 }
0da46a6e 581 ret = sigaction(host_sig, &act1, NULL);
773b93ee 582 }
66fb9763 583 }
0da46a6e 584 return ret;
66fb9763
FB
585}
586
5fafdf24 587static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
43fff238
FB
588 const target_siginfo_t *info)
589{
590 tswap_siginfo(tinfo, info);
591 return 0;
592}
593
c3b5bc8a
TS
594static inline int current_exec_domain_sig(int sig)
595{
596 return /* current->exec_domain && current->exec_domain->signal_invmap
597 && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
598}
599
459a4017 600#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
66fb9763
FB
601
602/* from the Linux kernel */
603
604struct target_fpreg {
605 uint16_t significand[4];
606 uint16_t exponent;
607};
608
609struct target_fpxreg {
610 uint16_t significand[4];
611 uint16_t exponent;
612 uint16_t padding[3];
613};
614
615struct target_xmmreg {
992f48a0 616 abi_ulong element[4];
66fb9763
FB
617};
618
619struct target_fpstate {
620 /* Regular FPU environment */
992f48a0
BS
621 abi_ulong cw;
622 abi_ulong sw;
623 abi_ulong tag;
624 abi_ulong ipoff;
625 abi_ulong cssel;
626 abi_ulong dataoff;
627 abi_ulong datasel;
66fb9763
FB
628 struct target_fpreg _st[8];
629 uint16_t status;
630 uint16_t magic; /* 0xffff = regular FPU data only */
631
632 /* FXSR FPU environment */
992f48a0
BS
633 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
634 abi_ulong mxcsr;
635 abi_ulong reserved;
66fb9763
FB
636 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
637 struct target_xmmreg _xmm[8];
992f48a0 638 abi_ulong padding[56];
66fb9763
FB
639};
640
641#define X86_FXSR_MAGIC 0x0000
642
643struct target_sigcontext {
644 uint16_t gs, __gsh;
645 uint16_t fs, __fsh;
646 uint16_t es, __esh;
647 uint16_t ds, __dsh;
992f48a0
BS
648 abi_ulong edi;
649 abi_ulong esi;
650 abi_ulong ebp;
651 abi_ulong esp;
652 abi_ulong ebx;
653 abi_ulong edx;
654 abi_ulong ecx;
655 abi_ulong eax;
656 abi_ulong trapno;
657 abi_ulong err;
658 abi_ulong eip;
66fb9763 659 uint16_t cs, __csh;
992f48a0
BS
660 abi_ulong eflags;
661 abi_ulong esp_at_signal;
66fb9763 662 uint16_t ss, __ssh;
992f48a0
BS
663 abi_ulong fpstate; /* pointer */
664 abi_ulong oldmask;
665 abi_ulong cr2;
66fb9763
FB
666};
667
66fb9763 668struct target_ucontext {
992f48a0
BS
669 abi_ulong tuc_flags;
670 abi_ulong tuc_link;
b8076a74
FB
671 target_stack_t tuc_stack;
672 struct target_sigcontext tuc_mcontext;
673 target_sigset_t tuc_sigmask; /* mask last for extensibility */
66fb9763
FB
674};
675
676struct sigframe
677{
992f48a0 678 abi_ulong pretcode;
66fb9763
FB
679 int sig;
680 struct target_sigcontext sc;
681 struct target_fpstate fpstate;
992f48a0 682 abi_ulong extramask[TARGET_NSIG_WORDS-1];
66fb9763
FB
683 char retcode[8];
684};
685
686struct rt_sigframe
687{
992f48a0 688 abi_ulong pretcode;
66fb9763 689 int sig;
992f48a0
BS
690 abi_ulong pinfo;
691 abi_ulong puc;
66fb9763
FB
692 struct target_siginfo info;
693 struct target_ucontext uc;
694 struct target_fpstate fpstate;
695 char retcode[8];
696};
697
698/*
699 * Set up a signal frame.
700 */
701
66fb9763
FB
702/* XXX: save x87 state */
703static int
704setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
28be6234 705 CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
66fb9763
FB
706{
707 int err = 0;
775b58d8 708 uint16_t magic;
66fb9763 709
579a97f7 710 /* already locked in setup_frame() */
a52c757c
FB
711 err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
712 err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
713 err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
714 err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
66fb9763
FB
715 err |= __put_user(env->regs[R_EDI], &sc->edi);
716 err |= __put_user(env->regs[R_ESI], &sc->esi);
717 err |= __put_user(env->regs[R_EBP], &sc->ebp);
718 err |= __put_user(env->regs[R_ESP], &sc->esp);
719 err |= __put_user(env->regs[R_EBX], &sc->ebx);
720 err |= __put_user(env->regs[R_EDX], &sc->edx);
721 err |= __put_user(env->regs[R_ECX], &sc->ecx);
722 err |= __put_user(env->regs[R_EAX], &sc->eax);
66099dd9
FB
723 err |= __put_user(env->exception_index, &sc->trapno);
724 err |= __put_user(env->error_code, &sc->err);
66fb9763 725 err |= __put_user(env->eip, &sc->eip);
a52c757c 726 err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
66fb9763
FB
727 err |= __put_user(env->eflags, &sc->eflags);
728 err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
a52c757c 729 err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
ed2dcdf6 730
28be6234 731 cpu_x86_fsave(env, fpstate_addr, 1);
ed2dcdf6 732 fpstate->status = fpstate->sw;
775b58d8
FB
733 magic = 0xffff;
734 err |= __put_user(magic, &fpstate->magic);
28be6234 735 err |= __put_user(fpstate_addr, &sc->fpstate);
ed2dcdf6 736
66fb9763
FB
737 /* non-iBCS2 extensions.. */
738 err |= __put_user(mask, &sc->oldmask);
a52c757c 739 err |= __put_user(env->cr[2], &sc->cr2);
66fb9763 740 return err;
31e31b8a
FB
741}
742
66fb9763
FB
743/*
744 * Determine which stack to use..
745 */
31e31b8a 746
579a97f7 747static inline abi_ulong
624f7979 748get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
31e31b8a 749{
66fb9763
FB
750 unsigned long esp;
751
752 /* Default to using normal stack */
753 esp = env->regs[R_ESP];
66fb9763 754 /* This is the X/Open sanctioned signal stack switching. */
624f7979 755 if (ka->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
756 if (sas_ss_flags(esp) == 0)
757 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
758 }
66fb9763
FB
759
760 /* This is the legacy signal stack switching. */
5fafdf24 761 else
a52c757c 762 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
624f7979
PB
763 !(ka->sa_flags & TARGET_SA_RESTORER) &&
764 ka->sa_restorer) {
765 esp = (unsigned long) ka->sa_restorer;
a52c757c 766 }
579a97f7 767 return (esp - frame_size) & -8ul;
66fb9763
FB
768}
769
579a97f7 770/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
624f7979 771static void setup_frame(int sig, struct target_sigaction *ka,
66fb9763
FB
772 target_sigset_t *set, CPUX86State *env)
773{
579a97f7 774 abi_ulong frame_addr;
66fb9763 775 struct sigframe *frame;
9231944d 776 int i, err = 0;
66fb9763 777
579a97f7 778 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 779
579a97f7 780 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 781 goto give_sigsegv;
579a97f7 782
c3b5bc8a 783 err |= __put_user(current_exec_domain_sig(sig),
66fb9763
FB
784 &frame->sig);
785 if (err)
786 goto give_sigsegv;
787
28be6234
FB
788 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
789 frame_addr + offsetof(struct sigframe, fpstate));
66fb9763
FB
790 if (err)
791 goto give_sigsegv;
792
9231944d
FB
793 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
794 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
795 goto give_sigsegv;
796 }
66fb9763
FB
797
798 /* Set up to return from userspace. If provided, use a stub
799 already in userspace. */
624f7979
PB
800 if (ka->sa_flags & TARGET_SA_RESTORER) {
801 err |= __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 802 } else {
775b58d8 803 uint16_t val16;
28be6234
FB
804 abi_ulong retcode_addr;
805 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
806 err |= __put_user(retcode_addr, &frame->pretcode);
66fb9763 807 /* This is popl %eax ; movl $,%eax ; int $0x80 */
775b58d8
FB
808 val16 = 0xb858;
809 err |= __put_user(val16, (uint16_t *)(frame->retcode+0));
66fb9763 810 err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
775b58d8
FB
811 val16 = 0x80cd;
812 err |= __put_user(val16, (uint16_t *)(frame->retcode+6));
66fb9763
FB
813 }
814
815 if (err)
816 goto give_sigsegv;
817
818 /* Set up registers for signal handler */
28be6234 819 env->regs[R_ESP] = frame_addr;
624f7979 820 env->eip = ka->_sa_handler;
66fb9763
FB
821
822 cpu_x86_load_seg(env, R_DS, __USER_DS);
823 cpu_x86_load_seg(env, R_ES, __USER_DS);
824 cpu_x86_load_seg(env, R_SS, __USER_DS);
825 cpu_x86_load_seg(env, R_CS, __USER_CS);
826 env->eflags &= ~TF_MASK;
827
579a97f7
FB
828 unlock_user_struct(frame, frame_addr, 1);
829
66fb9763
FB
830 return;
831
832give_sigsegv:
579a97f7 833 unlock_user_struct(frame, frame_addr, 1);
66fb9763 834 if (sig == TARGET_SIGSEGV)
624f7979 835 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
836 force_sig(TARGET_SIGSEGV /* , current */);
837}
838
579a97f7 839/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
624f7979 840static void setup_rt_frame(int sig, struct target_sigaction *ka,
9de5e440 841 target_siginfo_t *info,
66fb9763
FB
842 target_sigset_t *set, CPUX86State *env)
843{
28be6234 844 abi_ulong frame_addr, addr;
66fb9763 845 struct rt_sigframe *frame;
9231944d 846 int i, err = 0;
66fb9763 847
579a97f7 848 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 849
579a97f7 850 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 851 goto give_sigsegv;
66fb9763 852
c3b5bc8a 853 err |= __put_user(current_exec_domain_sig(sig),
66fb9763 854 &frame->sig);
28be6234
FB
855 addr = frame_addr + offsetof(struct rt_sigframe, info);
856 err |= __put_user(addr, &frame->pinfo);
857 addr = frame_addr + offsetof(struct rt_sigframe, uc);
858 err |= __put_user(addr, &frame->puc);
66fb9763
FB
859 err |= copy_siginfo_to_user(&frame->info, info);
860 if (err)
861 goto give_sigsegv;
31e31b8a 862
66fb9763 863 /* Create the ucontext. */
b8076a74
FB
864 err |= __put_user(0, &frame->uc.tuc_flags);
865 err |= __put_user(0, &frame->uc.tuc_link);
a04e134a 866 err |= __put_user(target_sigaltstack_used.ss_sp,
b8076a74 867 &frame->uc.tuc_stack.ss_sp);
a04e134a 868 err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
b8076a74 869 &frame->uc.tuc_stack.ss_flags);
a04e134a 870 err |= __put_user(target_sigaltstack_used.ss_size,
b8076a74
FB
871 &frame->uc.tuc_stack.ss_size);
872 err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
28be6234
FB
873 env, set->sig[0],
874 frame_addr + offsetof(struct rt_sigframe, fpstate));
9231944d 875 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
b8076a74 876 if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
9231944d
FB
877 goto give_sigsegv;
878 }
31e31b8a 879
66fb9763
FB
880 /* Set up to return from userspace. If provided, use a stub
881 already in userspace. */
624f7979
PB
882 if (ka->sa_flags & TARGET_SA_RESTORER) {
883 err |= __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 884 } else {
775b58d8 885 uint16_t val16;
28be6234
FB
886 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
887 err |= __put_user(addr, &frame->pretcode);
66fb9763 888 /* This is movl $,%eax ; int $0x80 */
775b58d8 889 err |= __put_user(0xb8, (char *)(frame->retcode+0));
66fb9763 890 err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
775b58d8
FB
891 val16 = 0x80cd;
892 err |= __put_user(val16, (uint16_t *)(frame->retcode+5));
66fb9763
FB
893 }
894
895 if (err)
896 goto give_sigsegv;
897
898 /* Set up registers for signal handler */
28be6234 899 env->regs[R_ESP] = frame_addr;
624f7979 900 env->eip = ka->_sa_handler;
66fb9763
FB
901
902 cpu_x86_load_seg(env, R_DS, __USER_DS);
903 cpu_x86_load_seg(env, R_ES, __USER_DS);
904 cpu_x86_load_seg(env, R_SS, __USER_DS);
905 cpu_x86_load_seg(env, R_CS, __USER_CS);
906 env->eflags &= ~TF_MASK;
907
579a97f7
FB
908 unlock_user_struct(frame, frame_addr, 1);
909
66fb9763
FB
910 return;
911
912give_sigsegv:
579a97f7 913 unlock_user_struct(frame, frame_addr, 1);
66fb9763 914 if (sig == TARGET_SIGSEGV)
624f7979 915 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
916 force_sig(TARGET_SIGSEGV /* , current */);
917}
918
919static int
920restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
921{
922 unsigned int err = 0;
28be6234
FB
923 abi_ulong fpstate_addr;
924 unsigned int tmpflags;
925
926 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
927 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
928 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
929 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
930
931 env->regs[R_EDI] = tswapl(sc->edi);
932 env->regs[R_ESI] = tswapl(sc->esi);
933 env->regs[R_EBP] = tswapl(sc->ebp);
934 env->regs[R_ESP] = tswapl(sc->esp);
935 env->regs[R_EBX] = tswapl(sc->ebx);
936 env->regs[R_EDX] = tswapl(sc->edx);
937 env->regs[R_ECX] = tswapl(sc->ecx);
938 env->eip = tswapl(sc->eip);
66fb9763
FB
939
940 cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
941 cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
5fafdf24 942
28be6234
FB
943 tmpflags = tswapl(sc->eflags);
944 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
945 // regs->orig_eax = -1; /* disable syscall checks */
66fb9763 946
28be6234
FB
947 fpstate_addr = tswapl(sc->fpstate);
948 if (fpstate_addr != 0) {
949 if (!access_ok(VERIFY_READ, fpstate_addr,
950 sizeof(struct target_fpstate)))
951 goto badframe;
952 cpu_x86_frstor(env, fpstate_addr, 1);
66fb9763 953 }
ed2dcdf6 954
28be6234 955 *peax = tswapl(sc->eax);
66fb9763 956 return err;
66fb9763
FB
957badframe:
958 return 1;
66fb9763
FB
959}
960
961long do_sigreturn(CPUX86State *env)
962{
579a97f7
FB
963 struct sigframe *frame;
964 abi_ulong frame_addr = env->regs[R_ESP] - 8;
66fb9763
FB
965 target_sigset_t target_set;
966 sigset_t set;
967 int eax, i;
968
447db213
FB
969#if defined(DEBUG_SIGNAL)
970 fprintf(stderr, "do_sigreturn\n");
971#endif
579a97f7
FB
972 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
973 goto badframe;
66fb9763 974 /* set blocked signals */
9231944d
FB
975 if (__get_user(target_set.sig[0], &frame->sc.oldmask))
976 goto badframe;
977 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
978 if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
979 goto badframe;
980 }
66fb9763 981
9231944d 982 target_to_host_sigset_internal(&set, &target_set);
66fb9763 983 sigprocmask(SIG_SETMASK, &set, NULL);
3b46e624 984
66fb9763
FB
985 /* restore registers */
986 if (restore_sigcontext(env, &frame->sc, &eax))
987 goto badframe;
579a97f7 988 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
989 return eax;
990
991badframe:
579a97f7 992 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
993 force_sig(TARGET_SIGSEGV);
994 return 0;
995}
996
997long do_rt_sigreturn(CPUX86State *env)
998{
28be6234
FB
999 abi_ulong frame_addr;
1000 struct rt_sigframe *frame;
66fb9763 1001 sigset_t set;
66fb9763
FB
1002 int eax;
1003
28be6234
FB
1004 frame_addr = env->regs[R_ESP] - 4;
1005 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1006 goto badframe;
b8076a74 1007 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
66fb9763 1008 sigprocmask(SIG_SETMASK, &set, NULL);
5fafdf24 1009
b8076a74 1010 if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
66fb9763
FB
1011 goto badframe;
1012
28be6234
FB
1013 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1014 get_sp_from_cpustate(env)) == -EFAULT)
66fb9763 1015 goto badframe;
a04e134a 1016
28be6234 1017 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1018 return eax;
1019
1020badframe:
28be6234
FB
1021 unlock_user_struct(frame, frame_addr, 0);
1022 force_sig(TARGET_SIGSEGV);
66fb9763
FB
1023 return 0;
1024}
1025
43fff238
FB
1026#elif defined(TARGET_ARM)
1027
1028struct target_sigcontext {
992f48a0
BS
1029 abi_ulong trap_no;
1030 abi_ulong error_code;
1031 abi_ulong oldmask;
1032 abi_ulong arm_r0;
1033 abi_ulong arm_r1;
1034 abi_ulong arm_r2;
1035 abi_ulong arm_r3;
1036 abi_ulong arm_r4;
1037 abi_ulong arm_r5;
1038 abi_ulong arm_r6;
1039 abi_ulong arm_r7;
1040 abi_ulong arm_r8;
1041 abi_ulong arm_r9;
1042 abi_ulong arm_r10;
1043 abi_ulong arm_fp;
1044 abi_ulong arm_ip;
1045 abi_ulong arm_sp;
1046 abi_ulong arm_lr;
1047 abi_ulong arm_pc;
1048 abi_ulong arm_cpsr;
1049 abi_ulong fault_address;
43fff238
FB
1050};
1051
a745ec6d
PB
1052struct target_ucontext_v1 {
1053 abi_ulong tuc_flags;
1054 abi_ulong tuc_link;
1055 target_stack_t tuc_stack;
1056 struct target_sigcontext tuc_mcontext;
1057 target_sigset_t tuc_sigmask; /* mask last for extensibility */
1058};
1059
1060struct target_ucontext_v2 {
992f48a0
BS
1061 abi_ulong tuc_flags;
1062 abi_ulong tuc_link;
b8076a74
FB
1063 target_stack_t tuc_stack;
1064 struct target_sigcontext tuc_mcontext;
1065 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a745ec6d
PB
1066 char __unused[128 - sizeof(sigset_t)];
1067 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
43fff238
FB
1068};
1069
a8c33204 1070struct sigframe_v1
43fff238
FB
1071{
1072 struct target_sigcontext sc;
992f48a0
BS
1073 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1074 abi_ulong retcode;
43fff238
FB
1075};
1076
a8c33204
PB
1077struct sigframe_v2
1078{
1079 struct target_ucontext_v2 uc;
1080 abi_ulong retcode;
1081};
1082
a745ec6d 1083struct rt_sigframe_v1
43fff238 1084{
f8b0aa25
FB
1085 abi_ulong pinfo;
1086 abi_ulong puc;
43fff238 1087 struct target_siginfo info;
a745ec6d
PB
1088 struct target_ucontext_v1 uc;
1089 abi_ulong retcode;
1090};
1091
1092struct rt_sigframe_v2
1093{
1094 struct target_siginfo info;
1095 struct target_ucontext_v2 uc;
992f48a0 1096 abi_ulong retcode;
43fff238
FB
1097};
1098
1099#define TARGET_CONFIG_CPU_32 1
1100
1101/*
1102 * For ARM syscalls, we encode the syscall number into the instruction.
1103 */
1104#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1105#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1106
1107/*
1108 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1109 * need two 16-bit instructions.
1110 */
1111#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1112#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1113
992f48a0 1114static const abi_ulong retcodes[4] = {
43fff238
FB
1115 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1116 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1117};
1118
1119
43fff238
FB
1120#define __get_user_error(x,p,e) __get_user(x, p)
1121
1122static inline int valid_user_regs(CPUState *regs)
1123{
1124 return 1;
1125}
1126
a8c33204 1127static void
43fff238 1128setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
f8b0aa25 1129 CPUState *env, abi_ulong mask)
43fff238 1130{
a8c33204
PB
1131 __put_user(env->regs[0], &sc->arm_r0);
1132 __put_user(env->regs[1], &sc->arm_r1);
1133 __put_user(env->regs[2], &sc->arm_r2);
1134 __put_user(env->regs[3], &sc->arm_r3);
1135 __put_user(env->regs[4], &sc->arm_r4);
1136 __put_user(env->regs[5], &sc->arm_r5);
1137 __put_user(env->regs[6], &sc->arm_r6);
1138 __put_user(env->regs[7], &sc->arm_r7);
1139 __put_user(env->regs[8], &sc->arm_r8);
1140 __put_user(env->regs[9], &sc->arm_r9);
1141 __put_user(env->regs[10], &sc->arm_r10);
1142 __put_user(env->regs[11], &sc->arm_fp);
1143 __put_user(env->regs[12], &sc->arm_ip);
1144 __put_user(env->regs[13], &sc->arm_sp);
1145 __put_user(env->regs[14], &sc->arm_lr);
1146 __put_user(env->regs[15], &sc->arm_pc);
43fff238 1147#ifdef TARGET_CONFIG_CPU_32
a8c33204 1148 __put_user(cpsr_read(env), &sc->arm_cpsr);
43fff238
FB
1149#endif
1150
a8c33204
PB
1151 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1152 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1153 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1154 __put_user(mask, &sc->oldmask);
43fff238
FB
1155}
1156
579a97f7 1157static inline abi_ulong
624f7979 1158get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
43fff238
FB
1159{
1160 unsigned long sp = regs->regs[13];
1161
43fff238
FB
1162 /*
1163 * This is the X/Open sanctioned signal stack switching.
1164 */
624f7979 1165 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
a04e134a 1166 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
43fff238
FB
1167 /*
1168 * ATPCS B01 mandates 8-byte alignment
1169 */
579a97f7 1170 return (sp - framesize) & ~7;
43fff238
FB
1171}
1172
1173static int
624f7979 1174setup_return(CPUState *env, struct target_sigaction *ka,
f8b0aa25 1175 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
43fff238 1176{
624f7979 1177 abi_ulong handler = ka->_sa_handler;
992f48a0 1178 abi_ulong retcode;
75b680e5 1179 int thumb = handler & 1;
43fff238 1180
624f7979
PB
1181 if (ka->sa_flags & TARGET_SA_RESTORER) {
1182 retcode = ka->sa_restorer;
43fff238
FB
1183 } else {
1184 unsigned int idx = thumb;
1185
624f7979 1186 if (ka->sa_flags & TARGET_SA_SIGINFO)
43fff238
FB
1187 idx += 2;
1188
1189 if (__put_user(retcodes[idx], rc))
1190 return 1;
1191#if 0
992f48a0
BS
1192 flush_icache_range((abi_ulong)rc,
1193 (abi_ulong)(rc + 1));
43fff238 1194#endif
f8b0aa25 1195 retcode = rc_addr + thumb;
43fff238
FB
1196 }
1197
1198 env->regs[0] = usig;
f8b0aa25 1199 env->regs[13] = frame_addr;
43fff238
FB
1200 env->regs[14] = retcode;
1201 env->regs[15] = handler & (thumb ? ~1 : ~3);
75b680e5 1202 env->thumb = thumb;
43fff238 1203
b5ff1b31 1204#if 0
43fff238
FB
1205#ifdef TARGET_CONFIG_CPU_32
1206 env->cpsr = cpsr;
b5ff1b31 1207#endif
43fff238
FB
1208#endif
1209
1210 return 0;
1211}
1212
a8c33204
PB
1213static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
1214 target_sigset_t *set, CPUState *env)
1215{
1216 struct target_sigaltstack stack;
1217 int i;
1218
1219 /* Clear all the bits of the ucontext we don't use. */
1220 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1221
1222 memset(&stack, 0, sizeof(stack));
1223 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1224 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1225 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1226 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1227
1228 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
1229 /* FIXME: Save coprocessor signal frame. */
1230 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1231 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1232 }
1233}
1234
579a97f7 1235/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
624f7979 1236static void setup_frame_v1(int usig, struct target_sigaction *ka,
a8c33204 1237 target_sigset_t *set, CPUState *regs)
43fff238 1238{
a8c33204 1239 struct sigframe_v1 *frame;
579a97f7 1240 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
a8c33204 1241 int i;
43fff238 1242
579a97f7
FB
1243 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1244 return;
1245
a8c33204 1246 setup_sigcontext(&frame->sc, regs, set->sig[0]);
43fff238 1247
9231944d
FB
1248 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1249 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
579a97f7 1250 goto end;
43fff238
FB
1251 }
1252
a8c33204
PB
1253 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1254 frame_addr + offsetof(struct sigframe_v1, retcode));
579a97f7
FB
1255
1256end:
1257 unlock_user_struct(frame, frame_addr, 1);
a8c33204
PB
1258}
1259
624f7979 1260static void setup_frame_v2(int usig, struct target_sigaction *ka,
a8c33204
PB
1261 target_sigset_t *set, CPUState *regs)
1262{
1263 struct sigframe_v2 *frame;
1264 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1265
1266 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1267 return;
1268
1269 setup_sigframe_v2(&frame->uc, set, regs);
1270
1271 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1272 frame_addr + offsetof(struct sigframe_v2, retcode));
1273
1274 unlock_user_struct(frame, frame_addr, 1);
1275}
1276
624f7979 1277static void setup_frame(int usig, struct target_sigaction *ka,
a8c33204
PB
1278 target_sigset_t *set, CPUState *regs)
1279{
1280 if (get_osversion() >= 0x020612) {
1281 setup_frame_v2(usig, ka, set, regs);
1282 } else {
1283 setup_frame_v1(usig, ka, set, regs);
1284 }
43fff238
FB
1285}
1286
579a97f7 1287/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
624f7979 1288static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
a745ec6d
PB
1289 target_siginfo_t *info,
1290 target_sigset_t *set, CPUState *env)
43fff238 1291{
a745ec6d 1292 struct rt_sigframe_v1 *frame;
579a97f7 1293 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a04e134a 1294 struct target_sigaltstack stack;
a8c33204 1295 int i;
f8b0aa25 1296 abi_ulong info_addr, uc_addr;
43fff238 1297
579a97f7 1298 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
edf779ff
FB
1299 return /* 1 */;
1300
a745ec6d 1301 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
a8c33204 1302 __put_user(info_addr, &frame->pinfo);
a745ec6d 1303 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
a8c33204
PB
1304 __put_user(uc_addr, &frame->puc);
1305 copy_siginfo_to_user(&frame->info, info);
43fff238
FB
1306
1307 /* Clear all the bits of the ucontext we don't use. */
a745ec6d 1308 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
43fff238 1309
a04e134a
TS
1310 memset(&stack, 0, sizeof(stack));
1311 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1312 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1313 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
775b58d8 1314 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
a04e134a 1315
a8c33204 1316 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
9231944d 1317 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
b8076a74 1318 if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
579a97f7 1319 goto end;
9231944d 1320 }
43fff238 1321
a8c33204
PB
1322 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1323 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
a745ec6d 1324
a8c33204
PB
1325 env->regs[1] = info_addr;
1326 env->regs[2] = uc_addr;
a745ec6d
PB
1327
1328end:
1329 unlock_user_struct(frame, frame_addr, 1);
a745ec6d
PB
1330}
1331
624f7979 1332static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
a745ec6d
PB
1333 target_siginfo_t *info,
1334 target_sigset_t *set, CPUState *env)
1335{
1336 struct rt_sigframe_v2 *frame;
1337 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a745ec6d
PB
1338 abi_ulong info_addr, uc_addr;
1339
1340 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1341 return /* 1 */;
1342
1343 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1344 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
a8c33204 1345 copy_siginfo_to_user(&frame->info, info);
a745ec6d 1346
a8c33204 1347 setup_sigframe_v2(&frame->uc, set, env);
a745ec6d 1348
a8c33204
PB
1349 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1350 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
a745ec6d 1351
a8c33204
PB
1352 env->regs[1] = info_addr;
1353 env->regs[2] = uc_addr;
43fff238 1354
579a97f7 1355 unlock_user_struct(frame, frame_addr, 1);
43fff238
FB
1356}
1357
624f7979 1358static void setup_rt_frame(int usig, struct target_sigaction *ka,
a745ec6d
PB
1359 target_siginfo_t *info,
1360 target_sigset_t *set, CPUState *env)
1361{
1362 if (get_osversion() >= 0x020612) {
1363 setup_rt_frame_v2(usig, ka, info, set, env);
1364 } else {
1365 setup_rt_frame_v1(usig, ka, info, set, env);
1366 }
1367}
1368
43fff238
FB
1369static int
1370restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1371{
1372 int err = 0;
b5ff1b31 1373 uint32_t cpsr;
43fff238
FB
1374
1375 __get_user_error(env->regs[0], &sc->arm_r0, err);
1376 __get_user_error(env->regs[1], &sc->arm_r1, err);
1377 __get_user_error(env->regs[2], &sc->arm_r2, err);
1378 __get_user_error(env->regs[3], &sc->arm_r3, err);
1379 __get_user_error(env->regs[4], &sc->arm_r4, err);
1380 __get_user_error(env->regs[5], &sc->arm_r5, err);
1381 __get_user_error(env->regs[6], &sc->arm_r6, err);
1382 __get_user_error(env->regs[7], &sc->arm_r7, err);
1383 __get_user_error(env->regs[8], &sc->arm_r8, err);
1384 __get_user_error(env->regs[9], &sc->arm_r9, err);
1385 __get_user_error(env->regs[10], &sc->arm_r10, err);
1386 __get_user_error(env->regs[11], &sc->arm_fp, err);
1387 __get_user_error(env->regs[12], &sc->arm_ip, err);
1388 __get_user_error(env->regs[13], &sc->arm_sp, err);
1389 __get_user_error(env->regs[14], &sc->arm_lr, err);
1390 __get_user_error(env->regs[15], &sc->arm_pc, err);
1391#ifdef TARGET_CONFIG_CPU_32
b5ff1b31 1392 __get_user_error(cpsr, &sc->arm_cpsr, err);
75b680e5 1393 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
43fff238
FB
1394#endif
1395
1396 err |= !valid_user_regs(env);
1397
1398 return err;
1399}
1400
a8c33204 1401long do_sigreturn_v1(CPUState *env)
43fff238 1402{
f8b0aa25 1403 abi_ulong frame_addr;
a8c33204 1404 struct sigframe_v1 *frame;
43fff238
FB
1405 target_sigset_t set;
1406 sigset_t host_set;
9231944d 1407 int i;
43fff238
FB
1408
1409 /*
1410 * Since we stacked the signal on a 64-bit boundary,
1411 * then 'sp' should be word aligned here. If it's
1412 * not, then the user is trying to mess with us.
1413 */
1414 if (env->regs[13] & 7)
1415 goto badframe;
1416
f8b0aa25
FB
1417 frame_addr = env->regs[13];
1418 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1419 goto badframe;
43fff238 1420
9231944d
FB
1421 if (__get_user(set.sig[0], &frame->sc.oldmask))
1422 goto badframe;
1423 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1424 if (__get_user(set.sig[i], &frame->extramask[i - 1]))
1425 goto badframe;
1426 }
43fff238 1427
9231944d 1428 target_to_host_sigset_internal(&host_set, &set);
43fff238
FB
1429 sigprocmask(SIG_SETMASK, &host_set, NULL);
1430
1431 if (restore_sigcontext(env, &frame->sc))
1432 goto badframe;
1433
1434#if 0
1435 /* Send SIGTRAP if we're single-stepping */
1436 if (ptrace_cancel_bpt(current))
1437 send_sig(SIGTRAP, current, 1);
1438#endif
f8b0aa25
FB
1439 unlock_user_struct(frame, frame_addr, 0);
1440 return env->regs[0];
43fff238
FB
1441
1442badframe:
f8b0aa25 1443 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1444 force_sig(SIGSEGV /* , current */);
1445 return 0;
1446}
1447
a8c33204
PB
1448static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
1449 struct target_ucontext_v2 *uc)
1450{
1451 sigset_t host_set;
1452
1453 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
1454 sigprocmask(SIG_SETMASK, &host_set, NULL);
1455
1456 if (restore_sigcontext(env, &uc->tuc_mcontext))
1457 return 1;
1458
1459 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1460 return 1;
1461
1462#if 0
1463 /* Send SIGTRAP if we're single-stepping */
1464 if (ptrace_cancel_bpt(current))
1465 send_sig(SIGTRAP, current, 1);
1466#endif
1467
1468 return 0;
1469}
1470
1471long do_sigreturn_v2(CPUState *env)
1472{
1473 abi_ulong frame_addr;
1474 struct sigframe_v2 *frame;
1475
1476 /*
1477 * Since we stacked the signal on a 64-bit boundary,
1478 * then 'sp' should be word aligned here. If it's
1479 * not, then the user is trying to mess with us.
1480 */
1481 if (env->regs[13] & 7)
1482 goto badframe;
1483
1484 frame_addr = env->regs[13];
1485 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1486 goto badframe;
1487
1488 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1489 goto badframe;
1490
1491 unlock_user_struct(frame, frame_addr, 0);
1492 return env->regs[0];
1493
1494badframe:
1495 unlock_user_struct(frame, frame_addr, 0);
1496 force_sig(SIGSEGV /* , current */);
1497 return 0;
1498}
1499
1500long do_sigreturn(CPUState *env)
1501{
1502 if (get_osversion() >= 0x020612) {
1503 return do_sigreturn_v2(env);
1504 } else {
1505 return do_sigreturn_v1(env);
1506 }
1507}
1508
a745ec6d 1509long do_rt_sigreturn_v1(CPUState *env)
43fff238 1510{
f8b0aa25 1511 abi_ulong frame_addr;
a745ec6d
PB
1512 struct rt_sigframe_v1 *frame;
1513 sigset_t host_set;
1514
1515 /*
1516 * Since we stacked the signal on a 64-bit boundary,
1517 * then 'sp' should be word aligned here. If it's
1518 * not, then the user is trying to mess with us.
1519 */
1520 if (env->regs[13] & 7)
1521 goto badframe;
1522
1523 frame_addr = env->regs[13];
1524 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1525 goto badframe;
1526
1527 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1528 sigprocmask(SIG_SETMASK, &host_set, NULL);
1529
1530 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1531 goto badframe;
1532
1533 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1534 goto badframe;
1535
1536#if 0
1537 /* Send SIGTRAP if we're single-stepping */
1538 if (ptrace_cancel_bpt(current))
1539 send_sig(SIGTRAP, current, 1);
1540#endif
1541 unlock_user_struct(frame, frame_addr, 0);
1542 return env->regs[0];
1543
1544badframe:
1545 unlock_user_struct(frame, frame_addr, 0);
1546 force_sig(SIGSEGV /* , current */);
1547 return 0;
1548}
1549
1550long do_rt_sigreturn_v2(CPUState *env)
1551{
1552 abi_ulong frame_addr;
1553 struct rt_sigframe_v2 *frame;
43fff238
FB
1554
1555 /*
1556 * Since we stacked the signal on a 64-bit boundary,
1557 * then 'sp' should be word aligned here. If it's
1558 * not, then the user is trying to mess with us.
1559 */
1560 if (env->regs[13] & 7)
1561 goto badframe;
1562
f8b0aa25
FB
1563 frame_addr = env->regs[13];
1564 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1565 goto badframe;
43fff238 1566
a8c33204
PB
1567 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1568 goto badframe;
a04e134a 1569
f8b0aa25 1570 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1571 return env->regs[0];
1572
1573badframe:
f8b0aa25 1574 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1575 force_sig(SIGSEGV /* , current */);
1576 return 0;
1577}
1578
a745ec6d
PB
1579long do_rt_sigreturn(CPUState *env)
1580{
1581 if (get_osversion() >= 0x020612) {
1582 return do_rt_sigreturn_v2(env);
1583 } else {
1584 return do_rt_sigreturn_v1(env);
1585 }
1586}
1587
6d5e216d 1588#elif defined(TARGET_SPARC)
80a9d035 1589
6d5e216d
FB
1590#define __SUNOS_MAXWIN 31
1591
1592/* This is what SunOS does, so shall I. */
1593struct target_sigcontext {
992f48a0 1594 abi_ulong sigc_onstack; /* state to restore */
6d5e216d 1595
992f48a0
BS
1596 abi_ulong sigc_mask; /* sigmask to restore */
1597 abi_ulong sigc_sp; /* stack pointer */
1598 abi_ulong sigc_pc; /* program counter */
1599 abi_ulong sigc_npc; /* next program counter */
1600 abi_ulong sigc_psr; /* for condition codes etc */
1601 abi_ulong sigc_g1; /* User uses these two registers */
1602 abi_ulong sigc_o0; /* within the trampoline code. */
6d5e216d
FB
1603
1604 /* Now comes information regarding the users window set
1605 * at the time of the signal.
1606 */
992f48a0 1607 abi_ulong sigc_oswins; /* outstanding windows */
6d5e216d
FB
1608
1609 /* stack ptrs for each regwin buf */
1610 char *sigc_spbuf[__SUNOS_MAXWIN];
1611
1612 /* Windows to restore after signal */
1613 struct {
992f48a0
BS
1614 abi_ulong locals[8];
1615 abi_ulong ins[8];
6d5e216d
FB
1616 } sigc_wbuf[__SUNOS_MAXWIN];
1617};
1618/* A Sparc stack frame */
1619struct sparc_stackf {
992f48a0
BS
1620 abi_ulong locals[8];
1621 abi_ulong ins[6];
6d5e216d 1622 struct sparc_stackf *fp;
992f48a0 1623 abi_ulong callers_pc;
6d5e216d 1624 char *structptr;
992f48a0
BS
1625 abi_ulong xargs[6];
1626 abi_ulong xxargs[1];
6d5e216d
FB
1627};
1628
1629typedef struct {
1630 struct {
992f48a0
BS
1631 abi_ulong psr;
1632 abi_ulong pc;
1633 abi_ulong npc;
1634 abi_ulong y;
1635 abi_ulong u_regs[16]; /* globals and ins */
6d5e216d
FB
1636 } si_regs;
1637 int si_mask;
1638} __siginfo_t;
1639
1640typedef struct {
1641 unsigned long si_float_regs [32];
1642 unsigned long si_fsr;
1643 unsigned long si_fpqdepth;
1644 struct {
1645 unsigned long *insn_addr;
1646 unsigned long insn;
1647 } si_fpqueue [16];
74ccb34e 1648} qemu_siginfo_fpu_t;
6d5e216d
FB
1649
1650
1651struct target_signal_frame {
1652 struct sparc_stackf ss;
1653 __siginfo_t info;
f8b0aa25 1654 abi_ulong fpu_save;
992f48a0
BS
1655 abi_ulong insns[2] __attribute__ ((aligned (8)));
1656 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
1657 abi_ulong extra_size; /* Should be 0 */
74ccb34e 1658 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
1659};
1660struct target_rt_signal_frame {
1661 struct sparc_stackf ss;
1662 siginfo_t info;
992f48a0 1663 abi_ulong regs[20];
6d5e216d 1664 sigset_t mask;
f8b0aa25 1665 abi_ulong fpu_save;
6d5e216d
FB
1666 unsigned int insns[2];
1667 stack_t stack;
1668 unsigned int extra_size; /* Should be 0 */
74ccb34e 1669 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
1670};
1671
e80cfcfc
FB
1672#define UREG_O0 16
1673#define UREG_O6 22
1674#define UREG_I0 0
1675#define UREG_I1 1
1676#define UREG_I2 2
5bfb56b2
BS
1677#define UREG_I3 3
1678#define UREG_I4 4
1679#define UREG_I5 5
e80cfcfc
FB
1680#define UREG_I6 6
1681#define UREG_I7 7
1682#define UREG_L0 8
6d5e216d
FB
1683#define UREG_FP UREG_I6
1684#define UREG_SP UREG_O6
1685
624f7979 1686static inline abi_ulong get_sigframe(struct target_sigaction *sa,
459a4017 1687 CPUState *env, unsigned long framesize)
6d5e216d 1688{
459a4017 1689 abi_ulong sp;
6d5e216d
FB
1690
1691 sp = env->regwptr[UREG_FP];
6d5e216d
FB
1692
1693 /* This is the X/Open sanctioned signal stack switching. */
624f7979 1694 if (sa->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
1695 if (!on_sig_stack(sp)
1696 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
1697 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6d5e216d 1698 }
459a4017 1699 return sp - framesize;
6d5e216d
FB
1700}
1701
1702static int
992f48a0 1703setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
6d5e216d
FB
1704{
1705 int err = 0, i;
1706
6d5e216d 1707 err |= __put_user(env->psr, &si->si_regs.psr);
6d5e216d
FB
1708 err |= __put_user(env->pc, &si->si_regs.pc);
1709 err |= __put_user(env->npc, &si->si_regs.npc);
1710 err |= __put_user(env->y, &si->si_regs.y);
a315a145 1711 for (i=0; i < 8; i++) {
6d5e216d
FB
1712 err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
1713 }
a315a145 1714 for (i=0; i < 8; i++) {
e80cfcfc 1715 err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
6d5e216d 1716 }
6d5e216d
FB
1717 err |= __put_user(mask, &si->si_mask);
1718 return err;
1719}
e80cfcfc 1720
80a9d035 1721#if 0
6d5e216d
FB
1722static int
1723setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1724 CPUState *env, unsigned long mask)
1725{
1726 int err = 0;
1727
1728 err |= __put_user(mask, &sc->sigc_mask);
1729 err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1730 err |= __put_user(env->pc, &sc->sigc_pc);
1731 err |= __put_user(env->npc, &sc->sigc_npc);
1732 err |= __put_user(env->psr, &sc->sigc_psr);
1733 err |= __put_user(env->gregs[1], &sc->sigc_g1);
1734 err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1735
1736 return err;
1737}
80a9d035 1738#endif
6d5e216d
FB
1739#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
1740
624f7979 1741static void setup_frame(int sig, struct target_sigaction *ka,
6d5e216d
FB
1742 target_sigset_t *set, CPUState *env)
1743{
459a4017 1744 abi_ulong sf_addr;
6d5e216d
FB
1745 struct target_signal_frame *sf;
1746 int sigframe_size, err, i;
1747
1748 /* 1. Make sure everything is clean */
1749 //synchronize_user_stack();
1750
1751 sigframe_size = NF_ALIGNEDSZ;
459a4017 1752 sf_addr = get_sigframe(ka, env, sigframe_size);
6d5e216d 1753
459a4017
FB
1754 sf = lock_user(VERIFY_WRITE, sf_addr,
1755 sizeof(struct target_signal_frame), 0);
1756 if (!sf)
1757 goto sigsegv;
1758
e80cfcfc 1759 //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
6d5e216d
FB
1760#if 0
1761 if (invalid_frame_pointer(sf, sigframe_size))
1762 goto sigill_and_return;
1763#endif
1764 /* 2. Save the current process state */
1765 err = setup___siginfo(&sf->info, env, set->sig[0]);
1766 err |= __put_user(0, &sf->extra_size);
1767
1768 //err |= save_fpu_state(regs, &sf->fpu_state);
1769 //err |= __put_user(&sf->fpu_state, &sf->fpu_save);
1770
1771 err |= __put_user(set->sig[0], &sf->info.si_mask);
1772 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1773 err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
1774 }
1775
a315a145 1776 for (i = 0; i < 8; i++) {
e80cfcfc 1777 err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
6d5e216d 1778 }
a315a145 1779 for (i = 0; i < 8; i++) {
e80cfcfc 1780 err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
6d5e216d 1781 }
6d5e216d
FB
1782 if (err)
1783 goto sigsegv;
1784
1785 /* 3. signal handler back-trampoline and parameters */
459a4017 1786 env->regwptr[UREG_FP] = sf_addr;
6d5e216d 1787 env->regwptr[UREG_I0] = sig;
459a4017
FB
1788 env->regwptr[UREG_I1] = sf_addr +
1789 offsetof(struct target_signal_frame, info);
1790 env->regwptr[UREG_I2] = sf_addr +
1791 offsetof(struct target_signal_frame, info);
6d5e216d
FB
1792
1793 /* 4. signal handler */
624f7979 1794 env->pc = ka->_sa_handler;
6d5e216d
FB
1795 env->npc = (env->pc + 4);
1796 /* 5. return to kernel instructions */
624f7979
PB
1797 if (ka->sa_restorer)
1798 env->regwptr[UREG_I7] = ka->sa_restorer;
6d5e216d 1799 else {
775b58d8 1800 uint32_t val32;
459a4017
FB
1801
1802 env->regwptr[UREG_I7] = sf_addr +
1803 offsetof(struct target_signal_frame, insns) - 2 * 4;
6d5e216d
FB
1804
1805 /* mov __NR_sigreturn, %g1 */
775b58d8
FB
1806 val32 = 0x821020d8;
1807 err |= __put_user(val32, &sf->insns[0]);
6d5e216d
FB
1808
1809 /* t 0x10 */
775b58d8
FB
1810 val32 = 0x91d02010;
1811 err |= __put_user(val32, &sf->insns[1]);
6d5e216d
FB
1812 if (err)
1813 goto sigsegv;
1814
1815 /* Flush instruction space. */
1816 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
80a9d035 1817 // tb_flush(env);
6d5e216d 1818 }
459a4017 1819 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d 1820 return;
459a4017
FB
1821#if 0
1822sigill_and_return:
6d5e216d 1823 force_sig(TARGET_SIGILL);
459a4017 1824#endif
6d5e216d 1825sigsegv:
e80cfcfc 1826 //fprintf(stderr, "force_sig\n");
459a4017 1827 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d
FB
1828 force_sig(TARGET_SIGSEGV);
1829}
1830static inline int
74ccb34e 1831restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
6d5e216d
FB
1832{
1833 int err;
1834#if 0
1835#ifdef CONFIG_SMP
1836 if (current->flags & PF_USEDFPU)
1837 regs->psr &= ~PSR_EF;
1838#else
1839 if (current == last_task_used_math) {
1840 last_task_used_math = 0;
1841 regs->psr &= ~PSR_EF;
1842 }
1843#endif
1844 current->used_math = 1;
1845 current->flags &= ~PF_USEDFPU;
1846#endif
1847#if 0
1848 if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
1849 return -EFAULT;
1850#endif
1851
fafffaef
FB
1852#if 0
1853 /* XXX: incorrect */
6d5e216d
FB
1854 err = __copy_from_user(&env->fpr[0], &fpu->si_float_regs[0],
1855 (sizeof(unsigned long) * 32));
fafffaef 1856#endif
6d5e216d
FB
1857 err |= __get_user(env->fsr, &fpu->si_fsr);
1858#if 0
1859 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
1860 if (current->thread.fpqdepth != 0)
1861 err |= __copy_from_user(&current->thread.fpqueue[0],
1862 &fpu->si_fpqueue[0],
1863 ((sizeof(unsigned long) +
1864 (sizeof(unsigned long *)))*16));
1865#endif
1866 return err;
1867}
1868
1869
624f7979 1870static void setup_rt_frame(int sig, struct target_sigaction *ka,
6d5e216d
FB
1871 target_siginfo_t *info,
1872 target_sigset_t *set, CPUState *env)
1873{
1874 fprintf(stderr, "setup_rt_frame: not implemented\n");
1875}
1876
1877long do_sigreturn(CPUState *env)
1878{
f8b0aa25 1879 abi_ulong sf_addr;
6d5e216d 1880 struct target_signal_frame *sf;
e80cfcfc 1881 uint32_t up_psr, pc, npc;
6d5e216d 1882 target_sigset_t set;
e80cfcfc 1883 sigset_t host_set;
f8b0aa25 1884 abi_ulong fpu_save_addr;
e80cfcfc 1885 int err, i;
6d5e216d 1886
f8b0aa25
FB
1887 sf_addr = env->regwptr[UREG_FP];
1888 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
1889 goto segv_and_exit;
80a9d035 1890#if 0
e80cfcfc
FB
1891 fprintf(stderr, "sigreturn\n");
1892 fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
80a9d035 1893#endif
e80cfcfc 1894 //cpu_dump_state(env, stderr, fprintf, 0);
6d5e216d
FB
1895
1896 /* 1. Make sure we are not getting garbage from the user */
6d5e216d 1897
f8b0aa25 1898 if (sf_addr & 3)
6d5e216d
FB
1899 goto segv_and_exit;
1900
1901 err = __get_user(pc, &sf->info.si_regs.pc);
1902 err |= __get_user(npc, &sf->info.si_regs.npc);
1903
6d5e216d
FB
1904 if ((pc | npc) & 3)
1905 goto segv_and_exit;
1906
1907 /* 2. Restore the state */
e80cfcfc
FB
1908 err |= __get_user(up_psr, &sf->info.si_regs.psr);
1909
6d5e216d 1910 /* User can only change condition codes and FPU enabling in %psr. */
a315a145
FB
1911 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
1912 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
1913
1914 env->pc = pc;
1915 env->npc = npc;
e80cfcfc 1916 err |= __get_user(env->y, &sf->info.si_regs.y);
a315a145 1917 for (i=0; i < 8; i++) {
e80cfcfc
FB
1918 err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
1919 }
a315a145 1920 for (i=0; i < 8; i++) {
e80cfcfc
FB
1921 err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
1922 }
6d5e216d 1923
f8b0aa25 1924 err |= __get_user(fpu_save_addr, &sf->fpu_save);
6d5e216d 1925
e80cfcfc
FB
1926 //if (fpu_save)
1927 // err |= restore_fpu_state(env, fpu_save);
6d5e216d
FB
1928
1929 /* This is pretty much atomic, no amount locking would prevent
1930 * the races which exist anyways.
1931 */
1932 err |= __get_user(set.sig[0], &sf->info.si_mask);
e80cfcfc
FB
1933 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1934 err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
1935 }
1936
1937 target_to_host_sigset_internal(&host_set, &set);
1938 sigprocmask(SIG_SETMASK, &host_set, NULL);
6d5e216d
FB
1939
1940 if (err)
1941 goto segv_and_exit;
f8b0aa25 1942 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
1943 return env->regwptr[0];
1944
1945segv_and_exit:
f8b0aa25 1946 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
1947 force_sig(TARGET_SIGSEGV);
1948}
1949
1950long do_rt_sigreturn(CPUState *env)
1951{
1952 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 1953 return -TARGET_ENOSYS;
6d5e216d
FB
1954}
1955
459a4017 1956#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
5bfb56b2
BS
1957#define MC_TSTATE 0
1958#define MC_PC 1
1959#define MC_NPC 2
1960#define MC_Y 3
1961#define MC_G1 4
1962#define MC_G2 5
1963#define MC_G3 6
1964#define MC_G4 7
1965#define MC_G5 8
1966#define MC_G6 9
1967#define MC_G7 10
1968#define MC_O0 11
1969#define MC_O1 12
1970#define MC_O2 13
1971#define MC_O3 14
1972#define MC_O4 15
1973#define MC_O5 16
1974#define MC_O6 17
1975#define MC_O7 18
1976#define MC_NGREG 19
1977
992f48a0 1978typedef abi_ulong target_mc_greg_t;
5bfb56b2
BS
1979typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
1980
1981struct target_mc_fq {
992f48a0 1982 abi_ulong *mcfq_addr;
5bfb56b2
BS
1983 uint32_t mcfq_insn;
1984};
1985
1986struct target_mc_fpu {
1987 union {
1988 uint32_t sregs[32];
1989 uint64_t dregs[32];
1990 //uint128_t qregs[16];
1991 } mcfpu_fregs;
992f48a0
BS
1992 abi_ulong mcfpu_fsr;
1993 abi_ulong mcfpu_fprs;
1994 abi_ulong mcfpu_gsr;
5bfb56b2
BS
1995 struct target_mc_fq *mcfpu_fq;
1996 unsigned char mcfpu_qcnt;
1997 unsigned char mcfpu_qentsz;
1998 unsigned char mcfpu_enab;
1999};
2000typedef struct target_mc_fpu target_mc_fpu_t;
2001
2002typedef struct {
2003 target_mc_gregset_t mc_gregs;
2004 target_mc_greg_t mc_fp;
2005 target_mc_greg_t mc_i7;
2006 target_mc_fpu_t mc_fpregs;
2007} target_mcontext_t;
2008
2009struct target_ucontext {
2010 struct target_ucontext *uc_link;
992f48a0 2011 abi_ulong uc_flags;
5bfb56b2
BS
2012 target_sigset_t uc_sigmask;
2013 target_mcontext_t uc_mcontext;
2014};
2015
2016/* A V9 register window */
2017struct target_reg_window {
992f48a0
BS
2018 abi_ulong locals[8];
2019 abi_ulong ins[8];
5bfb56b2
BS
2020};
2021
2022#define TARGET_STACK_BIAS 2047
2023
2024/* {set, get}context() needed for 64-bit SparcLinux userland. */
2025void sparc64_set_context(CPUSPARCState *env)
2026{
459a4017
FB
2027 abi_ulong ucp_addr;
2028 struct target_ucontext *ucp;
5bfb56b2 2029 target_mc_gregset_t *grp;
992f48a0 2030 abi_ulong pc, npc, tstate;
459a4017 2031 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2032 unsigned char fenab;
2033 int err;
2034 unsigned int i;
5bfb56b2 2035
459a4017
FB
2036 ucp_addr = env->regwptr[UREG_I0];
2037 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2038 goto do_sigsegv;
5bfb56b2 2039 grp = &ucp->uc_mcontext.mc_gregs;
579a97f7
FB
2040 err = __get_user(pc, &((*grp)[MC_PC]));
2041 err |= __get_user(npc, &((*grp)[MC_NPC]));
5bfb56b2
BS
2042 if (err || ((pc | npc) & 3))
2043 goto do_sigsegv;
2044 if (env->regwptr[UREG_I1]) {
2045 target_sigset_t target_set;
2046 sigset_t set;
2047
2048 if (TARGET_NSIG_WORDS == 1) {
579a97f7 2049 if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
5bfb56b2
BS
2050 goto do_sigsegv;
2051 } else {
459a4017
FB
2052 abi_ulong *src, *dst;
2053 src = ucp->uc_sigmask.sig;
2054 dst = target_set.sig;
992f48a0 2055 for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
5bfb56b2 2056 i++, dst++, src++)
459a4017 2057 err |= __get_user(*dst, src);
5bfb56b2
BS
2058 if (err)
2059 goto do_sigsegv;
2060 }
2061 target_to_host_sigset_internal(&set, &target_set);
2062 sigprocmask(SIG_SETMASK, &set, NULL);
2063 }
2064 env->pc = pc;
2065 env->npc = npc;
579a97f7
FB
2066 err |= __get_user(env->y, &((*grp)[MC_Y]));
2067 err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
5bfb56b2
BS
2068 env->asi = (tstate >> 24) & 0xff;
2069 PUT_CCR(env, tstate >> 32);
2070 PUT_CWP64(env, tstate & 0x1f);
579a97f7
FB
2071 err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2072 err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2073 err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2074 err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2075 err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2076 err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2077 err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2078 err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2079 err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2080 err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2081 err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2082 err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2083 err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2084 err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2085 err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2086
2087 err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
2088 err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
579a97f7 2089
459a4017
FB
2090 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2091 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2092 abi_ulong) != 0)
2093 goto do_sigsegv;
2094 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2095 abi_ulong) != 0)
2096 goto do_sigsegv;
579a97f7
FB
2097 err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
2098 err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
459a4017
FB
2099 {
2100 uint32_t *src, *dst;
2101 src = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2102 dst = env->fpr;
2103 /* XXX: check that the CPU storage is the same as user context */
2104 for (i = 0; i < 64; i++, dst++, src++)
2105 err |= __get_user(*dst, src);
2106 }
579a97f7
FB
2107 err |= __get_user(env->fsr,
2108 &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
2109 err |= __get_user(env->gsr,
2110 &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
5bfb56b2
BS
2111 if (err)
2112 goto do_sigsegv;
459a4017 2113 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2
BS
2114 return;
2115 do_sigsegv:
459a4017 2116 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2
BS
2117 force_sig(SIGSEGV);
2118}
2119
2120void sparc64_get_context(CPUSPARCState *env)
2121{
459a4017
FB
2122 abi_ulong ucp_addr;
2123 struct target_ucontext *ucp;
5bfb56b2
BS
2124 target_mc_gregset_t *grp;
2125 target_mcontext_t *mcp;
459a4017 2126 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2127 int err;
2128 unsigned int i;
5bfb56b2
BS
2129 target_sigset_t target_set;
2130 sigset_t set;
2131
459a4017
FB
2132 ucp_addr = env->regwptr[UREG_I0];
2133 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2134 goto do_sigsegv;
2135
5bfb56b2
BS
2136 mcp = &ucp->uc_mcontext;
2137 grp = &mcp->mc_gregs;
2138
2139 /* Skip over the trap instruction, first. */
2140 env->pc = env->npc;
2141 env->npc += 4;
2142
2143 err = 0;
2144
2145 sigprocmask(0, NULL, &set);
2146 host_to_target_sigset_internal(&target_set, &set);
459a4017 2147 if (TARGET_NSIG_WORDS == 1) {
579a97f7
FB
2148 err |= __put_user(target_set.sig[0],
2149 (abi_ulong *)&ucp->uc_sigmask);
459a4017
FB
2150 } else {
2151 abi_ulong *src, *dst;
2152 src = target_set.sig;
2153 dst = ucp->uc_sigmask.sig;
992f48a0 2154 for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
5bfb56b2 2155 i++, dst++, src++)
459a4017 2156 err |= __put_user(*src, dst);
5bfb56b2
BS
2157 if (err)
2158 goto do_sigsegv;
2159 }
2160
459a4017
FB
2161 /* XXX: tstate must be saved properly */
2162 // err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
579a97f7
FB
2163 err |= __put_user(env->pc, &((*grp)[MC_PC]));
2164 err |= __put_user(env->npc, &((*grp)[MC_NPC]));
2165 err |= __put_user(env->y, &((*grp)[MC_Y]));
2166 err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
2167 err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
2168 err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
2169 err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
2170 err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
2171 err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
2172 err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
2173 err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2174 err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2175 err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2176 err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2177 err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2178 err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2179 err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2180 err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
2181
459a4017
FB
2182 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2183 fp = i7 = 0;
2184 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2185 abi_ulong) != 0)
2186 goto do_sigsegv;
2187 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2188 abi_ulong) != 0)
2189 goto do_sigsegv;
579a97f7
FB
2190 err |= __put_user(fp, &(mcp->mc_fp));
2191 err |= __put_user(i7, &(mcp->mc_i7));
5bfb56b2 2192
459a4017
FB
2193 {
2194 uint32_t *src, *dst;
2195 src = env->fpr;
2196 dst = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2197 /* XXX: check that the CPU storage is the same as user context */
2198 for (i = 0; i < 64; i++, dst++, src++)
2199 err |= __put_user(*src, dst);
2200 }
579a97f7
FB
2201 err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2202 err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2203 err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
5bfb56b2
BS
2204
2205 if (err)
2206 goto do_sigsegv;
459a4017 2207 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2
BS
2208 return;
2209 do_sigsegv:
459a4017 2210 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2
BS
2211 force_sig(SIGSEGV);
2212}
2213#endif
d26bc211 2214#elif defined(TARGET_ABI_MIPSN64)
540635ba
TS
2215
2216# warning signal handling not implemented
2217
624f7979 2218static void setup_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2219 target_sigset_t *set, CPUState *env)
2220{
2221 fprintf(stderr, "setup_frame: not implemented\n");
2222}
2223
624f7979 2224static void setup_rt_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2225 target_siginfo_t *info,
2226 target_sigset_t *set, CPUState *env)
2227{
2228 fprintf(stderr, "setup_rt_frame: not implemented\n");
2229}
2230
2231long do_sigreturn(CPUState *env)
2232{
2233 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 2234 return -TARGET_ENOSYS;
540635ba
TS
2235}
2236
2237long do_rt_sigreturn(CPUState *env)
2238{
2239 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2240 return -TARGET_ENOSYS;
540635ba
TS
2241}
2242
d26bc211 2243#elif defined(TARGET_ABI_MIPSN32)
540635ba
TS
2244
2245# warning signal handling not implemented
2246
624f7979 2247static void setup_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2248 target_sigset_t *set, CPUState *env)
2249{
2250 fprintf(stderr, "setup_frame: not implemented\n");
2251}
2252
624f7979 2253static void setup_rt_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2254 target_siginfo_t *info,
2255 target_sigset_t *set, CPUState *env)
2256{
2257 fprintf(stderr, "setup_rt_frame: not implemented\n");
2258}
2259
2260long do_sigreturn(CPUState *env)
2261{
2262 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 2263 return -TARGET_ENOSYS;
540635ba
TS
2264}
2265
2266long do_rt_sigreturn(CPUState *env)
2267{
2268 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2269 return -TARGET_ENOSYS;
540635ba
TS
2270}
2271
d26bc211 2272#elif defined(TARGET_ABI_MIPSO32)
106ec879
FB
2273
2274struct target_sigcontext {
2275 uint32_t sc_regmask; /* Unused */
2276 uint32_t sc_status;
2277 uint64_t sc_pc;
2278 uint64_t sc_regs[32];
2279 uint64_t sc_fpregs[32];
2280 uint32_t sc_ownedfp; /* Unused */
2281 uint32_t sc_fpc_csr;
2282 uint32_t sc_fpc_eir; /* Unused */
2283 uint32_t sc_used_math;
2284 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
2285 uint64_t sc_mdhi;
2286 uint64_t sc_mdlo;
2287 target_ulong sc_hi1; /* Was sc_cause */
2288 target_ulong sc_lo1; /* Was sc_badvaddr */
2289 target_ulong sc_hi2; /* Was sc_sigset[4] */
2290 target_ulong sc_lo2;
2291 target_ulong sc_hi3;
2292 target_ulong sc_lo3;
2293};
2294
2295struct sigframe {
2296 uint32_t sf_ass[4]; /* argument save space for o32 */
2297 uint32_t sf_code[2]; /* signal trampoline */
2298 struct target_sigcontext sf_sc;
2299 target_sigset_t sf_mask;
2300};
2301
2302/* Install trampoline to jump back from signal handler */
2303static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2304{
2305 int err;
2306
2307 /*
2308 * Set up the return code ...
2309 *
2310 * li v0, __NR__foo_sigreturn
2311 * syscall
2312 */
2313
2314 err = __put_user(0x24020000 + syscall, tramp + 0);
2315 err |= __put_user(0x0000000c , tramp + 1);
2316 /* flush_cache_sigtramp((unsigned long) tramp); */
2317 return err;
2318}
2319
2320static inline int
2321setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2322{
2323 int err = 0;
2324
b5dc7732 2325 err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
106ec879 2326
b5dc7732
TS
2327#define save_gp_reg(i) do { \
2328 err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
106ec879
FB
2329 } while(0)
2330 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
2331 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
2332 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
2333 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
2334 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
2335 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
2336 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
2337 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
2338 save_gp_reg(31);
388bb21a 2339#undef save_gp_reg
106ec879 2340
b5dc7732
TS
2341 err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2342 err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879
FB
2343
2344 /* Not used yet, but might be useful if we ever have DSP suppport */
2345#if 0
2346 if (cpu_has_dsp) {
2347 err |= __put_user(mfhi1(), &sc->sc_hi1);
2348 err |= __put_user(mflo1(), &sc->sc_lo1);
2349 err |= __put_user(mfhi2(), &sc->sc_hi2);
2350 err |= __put_user(mflo2(), &sc->sc_lo2);
2351 err |= __put_user(mfhi3(), &sc->sc_hi3);
2352 err |= __put_user(mflo3(), &sc->sc_lo3);
2353 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2354 }
2355 /* same with 64 bit */
388bb21a 2356#ifdef CONFIG_64BIT
106ec879
FB
2357 err |= __put_user(regs->hi, &sc->sc_hi[0]);
2358 err |= __put_user(regs->lo, &sc->sc_lo[0]);
2359 if (cpu_has_dsp) {
2360 err |= __put_user(mfhi1(), &sc->sc_hi[1]);
2361 err |= __put_user(mflo1(), &sc->sc_lo[1]);
2362 err |= __put_user(mfhi2(), &sc->sc_hi[2]);
2363 err |= __put_user(mflo2(), &sc->sc_lo[2]);
2364 err |= __put_user(mfhi3(), &sc->sc_hi[3]);
2365 err |= __put_user(mflo3(), &sc->sc_lo[3]);
2366 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2367 }
388bb21a
TS
2368#endif
2369#endif
106ec879 2370
388bb21a 2371#if 0
106ec879
FB
2372 err |= __put_user(!!used_math(), &sc->sc_used_math);
2373
2374 if (!used_math())
2375 goto out;
2376
2377 /*
2378 * Save FPU state to signal context. Signal handler will "inherit"
2379 * current FPU state.
2380 */
2381 preempt_disable();
2382
2383 if (!is_fpu_owner()) {
2384 own_fpu();
2385 restore_fp(current);
2386 }
2387 err |= save_fp_context(sc);
2388
2389 preempt_enable();
2390 out:
2391#endif
2392 return err;
2393}
2394
2395static inline int
2396restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2397{
2398 int err = 0;
2399
2400 err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
2401
b5dc7732
TS
2402 err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2403 err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2404
ead9360e 2405#define restore_gp_reg(i) do { \
b5dc7732 2406 err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
106ec879
FB
2407 } while(0)
2408 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
2409 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
2410 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
2411 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
2412 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
2413 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
2414 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
2415 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
2416 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
2417 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
2418 restore_gp_reg(31);
388bb21a 2419#undef restore_gp_reg
106ec879
FB
2420
2421#if 0
2422 if (cpu_has_dsp) {
2423 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
2424 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
2425 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
2426 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
2427 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
2428 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
2429 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2430 }
388bb21a 2431#ifdef CONFIG_64BIT
106ec879
FB
2432 err |= __get_user(regs->hi, &sc->sc_hi[0]);
2433 err |= __get_user(regs->lo, &sc->sc_lo[0]);
2434 if (cpu_has_dsp) {
2435 err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
2436 err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
2437 err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
2438 err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
2439 err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
2440 err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
2441 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2442 }
388bb21a 2443#endif
106ec879
FB
2444
2445 err |= __get_user(used_math, &sc->sc_used_math);
2446 conditional_used_math(used_math);
2447
2448 preempt_disable();
2449
2450 if (used_math()) {
2451 /* restore fpu context if we have used it before */
2452 own_fpu();
2453 err |= restore_fp_context(sc);
2454 } else {
2455 /* signal handler may have used FPU. Give it up. */
2456 lose_fpu();
2457 }
2458
2459 preempt_enable();
2460#endif
2461 return err;
2462}
2463/*
2464 * Determine which stack to use..
2465 */
579a97f7 2466static inline abi_ulong
624f7979 2467get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
106ec879
FB
2468{
2469 unsigned long sp;
2470
2471 /* Default to using normal stack */
b5dc7732 2472 sp = regs->active_tc.gpr[29];
106ec879
FB
2473
2474 /*
2475 * FPU emulator may have it's own trampoline active just
2476 * above the user stack, 16-bytes before the next lowest
2477 * 16 byte boundary. Try to avoid trashing it.
2478 */
2479 sp -= 32;
2480
106ec879 2481 /* This is the X/Open sanctioned signal stack switching. */
624f7979 2482 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
a04e134a
TS
2483 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2484 }
106ec879 2485
579a97f7 2486 return (sp - frame_size) & ~7;
106ec879
FB
2487}
2488
579a97f7 2489/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
624f7979 2490static void setup_frame(int sig, struct target_sigaction * ka,
579a97f7 2491 target_sigset_t *set, CPUState *regs)
106ec879
FB
2492{
2493 struct sigframe *frame;
579a97f7 2494 abi_ulong frame_addr;
106ec879
FB
2495 int i;
2496
579a97f7
FB
2497 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2498 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
106ec879
FB
2499 goto give_sigsegv;
2500
2501 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2502
2503 if(setup_sigcontext(regs, &frame->sf_sc))
2504 goto give_sigsegv;
2505
2506 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2507 if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
2508 goto give_sigsegv;
2509 }
2510
2511 /*
2512 * Arguments to signal handler:
2513 *
2514 * a0 = signal number
2515 * a1 = 0 (should be cause)
2516 * a2 = pointer to struct sigcontext
2517 *
2518 * $25 and PC point to the signal handler, $29 points to the
2519 * struct sigframe.
2520 */
b5dc7732
TS
2521 regs->active_tc.gpr[ 4] = sig;
2522 regs->active_tc.gpr[ 5] = 0;
2523 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2524 regs->active_tc.gpr[29] = frame_addr;
2525 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
106ec879
FB
2526 /* The original kernel code sets CP0_EPC to the handler
2527 * since it returns to userland using eret
2528 * we cannot do this here, and we must set PC directly */
b5dc7732 2529 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
579a97f7 2530 unlock_user_struct(frame, frame_addr, 1);
106ec879
FB
2531 return;
2532
2533give_sigsegv:
579a97f7 2534 unlock_user_struct(frame, frame_addr, 1);
106ec879 2535 force_sig(TARGET_SIGSEGV/*, current*/);
5fafdf24 2536 return;
106ec879
FB
2537}
2538
2539long do_sigreturn(CPUState *regs)
2540{
388bb21a 2541 struct sigframe *frame;
579a97f7 2542 abi_ulong frame_addr;
388bb21a
TS
2543 sigset_t blocked;
2544 target_sigset_t target_set;
2545 int i;
106ec879
FB
2546
2547#if defined(DEBUG_SIGNAL)
388bb21a 2548 fprintf(stderr, "do_sigreturn\n");
106ec879 2549#endif
b5dc7732 2550 frame_addr = regs->active_tc.gpr[29];
579a97f7 2551 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
106ec879
FB
2552 goto badframe;
2553
388bb21a 2554 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
106ec879
FB
2555 if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
2556 goto badframe;
388bb21a 2557 }
106ec879 2558
388bb21a
TS
2559 target_to_host_sigset_internal(&blocked, &target_set);
2560 sigprocmask(SIG_SETMASK, &blocked, NULL);
106ec879 2561
388bb21a 2562 if (restore_sigcontext(regs, &frame->sf_sc))
106ec879
FB
2563 goto badframe;
2564
2565#if 0
388bb21a
TS
2566 /*
2567 * Don't let your children do this ...
2568 */
2569 __asm__ __volatile__(
106ec879
FB
2570 "move\t$29, %0\n\t"
2571 "j\tsyscall_exit"
2572 :/* no outputs */
2573 :"r" (&regs));
388bb21a 2574 /* Unreached */
106ec879 2575#endif
3b46e624 2576
b5dc7732 2577 regs->active_tc.PC = regs->CP0_EPC;
388bb21a 2578 /* I am not sure this is right, but it seems to work
106ec879
FB
2579 * maybe a problem with nested signals ? */
2580 regs->CP0_EPC = 0;
2581 return 0;
2582
2583badframe:
388bb21a
TS
2584 force_sig(TARGET_SIGSEGV/*, current*/);
2585 return 0;
106ec879
FB
2586}
2587
624f7979 2588static void setup_rt_frame(int sig, struct target_sigaction *ka,
106ec879
FB
2589 target_siginfo_t *info,
2590 target_sigset_t *set, CPUState *env)
2591{
2592 fprintf(stderr, "setup_rt_frame: not implemented\n");
2593}
2594
2595long do_rt_sigreturn(CPUState *env)
2596{
2597 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2598 return -TARGET_ENOSYS;
106ec879 2599}
6d5e216d 2600
c3b5bc8a
TS
2601#elif defined(TARGET_SH4)
2602
2603/*
2604 * code and data structures from linux kernel:
2605 * include/asm-sh/sigcontext.h
2606 * arch/sh/kernel/signal.c
2607 */
2608
2609struct target_sigcontext {
2610 target_ulong oldmask;
2611
2612 /* CPU registers */
2613 target_ulong sc_gregs[16];
2614 target_ulong sc_pc;
2615 target_ulong sc_pr;
2616 target_ulong sc_sr;
2617 target_ulong sc_gbr;
2618 target_ulong sc_mach;
2619 target_ulong sc_macl;
2620
2621 /* FPU registers */
2622 target_ulong sc_fpregs[16];
2623 target_ulong sc_xfpregs[16];
2624 unsigned int sc_fpscr;
2625 unsigned int sc_fpul;
2626 unsigned int sc_ownedfp;
2627};
2628
2629struct target_sigframe
2630{
2631 struct target_sigcontext sc;
2632 target_ulong extramask[TARGET_NSIG_WORDS-1];
2633 uint16_t retcode[3];
2634};
2635
2636
2637struct target_ucontext {
2638 target_ulong uc_flags;
2639 struct target_ucontext *uc_link;
2640 target_stack_t uc_stack;
2641 struct target_sigcontext uc_mcontext;
2642 target_sigset_t uc_sigmask; /* mask last for extensibility */
2643};
2644
2645struct target_rt_sigframe
2646{
2647 struct target_siginfo info;
2648 struct target_ucontext uc;
2649 uint16_t retcode[3];
2650};
2651
2652
2653#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
2654#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
2655
624f7979 2656static abi_ulong get_sigframe(struct target_sigaction *ka,
c3b5bc8a
TS
2657 unsigned long sp, size_t frame_size)
2658{
624f7979 2659 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
c3b5bc8a
TS
2660 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2661 }
2662
2663 return (sp - frame_size) & -8ul;
2664}
2665
2666static int setup_sigcontext(struct target_sigcontext *sc,
2667 CPUState *regs, unsigned long mask)
2668{
2669 int err = 0;
2670
2671#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
2672 COPY(gregs[0]); COPY(gregs[1]);
2673 COPY(gregs[2]); COPY(gregs[3]);
2674 COPY(gregs[4]); COPY(gregs[5]);
2675 COPY(gregs[6]); COPY(gregs[7]);
2676 COPY(gregs[8]); COPY(gregs[9]);
2677 COPY(gregs[10]); COPY(gregs[11]);
2678 COPY(gregs[12]); COPY(gregs[13]);
2679 COPY(gregs[14]); COPY(gregs[15]);
2680 COPY(gbr); COPY(mach);
2681 COPY(macl); COPY(pr);
2682 COPY(sr); COPY(pc);
2683#undef COPY
2684
2685 /* todo: save FPU registers here */
2686
2687 /* non-iBCS2 extensions.. */
2688 err |= __put_user(mask, &sc->oldmask);
2689
2690 return err;
2691}
2692
2693static int restore_sigcontext(struct CPUState *regs,
2694 struct target_sigcontext *sc)
2695{
2696 unsigned int err = 0;
2697
2698#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
2699 COPY(gregs[1]);
2700 COPY(gregs[2]); COPY(gregs[3]);
2701 COPY(gregs[4]); COPY(gregs[5]);
2702 COPY(gregs[6]); COPY(gregs[7]);
2703 COPY(gregs[8]); COPY(gregs[9]);
2704 COPY(gregs[10]); COPY(gregs[11]);
2705 COPY(gregs[12]); COPY(gregs[13]);
2706 COPY(gregs[14]); COPY(gregs[15]);
2707 COPY(gbr); COPY(mach);
2708 COPY(macl); COPY(pr);
2709 COPY(sr); COPY(pc);
2710#undef COPY
2711
2712 /* todo: restore FPU registers here */
2713
2714 regs->tra = -1; /* disable syscall checks */
2715 return err;
2716}
2717
624f7979 2718static void setup_frame(int sig, struct target_sigaction *ka,
c3b5bc8a
TS
2719 target_sigset_t *set, CPUState *regs)
2720{
2721 struct target_sigframe *frame;
2722 abi_ulong frame_addr;
2723 int i;
2724 int err = 0;
2725 int signal;
2726
2727 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2728 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2729 goto give_sigsegv;
2730
2731 signal = current_exec_domain_sig(sig);
2732
2733 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
2734
2735 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
2736 err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
2737 }
2738
2739 /* Set up to return from userspace. If provided, use a stub
2740 already in userspace. */
624f7979
PB
2741 if (ka->sa_flags & TARGET_SA_RESTORER) {
2742 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
2743 } else {
2744 /* Generate return code (system call to sigreturn) */
2745 err |= __put_user(MOVW(2), &frame->retcode[0]);
2746 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2747 err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
2748 regs->pr = (unsigned long) frame->retcode;
2749 }
2750
2751 if (err)
2752 goto give_sigsegv;
2753
2754 /* Set up registers for signal handler */
2755 regs->gregs[15] = (unsigned long) frame;
2756 regs->gregs[4] = signal; /* Arg for signal handler */
2757 regs->gregs[5] = 0;
2758 regs->gregs[6] = (unsigned long) &frame->sc;
624f7979 2759 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
2760
2761 unlock_user_struct(frame, frame_addr, 1);
2762 return;
2763
2764give_sigsegv:
2765 unlock_user_struct(frame, frame_addr, 1);
2766 force_sig(SIGSEGV);
2767}
2768
624f7979 2769static void setup_rt_frame(int sig, struct target_sigaction *ka,
c3b5bc8a
TS
2770 target_siginfo_t *info,
2771 target_sigset_t *set, CPUState *regs)
2772{
2773 struct target_rt_sigframe *frame;
2774 abi_ulong frame_addr;
2775 int i;
2776 int err = 0;
2777 int signal;
2778
2779 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2780 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2781 goto give_sigsegv;
2782
2783 signal = current_exec_domain_sig(sig);
2784
2785 err |= copy_siginfo_to_user(&frame->info, info);
2786
2787 /* Create the ucontext. */
2788 err |= __put_user(0, &frame->uc.uc_flags);
2789 err |= __put_user(0, (unsigned long *)&frame->uc.uc_link);
526ccb7a 2790 err |= __put_user((unsigned long)target_sigaltstack_used.ss_sp,
c3b5bc8a
TS
2791 &frame->uc.uc_stack.ss_sp);
2792 err |= __put_user(sas_ss_flags(regs->gregs[15]),
2793 &frame->uc.uc_stack.ss_flags);
2794 err |= __put_user(target_sigaltstack_used.ss_size,
2795 &frame->uc.uc_stack.ss_size);
2796 err |= setup_sigcontext(&frame->uc.uc_mcontext,
2797 regs, set->sig[0]);
2798 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2799 err |= __put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]);
2800 }
2801
2802 /* Set up to return from userspace. If provided, use a stub
2803 already in userspace. */
624f7979
PB
2804 if (ka->sa_flags & TARGET_SA_RESTORER) {
2805 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
2806 } else {
2807 /* Generate return code (system call to sigreturn) */
2808 err |= __put_user(MOVW(2), &frame->retcode[0]);
2809 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2810 err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
2811 regs->pr = (unsigned long) frame->retcode;
2812 }
2813
2814 if (err)
2815 goto give_sigsegv;
2816
2817 /* Set up registers for signal handler */
2818 regs->gregs[15] = (unsigned long) frame;
2819 regs->gregs[4] = signal; /* Arg for signal handler */
2820 regs->gregs[5] = (unsigned long) &frame->info;
2821 regs->gregs[6] = (unsigned long) &frame->uc;
624f7979 2822 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
2823
2824 unlock_user_struct(frame, frame_addr, 1);
2825 return;
2826
2827give_sigsegv:
2828 unlock_user_struct(frame, frame_addr, 1);
2829 force_sig(SIGSEGV);
2830}
2831
2832long do_sigreturn(CPUState *regs)
2833{
2834 struct target_sigframe *frame;
2835 abi_ulong frame_addr;
2836 sigset_t blocked;
2837 target_sigset_t target_set;
2838 int i;
2839 int err = 0;
2840
2841#if defined(DEBUG_SIGNAL)
2842 fprintf(stderr, "do_sigreturn\n");
2843#endif
2844 frame_addr = regs->gregs[15];
2845 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2846 goto badframe;
2847
2848 err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
2849 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2850 err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
2851 }
2852
2853 if (err)
2854 goto badframe;
2855
2856 target_to_host_sigset_internal(&blocked, &target_set);
2857 sigprocmask(SIG_SETMASK, &blocked, NULL);
2858
2859 if (restore_sigcontext(regs, &frame->sc))
2860 goto badframe;
2861
2862 unlock_user_struct(frame, frame_addr, 0);
2863 return regs->gregs[0];
2864
2865badframe:
2866 unlock_user_struct(frame, frame_addr, 0);
2867 force_sig(TARGET_SIGSEGV);
2868 return 0;
2869}
2870
2871long do_rt_sigreturn(CPUState *regs)
2872{
2873 struct target_rt_sigframe *frame;
2874 abi_ulong frame_addr;
2875 sigset_t blocked;
2876
2877#if defined(DEBUG_SIGNAL)
2878 fprintf(stderr, "do_rt_sigreturn\n");
2879#endif
2880 frame_addr = regs->gregs[15];
2881 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2882 goto badframe;
2883
2884 target_to_host_sigset(&blocked, &frame->uc.uc_sigmask);
2885 sigprocmask(SIG_SETMASK, &blocked, NULL);
2886
2887 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
2888 goto badframe;
2889
2890 if (do_sigaltstack(frame_addr +
2891 offsetof(struct target_rt_sigframe, uc.uc_stack),
2892 0, get_sp_from_cpustate(regs)) == -EFAULT)
2893 goto badframe;
2894
2895 unlock_user_struct(frame, frame_addr, 0);
2896 return regs->gregs[0];
2897
2898badframe:
2899 unlock_user_struct(frame, frame_addr, 0);
2900 force_sig(TARGET_SIGSEGV);
2901 return 0;
2902}
b6d3abda
EI
2903#elif defined(TARGET_CRIS)
2904
2905struct target_sigcontext {
2906 struct target_pt_regs regs; /* needs to be first */
2907 uint32_t oldmask;
2908 uint32_t usp; /* usp before stacking this gunk on it */
2909};
2910
2911/* Signal frames. */
2912struct target_signal_frame {
2913 struct target_sigcontext sc;
2914 uint32_t extramask[TARGET_NSIG_WORDS - 1];
2915 uint8_t retcode[8]; /* Trampoline code. */
2916};
2917
2918struct rt_signal_frame {
2919 struct siginfo *pinfo;
2920 void *puc;
2921 struct siginfo info;
2922 struct ucontext uc;
2923 uint8_t retcode[8]; /* Trampoline code. */
2924};
2925
2926static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
2927{
9664d928
EI
2928 __put_user(env->regs[0], &sc->regs.r0);
2929 __put_user(env->regs[1], &sc->regs.r1);
2930 __put_user(env->regs[2], &sc->regs.r2);
2931 __put_user(env->regs[3], &sc->regs.r3);
2932 __put_user(env->regs[4], &sc->regs.r4);
2933 __put_user(env->regs[5], &sc->regs.r5);
2934 __put_user(env->regs[6], &sc->regs.r6);
2935 __put_user(env->regs[7], &sc->regs.r7);
2936 __put_user(env->regs[8], &sc->regs.r8);
2937 __put_user(env->regs[9], &sc->regs.r9);
2938 __put_user(env->regs[10], &sc->regs.r10);
2939 __put_user(env->regs[11], &sc->regs.r11);
2940 __put_user(env->regs[12], &sc->regs.r12);
2941 __put_user(env->regs[13], &sc->regs.r13);
2942 __put_user(env->regs[14], &sc->usp);
2943 __put_user(env->regs[15], &sc->regs.acr);
2944 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
2945 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
2946 __put_user(env->pc, &sc->regs.erp);
b6d3abda 2947}
9664d928 2948
b6d3abda
EI
2949static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
2950{
9664d928
EI
2951 __get_user(env->regs[0], &sc->regs.r0);
2952 __get_user(env->regs[1], &sc->regs.r1);
2953 __get_user(env->regs[2], &sc->regs.r2);
2954 __get_user(env->regs[3], &sc->regs.r3);
2955 __get_user(env->regs[4], &sc->regs.r4);
2956 __get_user(env->regs[5], &sc->regs.r5);
2957 __get_user(env->regs[6], &sc->regs.r6);
2958 __get_user(env->regs[7], &sc->regs.r7);
2959 __get_user(env->regs[8], &sc->regs.r8);
2960 __get_user(env->regs[9], &sc->regs.r9);
2961 __get_user(env->regs[10], &sc->regs.r10);
2962 __get_user(env->regs[11], &sc->regs.r11);
2963 __get_user(env->regs[12], &sc->regs.r12);
2964 __get_user(env->regs[13], &sc->regs.r13);
2965 __get_user(env->regs[14], &sc->usp);
2966 __get_user(env->regs[15], &sc->regs.acr);
2967 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
2968 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
2969 __get_user(env->pc, &sc->regs.erp);
2970}
2971
2972static abi_ulong get_sigframe(CPUState *env, int framesize)
2973{
2974 abi_ulong sp;
b6d3abda 2975 /* Align the stack downwards to 4. */
9664d928
EI
2976 sp = (env->regs[R_SP] & ~3);
2977 return sp - framesize;
b6d3abda
EI
2978}
2979
624f7979 2980static void setup_frame(int sig, struct target_sigaction *ka,
b6d3abda
EI
2981 target_sigset_t *set, CPUState *env)
2982{
2983 struct target_signal_frame *frame;
9664d928 2984 abi_ulong frame_addr;
b6d3abda
EI
2985 int err = 0;
2986 int i;
b6d3abda 2987
9664d928
EI
2988 frame_addr = get_sigframe(env, sizeof *frame);
2989 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
b6d3abda
EI
2990 goto badframe;
2991
2992 /*
2993 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
2994 * use this trampoline anymore but it sets it up for GDB.
2995 * In QEMU, using the trampoline simplifies things a bit so we use it.
2996 *
2997 * This is movu.w __NR_sigreturn, r9; break 13;
2998 */
2999 err |= __put_user(0x9c5f, frame->retcode+0);
3000 err |= __put_user(TARGET_NR_sigreturn,
3001 frame->retcode+2);
3002 err |= __put_user(0xe93d, frame->retcode+4);
3003
3004 /* Save the mask. */
3005 err |= __put_user(set->sig[0], &frame->sc.oldmask);
3006 if (err)
3007 goto badframe;
3008
3009 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3010 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3011 goto badframe;
3012 }
3013
3014 setup_sigcontext(&frame->sc, env);
3015
3016 /* Move the stack and setup the arguments for the handler. */
526ccb7a 3017 env->regs[R_SP] = (uint32_t) (unsigned long) frame;
b6d3abda 3018 env->regs[10] = sig;
624f7979 3019 env->pc = (unsigned long) ka->_sa_handler;
b6d3abda 3020 /* Link SRP so the guest returns through the trampoline. */
526ccb7a 3021 env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0];
b6d3abda 3022
9664d928 3023 unlock_user_struct(frame, frame_addr, 1);
b6d3abda
EI
3024 return;
3025 badframe:
9664d928 3026 unlock_user_struct(frame, frame_addr, 1);
b6d3abda
EI
3027 force_sig(TARGET_SIGSEGV);
3028}
3029
624f7979 3030static void setup_rt_frame(int sig, struct target_sigaction *ka,
b6d3abda
EI
3031 target_siginfo_t *info,
3032 target_sigset_t *set, CPUState *env)
3033{
3034 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3035}
3036
3037long do_sigreturn(CPUState *env)
3038{
3039 struct target_signal_frame *frame;
9664d928 3040 abi_ulong frame_addr;
b6d3abda
EI
3041 target_sigset_t target_set;
3042 sigset_t set;
3043 int i;
3044
9664d928 3045 frame_addr = env->regs[R_SP];
b6d3abda 3046 /* Make sure the guest isn't playing games. */
9664d928 3047 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
b6d3abda
EI
3048 goto badframe;
3049
3050 /* Restore blocked signals */
3051 if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3052 goto badframe;
3053 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3054 if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3055 goto badframe;
3056 }
3057 target_to_host_sigset_internal(&set, &target_set);
3058 sigprocmask(SIG_SETMASK, &set, NULL);
3059
3060 restore_sigcontext(&frame->sc, env);
9664d928 3061 unlock_user_struct(frame, frame_addr, 0);
b6d3abda
EI
3062 return env->regs[10];
3063 badframe:
9664d928 3064 unlock_user_struct(frame, frame_addr, 0);
b6d3abda
EI
3065 force_sig(TARGET_SIGSEGV);
3066}
3067
3068long do_rt_sigreturn(CPUState *env)
3069{
3070 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3071 return -TARGET_ENOSYS;
3072}
c3b5bc8a 3073
b346ff46
FB
3074#else
3075
624f7979 3076static void setup_frame(int sig, struct target_sigaction *ka,
b346ff46
FB
3077 target_sigset_t *set, CPUState *env)
3078{
3079 fprintf(stderr, "setup_frame: not implemented\n");
3080}
3081
624f7979 3082static void setup_rt_frame(int sig, struct target_sigaction *ka,
b346ff46
FB
3083 target_siginfo_t *info,
3084 target_sigset_t *set, CPUState *env)
3085{
3086 fprintf(stderr, "setup_rt_frame: not implemented\n");
3087}
3088
3089long do_sigreturn(CPUState *env)
3090{
3091 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 3092 return -TARGET_ENOSYS;
b346ff46
FB
3093}
3094
3095long do_rt_sigreturn(CPUState *env)
3096{
3097 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 3098 return -TARGET_ENOSYS;
b346ff46
FB
3099}
3100
66fb9763
FB
3101#endif
3102
624f7979 3103void process_pending_signals(CPUState *cpu_env)
66fb9763
FB
3104{
3105 int sig;
992f48a0 3106 abi_ulong handler;
9de5e440
FB
3107 sigset_t set, old_set;
3108 target_sigset_t target_old_set;
624f7979
PB
3109 struct emulated_sigtable *k;
3110 struct target_sigaction *sa;
66fb9763 3111 struct sigqueue *q;
624f7979 3112 TaskState *ts = cpu_env->opaque;
3b46e624 3113
624f7979 3114 if (!ts->signal_pending)
31e31b8a
FB
3115 return;
3116
624f7979
PB
3117 /* FIXME: This is not threadsafe. */
3118 k = ts->sigtab;
66fb9763
FB
3119 for(sig = 1; sig <= TARGET_NSIG; sig++) {
3120 if (k->pending)
31e31b8a 3121 goto handle_signal;
66fb9763 3122 k++;
31e31b8a
FB
3123 }
3124 /* if no signal is pending, just return */
624f7979 3125 ts->signal_pending = 0;
31e31b8a 3126 return;
66fb9763 3127
31e31b8a 3128 handle_signal:
66fb9763 3129#ifdef DEBUG_SIGNAL
bc8a22cc 3130 fprintf(stderr, "qemu: process signal %d\n", sig);
66fb9763
FB
3131#endif
3132 /* dequeue signal */
3133 q = k->first;
3134 k->first = q->next;
3135 if (!k->first)
3136 k->pending = 0;
3b46e624 3137
1fddef4b
FB
3138 sig = gdb_handlesig (cpu_env, sig);
3139 if (!sig) {
ca587a8e
AJ
3140 sa = NULL;
3141 handler = TARGET_SIG_IGN;
3142 } else {
3143 sa = &sigact_table[sig - 1];
3144 handler = sa->_sa_handler;
1fddef4b 3145 }
66fb9763 3146
66fb9763 3147 if (handler == TARGET_SIG_DFL) {
ca587a8e
AJ
3148 /* default handler : ignore some signal. The other are job control or fatal */
3149 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
3150 kill(getpid(),SIGSTOP);
3151 } else if (sig != TARGET_SIGCHLD &&
3152 sig != TARGET_SIGURG &&
3153 sig != TARGET_SIGWINCH &&
3154 sig != TARGET_SIGCONT) {
66fb9763
FB
3155 force_sig(sig);
3156 }
3157 } else if (handler == TARGET_SIG_IGN) {
3158 /* ignore sig */
3159 } else if (handler == TARGET_SIG_ERR) {
3160 force_sig(sig);
3161 } else {
9de5e440 3162 /* compute the blocked signals during the handler execution */
624f7979 3163 target_to_host_sigset(&set, &sa->sa_mask);
9de5e440
FB
3164 /* SA_NODEFER indicates that the current signal should not be
3165 blocked during the handler */
624f7979 3166 if (!(sa->sa_flags & TARGET_SA_NODEFER))
9de5e440 3167 sigaddset(&set, target_to_host_signal(sig));
3b46e624 3168
9de5e440
FB
3169 /* block signals in the handler using Linux */
3170 sigprocmask(SIG_BLOCK, &set, &old_set);
3171 /* save the previous blocked signal state to restore it at the
3172 end of the signal execution (see do_sigreturn) */
9231944d 3173 host_to_target_sigset_internal(&target_old_set, &old_set);
9de5e440 3174
bc8a22cc 3175 /* if the CPU is in VM86 mode, we restore the 32 bit values */
84409ddb 3176#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bc8a22cc
FB
3177 {
3178 CPUX86State *env = cpu_env;
3179 if (env->eflags & VM_MASK)
3180 save_v86_state(env);
3181 }
3182#endif
9de5e440 3183 /* prepare the stack frame of the virtual CPU */
624f7979
PB
3184 if (sa->sa_flags & TARGET_SA_SIGINFO)
3185 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
66fb9763 3186 else
624f7979
PB
3187 setup_frame(sig, sa, &target_old_set, cpu_env);
3188 if (sa->sa_flags & TARGET_SA_RESETHAND)
3189 sa->_sa_handler = TARGET_SIG_DFL;
31e31b8a 3190 }
66fb9763 3191 if (q != &k->info)
624f7979 3192 free_sigqueue(cpu_env, q);
66fb9763 3193}