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