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