Statistics
| Branch: | Revision:

root / linux-user / signal.c @ 5ba18547

History | View | Annotate | Download (145.1 kB)

1 31e31b8a bellard
/*
2 66fb9763 bellard
 *  Emulation of Linux signals
3 5fafdf24 ths
 *
4 31e31b8a bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 31e31b8a bellard
 *
6 31e31b8a bellard
 *  This program is free software; you can redistribute it and/or modify
7 31e31b8a bellard
 *  it under the terms of the GNU General Public License as published by
8 31e31b8a bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 31e31b8a bellard
 *  (at your option) any later version.
10 31e31b8a bellard
 *
11 31e31b8a bellard
 *  This program is distributed in the hope that it will be useful,
12 31e31b8a bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 31e31b8a bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 31e31b8a bellard
 *  GNU General Public License for more details.
15 31e31b8a bellard
 *
16 31e31b8a bellard
 *  You should have received a copy of the GNU General Public License
17 8167ee88 Blue Swirl
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18 31e31b8a bellard
 */
19 31e31b8a bellard
#include <stdlib.h>
20 31e31b8a bellard
#include <stdio.h>
21 66fb9763 bellard
#include <string.h>
22 31e31b8a bellard
#include <stdarg.h>
23 2677e107 bellard
#include <unistd.h>
24 31e31b8a bellard
#include <signal.h>
25 66fb9763 bellard
#include <errno.h>
26 603e4fd7 aurel32
#include <assert.h>
27 31e31b8a bellard
#include <sys/ucontext.h>
28 edf8e2af Mika Westerberg
#include <sys/resource.h>
29 31e31b8a bellard
30 3ef693a0 bellard
#include "qemu.h"
31 7d99a001 blueswir1
#include "qemu-common.h"
32 992f48a0 blueswir1
#include "target_signal.h"
33 66fb9763 bellard
34 66fb9763 bellard
//#define DEBUG_SIGNAL
35 66fb9763 bellard
36 249c4c32 blueswir1
static struct target_sigaltstack target_sigaltstack_used = {
37 a04e134a ths
    .ss_sp = 0,
38 a04e134a ths
    .ss_size = 0,
39 a04e134a ths
    .ss_flags = TARGET_SS_DISABLE,
40 a04e134a ths
};
41 a04e134a ths
42 624f7979 pbrook
static struct target_sigaction sigact_table[TARGET_NSIG];
43 31e31b8a bellard
44 5fafdf24 ths
static void host_signal_handler(int host_signum, siginfo_t *info,
45 66fb9763 bellard
                                void *puc);
46 66fb9763 bellard
47 3ca05588 Arnaud Patard
static uint8_t host_to_target_signal_table[_NSIG] = {
48 9e5f5284 bellard
    [SIGHUP] = TARGET_SIGHUP,
49 9e5f5284 bellard
    [SIGINT] = TARGET_SIGINT,
50 9e5f5284 bellard
    [SIGQUIT] = TARGET_SIGQUIT,
51 9e5f5284 bellard
    [SIGILL] = TARGET_SIGILL,
52 9e5f5284 bellard
    [SIGTRAP] = TARGET_SIGTRAP,
53 9e5f5284 bellard
    [SIGABRT] = TARGET_SIGABRT,
54 01e3b763 bellard
/*    [SIGIOT] = TARGET_SIGIOT,*/
55 9e5f5284 bellard
    [SIGBUS] = TARGET_SIGBUS,
56 9e5f5284 bellard
    [SIGFPE] = TARGET_SIGFPE,
57 9e5f5284 bellard
    [SIGKILL] = TARGET_SIGKILL,
58 9e5f5284 bellard
    [SIGUSR1] = TARGET_SIGUSR1,
59 9e5f5284 bellard
    [SIGSEGV] = TARGET_SIGSEGV,
60 9e5f5284 bellard
    [SIGUSR2] = TARGET_SIGUSR2,
61 9e5f5284 bellard
    [SIGPIPE] = TARGET_SIGPIPE,
62 9e5f5284 bellard
    [SIGALRM] = TARGET_SIGALRM,
63 9e5f5284 bellard
    [SIGTERM] = TARGET_SIGTERM,
64 9e5f5284 bellard
#ifdef SIGSTKFLT
65 9e5f5284 bellard
    [SIGSTKFLT] = TARGET_SIGSTKFLT,
66 9e5f5284 bellard
#endif
67 9e5f5284 bellard
    [SIGCHLD] = TARGET_SIGCHLD,
68 9e5f5284 bellard
    [SIGCONT] = TARGET_SIGCONT,
69 9e5f5284 bellard
    [SIGSTOP] = TARGET_SIGSTOP,
70 9e5f5284 bellard
    [SIGTSTP] = TARGET_SIGTSTP,
71 9e5f5284 bellard
    [SIGTTIN] = TARGET_SIGTTIN,
72 9e5f5284 bellard
    [SIGTTOU] = TARGET_SIGTTOU,
73 9e5f5284 bellard
    [SIGURG] = TARGET_SIGURG,
74 9e5f5284 bellard
    [SIGXCPU] = TARGET_SIGXCPU,
75 9e5f5284 bellard
    [SIGXFSZ] = TARGET_SIGXFSZ,
76 9e5f5284 bellard
    [SIGVTALRM] = TARGET_SIGVTALRM,
77 9e5f5284 bellard
    [SIGPROF] = TARGET_SIGPROF,
78 9e5f5284 bellard
    [SIGWINCH] = TARGET_SIGWINCH,
79 9e5f5284 bellard
    [SIGIO] = TARGET_SIGIO,
80 9e5f5284 bellard
    [SIGPWR] = TARGET_SIGPWR,
81 9e5f5284 bellard
    [SIGSYS] = TARGET_SIGSYS,
82 9e5f5284 bellard
    /* next signals stay the same */
83 624f7979 pbrook
    /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
84 624f7979 pbrook
       host libpthread signals.  This assumes noone actually uses SIGRTMAX :-/
85 624f7979 pbrook
       To fix this properly we need to do manual signal delivery multiplexed
86 624f7979 pbrook
       over a single host signal.  */
87 624f7979 pbrook
    [__SIGRTMIN] = __SIGRTMAX,
88 624f7979 pbrook
    [__SIGRTMAX] = __SIGRTMIN,
89 9e5f5284 bellard
};
90 3ca05588 Arnaud Patard
static uint8_t target_to_host_signal_table[_NSIG];
91 9e5f5284 bellard
92 a04e134a ths
static inline int on_sig_stack(unsigned long sp)
93 a04e134a ths
{
94 a04e134a ths
    return (sp - target_sigaltstack_used.ss_sp
95 a04e134a ths
            < target_sigaltstack_used.ss_size);
96 a04e134a ths
}
97 a04e134a ths
98 a04e134a ths
static inline int sas_ss_flags(unsigned long sp)
99 a04e134a ths
{
100 a04e134a ths
    return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
101 a04e134a ths
            : on_sig_stack(sp) ? SS_ONSTACK : 0);
102 a04e134a ths
}
103 a04e134a ths
104 1d9d8b55 pbrook
int host_to_target_signal(int sig)
105 31e31b8a bellard
{
106 3ca05588 Arnaud Patard
    if (sig >= _NSIG)
107 4cb05961 pbrook
        return sig;
108 9e5f5284 bellard
    return host_to_target_signal_table[sig];
109 31e31b8a bellard
}
110 31e31b8a bellard
111 4cb05961 pbrook
int target_to_host_signal(int sig)
112 31e31b8a bellard
{
113 3ca05588 Arnaud Patard
    if (sig >= _NSIG)
114 4cb05961 pbrook
        return sig;
115 9e5f5284 bellard
    return target_to_host_signal_table[sig];
116 31e31b8a bellard
}
117 31e31b8a bellard
118 c227f099 Anthony Liguori
static inline void target_sigemptyset(target_sigset_t *set)
119 f5545b5c pbrook
{
120 f5545b5c pbrook
    memset(set, 0, sizeof(*set));
121 f5545b5c pbrook
}
122 f5545b5c pbrook
123 c227f099 Anthony Liguori
static inline void target_sigaddset(target_sigset_t *set, int signum)
124 f5545b5c pbrook
{
125 f5545b5c pbrook
    signum--;
126 f5545b5c pbrook
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 f5545b5c pbrook
    set->sig[signum / TARGET_NSIG_BPW] |= mask;
128 f5545b5c pbrook
}
129 f5545b5c pbrook
130 c227f099 Anthony Liguori
static inline int target_sigismember(const target_sigset_t *set, int signum)
131 f5545b5c pbrook
{
132 f5545b5c pbrook
    signum--;
133 f5545b5c pbrook
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
134 f5545b5c pbrook
    return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
135 f5545b5c pbrook
}
136 f5545b5c pbrook
137 c227f099 Anthony Liguori
static void host_to_target_sigset_internal(target_sigset_t *d,
138 9231944d bellard
                                           const sigset_t *s)
139 66fb9763 bellard
{
140 66fb9763 bellard
    int i;
141 f5545b5c pbrook
    target_sigemptyset(d);
142 f5545b5c pbrook
    for (i = 1; i <= TARGET_NSIG; i++) {
143 f5545b5c pbrook
        if (sigismember(s, i)) {
144 f5545b5c pbrook
            target_sigaddset(d, host_to_target_signal(i));
145 f5545b5c pbrook
        }
146 66fb9763 bellard
    }
147 66fb9763 bellard
}
148 66fb9763 bellard
149 c227f099 Anthony Liguori
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
150 9231944d bellard
{
151 c227f099 Anthony Liguori
    target_sigset_t d1;
152 9231944d bellard
    int i;
153 9231944d bellard
154 9231944d bellard
    host_to_target_sigset_internal(&d1, s);
155 9231944d bellard
    for(i = 0;i < TARGET_NSIG_WORDS; i++)
156 53a5960a pbrook
        d->sig[i] = tswapl(d1.sig[i]);
157 9231944d bellard
}
158 9231944d bellard
159 8fcd3692 blueswir1
static void target_to_host_sigset_internal(sigset_t *d,
160 c227f099 Anthony Liguori
                                           const target_sigset_t *s)
161 66fb9763 bellard
{
162 66fb9763 bellard
    int i;
163 f5545b5c pbrook
    sigemptyset(d);
164 f5545b5c pbrook
    for (i = 1; i <= TARGET_NSIG; i++) {
165 f5545b5c pbrook
        if (target_sigismember(s, i)) {
166 f5545b5c pbrook
            sigaddset(d, target_to_host_signal(i));
167 f5545b5c pbrook
        }
168 f5545b5c pbrook
     }
169 66fb9763 bellard
}
170 66fb9763 bellard
171 c227f099 Anthony Liguori
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
172 9231944d bellard
{
173 c227f099 Anthony Liguori
    target_sigset_t s1;
174 9231944d bellard
    int i;
175 9231944d bellard
176 9231944d bellard
    for(i = 0;i < TARGET_NSIG_WORDS; i++)
177 53a5960a pbrook
        s1.sig[i] = tswapl(s->sig[i]);
178 9231944d bellard
    target_to_host_sigset_internal(d, &s1);
179 9231944d bellard
}
180 3b46e624 ths
181 992f48a0 blueswir1
void host_to_target_old_sigset(abi_ulong *old_sigset,
182 66fb9763 bellard
                               const sigset_t *sigset)
183 66fb9763 bellard
{
184 c227f099 Anthony Liguori
    target_sigset_t d;
185 9e5f5284 bellard
    host_to_target_sigset(&d, sigset);
186 9e5f5284 bellard
    *old_sigset = d.sig[0];
187 66fb9763 bellard
}
188 66fb9763 bellard
189 5fafdf24 ths
void target_to_host_old_sigset(sigset_t *sigset,
190 992f48a0 blueswir1
                               const abi_ulong *old_sigset)
191 66fb9763 bellard
{
192 c227f099 Anthony Liguori
    target_sigset_t d;
193 9e5f5284 bellard
    int i;
194 9e5f5284 bellard
195 9e5f5284 bellard
    d.sig[0] = *old_sigset;
196 9e5f5284 bellard
    for(i = 1;i < TARGET_NSIG_WORDS; i++)
197 9e5f5284 bellard
        d.sig[i] = 0;
198 9e5f5284 bellard
    target_to_host_sigset(sigset, &d);
199 66fb9763 bellard
}
200 66fb9763 bellard
201 9de5e440 bellard
/* siginfo conversion */
202 9de5e440 bellard
203 c227f099 Anthony Liguori
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
204 9de5e440 bellard
                                                 const siginfo_t *info)
205 66fb9763 bellard
{
206 9de5e440 bellard
    int sig;
207 9de5e440 bellard
    sig = host_to_target_signal(info->si_signo);
208 9de5e440 bellard
    tinfo->si_signo = sig;
209 9de5e440 bellard
    tinfo->si_errno = 0;
210 afd7cd92 pbrook
    tinfo->si_code = info->si_code;
211 5fafdf24 ths
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
212 447db213 bellard
        sig == SIGBUS || sig == SIGTRAP) {
213 9de5e440 bellard
        /* should never come here, but who knows. The information for
214 9de5e440 bellard
           the target is irrelevant */
215 9de5e440 bellard
        tinfo->_sifields._sigfault._addr = 0;
216 7f7f7c84 ths
    } else if (sig == SIGIO) {
217 7f7f7c84 ths
        tinfo->_sifields._sigpoll._fd = info->si_fd;
218 9de5e440 bellard
    } else if (sig >= TARGET_SIGRTMIN) {
219 9de5e440 bellard
        tinfo->_sifields._rt._pid = info->si_pid;
220 9de5e440 bellard
        tinfo->_sifields._rt._uid = info->si_uid;
221 9de5e440 bellard
        /* XXX: potential problem if 64 bit */
222 5fafdf24 ths
        tinfo->_sifields._rt._sigval.sival_ptr =
223 459a4017 bellard
            (abi_ulong)(unsigned long)info->si_value.sival_ptr;
224 9de5e440 bellard
    }
225 9de5e440 bellard
}
226 9de5e440 bellard
227 c227f099 Anthony Liguori
static void tswap_siginfo(target_siginfo_t *tinfo,
228 c227f099 Anthony Liguori
                          const target_siginfo_t *info)
229 9de5e440 bellard
{
230 9de5e440 bellard
    int sig;
231 9de5e440 bellard
    sig = info->si_signo;
232 9de5e440 bellard
    tinfo->si_signo = tswap32(sig);
233 66fb9763 bellard
    tinfo->si_errno = tswap32(info->si_errno);
234 66fb9763 bellard
    tinfo->si_code = tswap32(info->si_code);
235 5fafdf24 ths
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
236 447db213 bellard
        sig == SIGBUS || sig == SIGTRAP) {
237 5fafdf24 ths
        tinfo->_sifields._sigfault._addr =
238 9de5e440 bellard
            tswapl(info->_sifields._sigfault._addr);
239 7f7f7c84 ths
    } else if (sig == SIGIO) {
240 7f7f7c84 ths
        tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
241 9de5e440 bellard
    } else if (sig >= TARGET_SIGRTMIN) {
242 9de5e440 bellard
        tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
243 9de5e440 bellard
        tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
244 5fafdf24 ths
        tinfo->_sifields._rt._sigval.sival_ptr =
245 9de5e440 bellard
            tswapl(info->_sifields._rt._sigval.sival_ptr);
246 9de5e440 bellard
    }
247 9de5e440 bellard
}
248 9de5e440 bellard
249 9de5e440 bellard
250 c227f099 Anthony Liguori
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
251 9de5e440 bellard
{
252 9de5e440 bellard
    host_to_target_siginfo_noswap(tinfo, info);
253 9de5e440 bellard
    tswap_siginfo(tinfo, tinfo);
254 66fb9763 bellard
}
255 66fb9763 bellard
256 9de5e440 bellard
/* XXX: we support only POSIX RT signals are used. */
257 aa1f17c1 ths
/* XXX: find a solution for 64 bit (additional malloced data is needed) */
258 c227f099 Anthony Liguori
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
259 66fb9763 bellard
{
260 66fb9763 bellard
    info->si_signo = tswap32(tinfo->si_signo);
261 66fb9763 bellard
    info->si_errno = tswap32(tinfo->si_errno);
262 66fb9763 bellard
    info->si_code = tswap32(tinfo->si_code);
263 9de5e440 bellard
    info->si_pid = tswap32(tinfo->_sifields._rt._pid);
264 9de5e440 bellard
    info->si_uid = tswap32(tinfo->_sifields._rt._uid);
265 5fafdf24 ths
    info->si_value.sival_ptr =
266 459a4017 bellard
            (void *)(long)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
267 66fb9763 bellard
}
268 66fb9763 bellard
269 ca587a8e aurel32
static int fatal_signal (int sig)
270 ca587a8e aurel32
{
271 ca587a8e aurel32
    switch (sig) {
272 ca587a8e aurel32
    case TARGET_SIGCHLD:
273 ca587a8e aurel32
    case TARGET_SIGURG:
274 ca587a8e aurel32
    case TARGET_SIGWINCH:
275 ca587a8e aurel32
        /* Ignored by default.  */
276 ca587a8e aurel32
        return 0;
277 ca587a8e aurel32
    case TARGET_SIGCONT:
278 ca587a8e aurel32
    case TARGET_SIGSTOP:
279 ca587a8e aurel32
    case TARGET_SIGTSTP:
280 ca587a8e aurel32
    case TARGET_SIGTTIN:
281 ca587a8e aurel32
    case TARGET_SIGTTOU:
282 ca587a8e aurel32
        /* Job control signals.  */
283 ca587a8e aurel32
        return 0;
284 ca587a8e aurel32
    default:
285 ca587a8e aurel32
        return 1;
286 ca587a8e aurel32
    }
287 ca587a8e aurel32
}
288 ca587a8e aurel32
289 edf8e2af Mika Westerberg
/* returns 1 if given signal should dump core if not handled */
290 edf8e2af Mika Westerberg
static int core_dump_signal(int sig)
291 edf8e2af Mika Westerberg
{
292 edf8e2af Mika Westerberg
    switch (sig) {
293 edf8e2af Mika Westerberg
    case TARGET_SIGABRT:
294 edf8e2af Mika Westerberg
    case TARGET_SIGFPE:
295 edf8e2af Mika Westerberg
    case TARGET_SIGILL:
296 edf8e2af Mika Westerberg
    case TARGET_SIGQUIT:
297 edf8e2af Mika Westerberg
    case TARGET_SIGSEGV:
298 edf8e2af Mika Westerberg
    case TARGET_SIGTRAP:
299 edf8e2af Mika Westerberg
    case TARGET_SIGBUS:
300 edf8e2af Mika Westerberg
        return (1);
301 edf8e2af Mika Westerberg
    default:
302 edf8e2af Mika Westerberg
        return (0);
303 edf8e2af Mika Westerberg
    }
304 edf8e2af Mika Westerberg
}
305 edf8e2af Mika Westerberg
306 31e31b8a bellard
void signal_init(void)
307 31e31b8a bellard
{
308 31e31b8a bellard
    struct sigaction act;
309 624f7979 pbrook
    struct sigaction oact;
310 9e5f5284 bellard
    int i, j;
311 624f7979 pbrook
    int host_sig;
312 31e31b8a bellard
313 9e5f5284 bellard
    /* generate signal conversion tables */
314 3ca05588 Arnaud Patard
    for(i = 1; i < _NSIG; i++) {
315 9e5f5284 bellard
        if (host_to_target_signal_table[i] == 0)
316 9e5f5284 bellard
            host_to_target_signal_table[i] = i;
317 9e5f5284 bellard
    }
318 3ca05588 Arnaud Patard
    for(i = 1; i < _NSIG; i++) {
319 9e5f5284 bellard
        j = host_to_target_signal_table[i];
320 9e5f5284 bellard
        target_to_host_signal_table[j] = i;
321 9e5f5284 bellard
    }
322 3b46e624 ths
323 9de5e440 bellard
    /* set all host signal handlers. ALL signals are blocked during
324 9de5e440 bellard
       the handlers to serialize them. */
325 624f7979 pbrook
    memset(sigact_table, 0, sizeof(sigact_table));
326 624f7979 pbrook
327 9de5e440 bellard
    sigfillset(&act.sa_mask);
328 31e31b8a bellard
    act.sa_flags = SA_SIGINFO;
329 31e31b8a bellard
    act.sa_sigaction = host_signal_handler;
330 624f7979 pbrook
    for(i = 1; i <= TARGET_NSIG; i++) {
331 624f7979 pbrook
        host_sig = target_to_host_signal(i);
332 624f7979 pbrook
        sigaction(host_sig, NULL, &oact);
333 624f7979 pbrook
        if (oact.sa_sigaction == (void *)SIG_IGN) {
334 624f7979 pbrook
            sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
335 624f7979 pbrook
        } else if (oact.sa_sigaction == (void *)SIG_DFL) {
336 624f7979 pbrook
            sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
337 624f7979 pbrook
        }
338 624f7979 pbrook
        /* If there's already a handler installed then something has
339 624f7979 pbrook
           gone horribly wrong, so don't even try to handle that case.  */
340 ca587a8e aurel32
        /* Install some handlers for our own use.  We need at least
341 ca587a8e aurel32
           SIGSEGV and SIGBUS, to detect exceptions.  We can not just
342 ca587a8e aurel32
           trap all signals because it affects syscall interrupt
343 ca587a8e aurel32
           behavior.  But do trap all default-fatal signals.  */
344 ca587a8e aurel32
        if (fatal_signal (i))
345 624f7979 pbrook
            sigaction(host_sig, &act, NULL);
346 31e31b8a bellard
    }
347 66fb9763 bellard
}
348 66fb9763 bellard
349 66fb9763 bellard
/* signal queue handling */
350 66fb9763 bellard
351 624f7979 pbrook
static inline struct sigqueue *alloc_sigqueue(CPUState *env)
352 66fb9763 bellard
{
353 624f7979 pbrook
    TaskState *ts = env->opaque;
354 624f7979 pbrook
    struct sigqueue *q = ts->first_free;
355 66fb9763 bellard
    if (!q)
356 66fb9763 bellard
        return NULL;
357 624f7979 pbrook
    ts->first_free = q->next;
358 66fb9763 bellard
    return q;
359 31e31b8a bellard
}
360 31e31b8a bellard
361 624f7979 pbrook
static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
362 66fb9763 bellard
{
363 624f7979 pbrook
    TaskState *ts = env->opaque;
364 624f7979 pbrook
    q->next = ts->first_free;
365 624f7979 pbrook
    ts->first_free = q;
366 66fb9763 bellard
}
367 66fb9763 bellard
368 9de5e440 bellard
/* abort execution with signal */
369 66393fb9 Riku Voipio
static void QEMU_NORETURN force_sig(int target_sig)
370 66fb9763 bellard
{
371 edf8e2af Mika Westerberg
    TaskState *ts = (TaskState *)thread_env->opaque;
372 edf8e2af Mika Westerberg
    int host_sig, core_dumped = 0;
373 603e4fd7 aurel32
    struct sigaction act;
374 66393fb9 Riku Voipio
    host_sig = target_to_host_signal(target_sig);
375 66393fb9 Riku Voipio
    gdb_signalled(thread_env, target_sig);
376 603e4fd7 aurel32
377 edf8e2af Mika Westerberg
    /* dump core if supported by target binary format */
378 66393fb9 Riku Voipio
    if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
379 edf8e2af Mika Westerberg
        stop_all_tasks();
380 edf8e2af Mika Westerberg
        core_dumped =
381 66393fb9 Riku Voipio
            ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
382 edf8e2af Mika Westerberg
    }
383 edf8e2af Mika Westerberg
    if (core_dumped) {
384 edf8e2af Mika Westerberg
        /* we already dumped the core of target process, we don't want
385 edf8e2af Mika Westerberg
         * a coredump of qemu itself */
386 edf8e2af Mika Westerberg
        struct rlimit nodump;
387 edf8e2af Mika Westerberg
        getrlimit(RLIMIT_CORE, &nodump);
388 edf8e2af Mika Westerberg
        nodump.rlim_cur=0;
389 edf8e2af Mika Westerberg
        setrlimit(RLIMIT_CORE, &nodump);
390 edf8e2af Mika Westerberg
        (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
391 66393fb9 Riku Voipio
            target_sig, strsignal(host_sig), "core dumped" );
392 edf8e2af Mika Westerberg
    }
393 edf8e2af Mika Westerberg
394 0c58751c Stefan Weil
    /* The proper exit code for dying from an uncaught signal is
395 603e4fd7 aurel32
     * -<signal>.  The kernel doesn't allow exit() or _exit() to pass
396 603e4fd7 aurel32
     * a negative value.  To get the proper exit code we need to
397 603e4fd7 aurel32
     * actually die from an uncaught signal.  Here the default signal
398 603e4fd7 aurel32
     * handler is installed, we send ourself a signal and we wait for
399 603e4fd7 aurel32
     * it to arrive. */
400 603e4fd7 aurel32
    sigfillset(&act.sa_mask);
401 603e4fd7 aurel32
    act.sa_handler = SIG_DFL;
402 603e4fd7 aurel32
    sigaction(host_sig, &act, NULL);
403 603e4fd7 aurel32
404 603e4fd7 aurel32
    /* For some reason raise(host_sig) doesn't send the signal when
405 603e4fd7 aurel32
     * statically linked on x86-64. */
406 603e4fd7 aurel32
    kill(getpid(), host_sig);
407 603e4fd7 aurel32
408 603e4fd7 aurel32
    /* Make sure the signal isn't masked (just reuse the mask inside
409 603e4fd7 aurel32
    of act) */
410 603e4fd7 aurel32
    sigdelset(&act.sa_mask, host_sig);
411 603e4fd7 aurel32
    sigsuspend(&act.sa_mask);
412 603e4fd7 aurel32
413 603e4fd7 aurel32
    /* unreachable */
414 a6c6f76c Blue Swirl
    abort();
415 66fb9763 bellard
}
416 66fb9763 bellard
417 9de5e440 bellard
/* queue a signal so that it will be send to the virtual CPU as soon
418 9de5e440 bellard
   as possible */
419 c227f099 Anthony Liguori
int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
420 31e31b8a bellard
{
421 624f7979 pbrook
    TaskState *ts = env->opaque;
422 624f7979 pbrook
    struct emulated_sigtable *k;
423 9de5e440 bellard
    struct sigqueue *q, **pq;
424 992f48a0 blueswir1
    abi_ulong handler;
425 ca587a8e aurel32
    int queue;
426 66fb9763 bellard
427 9de5e440 bellard
#if defined(DEBUG_SIGNAL)
428 5fafdf24 ths
    fprintf(stderr, "queue_signal: sig=%d\n",
429 9de5e440 bellard
            sig);
430 66fb9763 bellard
#endif
431 624f7979 pbrook
    k = &ts->sigtab[sig - 1];
432 ca587a8e aurel32
    queue = gdb_queuesig ();
433 624f7979 pbrook
    handler = sigact_table[sig - 1]._sa_handler;
434 ca587a8e aurel32
    if (!queue && handler == TARGET_SIG_DFL) {
435 60b19691 ths
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
436 60b19691 ths
            kill(getpid(),SIGSTOP);
437 60b19691 ths
            return 0;
438 60b19691 ths
        } else
439 66fb9763 bellard
        /* default handler : ignore some signal. The other are fatal */
440 5fafdf24 ths
        if (sig != TARGET_SIGCHLD &&
441 5fafdf24 ths
            sig != TARGET_SIGURG &&
442 60b19691 ths
            sig != TARGET_SIGWINCH &&
443 60b19691 ths
            sig != TARGET_SIGCONT) {
444 66fb9763 bellard
            force_sig(sig);
445 9de5e440 bellard
        } else {
446 9de5e440 bellard
            return 0; /* indicate ignored */
447 66fb9763 bellard
        }
448 ca587a8e aurel32
    } else if (!queue && handler == TARGET_SIG_IGN) {
449 66fb9763 bellard
        /* ignore signal */
450 9de5e440 bellard
        return 0;
451 ca587a8e aurel32
    } else if (!queue && handler == TARGET_SIG_ERR) {
452 66fb9763 bellard
        force_sig(sig);
453 66fb9763 bellard
    } else {
454 9de5e440 bellard
        pq = &k->first;
455 9de5e440 bellard
        if (sig < TARGET_SIGRTMIN) {
456 9de5e440 bellard
            /* if non real time signal, we queue exactly one signal */
457 9de5e440 bellard
            if (!k->pending)
458 9de5e440 bellard
                q = &k->info;
459 9de5e440 bellard
            else
460 9de5e440 bellard
                return 0;
461 9de5e440 bellard
        } else {
462 9de5e440 bellard
            if (!k->pending) {
463 9de5e440 bellard
                /* first signal */
464 9de5e440 bellard
                q = &k->info;
465 9de5e440 bellard
            } else {
466 624f7979 pbrook
                q = alloc_sigqueue(env);
467 9de5e440 bellard
                if (!q)
468 9de5e440 bellard
                    return -EAGAIN;
469 9de5e440 bellard
                while (*pq != NULL)
470 9de5e440 bellard
                    pq = &(*pq)->next;
471 9de5e440 bellard
            }
472 9de5e440 bellard
        }
473 9de5e440 bellard
        *pq = q;
474 9de5e440 bellard
        q->info = *info;
475 9de5e440 bellard
        q->next = NULL;
476 9de5e440 bellard
        k->pending = 1;
477 9de5e440 bellard
        /* signal that a new signal is pending */
478 624f7979 pbrook
        ts->signal_pending = 1;
479 9de5e440 bellard
        return 1; /* indicates that the signal was queued */
480 9de5e440 bellard
    }
481 9de5e440 bellard
}
482 9de5e440 bellard
483 5fafdf24 ths
static void host_signal_handler(int host_signum, siginfo_t *info,
484 9de5e440 bellard
                                void *puc)
485 9de5e440 bellard
{
486 9de5e440 bellard
    int sig;
487 c227f099 Anthony Liguori
    target_siginfo_t tinfo;
488 9de5e440 bellard
489 9de5e440 bellard
    /* the CPU emulator uses some host signals to detect exceptions,
490 eaa449b9 aurel32
       we forward to it some signals */
491 ca587a8e aurel32
    if ((host_signum == SIGSEGV || host_signum == SIGBUS)
492 eaa449b9 aurel32
        && info->si_code > 0) {
493 b346ff46 bellard
        if (cpu_signal_handler(host_signum, info, puc))
494 9de5e440 bellard
            return;
495 9de5e440 bellard
    }
496 9de5e440 bellard
497 9de5e440 bellard
    /* get target signal number */
498 9de5e440 bellard
    sig = host_to_target_signal(host_signum);
499 9de5e440 bellard
    if (sig < 1 || sig > TARGET_NSIG)
500 9de5e440 bellard
        return;
501 9de5e440 bellard
#if defined(DEBUG_SIGNAL)
502 bc8a22cc bellard
    fprintf(stderr, "qemu: got signal %d\n", sig);
503 9de5e440 bellard
#endif
504 9de5e440 bellard
    host_to_target_siginfo_noswap(&tinfo, info);
505 d5975363 pbrook
    if (queue_signal(thread_env, sig, &tinfo) == 1) {
506 9de5e440 bellard
        /* interrupt the virtual CPU as soon as possible */
507 3098dba0 aurel32
        cpu_exit(thread_env);
508 66fb9763 bellard
    }
509 66fb9763 bellard
}
510 66fb9763 bellard
511 0da46a6e ths
/* do_sigaltstack() returns target values and errnos. */
512 579a97f7 bellard
/* compare linux/kernel/signal.c:do_sigaltstack() */
513 579a97f7 bellard
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
514 a04e134a ths
{
515 a04e134a ths
    int ret;
516 a04e134a ths
    struct target_sigaltstack oss;
517 a04e134a ths
518 a04e134a ths
    /* XXX: test errors */
519 579a97f7 bellard
    if(uoss_addr)
520 a04e134a ths
    {
521 a04e134a ths
        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
522 a04e134a ths
        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
523 a04e134a ths
        __put_user(sas_ss_flags(sp), &oss.ss_flags);
524 a04e134a ths
    }
525 a04e134a ths
526 579a97f7 bellard
    if(uss_addr)
527 a04e134a ths
    {
528 579a97f7 bellard
        struct target_sigaltstack *uss;
529 579a97f7 bellard
        struct target_sigaltstack ss;
530 a04e134a ths
531 0da46a6e ths
        ret = -TARGET_EFAULT;
532 579a97f7 bellard
        if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
533 a04e134a ths
            || __get_user(ss.ss_sp, &uss->ss_sp)
534 a04e134a ths
            || __get_user(ss.ss_size, &uss->ss_size)
535 a04e134a ths
            || __get_user(ss.ss_flags, &uss->ss_flags))
536 a04e134a ths
            goto out;
537 579a97f7 bellard
        unlock_user_struct(uss, uss_addr, 0);
538 a04e134a ths
539 0da46a6e ths
        ret = -TARGET_EPERM;
540 a04e134a ths
        if (on_sig_stack(sp))
541 a04e134a ths
            goto out;
542 a04e134a ths
543 0da46a6e ths
        ret = -TARGET_EINVAL;
544 a04e134a ths
        if (ss.ss_flags != TARGET_SS_DISABLE
545 a04e134a ths
            && ss.ss_flags != TARGET_SS_ONSTACK
546 a04e134a ths
            && ss.ss_flags != 0)
547 a04e134a ths
            goto out;
548 a04e134a ths
549 a04e134a ths
        if (ss.ss_flags == TARGET_SS_DISABLE) {
550 a04e134a ths
            ss.ss_size = 0;
551 a04e134a ths
            ss.ss_sp = 0;
552 a04e134a ths
        } else {
553 0da46a6e ths
            ret = -TARGET_ENOMEM;
554 a04e134a ths
            if (ss.ss_size < MINSIGSTKSZ)
555 a04e134a ths
                goto out;
556 a04e134a ths
        }
557 a04e134a ths
558 a04e134a ths
        target_sigaltstack_used.ss_sp = ss.ss_sp;
559 a04e134a ths
        target_sigaltstack_used.ss_size = ss.ss_size;
560 a04e134a ths
    }
561 a04e134a ths
562 579a97f7 bellard
    if (uoss_addr) {
563 0da46a6e ths
        ret = -TARGET_EFAULT;
564 579a97f7 bellard
        if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
565 a04e134a ths
            goto out;
566 a04e134a ths
    }
567 a04e134a ths
568 a04e134a ths
    ret = 0;
569 a04e134a ths
out:
570 a04e134a ths
    return ret;
571 a04e134a ths
}
572 a04e134a ths
573 0da46a6e ths
/* do_sigaction() return host values and errnos */
574 66fb9763 bellard
int do_sigaction(int sig, const struct target_sigaction *act,
575 66fb9763 bellard
                 struct target_sigaction *oact)
576 66fb9763 bellard
{
577 624f7979 pbrook
    struct target_sigaction *k;
578 773b93ee bellard
    struct sigaction act1;
579 773b93ee bellard
    int host_sig;
580 0da46a6e ths
    int ret = 0;
581 66fb9763 bellard
582 2a913eb1 ths
    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
583 66fb9763 bellard
        return -EINVAL;
584 66fb9763 bellard
    k = &sigact_table[sig - 1];
585 773b93ee bellard
#if defined(DEBUG_SIGNAL)
586 0bf9e31a Blue Swirl
    fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
587 0bf9e31a Blue Swirl
            sig, act, oact);
588 66fb9763 bellard
#endif
589 66fb9763 bellard
    if (oact) {
590 624f7979 pbrook
        oact->_sa_handler = tswapl(k->_sa_handler);
591 624f7979 pbrook
        oact->sa_flags = tswapl(k->sa_flags);
592 388bb21a ths
#if !defined(TARGET_MIPS)
593 624f7979 pbrook
        oact->sa_restorer = tswapl(k->sa_restorer);
594 388bb21a ths
#endif
595 624f7979 pbrook
        oact->sa_mask = k->sa_mask;
596 66fb9763 bellard
    }
597 66fb9763 bellard
    if (act) {
598 624f7979 pbrook
        /* FIXME: This is not threadsafe.  */
599 624f7979 pbrook
        k->_sa_handler = tswapl(act->_sa_handler);
600 624f7979 pbrook
        k->sa_flags = tswapl(act->sa_flags);
601 388bb21a ths
#if !defined(TARGET_MIPS)
602 624f7979 pbrook
        k->sa_restorer = tswapl(act->sa_restorer);
603 388bb21a ths
#endif
604 624f7979 pbrook
        k->sa_mask = act->sa_mask;
605 773b93ee bellard
606 773b93ee bellard
        /* we update the host linux signal state */
607 773b93ee bellard
        host_sig = target_to_host_signal(sig);
608 773b93ee bellard
        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
609 773b93ee bellard
            sigfillset(&act1.sa_mask);
610 773b93ee bellard
            act1.sa_flags = SA_SIGINFO;
611 624f7979 pbrook
            if (k->sa_flags & TARGET_SA_RESTART)
612 773b93ee bellard
                act1.sa_flags |= SA_RESTART;
613 773b93ee bellard
            /* NOTE: it is important to update the host kernel signal
614 773b93ee bellard
               ignore state to avoid getting unexpected interrupted
615 773b93ee bellard
               syscalls */
616 624f7979 pbrook
            if (k->_sa_handler == TARGET_SIG_IGN) {
617 773b93ee bellard
                act1.sa_sigaction = (void *)SIG_IGN;
618 624f7979 pbrook
            } else if (k->_sa_handler == TARGET_SIG_DFL) {
619 ca587a8e aurel32
                if (fatal_signal (sig))
620 ca587a8e aurel32
                    act1.sa_sigaction = host_signal_handler;
621 ca587a8e aurel32
                else
622 ca587a8e aurel32
                    act1.sa_sigaction = (void *)SIG_DFL;
623 773b93ee bellard
            } else {
624 773b93ee bellard
                act1.sa_sigaction = host_signal_handler;
625 773b93ee bellard
            }
626 0da46a6e ths
            ret = sigaction(host_sig, &act1, NULL);
627 773b93ee bellard
        }
628 66fb9763 bellard
    }
629 0da46a6e ths
    return ret;
630 66fb9763 bellard
}
631 66fb9763 bellard
632 c227f099 Anthony Liguori
static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
633 c227f099 Anthony Liguori
                                       const target_siginfo_t *info)
634 43fff238 bellard
{
635 43fff238 bellard
    tswap_siginfo(tinfo, info);
636 43fff238 bellard
    return 0;
637 43fff238 bellard
}
638 43fff238 bellard
639 c3b5bc8a ths
static inline int current_exec_domain_sig(int sig)
640 c3b5bc8a ths
{
641 c3b5bc8a ths
    return /* current->exec_domain && current->exec_domain->signal_invmap
642 c3b5bc8a ths
              && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
643 c3b5bc8a ths
}
644 c3b5bc8a ths
645 459a4017 bellard
#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
646 66fb9763 bellard
647 66fb9763 bellard
/* from the Linux kernel */
648 66fb9763 bellard
649 66fb9763 bellard
struct target_fpreg {
650 66fb9763 bellard
        uint16_t significand[4];
651 66fb9763 bellard
        uint16_t exponent;
652 66fb9763 bellard
};
653 66fb9763 bellard
654 66fb9763 bellard
struct target_fpxreg {
655 66fb9763 bellard
        uint16_t significand[4];
656 66fb9763 bellard
        uint16_t exponent;
657 66fb9763 bellard
        uint16_t padding[3];
658 66fb9763 bellard
};
659 66fb9763 bellard
660 66fb9763 bellard
struct target_xmmreg {
661 992f48a0 blueswir1
        abi_ulong element[4];
662 66fb9763 bellard
};
663 66fb9763 bellard
664 66fb9763 bellard
struct target_fpstate {
665 66fb9763 bellard
        /* Regular FPU environment */
666 992f48a0 blueswir1
        abi_ulong       cw;
667 992f48a0 blueswir1
        abi_ulong       sw;
668 992f48a0 blueswir1
        abi_ulong       tag;
669 992f48a0 blueswir1
        abi_ulong       ipoff;
670 992f48a0 blueswir1
        abi_ulong       cssel;
671 992f48a0 blueswir1
        abi_ulong       dataoff;
672 992f48a0 blueswir1
        abi_ulong       datasel;
673 66fb9763 bellard
        struct target_fpreg        _st[8];
674 66fb9763 bellard
        uint16_t        status;
675 66fb9763 bellard
        uint16_t        magic;                /* 0xffff = regular FPU data only */
676 66fb9763 bellard
677 66fb9763 bellard
        /* FXSR FPU environment */
678 992f48a0 blueswir1
        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */
679 992f48a0 blueswir1
        abi_ulong       mxcsr;
680 992f48a0 blueswir1
        abi_ulong       reserved;
681 66fb9763 bellard
        struct target_fpxreg        _fxsr_st[8];        /* FXSR FPU reg data is ignored */
682 66fb9763 bellard
        struct target_xmmreg        _xmm[8];
683 992f48a0 blueswir1
        abi_ulong       padding[56];
684 66fb9763 bellard
};
685 66fb9763 bellard
686 66fb9763 bellard
#define X86_FXSR_MAGIC                0x0000
687 66fb9763 bellard
688 66fb9763 bellard
struct target_sigcontext {
689 66fb9763 bellard
        uint16_t gs, __gsh;
690 66fb9763 bellard
        uint16_t fs, __fsh;
691 66fb9763 bellard
        uint16_t es, __esh;
692 66fb9763 bellard
        uint16_t ds, __dsh;
693 992f48a0 blueswir1
        abi_ulong edi;
694 992f48a0 blueswir1
        abi_ulong esi;
695 992f48a0 blueswir1
        abi_ulong ebp;
696 992f48a0 blueswir1
        abi_ulong esp;
697 992f48a0 blueswir1
        abi_ulong ebx;
698 992f48a0 blueswir1
        abi_ulong edx;
699 992f48a0 blueswir1
        abi_ulong ecx;
700 992f48a0 blueswir1
        abi_ulong eax;
701 992f48a0 blueswir1
        abi_ulong trapno;
702 992f48a0 blueswir1
        abi_ulong err;
703 992f48a0 blueswir1
        abi_ulong eip;
704 66fb9763 bellard
        uint16_t cs, __csh;
705 992f48a0 blueswir1
        abi_ulong eflags;
706 992f48a0 blueswir1
        abi_ulong esp_at_signal;
707 66fb9763 bellard
        uint16_t ss, __ssh;
708 992f48a0 blueswir1
        abi_ulong fpstate; /* pointer */
709 992f48a0 blueswir1
        abi_ulong oldmask;
710 992f48a0 blueswir1
        abi_ulong cr2;
711 66fb9763 bellard
};
712 66fb9763 bellard
713 66fb9763 bellard
struct target_ucontext {
714 992f48a0 blueswir1
        abi_ulong         tuc_flags;
715 992f48a0 blueswir1
        abi_ulong         tuc_link;
716 c227f099 Anthony Liguori
        target_stack_t          tuc_stack;
717 b8076a74 bellard
        struct target_sigcontext tuc_mcontext;
718 c227f099 Anthony Liguori
        target_sigset_t          tuc_sigmask;        /* mask last for extensibility */
719 66fb9763 bellard
};
720 66fb9763 bellard
721 66fb9763 bellard
struct sigframe
722 66fb9763 bellard
{
723 992f48a0 blueswir1
    abi_ulong pretcode;
724 66fb9763 bellard
    int sig;
725 66fb9763 bellard
    struct target_sigcontext sc;
726 66fb9763 bellard
    struct target_fpstate fpstate;
727 992f48a0 blueswir1
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
728 66fb9763 bellard
    char retcode[8];
729 66fb9763 bellard
};
730 66fb9763 bellard
731 66fb9763 bellard
struct rt_sigframe
732 66fb9763 bellard
{
733 992f48a0 blueswir1
    abi_ulong pretcode;
734 66fb9763 bellard
    int sig;
735 992f48a0 blueswir1
    abi_ulong pinfo;
736 992f48a0 blueswir1
    abi_ulong puc;
737 66fb9763 bellard
    struct target_siginfo info;
738 66fb9763 bellard
    struct target_ucontext uc;
739 66fb9763 bellard
    struct target_fpstate fpstate;
740 66fb9763 bellard
    char retcode[8];
741 66fb9763 bellard
};
742 66fb9763 bellard
743 66fb9763 bellard
/*
744 66fb9763 bellard
 * Set up a signal frame.
745 66fb9763 bellard
 */
746 66fb9763 bellard
747 66fb9763 bellard
/* XXX: save x87 state */
748 66fb9763 bellard
static int
749 66fb9763 bellard
setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
750 28be6234 bellard
                 CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
751 66fb9763 bellard
{
752 66fb9763 bellard
        int err = 0;
753 775b58d8 bellard
        uint16_t magic;
754 66fb9763 bellard
755 579a97f7 bellard
        /* already locked in setup_frame() */
756 a52c757c bellard
        err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
757 a52c757c bellard
        err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
758 a52c757c bellard
        err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
759 a52c757c bellard
        err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
760 66fb9763 bellard
        err |= __put_user(env->regs[R_EDI], &sc->edi);
761 66fb9763 bellard
        err |= __put_user(env->regs[R_ESI], &sc->esi);
762 66fb9763 bellard
        err |= __put_user(env->regs[R_EBP], &sc->ebp);
763 66fb9763 bellard
        err |= __put_user(env->regs[R_ESP], &sc->esp);
764 66fb9763 bellard
        err |= __put_user(env->regs[R_EBX], &sc->ebx);
765 66fb9763 bellard
        err |= __put_user(env->regs[R_EDX], &sc->edx);
766 66fb9763 bellard
        err |= __put_user(env->regs[R_ECX], &sc->ecx);
767 66fb9763 bellard
        err |= __put_user(env->regs[R_EAX], &sc->eax);
768 66099dd9 bellard
        err |= __put_user(env->exception_index, &sc->trapno);
769 66099dd9 bellard
        err |= __put_user(env->error_code, &sc->err);
770 66fb9763 bellard
        err |= __put_user(env->eip, &sc->eip);
771 a52c757c bellard
        err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
772 66fb9763 bellard
        err |= __put_user(env->eflags, &sc->eflags);
773 66fb9763 bellard
        err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
774 a52c757c bellard
        err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
775 ed2dcdf6 bellard
776 28be6234 bellard
        cpu_x86_fsave(env, fpstate_addr, 1);
777 ed2dcdf6 bellard
        fpstate->status = fpstate->sw;
778 775b58d8 bellard
        magic = 0xffff;
779 775b58d8 bellard
        err |= __put_user(magic, &fpstate->magic);
780 28be6234 bellard
        err |= __put_user(fpstate_addr, &sc->fpstate);
781 ed2dcdf6 bellard
782 66fb9763 bellard
        /* non-iBCS2 extensions.. */
783 66fb9763 bellard
        err |= __put_user(mask, &sc->oldmask);
784 a52c757c bellard
        err |= __put_user(env->cr[2], &sc->cr2);
785 66fb9763 bellard
        return err;
786 31e31b8a bellard
}
787 31e31b8a bellard
788 66fb9763 bellard
/*
789 66fb9763 bellard
 * Determine which stack to use..
790 66fb9763 bellard
 */
791 31e31b8a bellard
792 579a97f7 bellard
static inline abi_ulong
793 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
794 31e31b8a bellard
{
795 66fb9763 bellard
        unsigned long esp;
796 66fb9763 bellard
797 66fb9763 bellard
        /* Default to using normal stack */
798 66fb9763 bellard
        esp = env->regs[R_ESP];
799 66fb9763 bellard
        /* This is the X/Open sanctioned signal stack switching.  */
800 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_ONSTACK) {
801 a04e134a ths
            if (sas_ss_flags(esp) == 0)
802 a04e134a ths
                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
803 a04e134a ths
        }
804 66fb9763 bellard
805 66fb9763 bellard
        /* This is the legacy signal stack switching. */
806 5fafdf24 ths
        else
807 a52c757c bellard
        if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
808 624f7979 pbrook
            !(ka->sa_flags & TARGET_SA_RESTORER) &&
809 624f7979 pbrook
            ka->sa_restorer) {
810 624f7979 pbrook
            esp = (unsigned long) ka->sa_restorer;
811 a52c757c bellard
        }
812 579a97f7 bellard
        return (esp - frame_size) & -8ul;
813 66fb9763 bellard
}
814 66fb9763 bellard
815 579a97f7 bellard
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
816 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
817 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUX86State *env)
818 66fb9763 bellard
{
819 579a97f7 bellard
        abi_ulong frame_addr;
820 66fb9763 bellard
        struct sigframe *frame;
821 9231944d bellard
        int i, err = 0;
822 66fb9763 bellard
823 579a97f7 bellard
        frame_addr = get_sigframe(ka, env, sizeof(*frame));
824 66fb9763 bellard
825 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
826 66fb9763 bellard
                goto give_sigsegv;
827 579a97f7 bellard
828 c3b5bc8a ths
        err |= __put_user(current_exec_domain_sig(sig),
829 66fb9763 bellard
                          &frame->sig);
830 66fb9763 bellard
        if (err)
831 66fb9763 bellard
                goto give_sigsegv;
832 66fb9763 bellard
833 28be6234 bellard
        setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
834 28be6234 bellard
                         frame_addr + offsetof(struct sigframe, fpstate));
835 66fb9763 bellard
        if (err)
836 66fb9763 bellard
                goto give_sigsegv;
837 66fb9763 bellard
838 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
839 9231944d bellard
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
840 9231944d bellard
                goto give_sigsegv;
841 9231944d bellard
        }
842 66fb9763 bellard
843 66fb9763 bellard
        /* Set up to return from userspace.  If provided, use a stub
844 66fb9763 bellard
           already in userspace.  */
845 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
846 624f7979 pbrook
                err |= __put_user(ka->sa_restorer, &frame->pretcode);
847 66fb9763 bellard
        } else {
848 775b58d8 bellard
                uint16_t val16;
849 28be6234 bellard
                abi_ulong retcode_addr;
850 28be6234 bellard
                retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
851 28be6234 bellard
                err |= __put_user(retcode_addr, &frame->pretcode);
852 66fb9763 bellard
                /* This is popl %eax ; movl $,%eax ; int $0x80 */
853 775b58d8 bellard
                val16 = 0xb858;
854 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+0));
855 66fb9763 bellard
                err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
856 775b58d8 bellard
                val16 = 0x80cd;
857 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+6));
858 66fb9763 bellard
        }
859 66fb9763 bellard
860 66fb9763 bellard
        if (err)
861 66fb9763 bellard
                goto give_sigsegv;
862 66fb9763 bellard
863 66fb9763 bellard
        /* Set up registers for signal handler */
864 28be6234 bellard
        env->regs[R_ESP] = frame_addr;
865 624f7979 pbrook
        env->eip = ka->_sa_handler;
866 66fb9763 bellard
867 66fb9763 bellard
        cpu_x86_load_seg(env, R_DS, __USER_DS);
868 66fb9763 bellard
        cpu_x86_load_seg(env, R_ES, __USER_DS);
869 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, __USER_DS);
870 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, __USER_CS);
871 66fb9763 bellard
        env->eflags &= ~TF_MASK;
872 66fb9763 bellard
873 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
874 579a97f7 bellard
875 66fb9763 bellard
        return;
876 66fb9763 bellard
877 66fb9763 bellard
give_sigsegv:
878 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
879 66fb9763 bellard
        if (sig == TARGET_SIGSEGV)
880 624f7979 pbrook
                ka->_sa_handler = TARGET_SIG_DFL;
881 66fb9763 bellard
        force_sig(TARGET_SIGSEGV /* , current */);
882 66fb9763 bellard
}
883 66fb9763 bellard
884 579a97f7 bellard
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
885 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
886 c227f099 Anthony Liguori
                           target_siginfo_t *info,
887 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUX86State *env)
888 66fb9763 bellard
{
889 28be6234 bellard
        abi_ulong frame_addr, addr;
890 66fb9763 bellard
        struct rt_sigframe *frame;
891 9231944d bellard
        int i, err = 0;
892 66fb9763 bellard
893 579a97f7 bellard
        frame_addr = get_sigframe(ka, env, sizeof(*frame));
894 66fb9763 bellard
895 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
896 66fb9763 bellard
                goto give_sigsegv;
897 66fb9763 bellard
898 c3b5bc8a ths
        err |= __put_user(current_exec_domain_sig(sig),
899 66fb9763 bellard
                          &frame->sig);
900 28be6234 bellard
        addr = frame_addr + offsetof(struct rt_sigframe, info);
901 28be6234 bellard
        err |= __put_user(addr, &frame->pinfo);
902 28be6234 bellard
        addr = frame_addr + offsetof(struct rt_sigframe, uc);
903 28be6234 bellard
        err |= __put_user(addr, &frame->puc);
904 66fb9763 bellard
        err |= copy_siginfo_to_user(&frame->info, info);
905 66fb9763 bellard
        if (err)
906 66fb9763 bellard
                goto give_sigsegv;
907 31e31b8a bellard
908 66fb9763 bellard
        /* Create the ucontext.  */
909 b8076a74 bellard
        err |= __put_user(0, &frame->uc.tuc_flags);
910 b8076a74 bellard
        err |= __put_user(0, &frame->uc.tuc_link);
911 a04e134a ths
        err |= __put_user(target_sigaltstack_used.ss_sp,
912 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_sp);
913 a04e134a ths
        err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
914 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_flags);
915 a04e134a ths
        err |= __put_user(target_sigaltstack_used.ss_size,
916 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_size);
917 b8076a74 bellard
        err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
918 28be6234 bellard
                                env, set->sig[0], 
919 28be6234 bellard
                                frame_addr + offsetof(struct rt_sigframe, fpstate));
920 9231944d bellard
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
921 b8076a74 bellard
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
922 9231944d bellard
                goto give_sigsegv;
923 9231944d bellard
        }
924 31e31b8a bellard
925 66fb9763 bellard
        /* Set up to return from userspace.  If provided, use a stub
926 66fb9763 bellard
           already in userspace.  */
927 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
928 624f7979 pbrook
                err |= __put_user(ka->sa_restorer, &frame->pretcode);
929 66fb9763 bellard
        } else {
930 775b58d8 bellard
                uint16_t val16;
931 28be6234 bellard
                addr = frame_addr + offsetof(struct rt_sigframe, retcode);
932 28be6234 bellard
                err |= __put_user(addr, &frame->pretcode);
933 66fb9763 bellard
                /* This is movl $,%eax ; int $0x80 */
934 775b58d8 bellard
                err |= __put_user(0xb8, (char *)(frame->retcode+0));
935 66fb9763 bellard
                err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
936 775b58d8 bellard
                val16 = 0x80cd;
937 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+5));
938 66fb9763 bellard
        }
939 66fb9763 bellard
940 66fb9763 bellard
        if (err)
941 66fb9763 bellard
                goto give_sigsegv;
942 66fb9763 bellard
943 66fb9763 bellard
        /* Set up registers for signal handler */
944 28be6234 bellard
        env->regs[R_ESP] = frame_addr;
945 624f7979 pbrook
        env->eip = ka->_sa_handler;
946 66fb9763 bellard
947 66fb9763 bellard
        cpu_x86_load_seg(env, R_DS, __USER_DS);
948 66fb9763 bellard
        cpu_x86_load_seg(env, R_ES, __USER_DS);
949 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, __USER_DS);
950 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, __USER_CS);
951 66fb9763 bellard
        env->eflags &= ~TF_MASK;
952 66fb9763 bellard
953 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
954 579a97f7 bellard
955 66fb9763 bellard
        return;
956 66fb9763 bellard
957 66fb9763 bellard
give_sigsegv:
958 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
959 66fb9763 bellard
        if (sig == TARGET_SIGSEGV)
960 624f7979 pbrook
                ka->_sa_handler = TARGET_SIG_DFL;
961 66fb9763 bellard
        force_sig(TARGET_SIGSEGV /* , current */);
962 66fb9763 bellard
}
963 66fb9763 bellard
964 66fb9763 bellard
static int
965 66fb9763 bellard
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
966 66fb9763 bellard
{
967 66fb9763 bellard
        unsigned int err = 0;
968 28be6234 bellard
        abi_ulong fpstate_addr;
969 28be6234 bellard
        unsigned int tmpflags;
970 28be6234 bellard
971 28be6234 bellard
        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
972 28be6234 bellard
        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
973 28be6234 bellard
        cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
974 28be6234 bellard
        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
975 28be6234 bellard
976 28be6234 bellard
        env->regs[R_EDI] = tswapl(sc->edi);
977 28be6234 bellard
        env->regs[R_ESI] = tswapl(sc->esi);
978 28be6234 bellard
        env->regs[R_EBP] = tswapl(sc->ebp);
979 28be6234 bellard
        env->regs[R_ESP] = tswapl(sc->esp);
980 28be6234 bellard
        env->regs[R_EBX] = tswapl(sc->ebx);
981 28be6234 bellard
        env->regs[R_EDX] = tswapl(sc->edx);
982 28be6234 bellard
        env->regs[R_ECX] = tswapl(sc->ecx);
983 28be6234 bellard
        env->eip = tswapl(sc->eip);
984 66fb9763 bellard
985 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
986 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
987 5fafdf24 ths
988 28be6234 bellard
        tmpflags = tswapl(sc->eflags);
989 28be6234 bellard
        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
990 28be6234 bellard
        //                regs->orig_eax = -1;                /* disable syscall checks */
991 66fb9763 bellard
992 28be6234 bellard
        fpstate_addr = tswapl(sc->fpstate);
993 28be6234 bellard
        if (fpstate_addr != 0) {
994 28be6234 bellard
                if (!access_ok(VERIFY_READ, fpstate_addr, 
995 28be6234 bellard
                               sizeof(struct target_fpstate)))
996 28be6234 bellard
                        goto badframe;
997 28be6234 bellard
                cpu_x86_frstor(env, fpstate_addr, 1);
998 66fb9763 bellard
        }
999 ed2dcdf6 bellard
1000 28be6234 bellard
        *peax = tswapl(sc->eax);
1001 66fb9763 bellard
        return err;
1002 66fb9763 bellard
badframe:
1003 66fb9763 bellard
        return 1;
1004 66fb9763 bellard
}
1005 66fb9763 bellard
1006 66fb9763 bellard
long do_sigreturn(CPUX86State *env)
1007 66fb9763 bellard
{
1008 579a97f7 bellard
    struct sigframe *frame;
1009 579a97f7 bellard
    abi_ulong frame_addr = env->regs[R_ESP] - 8;
1010 c227f099 Anthony Liguori
    target_sigset_t target_set;
1011 66fb9763 bellard
    sigset_t set;
1012 66fb9763 bellard
    int eax, i;
1013 66fb9763 bellard
1014 447db213 bellard
#if defined(DEBUG_SIGNAL)
1015 447db213 bellard
    fprintf(stderr, "do_sigreturn\n");
1016 447db213 bellard
#endif
1017 579a97f7 bellard
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1018 579a97f7 bellard
        goto badframe;
1019 66fb9763 bellard
    /* set blocked signals */
1020 9231944d bellard
    if (__get_user(target_set.sig[0], &frame->sc.oldmask))
1021 9231944d bellard
        goto badframe;
1022 9231944d bellard
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1023 9231944d bellard
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
1024 9231944d bellard
            goto badframe;
1025 9231944d bellard
    }
1026 66fb9763 bellard
1027 9231944d bellard
    target_to_host_sigset_internal(&set, &target_set);
1028 66fb9763 bellard
    sigprocmask(SIG_SETMASK, &set, NULL);
1029 3b46e624 ths
1030 66fb9763 bellard
    /* restore registers */
1031 66fb9763 bellard
    if (restore_sigcontext(env, &frame->sc, &eax))
1032 66fb9763 bellard
        goto badframe;
1033 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 0);
1034 66fb9763 bellard
    return eax;
1035 66fb9763 bellard
1036 66fb9763 bellard
badframe:
1037 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 0);
1038 66fb9763 bellard
    force_sig(TARGET_SIGSEGV);
1039 66fb9763 bellard
    return 0;
1040 66fb9763 bellard
}
1041 66fb9763 bellard
1042 66fb9763 bellard
long do_rt_sigreturn(CPUX86State *env)
1043 66fb9763 bellard
{
1044 28be6234 bellard
        abi_ulong frame_addr;
1045 28be6234 bellard
        struct rt_sigframe *frame;
1046 66fb9763 bellard
        sigset_t set;
1047 66fb9763 bellard
        int eax;
1048 66fb9763 bellard
1049 28be6234 bellard
        frame_addr = env->regs[R_ESP] - 4;
1050 28be6234 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1051 28be6234 bellard
                goto badframe;
1052 b8076a74 bellard
        target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1053 66fb9763 bellard
        sigprocmask(SIG_SETMASK, &set, NULL);
1054 5fafdf24 ths
1055 b8076a74 bellard
        if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
1056 66fb9763 bellard
                goto badframe;
1057 66fb9763 bellard
1058 28be6234 bellard
        if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, 
1059 28be6234 bellard
                           get_sp_from_cpustate(env)) == -EFAULT)
1060 66fb9763 bellard
                goto badframe;
1061 a04e134a ths
1062 28be6234 bellard
        unlock_user_struct(frame, frame_addr, 0);
1063 66fb9763 bellard
        return eax;
1064 66fb9763 bellard
1065 66fb9763 bellard
badframe:
1066 28be6234 bellard
        unlock_user_struct(frame, frame_addr, 0);
1067 28be6234 bellard
        force_sig(TARGET_SIGSEGV);
1068 66fb9763 bellard
        return 0;
1069 66fb9763 bellard
}
1070 66fb9763 bellard
1071 43fff238 bellard
#elif defined(TARGET_ARM)
1072 43fff238 bellard
1073 43fff238 bellard
struct target_sigcontext {
1074 992f48a0 blueswir1
        abi_ulong trap_no;
1075 992f48a0 blueswir1
        abi_ulong error_code;
1076 992f48a0 blueswir1
        abi_ulong oldmask;
1077 992f48a0 blueswir1
        abi_ulong arm_r0;
1078 992f48a0 blueswir1
        abi_ulong arm_r1;
1079 992f48a0 blueswir1
        abi_ulong arm_r2;
1080 992f48a0 blueswir1
        abi_ulong arm_r3;
1081 992f48a0 blueswir1
        abi_ulong arm_r4;
1082 992f48a0 blueswir1
        abi_ulong arm_r5;
1083 992f48a0 blueswir1
        abi_ulong arm_r6;
1084 992f48a0 blueswir1
        abi_ulong arm_r7;
1085 992f48a0 blueswir1
        abi_ulong arm_r8;
1086 992f48a0 blueswir1
        abi_ulong arm_r9;
1087 992f48a0 blueswir1
        abi_ulong arm_r10;
1088 992f48a0 blueswir1
        abi_ulong arm_fp;
1089 992f48a0 blueswir1
        abi_ulong arm_ip;
1090 992f48a0 blueswir1
        abi_ulong arm_sp;
1091 992f48a0 blueswir1
        abi_ulong arm_lr;
1092 992f48a0 blueswir1
        abi_ulong arm_pc;
1093 992f48a0 blueswir1
        abi_ulong arm_cpsr;
1094 992f48a0 blueswir1
        abi_ulong fault_address;
1095 43fff238 bellard
};
1096 43fff238 bellard
1097 a745ec6d pbrook
struct target_ucontext_v1 {
1098 a745ec6d pbrook
    abi_ulong tuc_flags;
1099 a745ec6d pbrook
    abi_ulong tuc_link;
1100 c227f099 Anthony Liguori
    target_stack_t tuc_stack;
1101 a745ec6d pbrook
    struct target_sigcontext tuc_mcontext;
1102 c227f099 Anthony Liguori
    target_sigset_t  tuc_sigmask;        /* mask last for extensibility */
1103 a745ec6d pbrook
};
1104 a745ec6d pbrook
1105 a745ec6d pbrook
struct target_ucontext_v2 {
1106 992f48a0 blueswir1
    abi_ulong tuc_flags;
1107 992f48a0 blueswir1
    abi_ulong tuc_link;
1108 c227f099 Anthony Liguori
    target_stack_t tuc_stack;
1109 b8076a74 bellard
    struct target_sigcontext tuc_mcontext;
1110 c227f099 Anthony Liguori
    target_sigset_t  tuc_sigmask;        /* mask last for extensibility */
1111 5f0b7c88 Peter Maydell
    char __unused[128 - sizeof(target_sigset_t)];
1112 a745ec6d pbrook
    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1113 43fff238 bellard
};
1114 43fff238 bellard
1115 0d871bdb Peter Maydell
struct target_user_vfp {
1116 0d871bdb Peter Maydell
    uint64_t fpregs[32];
1117 0d871bdb Peter Maydell
    abi_ulong fpscr;
1118 0d871bdb Peter Maydell
};
1119 0d871bdb Peter Maydell
1120 0d871bdb Peter Maydell
struct target_user_vfp_exc {
1121 0d871bdb Peter Maydell
    abi_ulong fpexc;
1122 0d871bdb Peter Maydell
    abi_ulong fpinst;
1123 0d871bdb Peter Maydell
    abi_ulong fpinst2;
1124 0d871bdb Peter Maydell
};
1125 0d871bdb Peter Maydell
1126 0d871bdb Peter Maydell
struct target_vfp_sigframe {
1127 0d871bdb Peter Maydell
    abi_ulong magic;
1128 0d871bdb Peter Maydell
    abi_ulong size;
1129 0d871bdb Peter Maydell
    struct target_user_vfp ufp;
1130 0d871bdb Peter Maydell
    struct target_user_vfp_exc ufp_exc;
1131 0d871bdb Peter Maydell
} __attribute__((__aligned__(8)));
1132 0d871bdb Peter Maydell
1133 08e11256 Peter Maydell
struct target_iwmmxt_sigframe {
1134 08e11256 Peter Maydell
    abi_ulong magic;
1135 08e11256 Peter Maydell
    abi_ulong size;
1136 08e11256 Peter Maydell
    uint64_t regs[16];
1137 08e11256 Peter Maydell
    /* Note that not all the coprocessor control registers are stored here */
1138 08e11256 Peter Maydell
    uint32_t wcssf;
1139 08e11256 Peter Maydell
    uint32_t wcasf;
1140 08e11256 Peter Maydell
    uint32_t wcgr0;
1141 08e11256 Peter Maydell
    uint32_t wcgr1;
1142 08e11256 Peter Maydell
    uint32_t wcgr2;
1143 08e11256 Peter Maydell
    uint32_t wcgr3;
1144 08e11256 Peter Maydell
} __attribute__((__aligned__(8)));
1145 08e11256 Peter Maydell
1146 0d871bdb Peter Maydell
#define TARGET_VFP_MAGIC 0x56465001
1147 08e11256 Peter Maydell
#define TARGET_IWMMXT_MAGIC 0x12ef842a
1148 0d871bdb Peter Maydell
1149 a8c33204 pbrook
struct sigframe_v1
1150 43fff238 bellard
{
1151 43fff238 bellard
    struct target_sigcontext sc;
1152 992f48a0 blueswir1
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
1153 992f48a0 blueswir1
    abi_ulong retcode;
1154 43fff238 bellard
};
1155 43fff238 bellard
1156 a8c33204 pbrook
struct sigframe_v2
1157 a8c33204 pbrook
{
1158 a8c33204 pbrook
    struct target_ucontext_v2 uc;
1159 a8c33204 pbrook
    abi_ulong retcode;
1160 a8c33204 pbrook
};
1161 a8c33204 pbrook
1162 a745ec6d pbrook
struct rt_sigframe_v1
1163 43fff238 bellard
{
1164 f8b0aa25 bellard
    abi_ulong pinfo;
1165 f8b0aa25 bellard
    abi_ulong puc;
1166 43fff238 bellard
    struct target_siginfo info;
1167 a745ec6d pbrook
    struct target_ucontext_v1 uc;
1168 a745ec6d pbrook
    abi_ulong retcode;
1169 a745ec6d pbrook
};
1170 a745ec6d pbrook
1171 a745ec6d pbrook
struct rt_sigframe_v2
1172 a745ec6d pbrook
{
1173 a745ec6d pbrook
    struct target_siginfo info;
1174 a745ec6d pbrook
    struct target_ucontext_v2 uc;
1175 992f48a0 blueswir1
    abi_ulong retcode;
1176 43fff238 bellard
};
1177 43fff238 bellard
1178 43fff238 bellard
#define TARGET_CONFIG_CPU_32 1
1179 43fff238 bellard
1180 43fff238 bellard
/*
1181 43fff238 bellard
 * For ARM syscalls, we encode the syscall number into the instruction.
1182 43fff238 bellard
 */
1183 43fff238 bellard
#define SWI_SYS_SIGRETURN        (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1184 43fff238 bellard
#define SWI_SYS_RT_SIGRETURN        (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1185 43fff238 bellard
1186 43fff238 bellard
/*
1187 43fff238 bellard
 * For Thumb syscalls, we pass the syscall number via r7.  We therefore
1188 43fff238 bellard
 * need two 16-bit instructions.
1189 43fff238 bellard
 */
1190 43fff238 bellard
#define SWI_THUMB_SIGRETURN        (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1191 43fff238 bellard
#define SWI_THUMB_RT_SIGRETURN        (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1192 43fff238 bellard
1193 992f48a0 blueswir1
static const abi_ulong retcodes[4] = {
1194 43fff238 bellard
        SWI_SYS_SIGRETURN,        SWI_THUMB_SIGRETURN,
1195 43fff238 bellard
        SWI_SYS_RT_SIGRETURN,        SWI_THUMB_RT_SIGRETURN
1196 43fff238 bellard
};
1197 43fff238 bellard
1198 43fff238 bellard
1199 43fff238 bellard
#define __get_user_error(x,p,e) __get_user(x, p)
1200 43fff238 bellard
1201 43fff238 bellard
static inline int valid_user_regs(CPUState *regs)
1202 43fff238 bellard
{
1203 43fff238 bellard
    return 1;
1204 43fff238 bellard
}
1205 43fff238 bellard
1206 a8c33204 pbrook
static void
1207 43fff238 bellard
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1208 f8b0aa25 bellard
                 CPUState *env, abi_ulong mask)
1209 43fff238 bellard
{
1210 a8c33204 pbrook
        __put_user(env->regs[0], &sc->arm_r0);
1211 a8c33204 pbrook
        __put_user(env->regs[1], &sc->arm_r1);
1212 a8c33204 pbrook
        __put_user(env->regs[2], &sc->arm_r2);
1213 a8c33204 pbrook
        __put_user(env->regs[3], &sc->arm_r3);
1214 a8c33204 pbrook
        __put_user(env->regs[4], &sc->arm_r4);
1215 a8c33204 pbrook
        __put_user(env->regs[5], &sc->arm_r5);
1216 a8c33204 pbrook
        __put_user(env->regs[6], &sc->arm_r6);
1217 a8c33204 pbrook
        __put_user(env->regs[7], &sc->arm_r7);
1218 a8c33204 pbrook
        __put_user(env->regs[8], &sc->arm_r8);
1219 a8c33204 pbrook
        __put_user(env->regs[9], &sc->arm_r9);
1220 a8c33204 pbrook
        __put_user(env->regs[10], &sc->arm_r10);
1221 a8c33204 pbrook
        __put_user(env->regs[11], &sc->arm_fp);
1222 a8c33204 pbrook
        __put_user(env->regs[12], &sc->arm_ip);
1223 a8c33204 pbrook
        __put_user(env->regs[13], &sc->arm_sp);
1224 a8c33204 pbrook
        __put_user(env->regs[14], &sc->arm_lr);
1225 a8c33204 pbrook
        __put_user(env->regs[15], &sc->arm_pc);
1226 43fff238 bellard
#ifdef TARGET_CONFIG_CPU_32
1227 a8c33204 pbrook
        __put_user(cpsr_read(env), &sc->arm_cpsr);
1228 43fff238 bellard
#endif
1229 43fff238 bellard
1230 a8c33204 pbrook
        __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1231 a8c33204 pbrook
        __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1232 a8c33204 pbrook
        __put_user(/* current->thread.address */ 0, &sc->fault_address);
1233 a8c33204 pbrook
        __put_user(mask, &sc->oldmask);
1234 43fff238 bellard
}
1235 43fff238 bellard
1236 579a97f7 bellard
static inline abi_ulong
1237 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
1238 43fff238 bellard
{
1239 43fff238 bellard
        unsigned long sp = regs->regs[13];
1240 43fff238 bellard
1241 43fff238 bellard
        /*
1242 43fff238 bellard
         * This is the X/Open sanctioned signal stack switching.
1243 43fff238 bellard
         */
1244 624f7979 pbrook
        if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
1245 a04e134a ths
            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1246 43fff238 bellard
        /*
1247 43fff238 bellard
         * ATPCS B01 mandates 8-byte alignment
1248 43fff238 bellard
         */
1249 579a97f7 bellard
        return (sp - framesize) & ~7;
1250 43fff238 bellard
}
1251 43fff238 bellard
1252 43fff238 bellard
static int
1253 624f7979 pbrook
setup_return(CPUState *env, struct target_sigaction *ka,
1254 f8b0aa25 bellard
             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
1255 43fff238 bellard
{
1256 624f7979 pbrook
        abi_ulong handler = ka->_sa_handler;
1257 992f48a0 blueswir1
        abi_ulong retcode;
1258 75b680e5 pbrook
        int thumb = handler & 1;
1259 964413d9 Peter Maydell
        uint32_t cpsr = cpsr_read(env);
1260 964413d9 Peter Maydell
1261 964413d9 Peter Maydell
        cpsr &= ~CPSR_IT;
1262 964413d9 Peter Maydell
        if (thumb) {
1263 964413d9 Peter Maydell
                cpsr |= CPSR_T;
1264 964413d9 Peter Maydell
        } else {
1265 964413d9 Peter Maydell
                cpsr &= ~CPSR_T;
1266 964413d9 Peter Maydell
        }
1267 43fff238 bellard
1268 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
1269 624f7979 pbrook
                retcode = ka->sa_restorer;
1270 43fff238 bellard
        } else {
1271 43fff238 bellard
                unsigned int idx = thumb;
1272 43fff238 bellard
1273 624f7979 pbrook
                if (ka->sa_flags & TARGET_SA_SIGINFO)
1274 43fff238 bellard
                        idx += 2;
1275 43fff238 bellard
1276 43fff238 bellard
                if (__put_user(retcodes[idx], rc))
1277 43fff238 bellard
                        return 1;
1278 43fff238 bellard
#if 0
1279 992f48a0 blueswir1
                flush_icache_range((abi_ulong)rc,
1280 992f48a0 blueswir1
                                   (abi_ulong)(rc + 1));
1281 43fff238 bellard
#endif
1282 f8b0aa25 bellard
                retcode = rc_addr + thumb;
1283 43fff238 bellard
        }
1284 43fff238 bellard
1285 43fff238 bellard
        env->regs[0] = usig;
1286 f8b0aa25 bellard
        env->regs[13] = frame_addr;
1287 43fff238 bellard
        env->regs[14] = retcode;
1288 43fff238 bellard
        env->regs[15] = handler & (thumb ? ~1 : ~3);
1289 964413d9 Peter Maydell
        cpsr_write(env, cpsr, 0xffffffff);
1290 43fff238 bellard
1291 43fff238 bellard
        return 0;
1292 43fff238 bellard
}
1293 43fff238 bellard
1294 0d871bdb Peter Maydell
static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
1295 0d871bdb Peter Maydell
{
1296 0d871bdb Peter Maydell
    int i;
1297 0d871bdb Peter Maydell
    struct target_vfp_sigframe *vfpframe;
1298 0d871bdb Peter Maydell
    vfpframe = (struct target_vfp_sigframe *)regspace;
1299 0d871bdb Peter Maydell
    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1300 0d871bdb Peter Maydell
    __put_user(sizeof(*vfpframe), &vfpframe->size);
1301 0d871bdb Peter Maydell
    for (i = 0; i < 32; i++) {
1302 005e1a0a Peter Maydell
        __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
1303 0d871bdb Peter Maydell
    }
1304 0d871bdb Peter Maydell
    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1305 0d871bdb Peter Maydell
    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1306 0d871bdb Peter Maydell
    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1307 0d871bdb Peter Maydell
    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1308 0d871bdb Peter Maydell
    return (abi_ulong*)(vfpframe+1);
1309 0d871bdb Peter Maydell
}
1310 0d871bdb Peter Maydell
1311 08e11256 Peter Maydell
static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
1312 08e11256 Peter Maydell
{
1313 08e11256 Peter Maydell
    int i;
1314 08e11256 Peter Maydell
    struct target_iwmmxt_sigframe *iwmmxtframe;
1315 08e11256 Peter Maydell
    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1316 08e11256 Peter Maydell
    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1317 08e11256 Peter Maydell
    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1318 08e11256 Peter Maydell
    for (i = 0; i < 16; i++) {
1319 08e11256 Peter Maydell
        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1320 08e11256 Peter Maydell
    }
1321 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1322 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1323 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1324 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1325 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1326 08e11256 Peter Maydell
    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1327 08e11256 Peter Maydell
    return (abi_ulong*)(iwmmxtframe+1);
1328 08e11256 Peter Maydell
}
1329 08e11256 Peter Maydell
1330 a8c33204 pbrook
static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
1331 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1332 a8c33204 pbrook
{
1333 a8c33204 pbrook
    struct target_sigaltstack stack;
1334 a8c33204 pbrook
    int i;
1335 0d871bdb Peter Maydell
    abi_ulong *regspace;
1336 a8c33204 pbrook
1337 a8c33204 pbrook
    /* Clear all the bits of the ucontext we don't use.  */
1338 a8c33204 pbrook
    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1339 a8c33204 pbrook
1340 a8c33204 pbrook
    memset(&stack, 0, sizeof(stack));
1341 a8c33204 pbrook
    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1342 a8c33204 pbrook
    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1343 a8c33204 pbrook
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1344 a8c33204 pbrook
    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1345 a8c33204 pbrook
1346 a8c33204 pbrook
    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
1347 0d871bdb Peter Maydell
    /* Save coprocessor signal frame.  */
1348 0d871bdb Peter Maydell
    regspace = uc->tuc_regspace;
1349 0d871bdb Peter Maydell
    if (arm_feature(env, ARM_FEATURE_VFP)) {
1350 0d871bdb Peter Maydell
        regspace = setup_sigframe_v2_vfp(regspace, env);
1351 0d871bdb Peter Maydell
    }
1352 08e11256 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1353 08e11256 Peter Maydell
        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1354 08e11256 Peter Maydell
    }
1355 08e11256 Peter Maydell
1356 0d871bdb Peter Maydell
    /* Write terminating magic word */
1357 0d871bdb Peter Maydell
    __put_user(0, regspace);
1358 0d871bdb Peter Maydell
1359 a8c33204 pbrook
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1360 a8c33204 pbrook
        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1361 a8c33204 pbrook
    }
1362 a8c33204 pbrook
}
1363 a8c33204 pbrook
1364 579a97f7 bellard
/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
1365 624f7979 pbrook
static void setup_frame_v1(int usig, struct target_sigaction *ka,
1366 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
1367 43fff238 bellard
{
1368 a8c33204 pbrook
        struct sigframe_v1 *frame;
1369 579a97f7 bellard
        abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1370 a8c33204 pbrook
        int i;
1371 43fff238 bellard
1372 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1373 579a97f7 bellard
                return;
1374 579a97f7 bellard
1375 a8c33204 pbrook
        setup_sigcontext(&frame->sc, regs, set->sig[0]);
1376 43fff238 bellard
1377 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1378 9231944d bellard
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
1379 579a97f7 bellard
                goto end;
1380 43fff238 bellard
        }
1381 43fff238 bellard
1382 a8c33204 pbrook
        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1383 a8c33204 pbrook
                     frame_addr + offsetof(struct sigframe_v1, retcode));
1384 579a97f7 bellard
1385 579a97f7 bellard
end:
1386 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
1387 a8c33204 pbrook
}
1388 a8c33204 pbrook
1389 624f7979 pbrook
static void setup_frame_v2(int usig, struct target_sigaction *ka,
1390 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
1391 a8c33204 pbrook
{
1392 a8c33204 pbrook
        struct sigframe_v2 *frame;
1393 a8c33204 pbrook
        abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1394 a8c33204 pbrook
1395 a8c33204 pbrook
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1396 a8c33204 pbrook
                return;
1397 a8c33204 pbrook
1398 a8c33204 pbrook
        setup_sigframe_v2(&frame->uc, set, regs);
1399 a8c33204 pbrook
1400 a8c33204 pbrook
        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1401 a8c33204 pbrook
                     frame_addr + offsetof(struct sigframe_v2, retcode));
1402 a8c33204 pbrook
1403 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 1);
1404 a8c33204 pbrook
}
1405 a8c33204 pbrook
1406 624f7979 pbrook
static void setup_frame(int usig, struct target_sigaction *ka,
1407 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
1408 a8c33204 pbrook
{
1409 a8c33204 pbrook
    if (get_osversion() >= 0x020612) {
1410 a8c33204 pbrook
        setup_frame_v2(usig, ka, set, regs);
1411 a8c33204 pbrook
    } else {
1412 a8c33204 pbrook
        setup_frame_v1(usig, ka, set, regs);
1413 a8c33204 pbrook
    }
1414 43fff238 bellard
}
1415 43fff238 bellard
1416 579a97f7 bellard
/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
1417 624f7979 pbrook
static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
1418 c227f099 Anthony Liguori
                              target_siginfo_t *info,
1419 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1420 43fff238 bellard
{
1421 a745ec6d pbrook
        struct rt_sigframe_v1 *frame;
1422 579a97f7 bellard
        abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1423 a04e134a ths
        struct target_sigaltstack stack;
1424 a8c33204 pbrook
        int i;
1425 f8b0aa25 bellard
        abi_ulong info_addr, uc_addr;
1426 43fff238 bellard
1427 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1428 edf779ff bellard
            return /* 1 */;
1429 edf779ff bellard
1430 a745ec6d pbrook
        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1431 a8c33204 pbrook
        __put_user(info_addr, &frame->pinfo);
1432 a745ec6d pbrook
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1433 a8c33204 pbrook
        __put_user(uc_addr, &frame->puc);
1434 a8c33204 pbrook
        copy_siginfo_to_user(&frame->info, info);
1435 43fff238 bellard
1436 43fff238 bellard
        /* Clear all the bits of the ucontext we don't use.  */
1437 a745ec6d pbrook
        memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
1438 43fff238 bellard
1439 a04e134a ths
        memset(&stack, 0, sizeof(stack));
1440 a04e134a ths
        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1441 a04e134a ths
        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1442 a04e134a ths
        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1443 775b58d8 bellard
        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
1444 a04e134a ths
1445 a8c33204 pbrook
        setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1446 9231944d bellard
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1447 b8076a74 bellard
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
1448 579a97f7 bellard
                goto end;
1449 9231944d bellard
        }
1450 43fff238 bellard
1451 a8c33204 pbrook
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
1452 a8c33204 pbrook
                     frame_addr + offsetof(struct rt_sigframe_v1, retcode));
1453 a745ec6d pbrook
1454 a8c33204 pbrook
        env->regs[1] = info_addr;
1455 a8c33204 pbrook
        env->regs[2] = uc_addr;
1456 a745ec6d pbrook
1457 a745ec6d pbrook
end:
1458 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 1);
1459 a745ec6d pbrook
}
1460 a745ec6d pbrook
1461 624f7979 pbrook
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
1462 c227f099 Anthony Liguori
                              target_siginfo_t *info,
1463 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1464 a745ec6d pbrook
{
1465 a745ec6d pbrook
        struct rt_sigframe_v2 *frame;
1466 a745ec6d pbrook
        abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1467 a745ec6d pbrook
        abi_ulong info_addr, uc_addr;
1468 a745ec6d pbrook
1469 a745ec6d pbrook
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1470 a745ec6d pbrook
            return /* 1 */;
1471 a745ec6d pbrook
1472 a745ec6d pbrook
        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1473 a745ec6d pbrook
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1474 a8c33204 pbrook
        copy_siginfo_to_user(&frame->info, info);
1475 a745ec6d pbrook
1476 a8c33204 pbrook
        setup_sigframe_v2(&frame->uc, set, env);
1477 a745ec6d pbrook
1478 a8c33204 pbrook
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
1479 a8c33204 pbrook
                     frame_addr + offsetof(struct rt_sigframe_v2, retcode));
1480 a745ec6d pbrook
1481 a8c33204 pbrook
        env->regs[1] = info_addr;
1482 a8c33204 pbrook
        env->regs[2] = uc_addr;
1483 43fff238 bellard
1484 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
1485 43fff238 bellard
}
1486 43fff238 bellard
1487 624f7979 pbrook
static void setup_rt_frame(int usig, struct target_sigaction *ka,
1488 c227f099 Anthony Liguori
                           target_siginfo_t *info,
1489 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
1490 a745ec6d pbrook
{
1491 a745ec6d pbrook
    if (get_osversion() >= 0x020612) {
1492 a745ec6d pbrook
        setup_rt_frame_v2(usig, ka, info, set, env);
1493 a745ec6d pbrook
    } else {
1494 a745ec6d pbrook
        setup_rt_frame_v1(usig, ka, info, set, env);
1495 a745ec6d pbrook
    }
1496 a745ec6d pbrook
}
1497 a745ec6d pbrook
1498 43fff238 bellard
static int
1499 43fff238 bellard
restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1500 43fff238 bellard
{
1501 43fff238 bellard
        int err = 0;
1502 b5ff1b31 bellard
        uint32_t cpsr;
1503 43fff238 bellard
1504 43fff238 bellard
        __get_user_error(env->regs[0], &sc->arm_r0, err);
1505 43fff238 bellard
        __get_user_error(env->regs[1], &sc->arm_r1, err);
1506 43fff238 bellard
        __get_user_error(env->regs[2], &sc->arm_r2, err);
1507 43fff238 bellard
        __get_user_error(env->regs[3], &sc->arm_r3, err);
1508 43fff238 bellard
        __get_user_error(env->regs[4], &sc->arm_r4, err);
1509 43fff238 bellard
        __get_user_error(env->regs[5], &sc->arm_r5, err);
1510 43fff238 bellard
        __get_user_error(env->regs[6], &sc->arm_r6, err);
1511 43fff238 bellard
        __get_user_error(env->regs[7], &sc->arm_r7, err);
1512 43fff238 bellard
        __get_user_error(env->regs[8], &sc->arm_r8, err);
1513 43fff238 bellard
        __get_user_error(env->regs[9], &sc->arm_r9, err);
1514 43fff238 bellard
        __get_user_error(env->regs[10], &sc->arm_r10, err);
1515 43fff238 bellard
        __get_user_error(env->regs[11], &sc->arm_fp, err);
1516 43fff238 bellard
        __get_user_error(env->regs[12], &sc->arm_ip, err);
1517 43fff238 bellard
        __get_user_error(env->regs[13], &sc->arm_sp, err);
1518 43fff238 bellard
        __get_user_error(env->regs[14], &sc->arm_lr, err);
1519 43fff238 bellard
        __get_user_error(env->regs[15], &sc->arm_pc, err);
1520 43fff238 bellard
#ifdef TARGET_CONFIG_CPU_32
1521 b5ff1b31 bellard
        __get_user_error(cpsr, &sc->arm_cpsr, err);
1522 75b680e5 pbrook
        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
1523 43fff238 bellard
#endif
1524 43fff238 bellard
1525 43fff238 bellard
        err |= !valid_user_regs(env);
1526 43fff238 bellard
1527 43fff238 bellard
        return err;
1528 43fff238 bellard
}
1529 43fff238 bellard
1530 dc7eea67 aurel32
static long do_sigreturn_v1(CPUState *env)
1531 43fff238 bellard
{
1532 f8b0aa25 bellard
        abi_ulong frame_addr;
1533 a8c33204 pbrook
        struct sigframe_v1 *frame;
1534 c227f099 Anthony Liguori
        target_sigset_t set;
1535 43fff238 bellard
        sigset_t host_set;
1536 9231944d bellard
        int i;
1537 43fff238 bellard
1538 43fff238 bellard
        /*
1539 43fff238 bellard
         * Since we stacked the signal on a 64-bit boundary,
1540 43fff238 bellard
         * then 'sp' should be word aligned here.  If it's
1541 43fff238 bellard
         * not, then the user is trying to mess with us.
1542 43fff238 bellard
         */
1543 43fff238 bellard
        if (env->regs[13] & 7)
1544 43fff238 bellard
                goto badframe;
1545 43fff238 bellard
1546 f8b0aa25 bellard
        frame_addr = env->regs[13];
1547 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1548 f8b0aa25 bellard
                goto badframe;
1549 43fff238 bellard
1550 9231944d bellard
        if (__get_user(set.sig[0], &frame->sc.oldmask))
1551 9231944d bellard
            goto badframe;
1552 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1553 9231944d bellard
            if (__get_user(set.sig[i], &frame->extramask[i - 1]))
1554 9231944d bellard
                goto badframe;
1555 9231944d bellard
        }
1556 43fff238 bellard
1557 9231944d bellard
        target_to_host_sigset_internal(&host_set, &set);
1558 43fff238 bellard
        sigprocmask(SIG_SETMASK, &host_set, NULL);
1559 43fff238 bellard
1560 43fff238 bellard
        if (restore_sigcontext(env, &frame->sc))
1561 43fff238 bellard
                goto badframe;
1562 43fff238 bellard
1563 43fff238 bellard
#if 0
1564 43fff238 bellard
        /* Send SIGTRAP if we're single-stepping */
1565 43fff238 bellard
        if (ptrace_cancel_bpt(current))
1566 43fff238 bellard
                send_sig(SIGTRAP, current, 1);
1567 43fff238 bellard
#endif
1568 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1569 f8b0aa25 bellard
        return env->regs[0];
1570 43fff238 bellard
1571 43fff238 bellard
badframe:
1572 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1573 66393fb9 Riku Voipio
        force_sig(TARGET_SIGSEGV /* , current */);
1574 43fff238 bellard
        return 0;
1575 43fff238 bellard
}
1576 43fff238 bellard
1577 5f9099d9 Peter Maydell
static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
1578 5f9099d9 Peter Maydell
{
1579 5f9099d9 Peter Maydell
    int i;
1580 5f9099d9 Peter Maydell
    abi_ulong magic, sz;
1581 5f9099d9 Peter Maydell
    uint32_t fpscr, fpexc;
1582 5f9099d9 Peter Maydell
    struct target_vfp_sigframe *vfpframe;
1583 5f9099d9 Peter Maydell
    vfpframe = (struct target_vfp_sigframe *)regspace;
1584 5f9099d9 Peter Maydell
1585 5f9099d9 Peter Maydell
    __get_user(magic, &vfpframe->magic);
1586 5f9099d9 Peter Maydell
    __get_user(sz, &vfpframe->size);
1587 5f9099d9 Peter Maydell
    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1588 5f9099d9 Peter Maydell
        return 0;
1589 5f9099d9 Peter Maydell
    }
1590 5f9099d9 Peter Maydell
    for (i = 0; i < 32; i++) {
1591 005e1a0a Peter Maydell
        __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
1592 5f9099d9 Peter Maydell
    }
1593 5f9099d9 Peter Maydell
    __get_user(fpscr, &vfpframe->ufp.fpscr);
1594 5f9099d9 Peter Maydell
    vfp_set_fpscr(env, fpscr);
1595 5f9099d9 Peter Maydell
    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1596 5f9099d9 Peter Maydell
    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1597 5f9099d9 Peter Maydell
     * and the exception flag is cleared
1598 5f9099d9 Peter Maydell
     */
1599 5f9099d9 Peter Maydell
    fpexc |= (1 << 30);
1600 5f9099d9 Peter Maydell
    fpexc &= ~((1 << 31) | (1 << 28));
1601 5f9099d9 Peter Maydell
    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1602 5f9099d9 Peter Maydell
    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1603 5f9099d9 Peter Maydell
    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1604 5f9099d9 Peter Maydell
    return (abi_ulong*)(vfpframe + 1);
1605 5f9099d9 Peter Maydell
}
1606 5f9099d9 Peter Maydell
1607 a59d69da Peter Maydell
static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
1608 a59d69da Peter Maydell
{
1609 a59d69da Peter Maydell
    int i;
1610 a59d69da Peter Maydell
    abi_ulong magic, sz;
1611 a59d69da Peter Maydell
    struct target_iwmmxt_sigframe *iwmmxtframe;
1612 a59d69da Peter Maydell
    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1613 a59d69da Peter Maydell
1614 a59d69da Peter Maydell
    __get_user(magic, &iwmmxtframe->magic);
1615 a59d69da Peter Maydell
    __get_user(sz, &iwmmxtframe->size);
1616 a59d69da Peter Maydell
    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1617 a59d69da Peter Maydell
        return 0;
1618 a59d69da Peter Maydell
    }
1619 a59d69da Peter Maydell
    for (i = 0; i < 16; i++) {
1620 a59d69da Peter Maydell
        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1621 a59d69da Peter Maydell
    }
1622 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1623 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1624 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1625 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1626 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1627 a59d69da Peter Maydell
    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1628 a59d69da Peter Maydell
    return (abi_ulong*)(iwmmxtframe + 1);
1629 a59d69da Peter Maydell
}
1630 a59d69da Peter Maydell
1631 a8c33204 pbrook
static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
1632 a8c33204 pbrook
                                 struct target_ucontext_v2 *uc)
1633 a8c33204 pbrook
{
1634 a8c33204 pbrook
    sigset_t host_set;
1635 5f9099d9 Peter Maydell
    abi_ulong *regspace;
1636 a8c33204 pbrook
1637 a8c33204 pbrook
    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
1638 a8c33204 pbrook
    sigprocmask(SIG_SETMASK, &host_set, NULL);
1639 a8c33204 pbrook
1640 a8c33204 pbrook
    if (restore_sigcontext(env, &uc->tuc_mcontext))
1641 a8c33204 pbrook
        return 1;
1642 a8c33204 pbrook
1643 5f9099d9 Peter Maydell
    /* Restore coprocessor signal frame */
1644 5f9099d9 Peter Maydell
    regspace = uc->tuc_regspace;
1645 5f9099d9 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_VFP)) {
1646 5f9099d9 Peter Maydell
        regspace = restore_sigframe_v2_vfp(env, regspace);
1647 5f9099d9 Peter Maydell
        if (!regspace) {
1648 5f9099d9 Peter Maydell
            return 1;
1649 5f9099d9 Peter Maydell
        }
1650 5f9099d9 Peter Maydell
    }
1651 a59d69da Peter Maydell
    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1652 a59d69da Peter Maydell
        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1653 a59d69da Peter Maydell
        if (!regspace) {
1654 a59d69da Peter Maydell
            return 1;
1655 a59d69da Peter Maydell
        }
1656 a59d69da Peter Maydell
    }
1657 5f9099d9 Peter Maydell
1658 a8c33204 pbrook
    if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1659 a8c33204 pbrook
        return 1;
1660 a8c33204 pbrook
1661 a8c33204 pbrook
#if 0
1662 a8c33204 pbrook
    /* Send SIGTRAP if we're single-stepping */
1663 a8c33204 pbrook
    if (ptrace_cancel_bpt(current))
1664 a8c33204 pbrook
            send_sig(SIGTRAP, current, 1);
1665 a8c33204 pbrook
#endif
1666 a8c33204 pbrook
1667 a8c33204 pbrook
    return 0;
1668 a8c33204 pbrook
}
1669 a8c33204 pbrook
1670 dc7eea67 aurel32
static long do_sigreturn_v2(CPUState *env)
1671 a8c33204 pbrook
{
1672 a8c33204 pbrook
        abi_ulong frame_addr;
1673 a8c33204 pbrook
        struct sigframe_v2 *frame;
1674 a8c33204 pbrook
1675 a8c33204 pbrook
        /*
1676 a8c33204 pbrook
         * Since we stacked the signal on a 64-bit boundary,
1677 a8c33204 pbrook
         * then 'sp' should be word aligned here.  If it's
1678 a8c33204 pbrook
         * not, then the user is trying to mess with us.
1679 a8c33204 pbrook
         */
1680 a8c33204 pbrook
        if (env->regs[13] & 7)
1681 a8c33204 pbrook
                goto badframe;
1682 a8c33204 pbrook
1683 a8c33204 pbrook
        frame_addr = env->regs[13];
1684 a8c33204 pbrook
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1685 a8c33204 pbrook
                goto badframe;
1686 a8c33204 pbrook
1687 a8c33204 pbrook
        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1688 a8c33204 pbrook
                goto badframe;
1689 a8c33204 pbrook
1690 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 0);
1691 a8c33204 pbrook
        return env->regs[0];
1692 a8c33204 pbrook
1693 a8c33204 pbrook
badframe:
1694 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 0);
1695 66393fb9 Riku Voipio
        force_sig(TARGET_SIGSEGV /* , current */);
1696 a8c33204 pbrook
        return 0;
1697 a8c33204 pbrook
}
1698 a8c33204 pbrook
1699 a8c33204 pbrook
long do_sigreturn(CPUState *env)
1700 a8c33204 pbrook
{
1701 a8c33204 pbrook
    if (get_osversion() >= 0x020612) {
1702 a8c33204 pbrook
        return do_sigreturn_v2(env);
1703 a8c33204 pbrook
    } else {
1704 a8c33204 pbrook
        return do_sigreturn_v1(env);
1705 a8c33204 pbrook
    }
1706 a8c33204 pbrook
}
1707 a8c33204 pbrook
1708 dc7eea67 aurel32
static long do_rt_sigreturn_v1(CPUState *env)
1709 43fff238 bellard
{
1710 f8b0aa25 bellard
        abi_ulong frame_addr;
1711 a745ec6d pbrook
        struct rt_sigframe_v1 *frame;
1712 a745ec6d pbrook
        sigset_t host_set;
1713 a745ec6d pbrook
1714 a745ec6d pbrook
        /*
1715 a745ec6d pbrook
         * Since we stacked the signal on a 64-bit boundary,
1716 a745ec6d pbrook
         * then 'sp' should be word aligned here.  If it's
1717 a745ec6d pbrook
         * not, then the user is trying to mess with us.
1718 a745ec6d pbrook
         */
1719 a745ec6d pbrook
        if (env->regs[13] & 7)
1720 a745ec6d pbrook
                goto badframe;
1721 a745ec6d pbrook
1722 a745ec6d pbrook
        frame_addr = env->regs[13];
1723 a745ec6d pbrook
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1724 a745ec6d pbrook
                goto badframe;
1725 a745ec6d pbrook
1726 a745ec6d pbrook
        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1727 a745ec6d pbrook
        sigprocmask(SIG_SETMASK, &host_set, NULL);
1728 a745ec6d pbrook
1729 a745ec6d pbrook
        if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1730 a745ec6d pbrook
                goto badframe;
1731 a745ec6d pbrook
1732 a745ec6d pbrook
        if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1733 a745ec6d pbrook
                goto badframe;
1734 a745ec6d pbrook
1735 a745ec6d pbrook
#if 0
1736 a745ec6d pbrook
        /* Send SIGTRAP if we're single-stepping */
1737 a745ec6d pbrook
        if (ptrace_cancel_bpt(current))
1738 a745ec6d pbrook
                send_sig(SIGTRAP, current, 1);
1739 a745ec6d pbrook
#endif
1740 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 0);
1741 a745ec6d pbrook
        return env->regs[0];
1742 a745ec6d pbrook
1743 a745ec6d pbrook
badframe:
1744 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 0);
1745 66393fb9 Riku Voipio
        force_sig(TARGET_SIGSEGV /* , current */);
1746 a745ec6d pbrook
        return 0;
1747 a745ec6d pbrook
}
1748 a745ec6d pbrook
1749 dc7eea67 aurel32
static long do_rt_sigreturn_v2(CPUState *env)
1750 a745ec6d pbrook
{
1751 a745ec6d pbrook
        abi_ulong frame_addr;
1752 a745ec6d pbrook
        struct rt_sigframe_v2 *frame;
1753 43fff238 bellard
1754 43fff238 bellard
        /*
1755 43fff238 bellard
         * Since we stacked the signal on a 64-bit boundary,
1756 43fff238 bellard
         * then 'sp' should be word aligned here.  If it's
1757 43fff238 bellard
         * not, then the user is trying to mess with us.
1758 43fff238 bellard
         */
1759 43fff238 bellard
        if (env->regs[13] & 7)
1760 43fff238 bellard
                goto badframe;
1761 43fff238 bellard
1762 f8b0aa25 bellard
        frame_addr = env->regs[13];
1763 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1764 f8b0aa25 bellard
                goto badframe;
1765 43fff238 bellard
1766 a8c33204 pbrook
        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1767 a8c33204 pbrook
                goto badframe;
1768 a04e134a ths
1769 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1770 43fff238 bellard
        return env->regs[0];
1771 43fff238 bellard
1772 43fff238 bellard
badframe:
1773 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1774 66393fb9 Riku Voipio
        force_sig(TARGET_SIGSEGV /* , current */);
1775 43fff238 bellard
        return 0;
1776 43fff238 bellard
}
1777 43fff238 bellard
1778 a745ec6d pbrook
long do_rt_sigreturn(CPUState *env)
1779 a745ec6d pbrook
{
1780 a745ec6d pbrook
    if (get_osversion() >= 0x020612) {
1781 a745ec6d pbrook
        return do_rt_sigreturn_v2(env);
1782 a745ec6d pbrook
    } else {
1783 a745ec6d pbrook
        return do_rt_sigreturn_v1(env);
1784 a745ec6d pbrook
    }
1785 a745ec6d pbrook
}
1786 a745ec6d pbrook
1787 6d5e216d bellard
#elif defined(TARGET_SPARC)
1788 80a9d035 bellard
1789 6d5e216d bellard
#define __SUNOS_MAXWIN   31
1790 6d5e216d bellard
1791 6d5e216d bellard
/* This is what SunOS does, so shall I. */
1792 6d5e216d bellard
struct target_sigcontext {
1793 992f48a0 blueswir1
        abi_ulong sigc_onstack;      /* state to restore */
1794 6d5e216d bellard
1795 992f48a0 blueswir1
        abi_ulong sigc_mask;         /* sigmask to restore */
1796 992f48a0 blueswir1
        abi_ulong sigc_sp;           /* stack pointer */
1797 992f48a0 blueswir1
        abi_ulong sigc_pc;           /* program counter */
1798 992f48a0 blueswir1
        abi_ulong sigc_npc;          /* next program counter */
1799 992f48a0 blueswir1
        abi_ulong sigc_psr;          /* for condition codes etc */
1800 992f48a0 blueswir1
        abi_ulong sigc_g1;           /* User uses these two registers */
1801 992f48a0 blueswir1
        abi_ulong sigc_o0;           /* within the trampoline code. */
1802 6d5e216d bellard
1803 6d5e216d bellard
        /* Now comes information regarding the users window set
1804 6d5e216d bellard
         * at the time of the signal.
1805 6d5e216d bellard
         */
1806 992f48a0 blueswir1
        abi_ulong sigc_oswins;       /* outstanding windows */
1807 6d5e216d bellard
1808 6d5e216d bellard
        /* stack ptrs for each regwin buf */
1809 6d5e216d bellard
        char *sigc_spbuf[__SUNOS_MAXWIN];
1810 6d5e216d bellard
1811 6d5e216d bellard
        /* Windows to restore after signal */
1812 6d5e216d bellard
        struct {
1813 992f48a0 blueswir1
                abi_ulong locals[8];
1814 992f48a0 blueswir1
                abi_ulong ins[8];
1815 6d5e216d bellard
        } sigc_wbuf[__SUNOS_MAXWIN];
1816 6d5e216d bellard
};
1817 6d5e216d bellard
/* A Sparc stack frame */
1818 6d5e216d bellard
struct sparc_stackf {
1819 992f48a0 blueswir1
        abi_ulong locals[8];
1820 e321c34a Peter Maydell
        abi_ulong ins[8];
1821 e321c34a Peter Maydell
        /* It's simpler to treat fp and callers_pc as elements of ins[]
1822 e321c34a Peter Maydell
         * since we never need to access them ourselves.
1823 e321c34a Peter Maydell
         */
1824 6d5e216d bellard
        char *structptr;
1825 992f48a0 blueswir1
        abi_ulong xargs[6];
1826 992f48a0 blueswir1
        abi_ulong xxargs[1];
1827 6d5e216d bellard
};
1828 6d5e216d bellard
1829 6d5e216d bellard
typedef struct {
1830 6d5e216d bellard
        struct {
1831 992f48a0 blueswir1
                abi_ulong psr;
1832 992f48a0 blueswir1
                abi_ulong pc;
1833 992f48a0 blueswir1
                abi_ulong npc;
1834 992f48a0 blueswir1
                abi_ulong y;
1835 992f48a0 blueswir1
                abi_ulong u_regs[16]; /* globals and ins */
1836 6d5e216d bellard
        }               si_regs;
1837 6d5e216d bellard
        int             si_mask;
1838 6d5e216d bellard
} __siginfo_t;
1839 6d5e216d bellard
1840 6d5e216d bellard
typedef struct {
1841 6d5e216d bellard
        unsigned   long si_float_regs [32];
1842 6d5e216d bellard
        unsigned   long si_fsr;
1843 6d5e216d bellard
        unsigned   long si_fpqdepth;
1844 6d5e216d bellard
        struct {
1845 6d5e216d bellard
                unsigned long *insn_addr;
1846 6d5e216d bellard
                unsigned long insn;
1847 6d5e216d bellard
        } si_fpqueue [16];
1848 c227f099 Anthony Liguori
} qemu_siginfo_fpu_t;
1849 6d5e216d bellard
1850 6d5e216d bellard
1851 6d5e216d bellard
struct target_signal_frame {
1852 6d5e216d bellard
        struct sparc_stackf        ss;
1853 6d5e216d bellard
        __siginfo_t                info;
1854 f8b0aa25 bellard
        abi_ulong               fpu_save;
1855 992f48a0 blueswir1
        abi_ulong                insns[2] __attribute__ ((aligned (8)));
1856 992f48a0 blueswir1
        abi_ulong                extramask[TARGET_NSIG_WORDS - 1];
1857 992f48a0 blueswir1
        abi_ulong                extra_size; /* Should be 0 */
1858 c227f099 Anthony Liguori
        qemu_siginfo_fpu_t        fpu_state;
1859 6d5e216d bellard
};
1860 6d5e216d bellard
struct target_rt_signal_frame {
1861 6d5e216d bellard
        struct sparc_stackf        ss;
1862 6d5e216d bellard
        siginfo_t                info;
1863 992f48a0 blueswir1
        abi_ulong                regs[20];
1864 6d5e216d bellard
        sigset_t                mask;
1865 f8b0aa25 bellard
        abi_ulong               fpu_save;
1866 6d5e216d bellard
        unsigned int                insns[2];
1867 6d5e216d bellard
        stack_t                        stack;
1868 6d5e216d bellard
        unsigned int                extra_size; /* Should be 0 */
1869 c227f099 Anthony Liguori
        qemu_siginfo_fpu_t        fpu_state;
1870 6d5e216d bellard
};
1871 6d5e216d bellard
1872 e80cfcfc bellard
#define UREG_O0        16
1873 e80cfcfc bellard
#define UREG_O6        22
1874 e80cfcfc bellard
#define UREG_I0        0
1875 e80cfcfc bellard
#define UREG_I1        1
1876 e80cfcfc bellard
#define UREG_I2        2
1877 5bfb56b2 blueswir1
#define UREG_I3        3
1878 5bfb56b2 blueswir1
#define UREG_I4        4
1879 5bfb56b2 blueswir1
#define UREG_I5        5
1880 e80cfcfc bellard
#define UREG_I6        6
1881 e80cfcfc bellard
#define UREG_I7        7
1882 e80cfcfc bellard
#define UREG_L0               8
1883 6d5e216d bellard
#define UREG_FP        UREG_I6
1884 6d5e216d bellard
#define UREG_SP        UREG_O6
1885 6d5e216d bellard
1886 624f7979 pbrook
static inline abi_ulong get_sigframe(struct target_sigaction *sa, 
1887 459a4017 bellard
                                     CPUState *env, unsigned long framesize)
1888 6d5e216d bellard
{
1889 459a4017 bellard
        abi_ulong sp;
1890 6d5e216d bellard
1891 6d5e216d bellard
        sp = env->regwptr[UREG_FP];
1892 6d5e216d bellard
1893 6d5e216d bellard
        /* This is the X/Open sanctioned signal stack switching.  */
1894 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_ONSTACK) {
1895 a04e134a ths
            if (!on_sig_stack(sp)
1896 a04e134a ths
                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
1897 a04e134a ths
                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1898 6d5e216d bellard
        }
1899 459a4017 bellard
        return sp - framesize;
1900 6d5e216d bellard
}
1901 6d5e216d bellard
1902 6d5e216d bellard
static int
1903 992f48a0 blueswir1
setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
1904 6d5e216d bellard
{
1905 6d5e216d bellard
        int err = 0, i;
1906 6d5e216d bellard
1907 6d5e216d bellard
        err |= __put_user(env->psr, &si->si_regs.psr);
1908 6d5e216d bellard
        err |= __put_user(env->pc, &si->si_regs.pc);
1909 6d5e216d bellard
        err |= __put_user(env->npc, &si->si_regs.npc);
1910 6d5e216d bellard
        err |= __put_user(env->y, &si->si_regs.y);
1911 a315a145 bellard
        for (i=0; i < 8; i++) {
1912 6d5e216d bellard
                err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
1913 6d5e216d bellard
        }
1914 a315a145 bellard
        for (i=0; i < 8; i++) {
1915 e80cfcfc bellard
                err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
1916 6d5e216d bellard
        }
1917 6d5e216d bellard
        err |= __put_user(mask, &si->si_mask);
1918 6d5e216d bellard
        return err;
1919 6d5e216d bellard
}
1920 e80cfcfc bellard
1921 80a9d035 bellard
#if 0
1922 6d5e216d bellard
static int
1923 6d5e216d bellard
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1924 6d5e216d bellard
                 CPUState *env, unsigned long mask)
1925 6d5e216d bellard
{
1926 6d5e216d bellard
        int err = 0;
1927 6d5e216d bellard

1928 6d5e216d bellard
        err |= __put_user(mask, &sc->sigc_mask);
1929 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1930 6d5e216d bellard
        err |= __put_user(env->pc, &sc->sigc_pc);
1931 6d5e216d bellard
        err |= __put_user(env->npc, &sc->sigc_npc);
1932 6d5e216d bellard
        err |= __put_user(env->psr, &sc->sigc_psr);
1933 6d5e216d bellard
        err |= __put_user(env->gregs[1], &sc->sigc_g1);
1934 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1935 6d5e216d bellard

1936 6d5e216d bellard
        return err;
1937 6d5e216d bellard
}
1938 80a9d035 bellard
#endif
1939 6d5e216d bellard
#define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
1940 6d5e216d bellard
1941 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
1942 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
1943 6d5e216d bellard
{
1944 459a4017 bellard
        abi_ulong sf_addr;
1945 6d5e216d bellard
        struct target_signal_frame *sf;
1946 6d5e216d bellard
        int sigframe_size, err, i;
1947 6d5e216d bellard
1948 6d5e216d bellard
        /* 1. Make sure everything is clean */
1949 6d5e216d bellard
        //synchronize_user_stack();
1950 6d5e216d bellard
1951 6d5e216d bellard
        sigframe_size = NF_ALIGNEDSZ;
1952 459a4017 bellard
        sf_addr = get_sigframe(ka, env, sigframe_size);
1953 6d5e216d bellard
1954 459a4017 bellard
        sf = lock_user(VERIFY_WRITE, sf_addr, 
1955 459a4017 bellard
                       sizeof(struct target_signal_frame), 0);
1956 459a4017 bellard
        if (!sf)
1957 459a4017 bellard
                goto sigsegv;
1958 459a4017 bellard
                
1959 e80cfcfc bellard
        //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
1960 6d5e216d bellard
#if 0
1961 6d5e216d bellard
        if (invalid_frame_pointer(sf, sigframe_size))
1962 6d5e216d bellard
                goto sigill_and_return;
1963 6d5e216d bellard
#endif
1964 6d5e216d bellard
        /* 2. Save the current process state */
1965 6d5e216d bellard
        err = setup___siginfo(&sf->info, env, set->sig[0]);
1966 6d5e216d bellard
        err |= __put_user(0, &sf->extra_size);
1967 6d5e216d bellard
1968 6d5e216d bellard
        //err |= save_fpu_state(regs, &sf->fpu_state);
1969 6d5e216d bellard
        //err |= __put_user(&sf->fpu_state, &sf->fpu_save);
1970 6d5e216d bellard
1971 6d5e216d bellard
        err |= __put_user(set->sig[0], &sf->info.si_mask);
1972 6d5e216d bellard
        for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1973 6d5e216d bellard
                err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
1974 6d5e216d bellard
        }
1975 6d5e216d bellard
1976 a315a145 bellard
        for (i = 0; i < 8; i++) {
1977 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
1978 6d5e216d bellard
        }
1979 a315a145 bellard
        for (i = 0; i < 8; i++) {
1980 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
1981 6d5e216d bellard
        }
1982 6d5e216d bellard
        if (err)
1983 6d5e216d bellard
                goto sigsegv;
1984 6d5e216d bellard
1985 6d5e216d bellard
        /* 3. signal handler back-trampoline and parameters */
1986 459a4017 bellard
        env->regwptr[UREG_FP] = sf_addr;
1987 6d5e216d bellard
        env->regwptr[UREG_I0] = sig;
1988 459a4017 bellard
        env->regwptr[UREG_I1] = sf_addr + 
1989 459a4017 bellard
                offsetof(struct target_signal_frame, info);
1990 459a4017 bellard
        env->regwptr[UREG_I2] = sf_addr + 
1991 459a4017 bellard
                offsetof(struct target_signal_frame, info);
1992 6d5e216d bellard
1993 6d5e216d bellard
        /* 4. signal handler */
1994 624f7979 pbrook
        env->pc = ka->_sa_handler;
1995 6d5e216d bellard
        env->npc = (env->pc + 4);
1996 6d5e216d bellard
        /* 5. return to kernel instructions */
1997 624f7979 pbrook
        if (ka->sa_restorer)
1998 624f7979 pbrook
                env->regwptr[UREG_I7] = ka->sa_restorer;
1999 6d5e216d bellard
        else {
2000 775b58d8 bellard
                uint32_t val32;
2001 459a4017 bellard
2002 459a4017 bellard
                env->regwptr[UREG_I7] = sf_addr + 
2003 459a4017 bellard
                        offsetof(struct target_signal_frame, insns) - 2 * 4;
2004 6d5e216d bellard
2005 6d5e216d bellard
                /* mov __NR_sigreturn, %g1 */
2006 775b58d8 bellard
                val32 = 0x821020d8;
2007 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[0]);
2008 6d5e216d bellard
2009 6d5e216d bellard
                /* t 0x10 */
2010 775b58d8 bellard
                val32 = 0x91d02010;
2011 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[1]);
2012 6d5e216d bellard
                if (err)
2013 6d5e216d bellard
                        goto sigsegv;
2014 6d5e216d bellard
2015 6d5e216d bellard
                /* Flush instruction space. */
2016 6d5e216d bellard
                //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2017 80a9d035 bellard
                //                tb_flush(env);
2018 6d5e216d bellard
        }
2019 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2020 6d5e216d bellard
        return;
2021 459a4017 bellard
#if 0
2022 459a4017 bellard
sigill_and_return:
2023 6d5e216d bellard
        force_sig(TARGET_SIGILL);
2024 459a4017 bellard
#endif
2025 6d5e216d bellard
sigsegv:
2026 e80cfcfc bellard
        //fprintf(stderr, "force_sig\n");
2027 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2028 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
2029 6d5e216d bellard
}
2030 6d5e216d bellard
static inline int
2031 c227f099 Anthony Liguori
restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
2032 6d5e216d bellard
{
2033 6d5e216d bellard
        int err;
2034 6d5e216d bellard
#if 0
2035 6d5e216d bellard
#ifdef CONFIG_SMP
2036 6d5e216d bellard
        if (current->flags & PF_USEDFPU)
2037 6d5e216d bellard
                regs->psr &= ~PSR_EF;
2038 6d5e216d bellard
#else
2039 6d5e216d bellard
        if (current == last_task_used_math) {
2040 6d5e216d bellard
                last_task_used_math = 0;
2041 6d5e216d bellard
                regs->psr &= ~PSR_EF;
2042 6d5e216d bellard
        }
2043 6d5e216d bellard
#endif
2044 6d5e216d bellard
        current->used_math = 1;
2045 6d5e216d bellard
        current->flags &= ~PF_USEDFPU;
2046 6d5e216d bellard
#endif
2047 6d5e216d bellard
#if 0
2048 6d5e216d bellard
        if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
2049 6d5e216d bellard
                return -EFAULT;
2050 6d5e216d bellard
#endif
2051 6d5e216d bellard
2052 fafffaef bellard
#if 0
2053 fafffaef bellard
        /* XXX: incorrect */
2054 6d5e216d bellard
        err = __copy_from_user(&env->fpr[0], &fpu->si_float_regs[0],
2055 6d5e216d bellard
                                     (sizeof(unsigned long) * 32));
2056 fafffaef bellard
#endif
2057 6d5e216d bellard
        err |= __get_user(env->fsr, &fpu->si_fsr);
2058 6d5e216d bellard
#if 0
2059 6d5e216d bellard
        err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
2060 6d5e216d bellard
        if (current->thread.fpqdepth != 0)
2061 6d5e216d bellard
                err |= __copy_from_user(&current->thread.fpqueue[0],
2062 6d5e216d bellard
                                        &fpu->si_fpqueue[0],
2063 6d5e216d bellard
                                        ((sizeof(unsigned long) +
2064 6d5e216d bellard
                                        (sizeof(unsigned long *)))*16));
2065 6d5e216d bellard
#endif
2066 6d5e216d bellard
        return err;
2067 6d5e216d bellard
}
2068 6d5e216d bellard
2069 6d5e216d bellard
2070 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2071 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2072 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2073 6d5e216d bellard
{
2074 6d5e216d bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2075 6d5e216d bellard
}
2076 6d5e216d bellard
2077 6d5e216d bellard
long do_sigreturn(CPUState *env)
2078 6d5e216d bellard
{
2079 f8b0aa25 bellard
        abi_ulong sf_addr;
2080 6d5e216d bellard
        struct target_signal_frame *sf;
2081 e80cfcfc bellard
        uint32_t up_psr, pc, npc;
2082 c227f099 Anthony Liguori
        target_sigset_t set;
2083 e80cfcfc bellard
        sigset_t host_set;
2084 f8b0aa25 bellard
        abi_ulong fpu_save_addr;
2085 e80cfcfc bellard
        int err, i;
2086 6d5e216d bellard
2087 f8b0aa25 bellard
        sf_addr = env->regwptr[UREG_FP];
2088 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
2089 f8b0aa25 bellard
                goto segv_and_exit;
2090 80a9d035 bellard
#if 0
2091 e80cfcfc bellard
        fprintf(stderr, "sigreturn\n");
2092 e80cfcfc bellard
        fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
2093 80a9d035 bellard
#endif
2094 e80cfcfc bellard
        //cpu_dump_state(env, stderr, fprintf, 0);
2095 6d5e216d bellard
2096 6d5e216d bellard
        /* 1. Make sure we are not getting garbage from the user */
2097 6d5e216d bellard
2098 f8b0aa25 bellard
        if (sf_addr & 3)
2099 6d5e216d bellard
                goto segv_and_exit;
2100 6d5e216d bellard
2101 6d5e216d bellard
        err = __get_user(pc,  &sf->info.si_regs.pc);
2102 6d5e216d bellard
        err |= __get_user(npc, &sf->info.si_regs.npc);
2103 6d5e216d bellard
2104 6d5e216d bellard
        if ((pc | npc) & 3)
2105 6d5e216d bellard
                goto segv_and_exit;
2106 6d5e216d bellard
2107 6d5e216d bellard
        /* 2. Restore the state */
2108 e80cfcfc bellard
        err |= __get_user(up_psr, &sf->info.si_regs.psr);
2109 e80cfcfc bellard
2110 6d5e216d bellard
        /* User can only change condition codes and FPU enabling in %psr. */
2111 a315a145 bellard
        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2112 a315a145 bellard
                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));
2113 a315a145 bellard
2114 a315a145 bellard
        env->pc = pc;
2115 a315a145 bellard
        env->npc = npc;
2116 e80cfcfc bellard
        err |= __get_user(env->y, &sf->info.si_regs.y);
2117 a315a145 bellard
        for (i=0; i < 8; i++) {
2118 e80cfcfc bellard
                err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2119 e80cfcfc bellard
        }
2120 a315a145 bellard
        for (i=0; i < 8; i++) {
2121 e80cfcfc bellard
                err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2122 e80cfcfc bellard
        }
2123 6d5e216d bellard
2124 f8b0aa25 bellard
        err |= __get_user(fpu_save_addr, &sf->fpu_save);
2125 6d5e216d bellard
2126 e80cfcfc bellard
        //if (fpu_save)
2127 e80cfcfc bellard
        //        err |= restore_fpu_state(env, fpu_save);
2128 6d5e216d bellard
2129 6d5e216d bellard
        /* This is pretty much atomic, no amount locking would prevent
2130 6d5e216d bellard
         * the races which exist anyways.
2131 6d5e216d bellard
         */
2132 6d5e216d bellard
        err |= __get_user(set.sig[0], &sf->info.si_mask);
2133 e80cfcfc bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2134 e80cfcfc bellard
            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
2135 e80cfcfc bellard
        }
2136 e80cfcfc bellard
2137 e80cfcfc bellard
        target_to_host_sigset_internal(&host_set, &set);
2138 e80cfcfc bellard
        sigprocmask(SIG_SETMASK, &host_set, NULL);
2139 6d5e216d bellard
2140 6d5e216d bellard
        if (err)
2141 6d5e216d bellard
                goto segv_and_exit;
2142 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
2143 6d5e216d bellard
        return env->regwptr[0];
2144 6d5e216d bellard
2145 6d5e216d bellard
segv_and_exit:
2146 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
2147 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
2148 6d5e216d bellard
}
2149 6d5e216d bellard
2150 6d5e216d bellard
long do_rt_sigreturn(CPUState *env)
2151 6d5e216d bellard
{
2152 6d5e216d bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2153 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2154 6d5e216d bellard
}
2155 6d5e216d bellard
2156 459a4017 bellard
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
2157 5bfb56b2 blueswir1
#define MC_TSTATE 0
2158 5bfb56b2 blueswir1
#define MC_PC 1
2159 5bfb56b2 blueswir1
#define MC_NPC 2
2160 5bfb56b2 blueswir1
#define MC_Y 3
2161 5bfb56b2 blueswir1
#define MC_G1 4
2162 5bfb56b2 blueswir1
#define MC_G2 5
2163 5bfb56b2 blueswir1
#define MC_G3 6
2164 5bfb56b2 blueswir1
#define MC_G4 7
2165 5bfb56b2 blueswir1
#define MC_G5 8
2166 5bfb56b2 blueswir1
#define MC_G6 9
2167 5bfb56b2 blueswir1
#define MC_G7 10
2168 5bfb56b2 blueswir1
#define MC_O0 11
2169 5bfb56b2 blueswir1
#define MC_O1 12
2170 5bfb56b2 blueswir1
#define MC_O2 13
2171 5bfb56b2 blueswir1
#define MC_O3 14
2172 5bfb56b2 blueswir1
#define MC_O4 15
2173 5bfb56b2 blueswir1
#define MC_O5 16
2174 5bfb56b2 blueswir1
#define MC_O6 17
2175 5bfb56b2 blueswir1
#define MC_O7 18
2176 5bfb56b2 blueswir1
#define MC_NGREG 19
2177 5bfb56b2 blueswir1
2178 c227f099 Anthony Liguori
typedef abi_ulong target_mc_greg_t;
2179 c227f099 Anthony Liguori
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
2180 5bfb56b2 blueswir1
2181 5bfb56b2 blueswir1
struct target_mc_fq {
2182 992f48a0 blueswir1
    abi_ulong *mcfq_addr;
2183 5bfb56b2 blueswir1
    uint32_t mcfq_insn;
2184 5bfb56b2 blueswir1
};
2185 5bfb56b2 blueswir1
2186 5bfb56b2 blueswir1
struct target_mc_fpu {
2187 5bfb56b2 blueswir1
    union {
2188 5bfb56b2 blueswir1
        uint32_t sregs[32];
2189 5bfb56b2 blueswir1
        uint64_t dregs[32];
2190 5bfb56b2 blueswir1
        //uint128_t qregs[16];
2191 5bfb56b2 blueswir1
    } mcfpu_fregs;
2192 992f48a0 blueswir1
    abi_ulong mcfpu_fsr;
2193 992f48a0 blueswir1
    abi_ulong mcfpu_fprs;
2194 992f48a0 blueswir1
    abi_ulong mcfpu_gsr;
2195 5bfb56b2 blueswir1
    struct target_mc_fq *mcfpu_fq;
2196 5bfb56b2 blueswir1
    unsigned char mcfpu_qcnt;
2197 5bfb56b2 blueswir1
    unsigned char mcfpu_qentsz;
2198 5bfb56b2 blueswir1
    unsigned char mcfpu_enab;
2199 5bfb56b2 blueswir1
};
2200 c227f099 Anthony Liguori
typedef struct target_mc_fpu target_mc_fpu_t;
2201 5bfb56b2 blueswir1
2202 5bfb56b2 blueswir1
typedef struct {
2203 c227f099 Anthony Liguori
    target_mc_gregset_t mc_gregs;
2204 c227f099 Anthony Liguori
    target_mc_greg_t mc_fp;
2205 c227f099 Anthony Liguori
    target_mc_greg_t mc_i7;
2206 c227f099 Anthony Liguori
    target_mc_fpu_t mc_fpregs;
2207 c227f099 Anthony Liguori
} target_mcontext_t;
2208 5bfb56b2 blueswir1
2209 5bfb56b2 blueswir1
struct target_ucontext {
2210 60e99246 Aurelien Jarno
    struct target_ucontext *tuc_link;
2211 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
2212 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
2213 60e99246 Aurelien Jarno
    target_mcontext_t tuc_mcontext;
2214 5bfb56b2 blueswir1
};
2215 5bfb56b2 blueswir1
2216 5bfb56b2 blueswir1
/* A V9 register window */
2217 5bfb56b2 blueswir1
struct target_reg_window {
2218 992f48a0 blueswir1
    abi_ulong locals[8];
2219 992f48a0 blueswir1
    abi_ulong ins[8];
2220 5bfb56b2 blueswir1
};
2221 5bfb56b2 blueswir1
2222 5bfb56b2 blueswir1
#define TARGET_STACK_BIAS 2047
2223 5bfb56b2 blueswir1
2224 5bfb56b2 blueswir1
/* {set, get}context() needed for 64-bit SparcLinux userland. */
2225 5bfb56b2 blueswir1
void sparc64_set_context(CPUSPARCState *env)
2226 5bfb56b2 blueswir1
{
2227 459a4017 bellard
    abi_ulong ucp_addr;
2228 459a4017 bellard
    struct target_ucontext *ucp;
2229 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2230 992f48a0 blueswir1
    abi_ulong pc, npc, tstate;
2231 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2232 5bfb56b2 blueswir1
    unsigned char fenab;
2233 5bfb56b2 blueswir1
    int err;
2234 5bfb56b2 blueswir1
    unsigned int i;
2235 5bfb56b2 blueswir1
2236 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2237 459a4017 bellard
    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2238 459a4017 bellard
        goto do_sigsegv;
2239 60e99246 Aurelien Jarno
    grp  = &ucp->tuc_mcontext.mc_gregs;
2240 579a97f7 bellard
    err  = __get_user(pc, &((*grp)[MC_PC]));
2241 579a97f7 bellard
    err |= __get_user(npc, &((*grp)[MC_NPC]));
2242 5bfb56b2 blueswir1
    if (err || ((pc | npc) & 3))
2243 5bfb56b2 blueswir1
        goto do_sigsegv;
2244 5bfb56b2 blueswir1
    if (env->regwptr[UREG_I1]) {
2245 c227f099 Anthony Liguori
        target_sigset_t target_set;
2246 5bfb56b2 blueswir1
        sigset_t set;
2247 5bfb56b2 blueswir1
2248 5bfb56b2 blueswir1
        if (TARGET_NSIG_WORDS == 1) {
2249 60e99246 Aurelien Jarno
            if (__get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]))
2250 5bfb56b2 blueswir1
                goto do_sigsegv;
2251 5bfb56b2 blueswir1
        } else {
2252 459a4017 bellard
            abi_ulong *src, *dst;
2253 60e99246 Aurelien Jarno
            src = ucp->tuc_sigmask.sig;
2254 459a4017 bellard
            dst = target_set.sig;
2255 c227f099 Anthony Liguori
            for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2256 5bfb56b2 blueswir1
                 i++, dst++, src++)
2257 459a4017 bellard
                err |= __get_user(*dst, src);
2258 5bfb56b2 blueswir1
            if (err)
2259 5bfb56b2 blueswir1
                goto do_sigsegv;
2260 5bfb56b2 blueswir1
        }
2261 5bfb56b2 blueswir1
        target_to_host_sigset_internal(&set, &target_set);
2262 5bfb56b2 blueswir1
        sigprocmask(SIG_SETMASK, &set, NULL);
2263 5bfb56b2 blueswir1
    }
2264 5bfb56b2 blueswir1
    env->pc = pc;
2265 5bfb56b2 blueswir1
    env->npc = npc;
2266 579a97f7 bellard
    err |= __get_user(env->y, &((*grp)[MC_Y]));
2267 579a97f7 bellard
    err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
2268 5bfb56b2 blueswir1
    env->asi = (tstate >> 24) & 0xff;
2269 5a834bb4 Blue Swirl
    cpu_put_ccr(env, tstate >> 32);
2270 5a834bb4 Blue Swirl
    cpu_put_cwp64(env, tstate & 0x1f);
2271 579a97f7 bellard
    err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2272 579a97f7 bellard
    err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2273 579a97f7 bellard
    err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2274 579a97f7 bellard
    err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2275 579a97f7 bellard
    err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2276 579a97f7 bellard
    err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2277 579a97f7 bellard
    err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2278 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2279 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2280 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2281 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2282 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2283 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2284 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2285 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2286 579a97f7 bellard
2287 60e99246 Aurelien Jarno
    err |= __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2288 60e99246 Aurelien Jarno
    err |= __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
2289 579a97f7 bellard
2290 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2291 459a4017 bellard
    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2292 459a4017 bellard
                 abi_ulong) != 0)
2293 459a4017 bellard
        goto do_sigsegv;
2294 459a4017 bellard
    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2295 459a4017 bellard
                 abi_ulong) != 0)
2296 459a4017 bellard
        goto do_sigsegv;
2297 60e99246 Aurelien Jarno
    err |= __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2298 60e99246 Aurelien Jarno
    err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
2299 459a4017 bellard
    {
2300 459a4017 bellard
        uint32_t *src, *dst;
2301 60e99246 Aurelien Jarno
        src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2302 459a4017 bellard
        dst = env->fpr;
2303 459a4017 bellard
        /* XXX: check that the CPU storage is the same as user context */
2304 459a4017 bellard
        for (i = 0; i < 64; i++, dst++, src++)
2305 459a4017 bellard
            err |= __get_user(*dst, src);
2306 459a4017 bellard
    }
2307 579a97f7 bellard
    err |= __get_user(env->fsr,
2308 60e99246 Aurelien Jarno
                      &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2309 579a97f7 bellard
    err |= __get_user(env->gsr,
2310 60e99246 Aurelien Jarno
                      &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
2311 5bfb56b2 blueswir1
    if (err)
2312 5bfb56b2 blueswir1
        goto do_sigsegv;
2313 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2314 5bfb56b2 blueswir1
    return;
2315 5bfb56b2 blueswir1
 do_sigsegv:
2316 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2317 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
2318 5bfb56b2 blueswir1
}
2319 5bfb56b2 blueswir1
2320 5bfb56b2 blueswir1
void sparc64_get_context(CPUSPARCState *env)
2321 5bfb56b2 blueswir1
{
2322 459a4017 bellard
    abi_ulong ucp_addr;
2323 459a4017 bellard
    struct target_ucontext *ucp;
2324 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2325 c227f099 Anthony Liguori
    target_mcontext_t *mcp;
2326 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2327 5bfb56b2 blueswir1
    int err;
2328 5bfb56b2 blueswir1
    unsigned int i;
2329 c227f099 Anthony Liguori
    target_sigset_t target_set;
2330 5bfb56b2 blueswir1
    sigset_t set;
2331 5bfb56b2 blueswir1
2332 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2333 459a4017 bellard
    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2334 459a4017 bellard
        goto do_sigsegv;
2335 459a4017 bellard
    
2336 60e99246 Aurelien Jarno
    mcp = &ucp->tuc_mcontext;
2337 5bfb56b2 blueswir1
    grp = &mcp->mc_gregs;
2338 5bfb56b2 blueswir1
2339 5bfb56b2 blueswir1
    /* Skip over the trap instruction, first. */
2340 5bfb56b2 blueswir1
    env->pc = env->npc;
2341 5bfb56b2 blueswir1
    env->npc += 4;
2342 5bfb56b2 blueswir1
2343 5bfb56b2 blueswir1
    err = 0;
2344 5bfb56b2 blueswir1
2345 5bfb56b2 blueswir1
    sigprocmask(0, NULL, &set);
2346 5bfb56b2 blueswir1
    host_to_target_sigset_internal(&target_set, &set);
2347 459a4017 bellard
    if (TARGET_NSIG_WORDS == 1) {
2348 579a97f7 bellard
        err |= __put_user(target_set.sig[0],
2349 60e99246 Aurelien Jarno
                          (abi_ulong *)&ucp->tuc_sigmask);
2350 459a4017 bellard
    } else {
2351 459a4017 bellard
        abi_ulong *src, *dst;
2352 459a4017 bellard
        src = target_set.sig;
2353 60e99246 Aurelien Jarno
        dst = ucp->tuc_sigmask.sig;
2354 c227f099 Anthony Liguori
        for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2355 5bfb56b2 blueswir1
             i++, dst++, src++)
2356 459a4017 bellard
            err |= __put_user(*src, dst);
2357 5bfb56b2 blueswir1
        if (err)
2358 5bfb56b2 blueswir1
            goto do_sigsegv;
2359 5bfb56b2 blueswir1
    }
2360 5bfb56b2 blueswir1
2361 459a4017 bellard
    /* XXX: tstate must be saved properly */
2362 459a4017 bellard
    //    err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2363 579a97f7 bellard
    err |= __put_user(env->pc, &((*grp)[MC_PC]));
2364 579a97f7 bellard
    err |= __put_user(env->npc, &((*grp)[MC_NPC]));
2365 579a97f7 bellard
    err |= __put_user(env->y, &((*grp)[MC_Y]));
2366 579a97f7 bellard
    err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
2367 579a97f7 bellard
    err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
2368 579a97f7 bellard
    err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
2369 579a97f7 bellard
    err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
2370 579a97f7 bellard
    err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
2371 579a97f7 bellard
    err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
2372 579a97f7 bellard
    err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
2373 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2374 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2375 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2376 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2377 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2378 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2379 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2380 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
2381 579a97f7 bellard
2382 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2383 459a4017 bellard
    fp = i7 = 0;
2384 459a4017 bellard
    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2385 459a4017 bellard
                 abi_ulong) != 0)
2386 459a4017 bellard
        goto do_sigsegv;
2387 459a4017 bellard
    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2388 459a4017 bellard
                 abi_ulong) != 0)
2389 459a4017 bellard
        goto do_sigsegv;
2390 579a97f7 bellard
    err |= __put_user(fp, &(mcp->mc_fp));
2391 579a97f7 bellard
    err |= __put_user(i7, &(mcp->mc_i7));
2392 5bfb56b2 blueswir1
2393 459a4017 bellard
    {
2394 459a4017 bellard
        uint32_t *src, *dst;
2395 459a4017 bellard
        src = env->fpr;
2396 60e99246 Aurelien Jarno
        dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2397 459a4017 bellard
        /* XXX: check that the CPU storage is the same as user context */
2398 459a4017 bellard
        for (i = 0; i < 64; i++, dst++, src++)
2399 459a4017 bellard
            err |= __put_user(*src, dst);
2400 459a4017 bellard
    }
2401 579a97f7 bellard
    err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2402 579a97f7 bellard
    err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2403 579a97f7 bellard
    err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
2404 5bfb56b2 blueswir1
2405 5bfb56b2 blueswir1
    if (err)
2406 5bfb56b2 blueswir1
        goto do_sigsegv;
2407 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2408 5bfb56b2 blueswir1
    return;
2409 5bfb56b2 blueswir1
 do_sigsegv:
2410 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2411 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
2412 5bfb56b2 blueswir1
}
2413 5bfb56b2 blueswir1
#endif
2414 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN64)
2415 540635ba ths
2416 540635ba ths
# warning signal handling not implemented
2417 540635ba ths
2418 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2419 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
2420 540635ba ths
{
2421 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2422 540635ba ths
}
2423 540635ba ths
2424 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2425 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2426 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2427 540635ba ths
{
2428 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2429 540635ba ths
}
2430 540635ba ths
2431 540635ba ths
long do_sigreturn(CPUState *env)
2432 540635ba ths
{
2433 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2434 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2435 540635ba ths
}
2436 540635ba ths
2437 540635ba ths
long do_rt_sigreturn(CPUState *env)
2438 540635ba ths
{
2439 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2440 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2441 540635ba ths
}
2442 540635ba ths
2443 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN32)
2444 540635ba ths
2445 540635ba ths
# warning signal handling not implemented
2446 540635ba ths
2447 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2448 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
2449 540635ba ths
{
2450 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2451 540635ba ths
}
2452 540635ba ths
2453 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2454 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2455 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2456 540635ba ths
{
2457 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2458 540635ba ths
}
2459 540635ba ths
2460 540635ba ths
long do_sigreturn(CPUState *env)
2461 540635ba ths
{
2462 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2463 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2464 540635ba ths
}
2465 540635ba ths
2466 540635ba ths
long do_rt_sigreturn(CPUState *env)
2467 540635ba ths
{
2468 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2469 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2470 540635ba ths
}
2471 540635ba ths
2472 d26bc211 ths
#elif defined(TARGET_ABI_MIPSO32)
2473 106ec879 bellard
2474 106ec879 bellard
struct target_sigcontext {
2475 106ec879 bellard
    uint32_t   sc_regmask;     /* Unused */
2476 106ec879 bellard
    uint32_t   sc_status;
2477 106ec879 bellard
    uint64_t   sc_pc;
2478 106ec879 bellard
    uint64_t   sc_regs[32];
2479 106ec879 bellard
    uint64_t   sc_fpregs[32];
2480 106ec879 bellard
    uint32_t   sc_ownedfp;     /* Unused */
2481 106ec879 bellard
    uint32_t   sc_fpc_csr;
2482 106ec879 bellard
    uint32_t   sc_fpc_eir;     /* Unused */
2483 106ec879 bellard
    uint32_t   sc_used_math;
2484 106ec879 bellard
    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
2485 94c5495d Paul Brook
    uint32_t   pad0;
2486 106ec879 bellard
    uint64_t   sc_mdhi;
2487 106ec879 bellard
    uint64_t   sc_mdlo;
2488 106ec879 bellard
    target_ulong   sc_hi1;         /* Was sc_cause */
2489 106ec879 bellard
    target_ulong   sc_lo1;         /* Was sc_badvaddr */
2490 106ec879 bellard
    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
2491 106ec879 bellard
    target_ulong   sc_lo2;
2492 106ec879 bellard
    target_ulong   sc_hi3;
2493 106ec879 bellard
    target_ulong   sc_lo3;
2494 106ec879 bellard
};
2495 106ec879 bellard
2496 106ec879 bellard
struct sigframe {
2497 106ec879 bellard
    uint32_t sf_ass[4];                        /* argument save space for o32 */
2498 106ec879 bellard
    uint32_t sf_code[2];                        /* signal trampoline */
2499 106ec879 bellard
    struct target_sigcontext sf_sc;
2500 c227f099 Anthony Liguori
    target_sigset_t sf_mask;
2501 106ec879 bellard
};
2502 106ec879 bellard
2503 0b1bcb00 pbrook
struct target_ucontext {
2504 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
2505 60e99246 Aurelien Jarno
    target_ulong tuc_link;
2506 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
2507 94c5495d Paul Brook
    target_ulong pad0;
2508 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
2509 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
2510 0b1bcb00 pbrook
};
2511 0b1bcb00 pbrook
2512 0b1bcb00 pbrook
struct target_rt_sigframe {
2513 0b1bcb00 pbrook
    uint32_t rs_ass[4];               /* argument save space for o32 */
2514 0b1bcb00 pbrook
    uint32_t rs_code[2];              /* signal trampoline */
2515 0b1bcb00 pbrook
    struct target_siginfo rs_info;
2516 0b1bcb00 pbrook
    struct target_ucontext rs_uc;
2517 0b1bcb00 pbrook
};
2518 0b1bcb00 pbrook
2519 106ec879 bellard
/* Install trampoline to jump back from signal handler */
2520 106ec879 bellard
static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
2521 106ec879 bellard
{
2522 106ec879 bellard
    int err;
2523 106ec879 bellard
2524 106ec879 bellard
    /*
2525 106ec879 bellard
    * Set up the return code ...
2526 106ec879 bellard
    *
2527 106ec879 bellard
    *         li      v0, __NR__foo_sigreturn
2528 106ec879 bellard
    *         syscall
2529 106ec879 bellard
    */
2530 106ec879 bellard
2531 106ec879 bellard
    err = __put_user(0x24020000 + syscall, tramp + 0);
2532 106ec879 bellard
    err |= __put_user(0x0000000c          , tramp + 1);
2533 106ec879 bellard
    /* flush_cache_sigtramp((unsigned long) tramp); */
2534 106ec879 bellard
    return err;
2535 106ec879 bellard
}
2536 106ec879 bellard
2537 106ec879 bellard
static inline int
2538 106ec879 bellard
setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2539 106ec879 bellard
{
2540 106ec879 bellard
    int err = 0;
2541 106ec879 bellard
2542 b5dc7732 ths
    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
2543 106ec879 bellard
2544 b5dc7732 ths
#define save_gp_reg(i) do {                                                   \
2545 b5dc7732 ths
        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);        \
2546 106ec879 bellard
    } while(0)
2547 106ec879 bellard
    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
2548 106ec879 bellard
    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
2549 106ec879 bellard
    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
2550 106ec879 bellard
    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
2551 106ec879 bellard
    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
2552 106ec879 bellard
    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
2553 106ec879 bellard
    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
2554 106ec879 bellard
    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
2555 106ec879 bellard
    save_gp_reg(31);
2556 388bb21a ths
#undef save_gp_reg
2557 106ec879 bellard
2558 b5dc7732 ths
    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2559 b5dc7732 ths
    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2560 106ec879 bellard
2561 106ec879 bellard
    /* Not used yet, but might be useful if we ever have DSP suppport */
2562 106ec879 bellard
#if 0
2563 106ec879 bellard
    if (cpu_has_dsp) {
2564 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi1);
2565 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo1);
2566 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi2);
2567 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo2);
2568 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi3);
2569 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo3);
2570 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2571 106ec879 bellard
    }
2572 106ec879 bellard
    /* same with 64 bit */
2573 388bb21a ths
#ifdef CONFIG_64BIT
2574 106ec879 bellard
    err |= __put_user(regs->hi, &sc->sc_hi[0]);
2575 106ec879 bellard
    err |= __put_user(regs->lo, &sc->sc_lo[0]);
2576 106ec879 bellard
    if (cpu_has_dsp) {
2577 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi[1]);
2578 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo[1]);
2579 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi[2]);
2580 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo[2]);
2581 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi[3]);
2582 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo[3]);
2583 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2584 106ec879 bellard
    }
2585 388bb21a ths
#endif
2586 388bb21a ths
#endif
2587 106ec879 bellard
2588 388bb21a ths
#if 0
2589 106ec879 bellard
    err |= __put_user(!!used_math(), &sc->sc_used_math);
2590 106ec879 bellard

2591 106ec879 bellard
    if (!used_math())
2592 106ec879 bellard
        goto out;
2593 106ec879 bellard

2594 106ec879 bellard
    /*
2595 106ec879 bellard
    * Save FPU state to signal context.  Signal handler will "inherit"
2596 106ec879 bellard
    * current FPU state.
2597 106ec879 bellard
    */
2598 106ec879 bellard
    preempt_disable();
2599 106ec879 bellard

2600 106ec879 bellard
    if (!is_fpu_owner()) {
2601 106ec879 bellard
        own_fpu();
2602 106ec879 bellard
        restore_fp(current);
2603 106ec879 bellard
    }
2604 106ec879 bellard
    err |= save_fp_context(sc);
2605 106ec879 bellard

2606 106ec879 bellard
    preempt_enable();
2607 106ec879 bellard
    out:
2608 106ec879 bellard
#endif
2609 106ec879 bellard
    return err;
2610 106ec879 bellard
}
2611 106ec879 bellard
2612 106ec879 bellard
static inline int
2613 106ec879 bellard
restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2614 106ec879 bellard
{
2615 106ec879 bellard
    int err = 0;
2616 106ec879 bellard
2617 106ec879 bellard
    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
2618 106ec879 bellard
2619 b5dc7732 ths
    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2620 b5dc7732 ths
    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2621 106ec879 bellard
2622 ead9360e ths
#define restore_gp_reg(i) do {                                                           \
2623 b5dc7732 ths
        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);                \
2624 106ec879 bellard
    } while(0)
2625 106ec879 bellard
    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
2626 106ec879 bellard
    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
2627 106ec879 bellard
    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
2628 106ec879 bellard
    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
2629 106ec879 bellard
    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
2630 106ec879 bellard
    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
2631 106ec879 bellard
    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
2632 106ec879 bellard
    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
2633 106ec879 bellard
    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
2634 106ec879 bellard
    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
2635 106ec879 bellard
    restore_gp_reg(31);
2636 388bb21a ths
#undef restore_gp_reg
2637 106ec879 bellard
2638 106ec879 bellard
#if 0
2639 106ec879 bellard
    if (cpu_has_dsp) {
2640 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
2641 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
2642 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
2643 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
2644 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
2645 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
2646 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2647 106ec879 bellard
    }
2648 388bb21a ths
#ifdef CONFIG_64BIT
2649 106ec879 bellard
    err |= __get_user(regs->hi, &sc->sc_hi[0]);
2650 106ec879 bellard
    err |= __get_user(regs->lo, &sc->sc_lo[0]);
2651 106ec879 bellard
    if (cpu_has_dsp) {
2652 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
2653 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
2654 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
2655 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
2656 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
2657 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
2658 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2659 106ec879 bellard
    }
2660 388bb21a ths
#endif
2661 106ec879 bellard
2662 106ec879 bellard
    err |= __get_user(used_math, &sc->sc_used_math);
2663 106ec879 bellard
    conditional_used_math(used_math);
2664 106ec879 bellard
2665 106ec879 bellard
    preempt_disable();
2666 106ec879 bellard
2667 106ec879 bellard
    if (used_math()) {
2668 106ec879 bellard
        /* restore fpu context if we have used it before */
2669 106ec879 bellard
        own_fpu();
2670 106ec879 bellard
        err |= restore_fp_context(sc);
2671 106ec879 bellard
    } else {
2672 106ec879 bellard
        /* signal handler may have used FPU.  Give it up. */
2673 106ec879 bellard
        lose_fpu();
2674 106ec879 bellard
    }
2675 106ec879 bellard
2676 106ec879 bellard
    preempt_enable();
2677 106ec879 bellard
#endif
2678 106ec879 bellard
    return err;
2679 106ec879 bellard
}
2680 106ec879 bellard
/*
2681 106ec879 bellard
 * Determine which stack to use..
2682 106ec879 bellard
 */
2683 579a97f7 bellard
static inline abi_ulong
2684 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
2685 106ec879 bellard
{
2686 106ec879 bellard
    unsigned long sp;
2687 106ec879 bellard
2688 106ec879 bellard
    /* Default to using normal stack */
2689 b5dc7732 ths
    sp = regs->active_tc.gpr[29];
2690 106ec879 bellard
2691 106ec879 bellard
    /*
2692 106ec879 bellard
     * FPU emulator may have it's own trampoline active just
2693 106ec879 bellard
     * above the user stack, 16-bytes before the next lowest
2694 106ec879 bellard
     * 16 byte boundary.  Try to avoid trashing it.
2695 106ec879 bellard
     */
2696 106ec879 bellard
    sp -= 32;
2697 106ec879 bellard
2698 106ec879 bellard
    /* This is the X/Open sanctioned signal stack switching.  */
2699 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
2700 a04e134a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2701 a04e134a ths
    }
2702 106ec879 bellard
2703 579a97f7 bellard
    return (sp - frame_size) & ~7;
2704 106ec879 bellard
}
2705 106ec879 bellard
2706 579a97f7 bellard
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
2707 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction * ka,
2708 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
2709 106ec879 bellard
{
2710 106ec879 bellard
    struct sigframe *frame;
2711 579a97f7 bellard
    abi_ulong frame_addr;
2712 106ec879 bellard
    int i;
2713 106ec879 bellard
2714 579a97f7 bellard
    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2715 579a97f7 bellard
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2716 106ec879 bellard
        goto give_sigsegv;
2717 106ec879 bellard
2718 106ec879 bellard
    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2719 106ec879 bellard
2720 106ec879 bellard
    if(setup_sigcontext(regs, &frame->sf_sc))
2721 106ec879 bellard
        goto give_sigsegv;
2722 106ec879 bellard
2723 106ec879 bellard
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2724 106ec879 bellard
        if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
2725 106ec879 bellard
            goto give_sigsegv;
2726 106ec879 bellard
    }
2727 106ec879 bellard
2728 106ec879 bellard
    /*
2729 106ec879 bellard
    * Arguments to signal handler:
2730 106ec879 bellard
    *
2731 106ec879 bellard
    *   a0 = signal number
2732 106ec879 bellard
    *   a1 = 0 (should be cause)
2733 106ec879 bellard
    *   a2 = pointer to struct sigcontext
2734 106ec879 bellard
    *
2735 106ec879 bellard
    * $25 and PC point to the signal handler, $29 points to the
2736 106ec879 bellard
    * struct sigframe.
2737 106ec879 bellard
    */
2738 b5dc7732 ths
    regs->active_tc.gpr[ 4] = sig;
2739 b5dc7732 ths
    regs->active_tc.gpr[ 5] = 0;
2740 b5dc7732 ths
    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2741 b5dc7732 ths
    regs->active_tc.gpr[29] = frame_addr;
2742 b5dc7732 ths
    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
2743 106ec879 bellard
    /* The original kernel code sets CP0_EPC to the handler
2744 106ec879 bellard
    * since it returns to userland using eret
2745 106ec879 bellard
    * we cannot do this here, and we must set PC directly */
2746 b5dc7732 ths
    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
2747 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2748 106ec879 bellard
    return;
2749 106ec879 bellard
2750 106ec879 bellard
give_sigsegv:
2751 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2752 106ec879 bellard
    force_sig(TARGET_SIGSEGV/*, current*/);
2753 5fafdf24 ths
    return;
2754 106ec879 bellard
}
2755 106ec879 bellard
2756 106ec879 bellard
long do_sigreturn(CPUState *regs)
2757 106ec879 bellard
{
2758 388bb21a ths
    struct sigframe *frame;
2759 579a97f7 bellard
    abi_ulong frame_addr;
2760 388bb21a ths
    sigset_t blocked;
2761 c227f099 Anthony Liguori
    target_sigset_t target_set;
2762 388bb21a ths
    int i;
2763 106ec879 bellard
2764 106ec879 bellard
#if defined(DEBUG_SIGNAL)
2765 388bb21a ths
    fprintf(stderr, "do_sigreturn\n");
2766 106ec879 bellard
#endif
2767 b5dc7732 ths
    frame_addr = regs->active_tc.gpr[29];
2768 579a97f7 bellard
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2769 106ec879 bellard
           goto badframe;
2770 106ec879 bellard
2771 388bb21a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2772 106ec879 bellard
           if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
2773 106ec879 bellard
            goto badframe;
2774 388bb21a ths
    }
2775 106ec879 bellard
2776 388bb21a ths
    target_to_host_sigset_internal(&blocked, &target_set);
2777 388bb21a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2778 106ec879 bellard
2779 388bb21a ths
    if (restore_sigcontext(regs, &frame->sf_sc))
2780 106ec879 bellard
           goto badframe;
2781 106ec879 bellard
2782 106ec879 bellard
#if 0
2783 388bb21a ths
    /*
2784 388bb21a ths
     * Don't let your children do this ...
2785 388bb21a ths
     */
2786 388bb21a ths
    __asm__ __volatile__(
2787 106ec879 bellard
           "move\t$29, %0\n\t"
2788 106ec879 bellard
           "j\tsyscall_exit"
2789 106ec879 bellard
           :/* no outputs */
2790 106ec879 bellard
           :"r" (&regs));
2791 388bb21a ths
    /* Unreached */
2792 106ec879 bellard
#endif
2793 3b46e624 ths
2794 b5dc7732 ths
    regs->active_tc.PC = regs->CP0_EPC;
2795 388bb21a ths
    /* I am not sure this is right, but it seems to work
2796 106ec879 bellard
    * maybe a problem with nested signals ? */
2797 106ec879 bellard
    regs->CP0_EPC = 0;
2798 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2799 106ec879 bellard
2800 106ec879 bellard
badframe:
2801 388bb21a ths
    force_sig(TARGET_SIGSEGV/*, current*/);
2802 388bb21a ths
    return 0;
2803 106ec879 bellard
}
2804 106ec879 bellard
2805 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2806 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2807 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2808 106ec879 bellard
{
2809 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2810 0b1bcb00 pbrook
    abi_ulong frame_addr;
2811 0b1bcb00 pbrook
    int i;
2812 0b1bcb00 pbrook
2813 0b1bcb00 pbrook
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
2814 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2815 0b1bcb00 pbrook
        goto give_sigsegv;
2816 0b1bcb00 pbrook
2817 0b1bcb00 pbrook
    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
2818 0b1bcb00 pbrook
2819 0b1bcb00 pbrook
    copy_siginfo_to_user(&frame->rs_info, info);
2820 0b1bcb00 pbrook
2821 60e99246 Aurelien Jarno
    __put_user(0, &frame->rs_uc.tuc_flags);
2822 60e99246 Aurelien Jarno
    __put_user(0, &frame->rs_uc.tuc_link);
2823 60e99246 Aurelien Jarno
    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
2824 60e99246 Aurelien Jarno
    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
2825 0b1bcb00 pbrook
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
2826 60e99246 Aurelien Jarno
               &frame->rs_uc.tuc_stack.ss_flags);
2827 0b1bcb00 pbrook
2828 60e99246 Aurelien Jarno
    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
2829 0b1bcb00 pbrook
2830 0b1bcb00 pbrook
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2831 60e99246 Aurelien Jarno
        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
2832 0b1bcb00 pbrook
    }
2833 0b1bcb00 pbrook
2834 0b1bcb00 pbrook
    /*
2835 0b1bcb00 pbrook
    * Arguments to signal handler:
2836 0b1bcb00 pbrook
    *
2837 0b1bcb00 pbrook
    *   a0 = signal number
2838 0b1bcb00 pbrook
    *   a1 = pointer to struct siginfo
2839 0b1bcb00 pbrook
    *   a2 = pointer to struct ucontext
2840 0b1bcb00 pbrook
    *
2841 0b1bcb00 pbrook
    * $25 and PC point to the signal handler, $29 points to the
2842 0b1bcb00 pbrook
    * struct sigframe.
2843 0b1bcb00 pbrook
    */
2844 0b1bcb00 pbrook
    env->active_tc.gpr[ 4] = sig;
2845 0b1bcb00 pbrook
    env->active_tc.gpr[ 5] = frame_addr
2846 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_info);
2847 0b1bcb00 pbrook
    env->active_tc.gpr[ 6] = frame_addr
2848 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_uc);
2849 0b1bcb00 pbrook
    env->active_tc.gpr[29] = frame_addr;
2850 0b1bcb00 pbrook
    env->active_tc.gpr[31] = frame_addr
2851 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_code);
2852 0b1bcb00 pbrook
    /* The original kernel code sets CP0_EPC to the handler
2853 0b1bcb00 pbrook
    * since it returns to userland using eret
2854 0b1bcb00 pbrook
    * we cannot do this here, and we must set PC directly */
2855 0b1bcb00 pbrook
    env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
2856 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2857 0b1bcb00 pbrook
    return;
2858 0b1bcb00 pbrook
2859 0b1bcb00 pbrook
give_sigsegv:
2860 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2861 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2862 0b1bcb00 pbrook
    return;
2863 106ec879 bellard
}
2864 106ec879 bellard
2865 106ec879 bellard
long do_rt_sigreturn(CPUState *env)
2866 106ec879 bellard
{
2867 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2868 0b1bcb00 pbrook
    abi_ulong frame_addr;
2869 0b1bcb00 pbrook
    sigset_t blocked;
2870 0b1bcb00 pbrook
2871 0b1bcb00 pbrook
#if defined(DEBUG_SIGNAL)
2872 0b1bcb00 pbrook
    fprintf(stderr, "do_rt_sigreturn\n");
2873 0b1bcb00 pbrook
#endif
2874 0b1bcb00 pbrook
    frame_addr = env->active_tc.gpr[29];
2875 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2876 0b1bcb00 pbrook
           goto badframe;
2877 0b1bcb00 pbrook
2878 60e99246 Aurelien Jarno
    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
2879 0b1bcb00 pbrook
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2880 0b1bcb00 pbrook
2881 60e99246 Aurelien Jarno
    if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
2882 0b1bcb00 pbrook
        goto badframe;
2883 0b1bcb00 pbrook
2884 0b1bcb00 pbrook
    if (do_sigaltstack(frame_addr +
2885 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
2886 0b1bcb00 pbrook
                       0, get_sp_from_cpustate(env)) == -EFAULT)
2887 0b1bcb00 pbrook
        goto badframe;
2888 0b1bcb00 pbrook
2889 0b1bcb00 pbrook
    env->active_tc.PC = env->CP0_EPC;
2890 0b1bcb00 pbrook
    /* I am not sure this is right, but it seems to work
2891 0b1bcb00 pbrook
    * maybe a problem with nested signals ? */
2892 0b1bcb00 pbrook
    env->CP0_EPC = 0;
2893 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2894 0b1bcb00 pbrook
2895 0b1bcb00 pbrook
badframe:
2896 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2897 0b1bcb00 pbrook
    return 0;
2898 106ec879 bellard
}
2899 6d5e216d bellard
2900 c3b5bc8a ths
#elif defined(TARGET_SH4)
2901 c3b5bc8a ths
2902 c3b5bc8a ths
/*
2903 c3b5bc8a ths
 * code and data structures from linux kernel:
2904 c3b5bc8a ths
 * include/asm-sh/sigcontext.h
2905 c3b5bc8a ths
 * arch/sh/kernel/signal.c
2906 c3b5bc8a ths
 */
2907 c3b5bc8a ths
2908 c3b5bc8a ths
struct target_sigcontext {
2909 c3b5bc8a ths
    target_ulong  oldmask;
2910 c3b5bc8a ths
2911 c3b5bc8a ths
    /* CPU registers */
2912 c3b5bc8a ths
    target_ulong  sc_gregs[16];
2913 c3b5bc8a ths
    target_ulong  sc_pc;
2914 c3b5bc8a ths
    target_ulong  sc_pr;
2915 c3b5bc8a ths
    target_ulong  sc_sr;
2916 c3b5bc8a ths
    target_ulong  sc_gbr;
2917 c3b5bc8a ths
    target_ulong  sc_mach;
2918 c3b5bc8a ths
    target_ulong  sc_macl;
2919 c3b5bc8a ths
2920 c3b5bc8a ths
    /* FPU registers */
2921 c3b5bc8a ths
    target_ulong  sc_fpregs[16];
2922 c3b5bc8a ths
    target_ulong  sc_xfpregs[16];
2923 c3b5bc8a ths
    unsigned int sc_fpscr;
2924 c3b5bc8a ths
    unsigned int sc_fpul;
2925 c3b5bc8a ths
    unsigned int sc_ownedfp;
2926 c3b5bc8a ths
};
2927 c3b5bc8a ths
2928 c3b5bc8a ths
struct target_sigframe
2929 c3b5bc8a ths
{
2930 c3b5bc8a ths
    struct target_sigcontext sc;
2931 c3b5bc8a ths
    target_ulong extramask[TARGET_NSIG_WORDS-1];
2932 c3b5bc8a ths
    uint16_t retcode[3];
2933 c3b5bc8a ths
};
2934 c3b5bc8a ths
2935 c3b5bc8a ths
2936 c3b5bc8a ths
struct target_ucontext {
2937 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
2938 60e99246 Aurelien Jarno
    struct target_ucontext *tuc_link;
2939 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
2940 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
2941 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;        /* mask last for extensibility */
2942 c3b5bc8a ths
};
2943 c3b5bc8a ths
2944 c3b5bc8a ths
struct target_rt_sigframe
2945 c3b5bc8a ths
{
2946 c3b5bc8a ths
    struct target_siginfo info;
2947 c3b5bc8a ths
    struct target_ucontext uc;
2948 c3b5bc8a ths
    uint16_t retcode[3];
2949 c3b5bc8a ths
};
2950 c3b5bc8a ths
2951 c3b5bc8a ths
2952 c3b5bc8a ths
#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
2953 c3b5bc8a ths
#define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */
2954 c3b5bc8a ths
2955 624f7979 pbrook
static abi_ulong get_sigframe(struct target_sigaction *ka,
2956 c3b5bc8a ths
                         unsigned long sp, size_t frame_size)
2957 c3b5bc8a ths
{
2958 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
2959 c3b5bc8a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2960 c3b5bc8a ths
    }
2961 c3b5bc8a ths
2962 c3b5bc8a ths
    return (sp - frame_size) & -8ul;
2963 c3b5bc8a ths
}
2964 c3b5bc8a ths
2965 c3b5bc8a ths
static int setup_sigcontext(struct target_sigcontext *sc,
2966 c3b5bc8a ths
                            CPUState *regs, unsigned long mask)
2967 c3b5bc8a ths
{
2968 c3b5bc8a ths
    int err = 0;
2969 d8714436 takasi-y@ops.dti.ne.jp
    int i;
2970 c3b5bc8a ths
2971 c3b5bc8a ths
#define COPY(x)         err |= __put_user(regs->x, &sc->sc_##x)
2972 c3b5bc8a ths
    COPY(gregs[0]); COPY(gregs[1]);
2973 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
2974 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
2975 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
2976 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
2977 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
2978 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
2979 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
2980 c3b5bc8a ths
    COPY(gbr); COPY(mach);
2981 c3b5bc8a ths
    COPY(macl); COPY(pr);
2982 c3b5bc8a ths
    COPY(sr); COPY(pc);
2983 c3b5bc8a ths
#undef COPY
2984 c3b5bc8a ths
2985 d8714436 takasi-y@ops.dti.ne.jp
    for (i=0; i<16; i++) {
2986 d8714436 takasi-y@ops.dti.ne.jp
        err |= __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
2987 d8714436 takasi-y@ops.dti.ne.jp
    }
2988 d8714436 takasi-y@ops.dti.ne.jp
    err |= __put_user(regs->fpscr, &sc->sc_fpscr);
2989 d8714436 takasi-y@ops.dti.ne.jp
    err |= __put_user(regs->fpul, &sc->sc_fpul);
2990 c3b5bc8a ths
2991 c3b5bc8a ths
    /* non-iBCS2 extensions.. */
2992 c3b5bc8a ths
    err |= __put_user(mask, &sc->oldmask);
2993 c3b5bc8a ths
2994 c3b5bc8a ths
    return err;
2995 c3b5bc8a ths
}
2996 c3b5bc8a ths
2997 d8714436 takasi-y@ops.dti.ne.jp
static int restore_sigcontext(CPUState *regs, struct target_sigcontext *sc,
2998 d8714436 takasi-y@ops.dti.ne.jp
                              target_ulong *r0_p)
2999 c3b5bc8a ths
{
3000 c3b5bc8a ths
    unsigned int err = 0;
3001 d8714436 takasi-y@ops.dti.ne.jp
    int i;
3002 c3b5bc8a ths
3003 c3b5bc8a ths
#define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
3004 c3b5bc8a ths
    COPY(gregs[1]);
3005 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
3006 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
3007 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
3008 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
3009 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
3010 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
3011 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
3012 c3b5bc8a ths
    COPY(gbr); COPY(mach);
3013 c3b5bc8a ths
    COPY(macl); COPY(pr);
3014 c3b5bc8a ths
    COPY(sr); COPY(pc);
3015 c3b5bc8a ths
#undef COPY
3016 c3b5bc8a ths
3017 d8714436 takasi-y@ops.dti.ne.jp
    for (i=0; i<16; i++) {
3018 d8714436 takasi-y@ops.dti.ne.jp
        err |= __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
3019 d8714436 takasi-y@ops.dti.ne.jp
    }
3020 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(regs->fpscr, &sc->sc_fpscr);
3021 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(regs->fpul, &sc->sc_fpul);
3022 c3b5bc8a ths
3023 c3b5bc8a ths
    regs->tra = -1;         /* disable syscall checks */
3024 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(*r0_p, &sc->sc_gregs[0]);
3025 c3b5bc8a ths
    return err;
3026 c3b5bc8a ths
}
3027 c3b5bc8a ths
3028 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
3029 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
3030 c3b5bc8a ths
{
3031 c3b5bc8a ths
    struct target_sigframe *frame;
3032 c3b5bc8a ths
    abi_ulong frame_addr;
3033 c3b5bc8a ths
    int i;
3034 c3b5bc8a ths
    int err = 0;
3035 c3b5bc8a ths
    int signal;
3036 c3b5bc8a ths
3037 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3038 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3039 c3b5bc8a ths
        goto give_sigsegv;
3040 c3b5bc8a ths
3041 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
3042 c3b5bc8a ths
3043 c3b5bc8a ths
    err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
3044 c3b5bc8a ths
3045 c3b5bc8a ths
    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
3046 c3b5bc8a ths
        err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
3047 c3b5bc8a ths
    }
3048 c3b5bc8a ths
3049 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
3050 c3b5bc8a ths
       already in userspace.  */
3051 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3052 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
3053 c3b5bc8a ths
    } else {
3054 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
3055 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
3056 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
3057 c3b5bc8a ths
        err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
3058 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
3059 c3b5bc8a ths
    }
3060 c3b5bc8a ths
3061 c3b5bc8a ths
    if (err)
3062 c3b5bc8a ths
        goto give_sigsegv;
3063 c3b5bc8a ths
3064 c3b5bc8a ths
    /* Set up registers for signal handler */
3065 c3b5bc8a ths
    regs->gregs[15] = (unsigned long) frame;
3066 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
3067 c3b5bc8a ths
    regs->gregs[5] = 0;
3068 c3b5bc8a ths
    regs->gregs[6] = (unsigned long) &frame->sc;
3069 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
3070 c3b5bc8a ths
3071 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3072 c3b5bc8a ths
    return;
3073 c3b5bc8a ths
3074 c3b5bc8a ths
give_sigsegv:
3075 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3076 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
3077 c3b5bc8a ths
}
3078 c3b5bc8a ths
3079 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3080 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3081 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
3082 c3b5bc8a ths
{
3083 c3b5bc8a ths
    struct target_rt_sigframe *frame;
3084 c3b5bc8a ths
    abi_ulong frame_addr;
3085 c3b5bc8a ths
    int i;
3086 c3b5bc8a ths
    int err = 0;
3087 c3b5bc8a ths
    int signal;
3088 c3b5bc8a ths
3089 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3090 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3091 c3b5bc8a ths
        goto give_sigsegv;
3092 c3b5bc8a ths
3093 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
3094 c3b5bc8a ths
3095 c3b5bc8a ths
    err |= copy_siginfo_to_user(&frame->info, info);
3096 c3b5bc8a ths
3097 c3b5bc8a ths
    /* Create the ucontext.  */
3098 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
3099 60e99246 Aurelien Jarno
    err |= __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3100 526ccb7a balrog
    err |= __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3101 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
3102 c3b5bc8a ths
    err |= __put_user(sas_ss_flags(regs->gregs[15]),
3103 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
3104 c3b5bc8a ths
    err |= __put_user(target_sigaltstack_used.ss_size,
3105 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
3106 60e99246 Aurelien Jarno
    err |= setup_sigcontext(&frame->uc.tuc_mcontext,
3107 c3b5bc8a ths
                            regs, set->sig[0]);
3108 c3b5bc8a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
3109 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
3110 c3b5bc8a ths
    }
3111 c3b5bc8a ths
3112 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
3113 c3b5bc8a ths
       already in userspace.  */
3114 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3115 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
3116 c3b5bc8a ths
    } else {
3117 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
3118 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
3119 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
3120 c3b5bc8a ths
        err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
3121 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
3122 c3b5bc8a ths
    }
3123 c3b5bc8a ths
3124 c3b5bc8a ths
    if (err)
3125 c3b5bc8a ths
        goto give_sigsegv;
3126 c3b5bc8a ths
3127 c3b5bc8a ths
    /* Set up registers for signal handler */
3128 c3b5bc8a ths
    regs->gregs[15] = (unsigned long) frame;
3129 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
3130 c3b5bc8a ths
    regs->gregs[5] = (unsigned long) &frame->info;
3131 c3b5bc8a ths
    regs->gregs[6] = (unsigned long) &frame->uc;
3132 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
3133 c3b5bc8a ths
3134 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3135 c3b5bc8a ths
    return;
3136 c3b5bc8a ths
3137 c3b5bc8a ths
give_sigsegv:
3138 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3139 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
3140 c3b5bc8a ths
}
3141 c3b5bc8a ths
3142 c3b5bc8a ths
long do_sigreturn(CPUState *regs)
3143 c3b5bc8a ths
{
3144 c3b5bc8a ths
    struct target_sigframe *frame;
3145 c3b5bc8a ths
    abi_ulong frame_addr;
3146 c3b5bc8a ths
    sigset_t blocked;
3147 c227f099 Anthony Liguori
    target_sigset_t target_set;
3148 d8714436 takasi-y@ops.dti.ne.jp
    target_ulong r0;
3149 c3b5bc8a ths
    int i;
3150 c3b5bc8a ths
    int err = 0;
3151 c3b5bc8a ths
3152 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
3153 c3b5bc8a ths
    fprintf(stderr, "do_sigreturn\n");
3154 c3b5bc8a ths
#endif
3155 c3b5bc8a ths
    frame_addr = regs->gregs[15];
3156 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3157 c3b5bc8a ths
           goto badframe;
3158 c3b5bc8a ths
3159 c3b5bc8a ths
    err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
3160 c3b5bc8a ths
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3161 c3b5bc8a ths
        err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
3162 c3b5bc8a ths
    }
3163 c3b5bc8a ths
3164 c3b5bc8a ths
    if (err)
3165 c3b5bc8a ths
        goto badframe;
3166 c3b5bc8a ths
3167 c3b5bc8a ths
    target_to_host_sigset_internal(&blocked, &target_set);
3168 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3169 c3b5bc8a ths
3170 d8714436 takasi-y@ops.dti.ne.jp
    if (restore_sigcontext(regs, &frame->sc, &r0))
3171 c3b5bc8a ths
        goto badframe;
3172 c3b5bc8a ths
3173 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3174 d8714436 takasi-y@ops.dti.ne.jp
    return r0;
3175 c3b5bc8a ths
3176 c3b5bc8a ths
badframe:
3177 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3178 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3179 c3b5bc8a ths
    return 0;
3180 c3b5bc8a ths
}
3181 c3b5bc8a ths
3182 c3b5bc8a ths
long do_rt_sigreturn(CPUState *regs)
3183 c3b5bc8a ths
{
3184 c3b5bc8a ths
    struct target_rt_sigframe *frame;
3185 c3b5bc8a ths
    abi_ulong frame_addr;
3186 c3b5bc8a ths
    sigset_t blocked;
3187 d8714436 takasi-y@ops.dti.ne.jp
    target_ulong r0;
3188 c3b5bc8a ths
3189 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
3190 c3b5bc8a ths
    fprintf(stderr, "do_rt_sigreturn\n");
3191 c3b5bc8a ths
#endif
3192 c3b5bc8a ths
    frame_addr = regs->gregs[15];
3193 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3194 c3b5bc8a ths
           goto badframe;
3195 c3b5bc8a ths
3196 60e99246 Aurelien Jarno
    target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
3197 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3198 c3b5bc8a ths
3199 60e99246 Aurelien Jarno
    if (restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0))
3200 c3b5bc8a ths
        goto badframe;
3201 c3b5bc8a ths
3202 c3b5bc8a ths
    if (do_sigaltstack(frame_addr +
3203 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
3204 c3b5bc8a ths
                       0, get_sp_from_cpustate(regs)) == -EFAULT)
3205 c3b5bc8a ths
        goto badframe;
3206 c3b5bc8a ths
3207 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3208 d8714436 takasi-y@ops.dti.ne.jp
    return r0;
3209 c3b5bc8a ths
3210 c3b5bc8a ths
badframe:
3211 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3212 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3213 c3b5bc8a ths
    return 0;
3214 c3b5bc8a ths
}
3215 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
3216 b779e29e Edgar E. Iglesias
3217 b779e29e Edgar E. Iglesias
struct target_sigcontext {
3218 b779e29e Edgar E. Iglesias
    struct target_pt_regs regs;  /* needs to be first */
3219 b779e29e Edgar E. Iglesias
    uint32_t oldmask;
3220 b779e29e Edgar E. Iglesias
};
3221 b779e29e Edgar E. Iglesias
3222 b2178704 Edgar E. Iglesias
struct target_stack_t {
3223 b2178704 Edgar E. Iglesias
    abi_ulong ss_sp;
3224 b2178704 Edgar E. Iglesias
    int ss_flags;
3225 b2178704 Edgar E. Iglesias
    unsigned int ss_size;
3226 b2178704 Edgar E. Iglesias
};
3227 b2178704 Edgar E. Iglesias
3228 b2178704 Edgar E. Iglesias
struct target_ucontext {
3229 f711df67 Richard Henderson
    abi_ulong tuc_flags;
3230 f711df67 Richard Henderson
    abi_ulong tuc_link;
3231 f711df67 Richard Henderson
    struct target_stack_t tuc_stack;
3232 f711df67 Richard Henderson
    struct target_sigcontext tuc_mcontext;
3233 f711df67 Richard Henderson
    uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
3234 b2178704 Edgar E. Iglesias
};
3235 b2178704 Edgar E. Iglesias
3236 b779e29e Edgar E. Iglesias
/* Signal frames. */
3237 b779e29e Edgar E. Iglesias
struct target_signal_frame {
3238 b2178704 Edgar E. Iglesias
    struct target_ucontext uc;
3239 b779e29e Edgar E. Iglesias
    uint32_t extramask[TARGET_NSIG_WORDS - 1];
3240 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3241 b779e29e Edgar E. Iglesias
};
3242 b779e29e Edgar E. Iglesias
3243 b779e29e Edgar E. Iglesias
struct rt_signal_frame {
3244 b779e29e Edgar E. Iglesias
    struct siginfo info;
3245 b779e29e Edgar E. Iglesias
    struct ucontext uc;
3246 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3247 b779e29e Edgar E. Iglesias
};
3248 b779e29e Edgar E. Iglesias
3249 b779e29e Edgar E. Iglesias
static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
3250 b779e29e Edgar E. Iglesias
{
3251 b779e29e Edgar E. Iglesias
    __put_user(env->regs[0], &sc->regs.r0);
3252 b779e29e Edgar E. Iglesias
    __put_user(env->regs[1], &sc->regs.r1);
3253 b779e29e Edgar E. Iglesias
    __put_user(env->regs[2], &sc->regs.r2);
3254 b779e29e Edgar E. Iglesias
    __put_user(env->regs[3], &sc->regs.r3);
3255 b779e29e Edgar E. Iglesias
    __put_user(env->regs[4], &sc->regs.r4);
3256 b779e29e Edgar E. Iglesias
    __put_user(env->regs[5], &sc->regs.r5);
3257 b779e29e Edgar E. Iglesias
    __put_user(env->regs[6], &sc->regs.r6);
3258 b779e29e Edgar E. Iglesias
    __put_user(env->regs[7], &sc->regs.r7);
3259 b779e29e Edgar E. Iglesias
    __put_user(env->regs[8], &sc->regs.r8);
3260 b779e29e Edgar E. Iglesias
    __put_user(env->regs[9], &sc->regs.r9);
3261 b779e29e Edgar E. Iglesias
    __put_user(env->regs[10], &sc->regs.r10);
3262 b779e29e Edgar E. Iglesias
    __put_user(env->regs[11], &sc->regs.r11);
3263 b779e29e Edgar E. Iglesias
    __put_user(env->regs[12], &sc->regs.r12);
3264 b779e29e Edgar E. Iglesias
    __put_user(env->regs[13], &sc->regs.r13);
3265 b779e29e Edgar E. Iglesias
    __put_user(env->regs[14], &sc->regs.r14);
3266 b779e29e Edgar E. Iglesias
    __put_user(env->regs[15], &sc->regs.r15);
3267 b779e29e Edgar E. Iglesias
    __put_user(env->regs[16], &sc->regs.r16);
3268 b779e29e Edgar E. Iglesias
    __put_user(env->regs[17], &sc->regs.r17);
3269 b779e29e Edgar E. Iglesias
    __put_user(env->regs[18], &sc->regs.r18);
3270 b779e29e Edgar E. Iglesias
    __put_user(env->regs[19], &sc->regs.r19);
3271 b779e29e Edgar E. Iglesias
    __put_user(env->regs[20], &sc->regs.r20);
3272 b779e29e Edgar E. Iglesias
    __put_user(env->regs[21], &sc->regs.r21);
3273 b779e29e Edgar E. Iglesias
    __put_user(env->regs[22], &sc->regs.r22);
3274 b779e29e Edgar E. Iglesias
    __put_user(env->regs[23], &sc->regs.r23);
3275 b779e29e Edgar E. Iglesias
    __put_user(env->regs[24], &sc->regs.r24);
3276 b779e29e Edgar E. Iglesias
    __put_user(env->regs[25], &sc->regs.r25);
3277 b779e29e Edgar E. Iglesias
    __put_user(env->regs[26], &sc->regs.r26);
3278 b779e29e Edgar E. Iglesias
    __put_user(env->regs[27], &sc->regs.r27);
3279 b779e29e Edgar E. Iglesias
    __put_user(env->regs[28], &sc->regs.r28);
3280 b779e29e Edgar E. Iglesias
    __put_user(env->regs[29], &sc->regs.r29);
3281 b779e29e Edgar E. Iglesias
    __put_user(env->regs[30], &sc->regs.r30);
3282 b779e29e Edgar E. Iglesias
    __put_user(env->regs[31], &sc->regs.r31);
3283 b779e29e Edgar E. Iglesias
    __put_user(env->sregs[SR_PC], &sc->regs.pc);
3284 b779e29e Edgar E. Iglesias
}
3285 b779e29e Edgar E. Iglesias
3286 b779e29e Edgar E. Iglesias
static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
3287 b779e29e Edgar E. Iglesias
{
3288 b779e29e Edgar E. Iglesias
    __get_user(env->regs[0], &sc->regs.r0);
3289 b779e29e Edgar E. Iglesias
    __get_user(env->regs[1], &sc->regs.r1);
3290 b779e29e Edgar E. Iglesias
    __get_user(env->regs[2], &sc->regs.r2);
3291 b779e29e Edgar E. Iglesias
    __get_user(env->regs[3], &sc->regs.r3);
3292 b779e29e Edgar E. Iglesias
    __get_user(env->regs[4], &sc->regs.r4);
3293 b779e29e Edgar E. Iglesias
    __get_user(env->regs[5], &sc->regs.r5);
3294 b779e29e Edgar E. Iglesias
    __get_user(env->regs[6], &sc->regs.r6);
3295 b779e29e Edgar E. Iglesias
    __get_user(env->regs[7], &sc->regs.r7);
3296 b779e29e Edgar E. Iglesias
    __get_user(env->regs[8], &sc->regs.r8);
3297 b779e29e Edgar E. Iglesias
    __get_user(env->regs[9], &sc->regs.r9);
3298 b779e29e Edgar E. Iglesias
    __get_user(env->regs[10], &sc->regs.r10);
3299 b779e29e Edgar E. Iglesias
    __get_user(env->regs[11], &sc->regs.r11);
3300 b779e29e Edgar E. Iglesias
    __get_user(env->regs[12], &sc->regs.r12);
3301 b779e29e Edgar E. Iglesias
    __get_user(env->regs[13], &sc->regs.r13);
3302 b779e29e Edgar E. Iglesias
    __get_user(env->regs[14], &sc->regs.r14);
3303 b779e29e Edgar E. Iglesias
    __get_user(env->regs[15], &sc->regs.r15);
3304 b779e29e Edgar E. Iglesias
    __get_user(env->regs[16], &sc->regs.r16);
3305 b779e29e Edgar E. Iglesias
    __get_user(env->regs[17], &sc->regs.r17);
3306 b779e29e Edgar E. Iglesias
    __get_user(env->regs[18], &sc->regs.r18);
3307 b779e29e Edgar E. Iglesias
    __get_user(env->regs[19], &sc->regs.r19);
3308 b779e29e Edgar E. Iglesias
    __get_user(env->regs[20], &sc->regs.r20);
3309 b779e29e Edgar E. Iglesias
    __get_user(env->regs[21], &sc->regs.r21);
3310 b779e29e Edgar E. Iglesias
    __get_user(env->regs[22], &sc->regs.r22);
3311 b779e29e Edgar E. Iglesias
    __get_user(env->regs[23], &sc->regs.r23);
3312 b779e29e Edgar E. Iglesias
    __get_user(env->regs[24], &sc->regs.r24);
3313 b779e29e Edgar E. Iglesias
    __get_user(env->regs[25], &sc->regs.r25);
3314 b779e29e Edgar E. Iglesias
    __get_user(env->regs[26], &sc->regs.r26);
3315 b779e29e Edgar E. Iglesias
    __get_user(env->regs[27], &sc->regs.r27);
3316 b779e29e Edgar E. Iglesias
    __get_user(env->regs[28], &sc->regs.r28);
3317 b779e29e Edgar E. Iglesias
    __get_user(env->regs[29], &sc->regs.r29);
3318 b779e29e Edgar E. Iglesias
    __get_user(env->regs[30], &sc->regs.r30);
3319 b779e29e Edgar E. Iglesias
    __get_user(env->regs[31], &sc->regs.r31);
3320 b779e29e Edgar E. Iglesias
    __get_user(env->sregs[SR_PC], &sc->regs.pc);
3321 b779e29e Edgar E. Iglesias
}
3322 b779e29e Edgar E. Iglesias
3323 b779e29e Edgar E. Iglesias
static abi_ulong get_sigframe(struct target_sigaction *ka,
3324 b779e29e Edgar E. Iglesias
                              CPUState *env, int frame_size)
3325 b779e29e Edgar E. Iglesias
{
3326 b779e29e Edgar E. Iglesias
    abi_ulong sp = env->regs[1];
3327 b779e29e Edgar E. Iglesias
3328 b779e29e Edgar E. Iglesias
    if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
3329 b779e29e Edgar E. Iglesias
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3330 b779e29e Edgar E. Iglesias
3331 b779e29e Edgar E. Iglesias
    return ((sp - frame_size) & -8UL);
3332 b779e29e Edgar E. Iglesias
}
3333 b779e29e Edgar E. Iglesias
3334 b779e29e Edgar E. Iglesias
static void setup_frame(int sig, struct target_sigaction *ka,
3335 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3336 b779e29e Edgar E. Iglesias
{
3337 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3338 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3339 b779e29e Edgar E. Iglesias
    int err = 0;
3340 b779e29e Edgar E. Iglesias
    int i;
3341 b779e29e Edgar E. Iglesias
3342 b779e29e Edgar E. Iglesias
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3343 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3344 b779e29e Edgar E. Iglesias
        goto badframe;
3345 b779e29e Edgar E. Iglesias
3346 b779e29e Edgar E. Iglesias
    /* Save the mask.  */
3347 f711df67 Richard Henderson
    err |= __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
3348 b779e29e Edgar E. Iglesias
    if (err)
3349 b779e29e Edgar E. Iglesias
        goto badframe;
3350 b779e29e Edgar E. Iglesias
3351 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3352 b779e29e Edgar E. Iglesias
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3353 b779e29e Edgar E. Iglesias
            goto badframe;
3354 b779e29e Edgar E. Iglesias
    }
3355 b779e29e Edgar E. Iglesias
3356 f711df67 Richard Henderson
    setup_sigcontext(&frame->uc.tuc_mcontext, env);
3357 b779e29e Edgar E. Iglesias
3358 b779e29e Edgar E. Iglesias
    /* Set up to return from userspace. If provided, use a stub
3359 b779e29e Edgar E. Iglesias
       already in userspace. */
3360 b779e29e Edgar E. Iglesias
    /* minus 8 is offset to cater for "rtsd r15,8" offset */
3361 b779e29e Edgar E. Iglesias
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3362 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3363 b779e29e Edgar E. Iglesias
    } else {
3364 b779e29e Edgar E. Iglesias
        uint32_t t;
3365 b779e29e Edgar E. Iglesias
        /* Note, these encodings are _big endian_! */
3366 b779e29e Edgar E. Iglesias
        /* addi r12, r0, __NR_sigreturn */
3367 b779e29e Edgar E. Iglesias
        t = 0x31800000UL | TARGET_NR_sigreturn;
3368 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 0);
3369 b779e29e Edgar E. Iglesias
        /* brki r14, 0x8 */
3370 b779e29e Edgar E. Iglesias
        t = 0xb9cc0008UL;
3371 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 1);
3372 b779e29e Edgar E. Iglesias
3373 b779e29e Edgar E. Iglesias
        /* Return from sighandler will jump to the tramp.
3374 b779e29e Edgar E. Iglesias
           Negative 8 offset because return is rtsd r15, 8 */
3375 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)frame->tramp) - 8;
3376 b779e29e Edgar E. Iglesias
    }
3377 b779e29e Edgar E. Iglesias
3378 b779e29e Edgar E. Iglesias
    if (err)
3379 b779e29e Edgar E. Iglesias
        goto badframe;
3380 b779e29e Edgar E. Iglesias
3381 b779e29e Edgar E. Iglesias
    /* Set up registers for signal handler */
3382 b779e29e Edgar E. Iglesias
    env->regs[1] = (unsigned long) frame;
3383 b779e29e Edgar E. Iglesias
    /* Signal handler args: */
3384 b779e29e Edgar E. Iglesias
    env->regs[5] = sig; /* Arg 0: signum */
3385 187b4e08 Edgar E. Iglesias
    env->regs[6] = 0;
3386 b2178704 Edgar E. Iglesias
    env->regs[7] = (unsigned long) &frame->uc; /* arg 1: sigcontext */
3387 b779e29e Edgar E. Iglesias
3388 b779e29e Edgar E. Iglesias
    /* Offset of 4 to handle microblaze rtid r14, 0 */
3389 b779e29e Edgar E. Iglesias
    env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3390 b779e29e Edgar E. Iglesias
3391 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3392 b779e29e Edgar E. Iglesias
    return;
3393 b779e29e Edgar E. Iglesias
  badframe:
3394 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3395 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3396 b779e29e Edgar E. Iglesias
}
3397 b779e29e Edgar E. Iglesias
3398 b779e29e Edgar E. Iglesias
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3399 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3400 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
3401 b779e29e Edgar E. Iglesias
{
3402 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3403 b779e29e Edgar E. Iglesias
}
3404 b779e29e Edgar E. Iglesias
3405 b779e29e Edgar E. Iglesias
long do_sigreturn(CPUState *env)
3406 b779e29e Edgar E. Iglesias
{
3407 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3408 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3409 c227f099 Anthony Liguori
    target_sigset_t target_set;
3410 b779e29e Edgar E. Iglesias
    sigset_t set;
3411 b779e29e Edgar E. Iglesias
    int i;
3412 b779e29e Edgar E. Iglesias
3413 b779e29e Edgar E. Iglesias
    frame_addr = env->regs[R_SP];
3414 b779e29e Edgar E. Iglesias
    /* Make sure the guest isn't playing games.  */
3415 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3416 b779e29e Edgar E. Iglesias
        goto badframe;
3417 b779e29e Edgar E. Iglesias
3418 b779e29e Edgar E. Iglesias
    /* Restore blocked signals */
3419 f711df67 Richard Henderson
    if (__get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask))
3420 b779e29e Edgar E. Iglesias
        goto badframe;
3421 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3422 b779e29e Edgar E. Iglesias
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3423 b779e29e Edgar E. Iglesias
            goto badframe;
3424 b779e29e Edgar E. Iglesias
    }
3425 b779e29e Edgar E. Iglesias
    target_to_host_sigset_internal(&set, &target_set);
3426 b779e29e Edgar E. Iglesias
    sigprocmask(SIG_SETMASK, &set, NULL);
3427 b779e29e Edgar E. Iglesias
3428 f711df67 Richard Henderson
    restore_sigcontext(&frame->uc.tuc_mcontext, env);
3429 b779e29e Edgar E. Iglesias
    /* We got here through a sigreturn syscall, our path back is via an
3430 b779e29e Edgar E. Iglesias
       rtb insn so setup r14 for that.  */
3431 b779e29e Edgar E. Iglesias
    env->regs[14] = env->sregs[SR_PC];
3432 b779e29e Edgar E. Iglesias
 
3433 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3434 b779e29e Edgar E. Iglesias
    return env->regs[10];
3435 b779e29e Edgar E. Iglesias
  badframe:
3436 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3437 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3438 b779e29e Edgar E. Iglesias
}
3439 b779e29e Edgar E. Iglesias
3440 b779e29e Edgar E. Iglesias
long do_rt_sigreturn(CPUState *env)
3441 b779e29e Edgar E. Iglesias
{
3442 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3443 b779e29e Edgar E. Iglesias
    return -TARGET_ENOSYS;
3444 b779e29e Edgar E. Iglesias
}
3445 b779e29e Edgar E. Iglesias
3446 b6d3abda edgar_igl
#elif defined(TARGET_CRIS)
3447 b6d3abda edgar_igl
3448 b6d3abda edgar_igl
struct target_sigcontext {
3449 b6d3abda edgar_igl
        struct target_pt_regs regs;  /* needs to be first */
3450 b6d3abda edgar_igl
        uint32_t oldmask;
3451 b6d3abda edgar_igl
        uint32_t usp;    /* usp before stacking this gunk on it */
3452 b6d3abda edgar_igl
};
3453 b6d3abda edgar_igl
3454 b6d3abda edgar_igl
/* Signal frames. */
3455 b6d3abda edgar_igl
struct target_signal_frame {
3456 b6d3abda edgar_igl
        struct target_sigcontext sc;
3457 b6d3abda edgar_igl
        uint32_t extramask[TARGET_NSIG_WORDS - 1];
3458 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3459 b6d3abda edgar_igl
};
3460 b6d3abda edgar_igl
3461 b6d3abda edgar_igl
struct rt_signal_frame {
3462 b6d3abda edgar_igl
        struct siginfo *pinfo;
3463 b6d3abda edgar_igl
        void *puc;
3464 b6d3abda edgar_igl
        struct siginfo info;
3465 b6d3abda edgar_igl
        struct ucontext uc;
3466 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3467 b6d3abda edgar_igl
};
3468 b6d3abda edgar_igl
3469 b6d3abda edgar_igl
static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
3470 b6d3abda edgar_igl
{
3471 9664d928 edgar_igl
        __put_user(env->regs[0], &sc->regs.r0);
3472 9664d928 edgar_igl
        __put_user(env->regs[1], &sc->regs.r1);
3473 9664d928 edgar_igl
        __put_user(env->regs[2], &sc->regs.r2);
3474 9664d928 edgar_igl
        __put_user(env->regs[3], &sc->regs.r3);
3475 9664d928 edgar_igl
        __put_user(env->regs[4], &sc->regs.r4);
3476 9664d928 edgar_igl
        __put_user(env->regs[5], &sc->regs.r5);
3477 9664d928 edgar_igl
        __put_user(env->regs[6], &sc->regs.r6);
3478 9664d928 edgar_igl
        __put_user(env->regs[7], &sc->regs.r7);
3479 9664d928 edgar_igl
        __put_user(env->regs[8], &sc->regs.r8);
3480 9664d928 edgar_igl
        __put_user(env->regs[9], &sc->regs.r9);
3481 9664d928 edgar_igl
        __put_user(env->regs[10], &sc->regs.r10);
3482 9664d928 edgar_igl
        __put_user(env->regs[11], &sc->regs.r11);
3483 9664d928 edgar_igl
        __put_user(env->regs[12], &sc->regs.r12);
3484 9664d928 edgar_igl
        __put_user(env->regs[13], &sc->regs.r13);
3485 9664d928 edgar_igl
        __put_user(env->regs[14], &sc->usp);
3486 9664d928 edgar_igl
        __put_user(env->regs[15], &sc->regs.acr);
3487 9664d928 edgar_igl
        __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3488 9664d928 edgar_igl
        __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3489 9664d928 edgar_igl
        __put_user(env->pc, &sc->regs.erp);
3490 b6d3abda edgar_igl
}
3491 9664d928 edgar_igl
3492 b6d3abda edgar_igl
static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
3493 b6d3abda edgar_igl
{
3494 9664d928 edgar_igl
        __get_user(env->regs[0], &sc->regs.r0);
3495 9664d928 edgar_igl
        __get_user(env->regs[1], &sc->regs.r1);
3496 9664d928 edgar_igl
        __get_user(env->regs[2], &sc->regs.r2);
3497 9664d928 edgar_igl
        __get_user(env->regs[3], &sc->regs.r3);
3498 9664d928 edgar_igl
        __get_user(env->regs[4], &sc->regs.r4);
3499 9664d928 edgar_igl
        __get_user(env->regs[5], &sc->regs.r5);
3500 9664d928 edgar_igl
        __get_user(env->regs[6], &sc->regs.r6);
3501 9664d928 edgar_igl
        __get_user(env->regs[7], &sc->regs.r7);
3502 9664d928 edgar_igl
        __get_user(env->regs[8], &sc->regs.r8);
3503 9664d928 edgar_igl
        __get_user(env->regs[9], &sc->regs.r9);
3504 9664d928 edgar_igl
        __get_user(env->regs[10], &sc->regs.r10);
3505 9664d928 edgar_igl
        __get_user(env->regs[11], &sc->regs.r11);
3506 9664d928 edgar_igl
        __get_user(env->regs[12], &sc->regs.r12);
3507 9664d928 edgar_igl
        __get_user(env->regs[13], &sc->regs.r13);
3508 9664d928 edgar_igl
        __get_user(env->regs[14], &sc->usp);
3509 9664d928 edgar_igl
        __get_user(env->regs[15], &sc->regs.acr);
3510 9664d928 edgar_igl
        __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3511 9664d928 edgar_igl
        __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3512 9664d928 edgar_igl
        __get_user(env->pc, &sc->regs.erp);
3513 9664d928 edgar_igl
}
3514 9664d928 edgar_igl
3515 9664d928 edgar_igl
static abi_ulong get_sigframe(CPUState *env, int framesize)
3516 9664d928 edgar_igl
{
3517 9664d928 edgar_igl
        abi_ulong sp;
3518 b6d3abda edgar_igl
        /* Align the stack downwards to 4.  */
3519 9664d928 edgar_igl
        sp = (env->regs[R_SP] & ~3);
3520 9664d928 edgar_igl
        return sp - framesize;
3521 b6d3abda edgar_igl
}
3522 b6d3abda edgar_igl
3523 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
3524 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3525 b6d3abda edgar_igl
{
3526 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3527 9664d928 edgar_igl
        abi_ulong frame_addr;
3528 b6d3abda edgar_igl
        int err = 0;
3529 b6d3abda edgar_igl
        int i;
3530 b6d3abda edgar_igl
3531 9664d928 edgar_igl
        frame_addr = get_sigframe(env, sizeof *frame);
3532 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3533 b6d3abda edgar_igl
                goto badframe;
3534 b6d3abda edgar_igl
3535 b6d3abda edgar_igl
        /*
3536 b6d3abda edgar_igl
         * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3537 b6d3abda edgar_igl
         * use this trampoline anymore but it sets it up for GDB.
3538 b6d3abda edgar_igl
         * In QEMU, using the trampoline simplifies things a bit so we use it.
3539 b6d3abda edgar_igl
         *
3540 b6d3abda edgar_igl
         * This is movu.w __NR_sigreturn, r9; break 13;
3541 b6d3abda edgar_igl
         */
3542 b6d3abda edgar_igl
        err |= __put_user(0x9c5f, frame->retcode+0);
3543 b6d3abda edgar_igl
        err |= __put_user(TARGET_NR_sigreturn, 
3544 b6d3abda edgar_igl
                          frame->retcode+2);
3545 b6d3abda edgar_igl
        err |= __put_user(0xe93d, frame->retcode+4);
3546 b6d3abda edgar_igl
3547 b6d3abda edgar_igl
        /* Save the mask.  */
3548 b6d3abda edgar_igl
        err |= __put_user(set->sig[0], &frame->sc.oldmask);
3549 b6d3abda edgar_igl
        if (err)
3550 b6d3abda edgar_igl
                goto badframe;
3551 b6d3abda edgar_igl
3552 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3553 b6d3abda edgar_igl
                if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3554 b6d3abda edgar_igl
                        goto badframe;
3555 b6d3abda edgar_igl
        }
3556 b6d3abda edgar_igl
3557 b6d3abda edgar_igl
        setup_sigcontext(&frame->sc, env);
3558 b6d3abda edgar_igl
3559 b6d3abda edgar_igl
        /* Move the stack and setup the arguments for the handler.  */
3560 526ccb7a balrog
        env->regs[R_SP] = (uint32_t) (unsigned long) frame;
3561 b6d3abda edgar_igl
        env->regs[10] = sig;
3562 624f7979 pbrook
        env->pc = (unsigned long) ka->_sa_handler;
3563 b6d3abda edgar_igl
        /* Link SRP so the guest returns through the trampoline.  */
3564 526ccb7a balrog
        env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0];
3565 b6d3abda edgar_igl
3566 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3567 b6d3abda edgar_igl
        return;
3568 b6d3abda edgar_igl
  badframe:
3569 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3570 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3571 b6d3abda edgar_igl
}
3572 b6d3abda edgar_igl
3573 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3574 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3575 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
3576 b6d3abda edgar_igl
{
3577 b6d3abda edgar_igl
    fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3578 b6d3abda edgar_igl
}
3579 b6d3abda edgar_igl
3580 b6d3abda edgar_igl
long do_sigreturn(CPUState *env)
3581 b6d3abda edgar_igl
{
3582 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3583 9664d928 edgar_igl
        abi_ulong frame_addr;
3584 c227f099 Anthony Liguori
        target_sigset_t target_set;
3585 b6d3abda edgar_igl
        sigset_t set;
3586 b6d3abda edgar_igl
        int i;
3587 b6d3abda edgar_igl
3588 9664d928 edgar_igl
        frame_addr = env->regs[R_SP];
3589 b6d3abda edgar_igl
        /* Make sure the guest isn't playing games.  */
3590 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3591 b6d3abda edgar_igl
                goto badframe;
3592 b6d3abda edgar_igl
3593 b6d3abda edgar_igl
        /* Restore blocked signals */
3594 b6d3abda edgar_igl
        if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3595 b6d3abda edgar_igl
                goto badframe;
3596 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3597 b6d3abda edgar_igl
                if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3598 b6d3abda edgar_igl
                        goto badframe;
3599 b6d3abda edgar_igl
        }
3600 b6d3abda edgar_igl
        target_to_host_sigset_internal(&set, &target_set);
3601 b6d3abda edgar_igl
        sigprocmask(SIG_SETMASK, &set, NULL);
3602 b6d3abda edgar_igl
3603 b6d3abda edgar_igl
        restore_sigcontext(&frame->sc, env);
3604 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3605 b6d3abda edgar_igl
        return env->regs[10];
3606 b6d3abda edgar_igl
  badframe:
3607 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3608 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3609 b6d3abda edgar_igl
}
3610 b6d3abda edgar_igl
3611 b6d3abda edgar_igl
long do_rt_sigreturn(CPUState *env)
3612 b6d3abda edgar_igl
{
3613 b6d3abda edgar_igl
    fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3614 b6d3abda edgar_igl
    return -TARGET_ENOSYS;
3615 b6d3abda edgar_igl
}
3616 c3b5bc8a ths
3617 bcd4933a Nathan Froyd
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
3618 bcd4933a Nathan Froyd
3619 bcd4933a Nathan Froyd
/* FIXME: Many of the structures are defined for both PPC and PPC64, but
3620 bcd4933a Nathan Froyd
   the signal handling is different enough that we haven't implemented
3621 bcd4933a Nathan Froyd
   support for PPC64 yet.  Hence the restriction above.
3622 bcd4933a Nathan Froyd

3623 bcd4933a Nathan Froyd
   There are various #if'd blocks for code for TARGET_PPC64.  These
3624 bcd4933a Nathan Froyd
   blocks should go away so that we can successfully run 32-bit and
3625 bcd4933a Nathan Froyd
   64-bit binaries on a QEMU configured for PPC64.  */
3626 bcd4933a Nathan Froyd
3627 bcd4933a Nathan Froyd
/* Size of dummy stack frame allocated when calling signal handler.
3628 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h.  */
3629 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3630 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 128
3631 bcd4933a Nathan Froyd
#else
3632 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 64
3633 bcd4933a Nathan Froyd
#endif
3634 bcd4933a Nathan Froyd
3635 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/sigcontext.h.  */
3636 bcd4933a Nathan Froyd
struct target_sigcontext {
3637 bcd4933a Nathan Froyd
    target_ulong _unused[4];
3638 bcd4933a Nathan Froyd
    int32_t signal;
3639 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3640 bcd4933a Nathan Froyd
    int32_t pad0;
3641 bcd4933a Nathan Froyd
#endif
3642 bcd4933a Nathan Froyd
    target_ulong handler;
3643 bcd4933a Nathan Froyd
    target_ulong oldmask;
3644 bcd4933a Nathan Froyd
    target_ulong regs;      /* struct pt_regs __user * */
3645 bcd4933a Nathan Froyd
    /* TODO: PPC64 includes extra bits here.  */
3646 bcd4933a Nathan Froyd
};
3647 bcd4933a Nathan Froyd
3648 bcd4933a Nathan Froyd
/* Indices for target_mcontext.mc_gregs, below.
3649 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h for details.  */
3650 bcd4933a Nathan Froyd
enum {
3651 bcd4933a Nathan Froyd
    TARGET_PT_R0 = 0,
3652 bcd4933a Nathan Froyd
    TARGET_PT_R1 = 1,
3653 bcd4933a Nathan Froyd
    TARGET_PT_R2 = 2,
3654 bcd4933a Nathan Froyd
    TARGET_PT_R3 = 3,
3655 bcd4933a Nathan Froyd
    TARGET_PT_R4 = 4,
3656 bcd4933a Nathan Froyd
    TARGET_PT_R5 = 5,
3657 bcd4933a Nathan Froyd
    TARGET_PT_R6 = 6,
3658 bcd4933a Nathan Froyd
    TARGET_PT_R7 = 7,
3659 bcd4933a Nathan Froyd
    TARGET_PT_R8 = 8,
3660 bcd4933a Nathan Froyd
    TARGET_PT_R9 = 9,
3661 bcd4933a Nathan Froyd
    TARGET_PT_R10 = 10,
3662 bcd4933a Nathan Froyd
    TARGET_PT_R11 = 11,
3663 bcd4933a Nathan Froyd
    TARGET_PT_R12 = 12,
3664 bcd4933a Nathan Froyd
    TARGET_PT_R13 = 13,
3665 bcd4933a Nathan Froyd
    TARGET_PT_R14 = 14,
3666 bcd4933a Nathan Froyd
    TARGET_PT_R15 = 15,
3667 bcd4933a Nathan Froyd
    TARGET_PT_R16 = 16,
3668 bcd4933a Nathan Froyd
    TARGET_PT_R17 = 17,
3669 bcd4933a Nathan Froyd
    TARGET_PT_R18 = 18,
3670 bcd4933a Nathan Froyd
    TARGET_PT_R19 = 19,
3671 bcd4933a Nathan Froyd
    TARGET_PT_R20 = 20,
3672 bcd4933a Nathan Froyd
    TARGET_PT_R21 = 21,
3673 bcd4933a Nathan Froyd
    TARGET_PT_R22 = 22,
3674 bcd4933a Nathan Froyd
    TARGET_PT_R23 = 23,
3675 bcd4933a Nathan Froyd
    TARGET_PT_R24 = 24,
3676 bcd4933a Nathan Froyd
    TARGET_PT_R25 = 25,
3677 bcd4933a Nathan Froyd
    TARGET_PT_R26 = 26,
3678 bcd4933a Nathan Froyd
    TARGET_PT_R27 = 27,
3679 bcd4933a Nathan Froyd
    TARGET_PT_R28 = 28,
3680 bcd4933a Nathan Froyd
    TARGET_PT_R29 = 29,
3681 bcd4933a Nathan Froyd
    TARGET_PT_R30 = 30,
3682 bcd4933a Nathan Froyd
    TARGET_PT_R31 = 31,
3683 bcd4933a Nathan Froyd
    TARGET_PT_NIP = 32,
3684 bcd4933a Nathan Froyd
    TARGET_PT_MSR = 33,
3685 bcd4933a Nathan Froyd
    TARGET_PT_ORIG_R3 = 34,
3686 bcd4933a Nathan Froyd
    TARGET_PT_CTR = 35,
3687 bcd4933a Nathan Froyd
    TARGET_PT_LNK = 36,
3688 bcd4933a Nathan Froyd
    TARGET_PT_XER = 37,
3689 bcd4933a Nathan Froyd
    TARGET_PT_CCR = 38,
3690 bcd4933a Nathan Froyd
    /* Yes, there are two registers with #39.  One is 64-bit only.  */
3691 bcd4933a Nathan Froyd
    TARGET_PT_MQ = 39,
3692 bcd4933a Nathan Froyd
    TARGET_PT_SOFTE = 39,
3693 bcd4933a Nathan Froyd
    TARGET_PT_TRAP = 40,
3694 bcd4933a Nathan Froyd
    TARGET_PT_DAR = 41,
3695 bcd4933a Nathan Froyd
    TARGET_PT_DSISR = 42,
3696 bcd4933a Nathan Froyd
    TARGET_PT_RESULT = 43,
3697 bcd4933a Nathan Froyd
    TARGET_PT_REGS_COUNT = 44
3698 bcd4933a Nathan Froyd
};
3699 bcd4933a Nathan Froyd
3700 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
3701 bcd4933a Nathan Froyd
   on 64-bit PPC, sigcontext and mcontext are one and the same.  */
3702 bcd4933a Nathan Froyd
struct target_mcontext {
3703 bcd4933a Nathan Froyd
    target_ulong mc_gregs[48];
3704 bcd4933a Nathan Froyd
    /* Includes fpscr.  */
3705 bcd4933a Nathan Froyd
    uint64_t mc_fregs[33];
3706 bcd4933a Nathan Froyd
    target_ulong mc_pad[2];
3707 bcd4933a Nathan Froyd
    /* We need to handle Altivec and SPE at the same time, which no
3708 bcd4933a Nathan Froyd
       kernel needs to do.  Fortunately, the kernel defines this bit to
3709 bcd4933a Nathan Froyd
       be Altivec-register-large all the time, rather than trying to
3710 bcd4933a Nathan Froyd
       twiddle it based on the specific platform.  */
3711 bcd4933a Nathan Froyd
    union {
3712 bcd4933a Nathan Froyd
        /* SPE vector registers.  One extra for SPEFSCR.  */
3713 bcd4933a Nathan Froyd
        uint32_t spe[33];
3714 bcd4933a Nathan Froyd
        /* Altivec vector registers.  The packing of VSCR and VRSAVE
3715 bcd4933a Nathan Froyd
           varies depending on whether we're PPC64 or not: PPC64 splits
3716 bcd4933a Nathan Froyd
           them apart; PPC32 stuffs them together.  */
3717 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3718 3efa9a67 malc
#define QEMU_NVRREG 34
3719 bcd4933a Nathan Froyd
#else
3720 3efa9a67 malc
#define QEMU_NVRREG 33
3721 bcd4933a Nathan Froyd
#endif
3722 c227f099 Anthony Liguori
        ppc_avr_t altivec[QEMU_NVRREG];
3723 3efa9a67 malc
#undef QEMU_NVRREG
3724 bcd4933a Nathan Froyd
    } mc_vregs __attribute__((__aligned__(16)));
3725 bcd4933a Nathan Froyd
};
3726 bcd4933a Nathan Froyd
3727 bcd4933a Nathan Froyd
struct target_ucontext {
3728 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
3729 60e99246 Aurelien Jarno
    target_ulong tuc_link;    /* struct ucontext __user * */
3730 60e99246 Aurelien Jarno
    struct target_sigaltstack tuc_stack;
3731 bcd4933a Nathan Froyd
#if !defined(TARGET_PPC64)
3732 60e99246 Aurelien Jarno
    int32_t tuc_pad[7];
3733 60e99246 Aurelien Jarno
    target_ulong tuc_regs;    /* struct mcontext __user *
3734 bcd4933a Nathan Froyd
                                points to uc_mcontext field */
3735 bcd4933a Nathan Froyd
#endif
3736 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
3737 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3738 c227f099 Anthony Liguori
    target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
3739 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
3740 bcd4933a Nathan Froyd
#else
3741 60e99246 Aurelien Jarno
    int32_t tuc_maskext[30];
3742 60e99246 Aurelien Jarno
    int32_t tuc_pad2[3];
3743 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
3744 bcd4933a Nathan Froyd
#endif
3745 bcd4933a Nathan Froyd
};
3746 bcd4933a Nathan Froyd
3747 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
3748 bcd4933a Nathan Froyd
struct target_sigframe {
3749 bcd4933a Nathan Froyd
    struct target_sigcontext sctx;
3750 bcd4933a Nathan Froyd
    struct target_mcontext mctx;
3751 bcd4933a Nathan Froyd
    int32_t abigap[56];
3752 bcd4933a Nathan Froyd
};
3753 bcd4933a Nathan Froyd
3754 bcd4933a Nathan Froyd
struct target_rt_sigframe {
3755 bcd4933a Nathan Froyd
    struct target_siginfo info;
3756 bcd4933a Nathan Froyd
    struct target_ucontext uc;
3757 bcd4933a Nathan Froyd
    int32_t abigap[56];
3758 bcd4933a Nathan Froyd
};
3759 bcd4933a Nathan Froyd
3760 bcd4933a Nathan Froyd
/* We use the mc_pad field for the signal return trampoline.  */
3761 bcd4933a Nathan Froyd
#define tramp mc_pad
3762 bcd4933a Nathan Froyd
3763 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal.c.  */
3764 bcd4933a Nathan Froyd
static target_ulong get_sigframe(struct target_sigaction *ka,
3765 bcd4933a Nathan Froyd
                                 CPUState *env,
3766 bcd4933a Nathan Froyd
                                 int frame_size)
3767 bcd4933a Nathan Froyd
{
3768 bcd4933a Nathan Froyd
    target_ulong oldsp, newsp;
3769 bcd4933a Nathan Froyd
3770 bcd4933a Nathan Froyd
    oldsp = env->gpr[1];
3771 bcd4933a Nathan Froyd
3772 bcd4933a Nathan Froyd
    if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
3773 bcd4933a Nathan Froyd
        (sas_ss_flags(oldsp))) {
3774 bcd4933a Nathan Froyd
        oldsp = (target_sigaltstack_used.ss_sp
3775 bcd4933a Nathan Froyd
                 + target_sigaltstack_used.ss_size);
3776 bcd4933a Nathan Froyd
    }
3777 bcd4933a Nathan Froyd
3778 bcd4933a Nathan Froyd
    newsp = (oldsp - frame_size) & ~0xFUL;
3779 bcd4933a Nathan Froyd
3780 bcd4933a Nathan Froyd
    return newsp;
3781 bcd4933a Nathan Froyd
}
3782 bcd4933a Nathan Froyd
3783 bcd4933a Nathan Froyd
static int save_user_regs(CPUState *env, struct target_mcontext *frame,
3784 bcd4933a Nathan Froyd
                          int sigret)
3785 bcd4933a Nathan Froyd
{
3786 bcd4933a Nathan Froyd
    target_ulong msr = env->msr;
3787 bcd4933a Nathan Froyd
    int i;
3788 bcd4933a Nathan Froyd
    target_ulong ccr = 0;
3789 bcd4933a Nathan Froyd
3790 bcd4933a Nathan Froyd
    /* In general, the kernel attempts to be intelligent about what it
3791 bcd4933a Nathan Froyd
       needs to save for Altivec/FP/SPE registers.  We don't care that
3792 bcd4933a Nathan Froyd
       much, so we just go ahead and save everything.  */
3793 bcd4933a Nathan Froyd
3794 bcd4933a Nathan Froyd
    /* Save general registers.  */
3795 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3796 bcd4933a Nathan Froyd
        if (__put_user(env->gpr[i], &frame->mc_gregs[i])) {
3797 bcd4933a Nathan Froyd
            return 1;
3798 bcd4933a Nathan Froyd
        }
3799 bcd4933a Nathan Froyd
    }
3800 bcd4933a Nathan Froyd
    if (__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
3801 bcd4933a Nathan Froyd
        || __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
3802 bcd4933a Nathan Froyd
        || __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
3803 bcd4933a Nathan Froyd
        || __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
3804 bcd4933a Nathan Froyd
        return 1;
3805 bcd4933a Nathan Froyd
3806 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
3807 bcd4933a Nathan Froyd
        ccr |= env->crf[i] << (32 - ((i + 1) * 4));
3808 bcd4933a Nathan Froyd
    }
3809 bcd4933a Nathan Froyd
    if (__put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
3810 bcd4933a Nathan Froyd
        return 1;
3811 bcd4933a Nathan Froyd
3812 bcd4933a Nathan Froyd
    /* Save Altivec registers if necessary.  */
3813 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
3814 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
3815 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
3816 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
3817 bcd4933a Nathan Froyd
3818 bcd4933a Nathan Froyd
            if (__put_user(avr->u64[0], &vreg->u64[0]) ||
3819 bcd4933a Nathan Froyd
                __put_user(avr->u64[1], &vreg->u64[1])) {
3820 bcd4933a Nathan Froyd
                return 1;
3821 bcd4933a Nathan Froyd
            }
3822 bcd4933a Nathan Froyd
        }
3823 bcd4933a Nathan Froyd
        /* Set MSR_VR in the saved MSR value to indicate that
3824 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3825 bcd4933a Nathan Froyd
        msr |= MSR_VR;
3826 bcd4933a Nathan Froyd
        if (__put_user((uint32_t)env->spr[SPR_VRSAVE],
3827 bcd4933a Nathan Froyd
                       &frame->mc_vregs.altivec[32].u32[3]))
3828 bcd4933a Nathan Froyd
            return 1;
3829 bcd4933a Nathan Froyd
    }
3830 bcd4933a Nathan Froyd
3831 bcd4933a Nathan Froyd
    /* Save floating point registers.  */
3832 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
3833 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
3834 bcd4933a Nathan Froyd
            if (__put_user(env->fpr[i], &frame->mc_fregs[i])) {
3835 bcd4933a Nathan Froyd
                return 1;
3836 bcd4933a Nathan Froyd
            }
3837 bcd4933a Nathan Froyd
        }
3838 bcd4933a Nathan Froyd
        if (__put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]))
3839 bcd4933a Nathan Froyd
            return 1;
3840 bcd4933a Nathan Froyd
    }
3841 bcd4933a Nathan Froyd
3842 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
3843 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
3844 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3845 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3846 bcd4933a Nathan Froyd
            if (__put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i])) {
3847 bcd4933a Nathan Froyd
                return 1;
3848 bcd4933a Nathan Froyd
            }
3849 bcd4933a Nathan Froyd
        }
3850 bcd4933a Nathan Froyd
#else
3851 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
3852 bcd4933a Nathan Froyd
            if (__put_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
3853 bcd4933a Nathan Froyd
                return 1;
3854 bcd4933a Nathan Froyd
            }
3855 bcd4933a Nathan Froyd
        }
3856 bcd4933a Nathan Froyd
#endif
3857 bcd4933a Nathan Froyd
        /* Set MSR_SPE in the saved MSR value to indicate that
3858 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3859 bcd4933a Nathan Froyd
        msr |= MSR_SPE;
3860 bcd4933a Nathan Froyd
        if (__put_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
3861 bcd4933a Nathan Froyd
            return 1;
3862 bcd4933a Nathan Froyd
    }
3863 bcd4933a Nathan Froyd
3864 bcd4933a Nathan Froyd
    /* Store MSR.  */
3865 bcd4933a Nathan Froyd
    if (__put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
3866 bcd4933a Nathan Froyd
        return 1;
3867 bcd4933a Nathan Froyd
3868 bcd4933a Nathan Froyd
    /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
3869 bcd4933a Nathan Froyd
    if (sigret) {
3870 bcd4933a Nathan Froyd
        if (__put_user(0x38000000UL | sigret, &frame->tramp[0]) ||
3871 bcd4933a Nathan Froyd
            __put_user(0x44000002UL, &frame->tramp[1])) {
3872 bcd4933a Nathan Froyd
            return 1;
3873 bcd4933a Nathan Froyd
        }
3874 bcd4933a Nathan Froyd
    }
3875 bcd4933a Nathan Froyd
3876 bcd4933a Nathan Froyd
    return 0;
3877 bcd4933a Nathan Froyd
}
3878 bcd4933a Nathan Froyd
3879 bcd4933a Nathan Froyd
static int restore_user_regs(CPUState *env,
3880 bcd4933a Nathan Froyd
                             struct target_mcontext *frame, int sig)
3881 bcd4933a Nathan Froyd
{
3882 bcd4933a Nathan Froyd
    target_ulong save_r2 = 0;
3883 bcd4933a Nathan Froyd
    target_ulong msr;
3884 bcd4933a Nathan Froyd
    target_ulong ccr;
3885 bcd4933a Nathan Froyd
3886 bcd4933a Nathan Froyd
    int i;
3887 bcd4933a Nathan Froyd
3888 bcd4933a Nathan Froyd
    if (!sig) {
3889 bcd4933a Nathan Froyd
        save_r2 = env->gpr[2];
3890 bcd4933a Nathan Froyd
    }
3891 bcd4933a Nathan Froyd
3892 bcd4933a Nathan Froyd
    /* Restore general registers.  */
3893 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3894 bcd4933a Nathan Froyd
        if (__get_user(env->gpr[i], &frame->mc_gregs[i])) {
3895 bcd4933a Nathan Froyd
            return 1;
3896 bcd4933a Nathan Froyd
        }
3897 bcd4933a Nathan Froyd
    }
3898 bcd4933a Nathan Froyd
    if (__get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
3899 bcd4933a Nathan Froyd
        || __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
3900 bcd4933a Nathan Froyd
        || __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
3901 bcd4933a Nathan Froyd
        || __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
3902 bcd4933a Nathan Froyd
        return 1;
3903 bcd4933a Nathan Froyd
    if (__get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
3904 bcd4933a Nathan Froyd
        return 1;
3905 bcd4933a Nathan Froyd
3906 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
3907 bcd4933a Nathan Froyd
        env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
3908 bcd4933a Nathan Froyd
    }
3909 bcd4933a Nathan Froyd
3910 bcd4933a Nathan Froyd
    if (!sig) {
3911 bcd4933a Nathan Froyd
        env->gpr[2] = save_r2;
3912 bcd4933a Nathan Froyd
    }
3913 bcd4933a Nathan Froyd
    /* Restore MSR.  */
3914 bcd4933a Nathan Froyd
    if (__get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
3915 bcd4933a Nathan Froyd
        return 1;
3916 bcd4933a Nathan Froyd
3917 bcd4933a Nathan Froyd
    /* If doing signal return, restore the previous little-endian mode.  */
3918 bcd4933a Nathan Froyd
    if (sig)
3919 bcd4933a Nathan Froyd
        env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
3920 bcd4933a Nathan Froyd
3921 bcd4933a Nathan Froyd
    /* Restore Altivec registers if necessary.  */
3922 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
3923 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
3924 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
3925 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
3926 bcd4933a Nathan Froyd
3927 bcd4933a Nathan Froyd
            if (__get_user(avr->u64[0], &vreg->u64[0]) ||
3928 bcd4933a Nathan Froyd
                __get_user(avr->u64[1], &vreg->u64[1])) {
3929 bcd4933a Nathan Froyd
                return 1;
3930 bcd4933a Nathan Froyd
            }
3931 bcd4933a Nathan Froyd
        }
3932 bcd4933a Nathan Froyd
        /* Set MSR_VEC in the saved MSR value to indicate that
3933 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3934 bcd4933a Nathan Froyd
        if (__get_user(env->spr[SPR_VRSAVE],
3935 bcd4933a Nathan Froyd
                       (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])))
3936 bcd4933a Nathan Froyd
            return 1;
3937 bcd4933a Nathan Froyd
    }
3938 bcd4933a Nathan Froyd
3939 bcd4933a Nathan Froyd
    /* Restore floating point registers.  */
3940 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
3941 bcd4933a Nathan Froyd
        uint64_t fpscr;
3942 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
3943 bcd4933a Nathan Froyd
            if (__get_user(env->fpr[i], &frame->mc_fregs[i])) {
3944 bcd4933a Nathan Froyd
                return 1;
3945 bcd4933a Nathan Froyd
            }
3946 bcd4933a Nathan Froyd
        }
3947 bcd4933a Nathan Froyd
        if (__get_user(fpscr, &frame->mc_fregs[32]))
3948 bcd4933a Nathan Froyd
            return 1;
3949 bcd4933a Nathan Froyd
        env->fpscr = (uint32_t) fpscr;
3950 bcd4933a Nathan Froyd
    }
3951 bcd4933a Nathan Froyd
3952 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
3953 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
3954 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3955 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3956 bcd4933a Nathan Froyd
            uint32_t hi;
3957 bcd4933a Nathan Froyd
3958 bcd4933a Nathan Froyd
            if (__get_user(hi, &frame->mc_vregs.spe[i])) {
3959 bcd4933a Nathan Froyd
                return 1;
3960 bcd4933a Nathan Froyd
            }
3961 bcd4933a Nathan Froyd
            env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
3962 bcd4933a Nathan Froyd
        }
3963 bcd4933a Nathan Froyd
#else
3964 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
3965 bcd4933a Nathan Froyd
            if (__get_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
3966 bcd4933a Nathan Froyd
                return 1;
3967 bcd4933a Nathan Froyd
            }
3968 bcd4933a Nathan Froyd
        }
3969 bcd4933a Nathan Froyd
#endif
3970 bcd4933a Nathan Froyd
        if (__get_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
3971 bcd4933a Nathan Froyd
            return 1;
3972 bcd4933a Nathan Froyd
    }
3973 bcd4933a Nathan Froyd
3974 bcd4933a Nathan Froyd
    return 0;
3975 bcd4933a Nathan Froyd
}
3976 bcd4933a Nathan Froyd
3977 bcd4933a Nathan Froyd
static void setup_frame(int sig, struct target_sigaction *ka,
3978 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3979 bcd4933a Nathan Froyd
{
3980 bcd4933a Nathan Froyd
    struct target_sigframe *frame;
3981 bcd4933a Nathan Froyd
    struct target_sigcontext *sc;
3982 bcd4933a Nathan Froyd
    target_ulong frame_addr, newsp;
3983 bcd4933a Nathan Froyd
    int err = 0;
3984 bcd4933a Nathan Froyd
    int signal;
3985 bcd4933a Nathan Froyd
3986 bcd4933a Nathan Froyd
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3987 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3988 bcd4933a Nathan Froyd
        goto sigsegv;
3989 bcd4933a Nathan Froyd
    sc = &frame->sctx;
3990 bcd4933a Nathan Froyd
3991 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
3992 bcd4933a Nathan Froyd
3993 bcd4933a Nathan Froyd
    err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
3994 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0], &sc->oldmask);
3995 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3996 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
3997 bcd4933a Nathan Froyd
#else
3998 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[1], &sc->_unused[3]);
3999 bcd4933a Nathan Froyd
#endif
4000 bcd4933a Nathan Froyd
    err |= __put_user(h2g(&frame->mctx), &sc->regs);
4001 bcd4933a Nathan Froyd
    err |= __put_user(sig, &sc->signal);
4002 bcd4933a Nathan Froyd
4003 bcd4933a Nathan Froyd
    /* Save user regs.  */
4004 bcd4933a Nathan Froyd
    err |= save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
4005 bcd4933a Nathan Froyd
4006 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4007 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4008 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->mctx.tramp);
4009 bcd4933a Nathan Froyd
4010 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4011 bcd4933a Nathan Froyd
    env->fpscr = 0;
4012 bcd4933a Nathan Froyd
4013 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4014 bcd4933a Nathan Froyd
    newsp = frame_addr - SIGNAL_FRAMESIZE;
4015 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
4016 bcd4933a Nathan Froyd
4017 bcd4933a Nathan Froyd
    if (err)
4018 bcd4933a Nathan Froyd
        goto sigsegv;
4019 bcd4933a Nathan Froyd
4020 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4021 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4022 bcd4933a Nathan Froyd
    env->gpr[3] = signal;
4023 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(sc);
4024 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4025 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4026 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4027 bcd4933a Nathan Froyd
4028 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4029 bcd4933a Nathan Froyd
    return;
4030 bcd4933a Nathan Froyd
4031 bcd4933a Nathan Froyd
sigsegv:
4032 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4033 bcd4933a Nathan Froyd
    if (logfile)
4034 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from setup_frame\n");
4035 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4036 bcd4933a Nathan Froyd
}
4037 bcd4933a Nathan Froyd
4038 bcd4933a Nathan Froyd
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4039 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4040 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
4041 bcd4933a Nathan Froyd
{
4042 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf;
4043 bcd4933a Nathan Froyd
    struct target_mcontext *frame;
4044 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr, newsp = 0;
4045 bcd4933a Nathan Froyd
    int i, err = 0;
4046 bcd4933a Nathan Froyd
    int signal;
4047 bcd4933a Nathan Froyd
4048 bcd4933a Nathan Froyd
    rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4049 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4050 bcd4933a Nathan Froyd
        goto sigsegv;
4051 bcd4933a Nathan Froyd
4052 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
4053 bcd4933a Nathan Froyd
4054 bcd4933a Nathan Froyd
    err |= copy_siginfo_to_user(&rt_sf->info, info);
4055 bcd4933a Nathan Froyd
4056 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_flags);
4057 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_link);
4058 bcd4933a Nathan Froyd
    err |= __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4059 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_sp);
4060 bcd4933a Nathan Froyd
    err |= __put_user(sas_ss_flags(env->gpr[1]),
4061 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_flags);
4062 bcd4933a Nathan Froyd
    err |= __put_user(target_sigaltstack_used.ss_size,
4063 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_size);
4064 60e99246 Aurelien Jarno
    err |= __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4065 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_regs);
4066 bcd4933a Nathan Froyd
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
4067 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
4068 bcd4933a Nathan Froyd
    }
4069 bcd4933a Nathan Froyd
4070 60e99246 Aurelien Jarno
    frame = &rt_sf->uc.tuc_mcontext;
4071 bcd4933a Nathan Froyd
    err |= save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
4072 bcd4933a Nathan Froyd
4073 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4074 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4075 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->tramp);
4076 bcd4933a Nathan Froyd
4077 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4078 bcd4933a Nathan Froyd
    env->fpscr = 0;
4079 bcd4933a Nathan Froyd
4080 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4081 bcd4933a Nathan Froyd
    newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
4082 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
4083 bcd4933a Nathan Froyd
4084 bcd4933a Nathan Froyd
    if (err)
4085 bcd4933a Nathan Froyd
        goto sigsegv;
4086 bcd4933a Nathan Froyd
4087 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4088 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4089 bcd4933a Nathan Froyd
    env->gpr[3] = (target_ulong) signal;
4090 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4091 bcd4933a Nathan Froyd
    env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4092 bcd4933a Nathan Froyd
    env->gpr[6] = (target_ulong) h2g(rt_sf);
4093 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4094 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4095 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4096 bcd4933a Nathan Froyd
4097 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4098 bcd4933a Nathan Froyd
    return;
4099 bcd4933a Nathan Froyd
4100 bcd4933a Nathan Froyd
sigsegv:
4101 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4102 bcd4933a Nathan Froyd
    if (logfile)
4103 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from setup_rt_frame\n");
4104 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4105 bcd4933a Nathan Froyd
4106 bcd4933a Nathan Froyd
}
4107 bcd4933a Nathan Froyd
4108 bcd4933a Nathan Froyd
long do_sigreturn(CPUState *env)
4109 bcd4933a Nathan Froyd
{
4110 bcd4933a Nathan Froyd
    struct target_sigcontext *sc = NULL;
4111 bcd4933a Nathan Froyd
    struct target_mcontext *sr = NULL;
4112 bcd4933a Nathan Froyd
    target_ulong sr_addr, sc_addr;
4113 bcd4933a Nathan Froyd
    sigset_t blocked;
4114 c227f099 Anthony Liguori
    target_sigset_t set;
4115 bcd4933a Nathan Froyd
4116 bcd4933a Nathan Froyd
    sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4117 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4118 bcd4933a Nathan Froyd
        goto sigsegv;
4119 bcd4933a Nathan Froyd
4120 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4121 bcd4933a Nathan Froyd
    set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
4122 bcd4933a Nathan Froyd
#else
4123 bcd4933a Nathan Froyd
    if(__get_user(set.sig[0], &sc->oldmask) ||
4124 bcd4933a Nathan Froyd
       __get_user(set.sig[1], &sc->_unused[3]))
4125 bcd4933a Nathan Froyd
       goto sigsegv;
4126 bcd4933a Nathan Froyd
#endif
4127 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4128 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4129 bcd4933a Nathan Froyd
4130 bcd4933a Nathan Froyd
    if (__get_user(sr_addr, &sc->regs))
4131 bcd4933a Nathan Froyd
        goto sigsegv;
4132 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4133 bcd4933a Nathan Froyd
        goto sigsegv;
4134 bcd4933a Nathan Froyd
    if (restore_user_regs(env, sr, 1))
4135 bcd4933a Nathan Froyd
        goto sigsegv;
4136 bcd4933a Nathan Froyd
4137 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4138 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4139 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4140 bcd4933a Nathan Froyd
4141 bcd4933a Nathan Froyd
sigsegv:
4142 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4143 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4144 bcd4933a Nathan Froyd
    if (logfile)
4145 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from do_sigreturn\n");
4146 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4147 bcd4933a Nathan Froyd
    return 0;
4148 bcd4933a Nathan Froyd
}
4149 bcd4933a Nathan Froyd
4150 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
4151 bcd4933a Nathan Froyd
static int do_setcontext(struct target_ucontext *ucp, CPUState *env, int sig)
4152 bcd4933a Nathan Froyd
{
4153 bcd4933a Nathan Froyd
    struct target_mcontext *mcp;
4154 bcd4933a Nathan Froyd
    target_ulong mcp_addr;
4155 bcd4933a Nathan Froyd
    sigset_t blocked;
4156 c227f099 Anthony Liguori
    target_sigset_t set;
4157 bcd4933a Nathan Froyd
4158 60e99246 Aurelien Jarno
    if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
4159 bcd4933a Nathan Froyd
                       sizeof (set)))
4160 bcd4933a Nathan Froyd
        return 1;
4161 bcd4933a Nathan Froyd
4162 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4163 bcd4933a Nathan Froyd
    fprintf (stderr, "do_setcontext: not implemented\n");
4164 bcd4933a Nathan Froyd
    return 0;
4165 bcd4933a Nathan Froyd
#else
4166 60e99246 Aurelien Jarno
    if (__get_user(mcp_addr, &ucp->tuc_regs))
4167 bcd4933a Nathan Froyd
        return 1;
4168 bcd4933a Nathan Froyd
4169 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4170 bcd4933a Nathan Froyd
        return 1;
4171 bcd4933a Nathan Froyd
4172 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4173 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4174 bcd4933a Nathan Froyd
    if (restore_user_regs(env, mcp, sig))
4175 bcd4933a Nathan Froyd
        goto sigsegv;
4176 bcd4933a Nathan Froyd
4177 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4178 bcd4933a Nathan Froyd
    return 0;
4179 bcd4933a Nathan Froyd
4180 bcd4933a Nathan Froyd
sigsegv:
4181 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4182 bcd4933a Nathan Froyd
    return 1;
4183 bcd4933a Nathan Froyd
#endif
4184 bcd4933a Nathan Froyd
}
4185 bcd4933a Nathan Froyd
4186 bcd4933a Nathan Froyd
long do_rt_sigreturn(CPUState *env)
4187 bcd4933a Nathan Froyd
{
4188 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf = NULL;
4189 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr;
4190 bcd4933a Nathan Froyd
4191 bcd4933a Nathan Froyd
    rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4192 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4193 bcd4933a Nathan Froyd
        goto sigsegv;
4194 bcd4933a Nathan Froyd
4195 bcd4933a Nathan Froyd
    if (do_setcontext(&rt_sf->uc, env, 1))
4196 bcd4933a Nathan Froyd
        goto sigsegv;
4197 bcd4933a Nathan Froyd
4198 bcd4933a Nathan Froyd
    do_sigaltstack(rt_sf_addr
4199 60e99246 Aurelien Jarno
                   + offsetof(struct target_rt_sigframe, uc.tuc_stack),
4200 bcd4933a Nathan Froyd
                   0, env->gpr[1]);
4201 bcd4933a Nathan Froyd
4202 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4203 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4204 bcd4933a Nathan Froyd
4205 bcd4933a Nathan Froyd
sigsegv:
4206 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4207 bcd4933a Nathan Froyd
    if (logfile)
4208 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from do_rt_sigreturn\n");
4209 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4210 bcd4933a Nathan Froyd
    return 0;
4211 bcd4933a Nathan Froyd
}
4212 bcd4933a Nathan Froyd
4213 492a8744 Laurent Vivier
#elif defined(TARGET_M68K)
4214 492a8744 Laurent Vivier
4215 492a8744 Laurent Vivier
struct target_sigcontext {
4216 492a8744 Laurent Vivier
    abi_ulong  sc_mask;
4217 492a8744 Laurent Vivier
    abi_ulong  sc_usp;
4218 492a8744 Laurent Vivier
    abi_ulong  sc_d0;
4219 492a8744 Laurent Vivier
    abi_ulong  sc_d1;
4220 492a8744 Laurent Vivier
    abi_ulong  sc_a0;
4221 492a8744 Laurent Vivier
    abi_ulong  sc_a1;
4222 492a8744 Laurent Vivier
    unsigned short sc_sr;
4223 492a8744 Laurent Vivier
    abi_ulong  sc_pc;
4224 492a8744 Laurent Vivier
};
4225 492a8744 Laurent Vivier
4226 492a8744 Laurent Vivier
struct target_sigframe
4227 492a8744 Laurent Vivier
{
4228 492a8744 Laurent Vivier
    abi_ulong pretcode;
4229 492a8744 Laurent Vivier
    int sig;
4230 492a8744 Laurent Vivier
    int code;
4231 492a8744 Laurent Vivier
    abi_ulong psc;
4232 492a8744 Laurent Vivier
    char retcode[8];
4233 492a8744 Laurent Vivier
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
4234 492a8744 Laurent Vivier
    struct target_sigcontext sc;
4235 492a8744 Laurent Vivier
};
4236 7181155d Laurent Vivier
 
4237 c227f099 Anthony Liguori
typedef int target_greg_t;
4238 7181155d Laurent Vivier
#define TARGET_NGREG 18
4239 c227f099 Anthony Liguori
typedef target_greg_t target_gregset_t[TARGET_NGREG];
4240 7181155d Laurent Vivier
4241 7181155d Laurent Vivier
typedef struct target_fpregset {
4242 7181155d Laurent Vivier
    int f_fpcntl[3];
4243 7181155d Laurent Vivier
    int f_fpregs[8*3];
4244 c227f099 Anthony Liguori
} target_fpregset_t;
4245 7181155d Laurent Vivier
4246 7181155d Laurent Vivier
struct target_mcontext {
4247 7181155d Laurent Vivier
    int version;
4248 c227f099 Anthony Liguori
    target_gregset_t gregs;
4249 c227f099 Anthony Liguori
    target_fpregset_t fpregs;
4250 7181155d Laurent Vivier
};
4251 7181155d Laurent Vivier
4252 7181155d Laurent Vivier
#define TARGET_MCONTEXT_VERSION 2
4253 7181155d Laurent Vivier
4254 7181155d Laurent Vivier
struct target_ucontext {
4255 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
4256 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
4257 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
4258 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
4259 60e99246 Aurelien Jarno
    abi_long tuc_filler[80];
4260 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4261 7181155d Laurent Vivier
};
4262 7181155d Laurent Vivier
4263 7181155d Laurent Vivier
struct target_rt_sigframe
4264 7181155d Laurent Vivier
{
4265 7181155d Laurent Vivier
    abi_ulong pretcode;
4266 7181155d Laurent Vivier
    int sig;
4267 7181155d Laurent Vivier
    abi_ulong pinfo;
4268 7181155d Laurent Vivier
    abi_ulong puc;
4269 7181155d Laurent Vivier
    char retcode[8];
4270 7181155d Laurent Vivier
    struct target_siginfo info;
4271 7181155d Laurent Vivier
    struct target_ucontext uc;
4272 7181155d Laurent Vivier
};
4273 492a8744 Laurent Vivier
4274 492a8744 Laurent Vivier
static int
4275 492a8744 Laurent Vivier
setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask)
4276 492a8744 Laurent Vivier
{
4277 492a8744 Laurent Vivier
    int err = 0;
4278 492a8744 Laurent Vivier
4279 492a8744 Laurent Vivier
    err |= __put_user(mask, &sc->sc_mask);
4280 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[7], &sc->sc_usp);
4281 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[0], &sc->sc_d0);
4282 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[1], &sc->sc_d1);
4283 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[0], &sc->sc_a0);
4284 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[1], &sc->sc_a1);
4285 492a8744 Laurent Vivier
    err |= __put_user(env->sr, &sc->sc_sr);
4286 492a8744 Laurent Vivier
    err |= __put_user(env->pc, &sc->sc_pc);
4287 492a8744 Laurent Vivier
4288 492a8744 Laurent Vivier
    return err;
4289 492a8744 Laurent Vivier
}
4290 492a8744 Laurent Vivier
4291 492a8744 Laurent Vivier
static int
4292 492a8744 Laurent Vivier
restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0)
4293 492a8744 Laurent Vivier
{
4294 492a8744 Laurent Vivier
    int err = 0;
4295 492a8744 Laurent Vivier
    int temp;
4296 492a8744 Laurent Vivier
4297 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[7], &sc->sc_usp);
4298 492a8744 Laurent Vivier
    err |= __get_user(env->dregs[1], &sc->sc_d1);
4299 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[0], &sc->sc_a0);
4300 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[1], &sc->sc_a1);
4301 492a8744 Laurent Vivier
    err |= __get_user(env->pc, &sc->sc_pc);
4302 492a8744 Laurent Vivier
    err |= __get_user(temp, &sc->sc_sr);
4303 492a8744 Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4304 492a8744 Laurent Vivier
4305 492a8744 Laurent Vivier
    *pd0 = tswapl(sc->sc_d0);
4306 492a8744 Laurent Vivier
4307 492a8744 Laurent Vivier
    return err;
4308 492a8744 Laurent Vivier
}
4309 492a8744 Laurent Vivier
4310 492a8744 Laurent Vivier
/*
4311 492a8744 Laurent Vivier
 * Determine which stack to use..
4312 492a8744 Laurent Vivier
 */
4313 492a8744 Laurent Vivier
static inline abi_ulong
4314 492a8744 Laurent Vivier
get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
4315 492a8744 Laurent Vivier
{
4316 492a8744 Laurent Vivier
    unsigned long sp;
4317 492a8744 Laurent Vivier
4318 492a8744 Laurent Vivier
    sp = regs->aregs[7];
4319 492a8744 Laurent Vivier
4320 492a8744 Laurent Vivier
    /* This is the X/Open sanctioned signal stack switching.  */
4321 492a8744 Laurent Vivier
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
4322 492a8744 Laurent Vivier
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4323 492a8744 Laurent Vivier
    }
4324 492a8744 Laurent Vivier
4325 492a8744 Laurent Vivier
    return ((sp - frame_size) & -8UL);
4326 492a8744 Laurent Vivier
}
4327 492a8744 Laurent Vivier
4328 492a8744 Laurent Vivier
static void setup_frame(int sig, struct target_sigaction *ka,
4329 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
4330 492a8744 Laurent Vivier
{
4331 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4332 492a8744 Laurent Vivier
    abi_ulong frame_addr;
4333 492a8744 Laurent Vivier
    abi_ulong retcode_addr;
4334 492a8744 Laurent Vivier
    abi_ulong sc_addr;
4335 492a8744 Laurent Vivier
    int err = 0;
4336 492a8744 Laurent Vivier
    int i;
4337 492a8744 Laurent Vivier
4338 492a8744 Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4339 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4340 492a8744 Laurent Vivier
        goto give_sigsegv;
4341 492a8744 Laurent Vivier
4342 492a8744 Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4343 492a8744 Laurent Vivier
4344 492a8744 Laurent Vivier
    sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
4345 492a8744 Laurent Vivier
    err |= __put_user(sc_addr, &frame->psc);
4346 492a8744 Laurent Vivier
4347 492a8744 Laurent Vivier
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
4348 492a8744 Laurent Vivier
    if (err)
4349 492a8744 Laurent Vivier
        goto give_sigsegv;
4350 492a8744 Laurent Vivier
4351 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4352 492a8744 Laurent Vivier
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
4353 492a8744 Laurent Vivier
            goto give_sigsegv;
4354 492a8744 Laurent Vivier
    }
4355 492a8744 Laurent Vivier
4356 492a8744 Laurent Vivier
    /* Set up to return from userspace.  */
4357 492a8744 Laurent Vivier
4358 492a8744 Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4359 492a8744 Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4360 492a8744 Laurent Vivier
4361 492a8744 Laurent Vivier
    /* moveq #,d0; trap #0 */
4362 492a8744 Laurent Vivier
4363 492a8744 Laurent Vivier
    err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
4364 492a8744 Laurent Vivier
                      (long *)(frame->retcode));
4365 492a8744 Laurent Vivier
4366 492a8744 Laurent Vivier
    if (err)
4367 492a8744 Laurent Vivier
        goto give_sigsegv;
4368 492a8744 Laurent Vivier
4369 492a8744 Laurent Vivier
    /* Set up to return from userspace */
4370 492a8744 Laurent Vivier
4371 492a8744 Laurent Vivier
    env->aregs[7] = frame_addr;
4372 492a8744 Laurent Vivier
    env->pc = ka->_sa_handler;
4373 492a8744 Laurent Vivier
4374 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4375 492a8744 Laurent Vivier
    return;
4376 492a8744 Laurent Vivier
4377 492a8744 Laurent Vivier
give_sigsegv:
4378 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4379 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4380 492a8744 Laurent Vivier
}
4381 492a8744 Laurent Vivier
4382 7181155d Laurent Vivier
static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
4383 7181155d Laurent Vivier
                                           CPUState *env)
4384 7181155d Laurent Vivier
{
4385 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
4386 7181155d Laurent Vivier
    int err;
4387 7181155d Laurent Vivier
4388 60e99246 Aurelien Jarno
    err = __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4389 7181155d Laurent Vivier
    err |= __put_user(env->dregs[0], &gregs[0]);
4390 7181155d Laurent Vivier
    err |= __put_user(env->dregs[1], &gregs[1]);
4391 7181155d Laurent Vivier
    err |= __put_user(env->dregs[2], &gregs[2]);
4392 7181155d Laurent Vivier
    err |= __put_user(env->dregs[3], &gregs[3]);
4393 7181155d Laurent Vivier
    err |= __put_user(env->dregs[4], &gregs[4]);
4394 7181155d Laurent Vivier
    err |= __put_user(env->dregs[5], &gregs[5]);
4395 7181155d Laurent Vivier
    err |= __put_user(env->dregs[6], &gregs[6]);
4396 7181155d Laurent Vivier
    err |= __put_user(env->dregs[7], &gregs[7]);
4397 7181155d Laurent Vivier
    err |= __put_user(env->aregs[0], &gregs[8]);
4398 7181155d Laurent Vivier
    err |= __put_user(env->aregs[1], &gregs[9]);
4399 7181155d Laurent Vivier
    err |= __put_user(env->aregs[2], &gregs[10]);
4400 7181155d Laurent Vivier
    err |= __put_user(env->aregs[3], &gregs[11]);
4401 7181155d Laurent Vivier
    err |= __put_user(env->aregs[4], &gregs[12]);
4402 7181155d Laurent Vivier
    err |= __put_user(env->aregs[5], &gregs[13]);
4403 7181155d Laurent Vivier
    err |= __put_user(env->aregs[6], &gregs[14]);
4404 7181155d Laurent Vivier
    err |= __put_user(env->aregs[7], &gregs[15]);
4405 7181155d Laurent Vivier
    err |= __put_user(env->pc, &gregs[16]);
4406 7181155d Laurent Vivier
    err |= __put_user(env->sr, &gregs[17]);
4407 7181155d Laurent Vivier
4408 7181155d Laurent Vivier
    return err;
4409 7181155d Laurent Vivier
}
4410 7181155d Laurent Vivier
 
4411 7181155d Laurent Vivier
static inline int target_rt_restore_ucontext(CPUState *env,
4412 7181155d Laurent Vivier
                                             struct target_ucontext *uc,
4413 7181155d Laurent Vivier
                                             int *pd0)
4414 7181155d Laurent Vivier
{
4415 7181155d Laurent Vivier
    int temp;
4416 7181155d Laurent Vivier
    int err;
4417 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
4418 7181155d Laurent Vivier
    
4419 60e99246 Aurelien Jarno
    err = __get_user(temp, &uc->tuc_mcontext.version);
4420 7181155d Laurent Vivier
    if (temp != TARGET_MCONTEXT_VERSION)
4421 7181155d Laurent Vivier
        goto badframe;
4422 7181155d Laurent Vivier
4423 7181155d Laurent Vivier
    /* restore passed registers */
4424 7181155d Laurent Vivier
    err |= __get_user(env->dregs[0], &gregs[0]);
4425 7181155d Laurent Vivier
    err |= __get_user(env->dregs[1], &gregs[1]);
4426 7181155d Laurent Vivier
    err |= __get_user(env->dregs[2], &gregs[2]);
4427 7181155d Laurent Vivier
    err |= __get_user(env->dregs[3], &gregs[3]);
4428 7181155d Laurent Vivier
    err |= __get_user(env->dregs[4], &gregs[4]);
4429 7181155d Laurent Vivier
    err |= __get_user(env->dregs[5], &gregs[5]);
4430 7181155d Laurent Vivier
    err |= __get_user(env->dregs[6], &gregs[6]);
4431 7181155d Laurent Vivier
    err |= __get_user(env->dregs[7], &gregs[7]);
4432 7181155d Laurent Vivier
    err |= __get_user(env->aregs[0], &gregs[8]);
4433 7181155d Laurent Vivier
    err |= __get_user(env->aregs[1], &gregs[9]);
4434 7181155d Laurent Vivier
    err |= __get_user(env->aregs[2], &gregs[10]);
4435 7181155d Laurent Vivier
    err |= __get_user(env->aregs[3], &gregs[11]);
4436 7181155d Laurent Vivier
    err |= __get_user(env->aregs[4], &gregs[12]);
4437 7181155d Laurent Vivier
    err |= __get_user(env->aregs[5], &gregs[13]);
4438 7181155d Laurent Vivier
    err |= __get_user(env->aregs[6], &gregs[14]);
4439 7181155d Laurent Vivier
    err |= __get_user(env->aregs[7], &gregs[15]);
4440 7181155d Laurent Vivier
    err |= __get_user(env->pc, &gregs[16]);
4441 7181155d Laurent Vivier
    err |= __get_user(temp, &gregs[17]);
4442 7181155d Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4443 7181155d Laurent Vivier
4444 7181155d Laurent Vivier
    *pd0 = env->dregs[0];
4445 7181155d Laurent Vivier
    return err;
4446 7181155d Laurent Vivier
4447 7181155d Laurent Vivier
badframe:
4448 7181155d Laurent Vivier
    return 1;
4449 7181155d Laurent Vivier
}
4450 7181155d Laurent Vivier
4451 492a8744 Laurent Vivier
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4452 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4453 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
4454 492a8744 Laurent Vivier
{
4455 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
4456 7181155d Laurent Vivier
    abi_ulong frame_addr;
4457 7181155d Laurent Vivier
    abi_ulong retcode_addr;
4458 7181155d Laurent Vivier
    abi_ulong info_addr;
4459 7181155d Laurent Vivier
    abi_ulong uc_addr;
4460 7181155d Laurent Vivier
    int err = 0;
4461 7181155d Laurent Vivier
    int i;
4462 7181155d Laurent Vivier
4463 7181155d Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4464 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4465 7181155d Laurent Vivier
        goto give_sigsegv;
4466 7181155d Laurent Vivier
4467 7181155d Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4468 7181155d Laurent Vivier
4469 7181155d Laurent Vivier
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
4470 7181155d Laurent Vivier
    err |= __put_user(info_addr, &frame->pinfo);
4471 7181155d Laurent Vivier
4472 7181155d Laurent Vivier
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
4473 7181155d Laurent Vivier
    err |= __put_user(uc_addr, &frame->puc);
4474 7181155d Laurent Vivier
4475 7181155d Laurent Vivier
    err |= copy_siginfo_to_user(&frame->info, info);
4476 7181155d Laurent Vivier
4477 7181155d Laurent Vivier
    /* Create the ucontext */
4478 7181155d Laurent Vivier
4479 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
4480 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
4481 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_sp,
4482 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
4483 7181155d Laurent Vivier
    err |= __put_user(sas_ss_flags(env->aregs[7]),
4484 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
4485 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_size,
4486 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
4487 7181155d Laurent Vivier
    err |= target_rt_setup_ucontext(&frame->uc, env);
4488 7181155d Laurent Vivier
4489 7181155d Laurent Vivier
    if (err)
4490 7181155d Laurent Vivier
            goto give_sigsegv;
4491 7181155d Laurent Vivier
4492 7181155d Laurent Vivier
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
4493 60e99246 Aurelien Jarno
        if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
4494 7181155d Laurent Vivier
            goto give_sigsegv;
4495 7181155d Laurent Vivier
    }
4496 7181155d Laurent Vivier
4497 7181155d Laurent Vivier
    /* Set up to return from userspace.  */
4498 7181155d Laurent Vivier
4499 7181155d Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4500 7181155d Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4501 7181155d Laurent Vivier
4502 7181155d Laurent Vivier
    /* moveq #,d0; notb d0; trap #0 */
4503 7181155d Laurent Vivier
4504 7181155d Laurent Vivier
    err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
4505 7181155d Laurent Vivier
                      (long *)(frame->retcode + 0));
4506 7181155d Laurent Vivier
    err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
4507 7181155d Laurent Vivier
4508 7181155d Laurent Vivier
    if (err)
4509 7181155d Laurent Vivier
        goto give_sigsegv;
4510 7181155d Laurent Vivier
4511 7181155d Laurent Vivier
    /* Set up to return from userspace */
4512 7181155d Laurent Vivier
4513 7181155d Laurent Vivier
    env->aregs[7] = frame_addr;
4514 7181155d Laurent Vivier
    env->pc = ka->_sa_handler;
4515 7181155d Laurent Vivier
4516 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4517 7181155d Laurent Vivier
    return;
4518 7181155d Laurent Vivier
4519 7181155d Laurent Vivier
give_sigsegv:
4520 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4521 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4522 492a8744 Laurent Vivier
}
4523 492a8744 Laurent Vivier
4524 492a8744 Laurent Vivier
long do_sigreturn(CPUState *env)
4525 492a8744 Laurent Vivier
{
4526 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4527 492a8744 Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
4528 c227f099 Anthony Liguori
    target_sigset_t target_set;
4529 492a8744 Laurent Vivier
    sigset_t set;
4530 492a8744 Laurent Vivier
    int d0, i;
4531 492a8744 Laurent Vivier
4532 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
4533 492a8744 Laurent Vivier
        goto badframe;
4534 492a8744 Laurent Vivier
4535 492a8744 Laurent Vivier
    /* set blocked signals */
4536 492a8744 Laurent Vivier
4537 492a8744 Laurent Vivier
    if (__get_user(target_set.sig[0], &frame->sc.sc_mask))
4538 492a8744 Laurent Vivier
        goto badframe;
4539 492a8744 Laurent Vivier
4540 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4541 492a8744 Laurent Vivier
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
4542 492a8744 Laurent Vivier
            goto badframe;
4543 492a8744 Laurent Vivier
    }
4544 492a8744 Laurent Vivier
4545 492a8744 Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
4546 492a8744 Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
4547 492a8744 Laurent Vivier
4548 492a8744 Laurent Vivier
    /* restore registers */
4549 492a8744 Laurent Vivier
4550 492a8744 Laurent Vivier
    if (restore_sigcontext(env, &frame->sc, &d0))
4551 492a8744 Laurent Vivier
        goto badframe;
4552 492a8744 Laurent Vivier
4553 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4554 492a8744 Laurent Vivier
    return d0;
4555 492a8744 Laurent Vivier
4556 492a8744 Laurent Vivier
badframe:
4557 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4558 492a8744 Laurent Vivier
    force_sig(TARGET_SIGSEGV);
4559 492a8744 Laurent Vivier
    return 0;
4560 492a8744 Laurent Vivier
}
4561 492a8744 Laurent Vivier
4562 492a8744 Laurent Vivier
long do_rt_sigreturn(CPUState *env)
4563 492a8744 Laurent Vivier
{
4564 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
4565 7181155d Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
4566 c227f099 Anthony Liguori
    target_sigset_t target_set;
4567 7181155d Laurent Vivier
    sigset_t set;
4568 7181155d Laurent Vivier
    int d0;
4569 7181155d Laurent Vivier
4570 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
4571 7181155d Laurent Vivier
        goto badframe;
4572 7181155d Laurent Vivier
4573 7181155d Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
4574 7181155d Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
4575 7181155d Laurent Vivier
4576 7181155d Laurent Vivier
    /* restore registers */
4577 7181155d Laurent Vivier
4578 7181155d Laurent Vivier
    if (target_rt_restore_ucontext(env, &frame->uc, &d0))
4579 7181155d Laurent Vivier
        goto badframe;
4580 7181155d Laurent Vivier
4581 7181155d Laurent Vivier
    if (do_sigaltstack(frame_addr +
4582 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
4583 7181155d Laurent Vivier
                       0, get_sp_from_cpustate(env)) == -EFAULT)
4584 7181155d Laurent Vivier
        goto badframe;
4585 7181155d Laurent Vivier
4586 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4587 7181155d Laurent Vivier
    return d0;
4588 7181155d Laurent Vivier
4589 7181155d Laurent Vivier
badframe:
4590 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4591 7181155d Laurent Vivier
    force_sig(TARGET_SIGSEGV);
4592 7181155d Laurent Vivier
    return 0;
4593 492a8744 Laurent Vivier
}
4594 492a8744 Laurent Vivier
4595 6049f4f8 Richard Henderson
#elif defined(TARGET_ALPHA)
4596 6049f4f8 Richard Henderson
4597 6049f4f8 Richard Henderson
struct target_sigcontext {
4598 6049f4f8 Richard Henderson
    abi_long sc_onstack;
4599 6049f4f8 Richard Henderson
    abi_long sc_mask;
4600 6049f4f8 Richard Henderson
    abi_long sc_pc;
4601 6049f4f8 Richard Henderson
    abi_long sc_ps;
4602 6049f4f8 Richard Henderson
    abi_long sc_regs[32];
4603 6049f4f8 Richard Henderson
    abi_long sc_ownedfp;
4604 6049f4f8 Richard Henderson
    abi_long sc_fpregs[32];
4605 6049f4f8 Richard Henderson
    abi_ulong sc_fpcr;
4606 6049f4f8 Richard Henderson
    abi_ulong sc_fp_control;
4607 6049f4f8 Richard Henderson
    abi_ulong sc_reserved1;
4608 6049f4f8 Richard Henderson
    abi_ulong sc_reserved2;
4609 6049f4f8 Richard Henderson
    abi_ulong sc_ssize;
4610 6049f4f8 Richard Henderson
    abi_ulong sc_sbase;
4611 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a0;
4612 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a1;
4613 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a2;
4614 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trap_pc;
4615 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_sum;
4616 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_inst;
4617 6049f4f8 Richard Henderson
};
4618 6049f4f8 Richard Henderson
4619 6049f4f8 Richard Henderson
struct target_ucontext {
4620 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
4621 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
4622 60e99246 Aurelien Jarno
    abi_ulong tuc_osf_sigmask;
4623 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
4624 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
4625 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4626 6049f4f8 Richard Henderson
};
4627 6049f4f8 Richard Henderson
4628 6049f4f8 Richard Henderson
struct target_sigframe {
4629 6049f4f8 Richard Henderson
    struct target_sigcontext sc;
4630 6049f4f8 Richard Henderson
    unsigned int retcode[3];
4631 6049f4f8 Richard Henderson
};
4632 6049f4f8 Richard Henderson
4633 6049f4f8 Richard Henderson
struct target_rt_sigframe {
4634 6049f4f8 Richard Henderson
    target_siginfo_t info;
4635 6049f4f8 Richard Henderson
    struct target_ucontext uc;
4636 6049f4f8 Richard Henderson
    unsigned int retcode[3];
4637 6049f4f8 Richard Henderson
};
4638 6049f4f8 Richard Henderson
4639 6049f4f8 Richard Henderson
#define INSN_MOV_R30_R16        0x47fe0410
4640 6049f4f8 Richard Henderson
#define INSN_LDI_R0             0x201f0000
4641 6049f4f8 Richard Henderson
#define INSN_CALLSYS            0x00000083
4642 6049f4f8 Richard Henderson
4643 6049f4f8 Richard Henderson
static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env,
4644 6049f4f8 Richard Henderson
                            abi_ulong frame_addr, target_sigset_t *set)
4645 6049f4f8 Richard Henderson
{
4646 6049f4f8 Richard Henderson
    int i, err = 0;
4647 6049f4f8 Richard Henderson
4648 6049f4f8 Richard Henderson
    err |= __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
4649 6049f4f8 Richard Henderson
    err |= __put_user(set->sig[0], &sc->sc_mask);
4650 6049f4f8 Richard Henderson
    err |= __put_user(env->pc, &sc->sc_pc);
4651 6049f4f8 Richard Henderson
    err |= __put_user(8, &sc->sc_ps);
4652 6049f4f8 Richard Henderson
4653 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
4654 6049f4f8 Richard Henderson
        err |= __put_user(env->ir[i], &sc->sc_regs[i]);
4655 6049f4f8 Richard Henderson
    }
4656 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_regs[31]);
4657 6049f4f8 Richard Henderson
4658 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
4659 6049f4f8 Richard Henderson
        err |= __put_user(env->fir[i], &sc->sc_fpregs[i]);
4660 6049f4f8 Richard Henderson
    }
4661 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_fpregs[31]);
4662 6049f4f8 Richard Henderson
    err |= __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
4663 6049f4f8 Richard Henderson
4664 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a0); /* FIXME */
4665 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a1); /* FIXME */
4666 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a2); /* FIXME */
4667 6049f4f8 Richard Henderson
4668 6049f4f8 Richard Henderson
    return err;
4669 6049f4f8 Richard Henderson
}
4670 6049f4f8 Richard Henderson
4671 6049f4f8 Richard Henderson
static int restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
4672 6049f4f8 Richard Henderson
{
4673 6049f4f8 Richard Henderson
    uint64_t fpcr;
4674 6049f4f8 Richard Henderson
    int i, err = 0;
4675 6049f4f8 Richard Henderson
4676 6049f4f8 Richard Henderson
    err |= __get_user(env->pc, &sc->sc_pc);
4677 6049f4f8 Richard Henderson
4678 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
4679 6049f4f8 Richard Henderson
        err |= __get_user(env->ir[i], &sc->sc_regs[i]);
4680 6049f4f8 Richard Henderson
    }
4681 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
4682 6049f4f8 Richard Henderson
        err |= __get_user(env->fir[i], &sc->sc_fpregs[i]);
4683 6049f4f8 Richard Henderson
    }
4684 6049f4f8 Richard Henderson
4685 6049f4f8 Richard Henderson
    err |= __get_user(fpcr, &sc->sc_fpcr);
4686 6049f4f8 Richard Henderson
    cpu_alpha_store_fpcr(env, fpcr);
4687 6049f4f8 Richard Henderson
4688 6049f4f8 Richard Henderson
    return err;
4689 6049f4f8 Richard Henderson
}
4690 6049f4f8 Richard Henderson
4691 6049f4f8 Richard Henderson
static inline abi_ulong get_sigframe(struct target_sigaction *sa,
4692 6049f4f8 Richard Henderson
                                     CPUState *env, unsigned long framesize)
4693 6049f4f8 Richard Henderson
{
4694 6049f4f8 Richard Henderson
    abi_ulong sp = env->ir[IR_SP];
4695 6049f4f8 Richard Henderson
4696 6049f4f8 Richard Henderson
    /* This is the X/Open sanctioned signal stack switching.  */
4697 6049f4f8 Richard Henderson
    if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
4698 6049f4f8 Richard Henderson
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4699 6049f4f8 Richard Henderson
    }
4700 6049f4f8 Richard Henderson
    return (sp - framesize) & -32;
4701 6049f4f8 Richard Henderson
}
4702 6049f4f8 Richard Henderson
4703 6049f4f8 Richard Henderson
static void setup_frame(int sig, struct target_sigaction *ka,
4704 6049f4f8 Richard Henderson
                        target_sigset_t *set, CPUState *env)
4705 6049f4f8 Richard Henderson
{
4706 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
4707 6049f4f8 Richard Henderson
    struct target_sigframe *frame;
4708 6049f4f8 Richard Henderson
    int err = 0;
4709 6049f4f8 Richard Henderson
4710 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
4711 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4712 6049f4f8 Richard Henderson
        goto give_sigsegv;
4713 6049f4f8 Richard Henderson
    }
4714 6049f4f8 Richard Henderson
4715 6049f4f8 Richard Henderson
    err |= setup_sigcontext(&frame->sc, env, frame_addr, set);
4716 6049f4f8 Richard Henderson
4717 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
4718 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
4719 6049f4f8 Richard Henderson
    } else {
4720 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
4721 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
4722 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
4723 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
4724 6049f4f8 Richard Henderson
        /* imb() */
4725 6049f4f8 Richard Henderson
        r26 = frame_addr;
4726 6049f4f8 Richard Henderson
    }
4727 6049f4f8 Richard Henderson
4728 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 1);
4729 6049f4f8 Richard Henderson
4730 6049f4f8 Richard Henderson
    if (err) {
4731 6049f4f8 Richard Henderson
    give_sigsegv:
4732 6049f4f8 Richard Henderson
        if (sig == TARGET_SIGSEGV) {
4733 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
4734 6049f4f8 Richard Henderson
        }
4735 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
4736 6049f4f8 Richard Henderson
    }
4737 6049f4f8 Richard Henderson
4738 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
4739 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
4740 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
4741 6049f4f8 Richard Henderson
    env->ir[IR_A1] = 0;
4742 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
4743 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
4744 6049f4f8 Richard Henderson
}
4745 6049f4f8 Richard Henderson
4746 6049f4f8 Richard Henderson
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4747 6049f4f8 Richard Henderson
                           target_siginfo_t *info,
4748 6049f4f8 Richard Henderson
                           target_sigset_t *set, CPUState *env)
4749 6049f4f8 Richard Henderson
{
4750 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
4751 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
4752 6049f4f8 Richard Henderson
    int i, err = 0;
4753 6049f4f8 Richard Henderson
4754 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
4755 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4756 6049f4f8 Richard Henderson
        goto give_sigsegv;
4757 6049f4f8 Richard Henderson
    }
4758 6049f4f8 Richard Henderson
4759 6049f4f8 Richard Henderson
    err |= copy_siginfo_to_user(&frame->info, info);
4760 6049f4f8 Richard Henderson
4761 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
4762 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
4763 60e99246 Aurelien Jarno
    err |= __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
4764 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_sp,
4765 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
4766 6049f4f8 Richard Henderson
    err |= __put_user(sas_ss_flags(env->ir[IR_SP]),
4767 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
4768 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_size,
4769 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
4770 60e99246 Aurelien Jarno
    err |= setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
4771 6049f4f8 Richard Henderson
    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
4772 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
4773 6049f4f8 Richard Henderson
    }
4774 6049f4f8 Richard Henderson
4775 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
4776 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
4777 6049f4f8 Richard Henderson
    } else {
4778 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
4779 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
4780 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
4781 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
4782 6049f4f8 Richard Henderson
        /* imb(); */
4783 6049f4f8 Richard Henderson
        r26 = frame_addr;
4784 6049f4f8 Richard Henderson
    }
4785 6049f4f8 Richard Henderson
4786 6049f4f8 Richard Henderson
    if (err) {
4787 6049f4f8 Richard Henderson
    give_sigsegv:
4788 6049f4f8 Richard Henderson
       if (sig == TARGET_SIGSEGV) {
4789 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
4790 6049f4f8 Richard Henderson
        }
4791 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
4792 6049f4f8 Richard Henderson
    }
4793 6049f4f8 Richard Henderson
4794 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
4795 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
4796 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
4797 6049f4f8 Richard Henderson
    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
4798 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
4799 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
4800 6049f4f8 Richard Henderson
}
4801 6049f4f8 Richard Henderson
4802 6049f4f8 Richard Henderson
long do_sigreturn(CPUState *env)
4803 6049f4f8 Richard Henderson
{
4804 6049f4f8 Richard Henderson
    struct target_sigcontext *sc;
4805 6049f4f8 Richard Henderson
    abi_ulong sc_addr = env->ir[IR_A0];
4806 6049f4f8 Richard Henderson
    target_sigset_t target_set;
4807 6049f4f8 Richard Henderson
    sigset_t set;
4808 6049f4f8 Richard Henderson
4809 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
4810 6049f4f8 Richard Henderson
        goto badframe;
4811 6049f4f8 Richard Henderson
    }
4812 6049f4f8 Richard Henderson
4813 6049f4f8 Richard Henderson
    target_sigemptyset(&target_set);
4814 6049f4f8 Richard Henderson
    if (__get_user(target_set.sig[0], &sc->sc_mask)) {
4815 6049f4f8 Richard Henderson
        goto badframe;
4816 6049f4f8 Richard Henderson
    }
4817 6049f4f8 Richard Henderson
4818 6049f4f8 Richard Henderson
    target_to_host_sigset_internal(&set, &target_set);
4819 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
4820 6049f4f8 Richard Henderson
4821 6049f4f8 Richard Henderson
    if (restore_sigcontext(env, sc)) {
4822 6049f4f8 Richard Henderson
        goto badframe;
4823 6049f4f8 Richard Henderson
    }
4824 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
4825 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
4826 6049f4f8 Richard Henderson
4827 6049f4f8 Richard Henderson
 badframe:
4828 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
4829 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
4830 6049f4f8 Richard Henderson
}
4831 6049f4f8 Richard Henderson
4832 6049f4f8 Richard Henderson
long do_rt_sigreturn(CPUState *env)
4833 6049f4f8 Richard Henderson
{
4834 6049f4f8 Richard Henderson
    abi_ulong frame_addr = env->ir[IR_A0];
4835 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
4836 6049f4f8 Richard Henderson
    sigset_t set;
4837 6049f4f8 Richard Henderson
4838 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4839 6049f4f8 Richard Henderson
        goto badframe;
4840 6049f4f8 Richard Henderson
    }
4841 60e99246 Aurelien Jarno
    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4842 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
4843 6049f4f8 Richard Henderson
4844 60e99246 Aurelien Jarno
    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
4845 6049f4f8 Richard Henderson
        goto badframe;
4846 6049f4f8 Richard Henderson
    }
4847 6049f4f8 Richard Henderson
    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
4848 60e99246 Aurelien Jarno
                                             uc.tuc_stack),
4849 6049f4f8 Richard Henderson
                       0, env->ir[IR_SP]) == -EFAULT) {
4850 6049f4f8 Richard Henderson
        goto badframe;
4851 6049f4f8 Richard Henderson
    }
4852 6049f4f8 Richard Henderson
4853 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
4854 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
4855 6049f4f8 Richard Henderson
4856 6049f4f8 Richard Henderson
4857 6049f4f8 Richard Henderson
 badframe:
4858 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
4859 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
4860 6049f4f8 Richard Henderson
}
4861 6049f4f8 Richard Henderson
4862 b346ff46 bellard
#else
4863 b346ff46 bellard
4864 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
4865 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
4866 b346ff46 bellard
{
4867 b346ff46 bellard
    fprintf(stderr, "setup_frame: not implemented\n");
4868 b346ff46 bellard
}
4869 b346ff46 bellard
4870 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4871 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4872 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
4873 b346ff46 bellard
{
4874 b346ff46 bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
4875 b346ff46 bellard
}
4876 b346ff46 bellard
4877 b346ff46 bellard
long do_sigreturn(CPUState *env)
4878 b346ff46 bellard
{
4879 b346ff46 bellard
    fprintf(stderr, "do_sigreturn: not implemented\n");
4880 f8b0aa25 bellard
    return -TARGET_ENOSYS;
4881 b346ff46 bellard
}
4882 b346ff46 bellard
4883 b346ff46 bellard
long do_rt_sigreturn(CPUState *env)
4884 b346ff46 bellard
{
4885 b346ff46 bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
4886 f8b0aa25 bellard
    return -TARGET_ENOSYS;
4887 b346ff46 bellard
}
4888 b346ff46 bellard
4889 66fb9763 bellard
#endif
4890 66fb9763 bellard
4891 624f7979 pbrook
void process_pending_signals(CPUState *cpu_env)
4892 66fb9763 bellard
{
4893 66fb9763 bellard
    int sig;
4894 992f48a0 blueswir1
    abi_ulong handler;
4895 9de5e440 bellard
    sigset_t set, old_set;
4896 c227f099 Anthony Liguori
    target_sigset_t target_old_set;
4897 624f7979 pbrook
    struct emulated_sigtable *k;
4898 624f7979 pbrook
    struct target_sigaction *sa;
4899 66fb9763 bellard
    struct sigqueue *q;
4900 624f7979 pbrook
    TaskState *ts = cpu_env->opaque;
4901 3b46e624 ths
4902 624f7979 pbrook
    if (!ts->signal_pending)
4903 31e31b8a bellard
        return;
4904 31e31b8a bellard
4905 624f7979 pbrook
    /* FIXME: This is not threadsafe.  */
4906 624f7979 pbrook
    k = ts->sigtab;
4907 66fb9763 bellard
    for(sig = 1; sig <= TARGET_NSIG; sig++) {
4908 66fb9763 bellard
        if (k->pending)
4909 31e31b8a bellard
            goto handle_signal;
4910 66fb9763 bellard
        k++;
4911 31e31b8a bellard
    }
4912 31e31b8a bellard
    /* if no signal is pending, just return */
4913 624f7979 pbrook
    ts->signal_pending = 0;
4914 31e31b8a bellard
    return;
4915 66fb9763 bellard
4916 31e31b8a bellard
 handle_signal:
4917 66fb9763 bellard
#ifdef DEBUG_SIGNAL
4918 bc8a22cc bellard
    fprintf(stderr, "qemu: process signal %d\n", sig);
4919 66fb9763 bellard
#endif
4920 66fb9763 bellard
    /* dequeue signal */
4921 66fb9763 bellard
    q = k->first;
4922 66fb9763 bellard
    k->first = q->next;
4923 66fb9763 bellard
    if (!k->first)
4924 66fb9763 bellard
        k->pending = 0;
4925 3b46e624 ths
4926 1fddef4b bellard
    sig = gdb_handlesig (cpu_env, sig);
4927 1fddef4b bellard
    if (!sig) {
4928 ca587a8e aurel32
        sa = NULL;
4929 ca587a8e aurel32
        handler = TARGET_SIG_IGN;
4930 ca587a8e aurel32
    } else {
4931 ca587a8e aurel32
        sa = &sigact_table[sig - 1];
4932 ca587a8e aurel32
        handler = sa->_sa_handler;
4933 1fddef4b bellard
    }
4934 66fb9763 bellard
4935 66fb9763 bellard
    if (handler == TARGET_SIG_DFL) {
4936 ca587a8e aurel32
        /* default handler : ignore some signal. The other are job control or fatal */
4937 ca587a8e aurel32
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
4938 ca587a8e aurel32
            kill(getpid(),SIGSTOP);
4939 ca587a8e aurel32
        } else if (sig != TARGET_SIGCHLD &&
4940 ca587a8e aurel32
                   sig != TARGET_SIGURG &&
4941 ca587a8e aurel32
                   sig != TARGET_SIGWINCH &&
4942 ca587a8e aurel32
                   sig != TARGET_SIGCONT) {
4943 66fb9763 bellard
            force_sig(sig);
4944 66fb9763 bellard
        }
4945 66fb9763 bellard
    } else if (handler == TARGET_SIG_IGN) {
4946 66fb9763 bellard
        /* ignore sig */
4947 66fb9763 bellard
    } else if (handler == TARGET_SIG_ERR) {
4948 66fb9763 bellard
        force_sig(sig);
4949 66fb9763 bellard
    } else {
4950 9de5e440 bellard
        /* compute the blocked signals during the handler execution */
4951 624f7979 pbrook
        target_to_host_sigset(&set, &sa->sa_mask);
4952 9de5e440 bellard
        /* SA_NODEFER indicates that the current signal should not be
4953 9de5e440 bellard
           blocked during the handler */
4954 624f7979 pbrook
        if (!(sa->sa_flags & TARGET_SA_NODEFER))
4955 9de5e440 bellard
            sigaddset(&set, target_to_host_signal(sig));
4956 3b46e624 ths
4957 9de5e440 bellard
        /* block signals in the handler using Linux */
4958 9de5e440 bellard
        sigprocmask(SIG_BLOCK, &set, &old_set);
4959 9de5e440 bellard
        /* save the previous blocked signal state to restore it at the
4960 9de5e440 bellard
           end of the signal execution (see do_sigreturn) */
4961 9231944d bellard
        host_to_target_sigset_internal(&target_old_set, &old_set);
4962 9de5e440 bellard
4963 bc8a22cc bellard
        /* if the CPU is in VM86 mode, we restore the 32 bit values */
4964 84409ddb j_mayer
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
4965 bc8a22cc bellard
        {
4966 bc8a22cc bellard
            CPUX86State *env = cpu_env;
4967 bc8a22cc bellard
            if (env->eflags & VM_MASK)
4968 bc8a22cc bellard
                save_v86_state(env);
4969 bc8a22cc bellard
        }
4970 bc8a22cc bellard
#endif
4971 9de5e440 bellard
        /* prepare the stack frame of the virtual CPU */
4972 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_SIGINFO)
4973 624f7979 pbrook
            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
4974 66fb9763 bellard
        else
4975 624f7979 pbrook
            setup_frame(sig, sa, &target_old_set, cpu_env);
4976 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_RESETHAND)
4977 624f7979 pbrook
            sa->_sa_handler = TARGET_SIG_DFL;
4978 31e31b8a bellard
    }
4979 66fb9763 bellard
    if (q != &k->info)
4980 624f7979 pbrook
        free_sigqueue(cpu_env, q);
4981 66fb9763 bellard
}