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