Statistics
| Branch: | Revision:

root / linux-user / signal.c @ 2c3c6689

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

1950 6d5e216d bellard
        err |= __put_user(mask, &sc->sigc_mask);
1951 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1952 6d5e216d bellard
        err |= __put_user(env->pc, &sc->sigc_pc);
1953 6d5e216d bellard
        err |= __put_user(env->npc, &sc->sigc_npc);
1954 6d5e216d bellard
        err |= __put_user(env->psr, &sc->sigc_psr);
1955 6d5e216d bellard
        err |= __put_user(env->gregs[1], &sc->sigc_g1);
1956 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1957 6d5e216d bellard

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

2560 106ec879 bellard
    if (!used_math())
2561 106ec879 bellard
        goto out;
2562 106ec879 bellard

2563 106ec879 bellard
    /*
2564 106ec879 bellard
    * Save FPU state to signal context.  Signal handler will "inherit"
2565 106ec879 bellard
    * current FPU state.
2566 106ec879 bellard
    */
2567 106ec879 bellard
    preempt_disable();
2568 106ec879 bellard

2569 106ec879 bellard
    if (!is_fpu_owner()) {
2570 106ec879 bellard
        own_fpu();
2571 106ec879 bellard
        restore_fp(current);
2572 106ec879 bellard
    }
2573 106ec879 bellard
    err |= save_fp_context(sc);
2574 106ec879 bellard

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

3618 d962783e Jia Liu
    /* Alwys make any pending restarted system call return -EINTR */
3619 d962783e Jia Liu
    current_thread_info()->restart_block.fn = do_no_restart_syscall;
3620 d962783e Jia Liu

3621 d962783e Jia Liu
    /* restore the regs from &sc->regs (same as sc, since regs is first)
3622 d962783e Jia Liu
     * (sc is already checked for VERIFY_READ since the sigframe was
3623 d962783e Jia Liu
     *  checked in sys_sigreturn previously)
3624 d962783e Jia Liu
     */
3625 d962783e Jia Liu

3626 d962783e Jia Liu
    if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3627 d962783e Jia Liu
        goto badframe;
3628 d962783e Jia Liu
    }
3629 d962783e Jia Liu

3630 d962783e Jia Liu
    /* make sure the U-flag is set so user-mode cannot fool us */
3631 d962783e Jia Liu

3632 d962783e Jia Liu
    regs->sr &= ~SR_SM;
3633 d962783e Jia Liu

3634 d962783e Jia Liu
    /* restore the old USP as it was before we stacked the sc etc.
3635 d962783e Jia Liu
     * (we cannot just pop the sigcontext since we aligned the sp and
3636 d962783e Jia Liu
     *  stuff after pushing it)
3637 d962783e Jia Liu
     */
3638 d962783e Jia Liu

3639 d962783e Jia Liu
    err |= __get_user(old_usp, &sc->usp);
3640 d962783e Jia Liu
    phx_signal("old_usp 0x%lx", old_usp);
3641 d962783e Jia Liu

3642 d962783e Jia Liu
    __PHX__ REALLY           /* ??? */
3643 d962783e Jia Liu
    wrusp(old_usp);
3644 d962783e Jia Liu
    regs->gpr[1] = old_usp;
3645 d962783e Jia Liu

3646 d962783e Jia Liu
    /* TODO: the other ports use regs->orig_XX to disable syscall checks
3647 d962783e Jia Liu
     * after this completes, but we don't use that mechanism. maybe we can
3648 d962783e Jia Liu
     * use it now ?
3649 d962783e Jia Liu
     */
3650 d962783e Jia Liu

3651 d962783e Jia Liu
    return err;
3652 d962783e Jia Liu

3653 d962783e Jia Liu
badframe:
3654 d962783e Jia Liu
    return 1;
3655 d962783e Jia Liu
}
3656 d962783e Jia Liu
#endif
3657 d962783e Jia Liu
3658 d962783e Jia Liu
/* Set up a signal frame.  */
3659 d962783e Jia Liu
3660 d962783e Jia Liu
static int setup_sigcontext(struct target_sigcontext *sc,
3661 d962783e Jia Liu
                            CPUOpenRISCState *regs,
3662 d962783e Jia Liu
                            unsigned long mask)
3663 d962783e Jia Liu
{
3664 d962783e Jia Liu
    int err = 0;
3665 d962783e Jia Liu
    unsigned long usp = regs->gpr[1];
3666 d962783e Jia Liu
3667 d962783e Jia Liu
    /* copy the regs. they are first in sc so we can use sc directly */
3668 d962783e Jia Liu
3669 d962783e Jia Liu
    /*err |= copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
3670 d962783e Jia Liu
3671 d962783e Jia Liu
    /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3672 d962783e Jia Liu
       the signal handler. The frametype will be restored to its previous
3673 d962783e Jia Liu
       value in restore_sigcontext. */
3674 d962783e Jia Liu
    /*regs->frametype = CRIS_FRAME_NORMAL;*/
3675 d962783e Jia Liu
3676 d962783e Jia Liu
    /* then some other stuff */
3677 d962783e Jia Liu
    err |= __put_user(mask, &sc->oldmask);
3678 d962783e Jia Liu
    err |= __put_user(usp, &sc->usp); return err;
3679 d962783e Jia Liu
}
3680 d962783e Jia Liu
3681 d962783e Jia Liu
static inline unsigned long align_sigframe(unsigned long sp)
3682 d962783e Jia Liu
{
3683 d962783e Jia Liu
    unsigned long i;
3684 d962783e Jia Liu
    i = sp & ~3UL;
3685 d962783e Jia Liu
    return i;
3686 d962783e Jia Liu
}
3687 d962783e Jia Liu
3688 d962783e Jia Liu
static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3689 d962783e Jia Liu
                                     CPUOpenRISCState *regs,
3690 d962783e Jia Liu
                                     size_t frame_size)
3691 d962783e Jia Liu
{
3692 d962783e Jia Liu
    unsigned long sp = regs->gpr[1];
3693 d962783e Jia Liu
    int onsigstack = on_sig_stack(sp);
3694 d962783e Jia Liu
3695 d962783e Jia Liu
    /* redzone */
3696 d962783e Jia Liu
    /* This is the X/Open sanctioned signal stack switching.  */
3697 d962783e Jia Liu
    if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
3698 d962783e Jia Liu
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3699 d962783e Jia Liu
    }
3700 d962783e Jia Liu
3701 d962783e Jia Liu
    sp = align_sigframe(sp - frame_size);
3702 d962783e Jia Liu
3703 d962783e Jia Liu
    /*
3704 d962783e Jia Liu
     * If we are on the alternate signal stack and would overflow it, don't.
3705 d962783e Jia Liu
     * Return an always-bogus address instead so we will die with SIGSEGV.
3706 d962783e Jia Liu
     */
3707 d962783e Jia Liu
3708 d962783e Jia Liu
    if (onsigstack && !likely(on_sig_stack(sp))) {
3709 d962783e Jia Liu
        return -1L;
3710 d962783e Jia Liu
    }
3711 d962783e Jia Liu
3712 d962783e Jia Liu
    return sp;
3713 d962783e Jia Liu
}
3714 d962783e Jia Liu
3715 d962783e Jia Liu
static void setup_frame(int sig, struct target_sigaction *ka,
3716 d962783e Jia Liu
                        target_sigset_t *set, CPUOpenRISCState *env)
3717 d962783e Jia Liu
{
3718 d962783e Jia Liu
    qemu_log("Not implement.\n");
3719 d962783e Jia Liu
}
3720 d962783e Jia Liu
3721 d962783e Jia Liu
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3722 d962783e Jia Liu
                           target_siginfo_t *info,
3723 d962783e Jia Liu
                           target_sigset_t *set, CPUOpenRISCState *env)
3724 d962783e Jia Liu
{
3725 d962783e Jia Liu
    int err = 0;
3726 d962783e Jia Liu
    abi_ulong frame_addr;
3727 d962783e Jia Liu
    unsigned long return_ip;
3728 d962783e Jia Liu
    struct target_rt_sigframe *frame;
3729 d962783e Jia Liu
    abi_ulong info_addr, uc_addr;
3730 d962783e Jia Liu
3731 d962783e Jia Liu
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3732 d962783e Jia Liu
3733 d962783e Jia Liu
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3734 d962783e Jia Liu
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3735 d962783e Jia Liu
        goto give_sigsegv;
3736 d962783e Jia Liu
    }
3737 d962783e Jia Liu
3738 d962783e Jia Liu
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
3739 d962783e Jia Liu
    err |= __put_user(info_addr, &frame->pinfo);
3740 d962783e Jia Liu
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
3741 d962783e Jia Liu
    err |= __put_user(uc_addr, &frame->puc);
3742 d962783e Jia Liu
3743 d962783e Jia Liu
    if (ka->sa_flags & SA_SIGINFO) {
3744 d962783e Jia Liu
        err |= copy_siginfo_to_user(&frame->info, info);
3745 d962783e Jia Liu
    }
3746 d962783e Jia Liu
    if (err) {
3747 d962783e Jia Liu
        goto give_sigsegv;
3748 d962783e Jia Liu
    }
3749 d962783e Jia Liu
3750 d962783e Jia Liu
    /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
3751 d962783e Jia Liu
    err |= __put_user(0, &frame->uc.tuc_flags);
3752 d962783e Jia Liu
    err |= __put_user(0, &frame->uc.tuc_link);
3753 d962783e Jia Liu
    err |= __put_user(target_sigaltstack_used.ss_sp,
3754 d962783e Jia Liu
                      &frame->uc.tuc_stack.ss_sp);
3755 d962783e Jia Liu
    err |= __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3756 d962783e Jia Liu
    err |= __put_user(target_sigaltstack_used.ss_size,
3757 d962783e Jia Liu
                      &frame->uc.tuc_stack.ss_size);
3758 d962783e Jia Liu
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
3759 d962783e Jia Liu
3760 d962783e Jia Liu
    /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3761 d962783e Jia Liu
3762 d962783e Jia Liu
    if (err) {
3763 d962783e Jia Liu
        goto give_sigsegv;
3764 d962783e Jia Liu
    }
3765 d962783e Jia Liu
3766 d962783e Jia Liu
    /* trampoline - the desired return ip is the retcode itself */
3767 d962783e Jia Liu
    return_ip = (unsigned long)&frame->retcode;
3768 d962783e Jia Liu
    /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
3769 d962783e Jia Liu
    err |= __put_user(0xa960, (short *)(frame->retcode + 0));
3770 d962783e Jia Liu
    err |= __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3771 d962783e Jia Liu
    err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3772 d962783e Jia Liu
    err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
3773 d962783e Jia Liu
3774 d962783e Jia Liu
    if (err) {
3775 d962783e Jia Liu
        goto give_sigsegv;
3776 d962783e Jia Liu
    }
3777 d962783e Jia Liu
3778 d962783e Jia Liu
    /* TODO what is the current->exec_domain stuff and invmap ? */
3779 d962783e Jia Liu
3780 d962783e Jia Liu
    /* Set up registers for signal handler */
3781 d962783e Jia Liu
    env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3782 d962783e Jia Liu
    env->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
3783 d962783e Jia Liu
    env->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
3784 d962783e Jia Liu
    env->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
3785 d962783e Jia Liu
    env->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
3786 d962783e Jia Liu
3787 d962783e Jia Liu
    /* actually move the usp to reflect the stacked frame */
3788 d962783e Jia Liu
    env->gpr[1] = (unsigned long)frame;
3789 d962783e Jia Liu
3790 d962783e Jia Liu
    return;
3791 d962783e Jia Liu
3792 d962783e Jia Liu
give_sigsegv:
3793 d962783e Jia Liu
    unlock_user_struct(frame, frame_addr, 1);
3794 d962783e Jia Liu
    if (sig == TARGET_SIGSEGV) {
3795 d962783e Jia Liu
        ka->_sa_handler = TARGET_SIG_DFL;
3796 d962783e Jia Liu
    }
3797 d962783e Jia Liu
    force_sig(TARGET_SIGSEGV);
3798 d962783e Jia Liu
}
3799 d962783e Jia Liu
3800 d962783e Jia Liu
long do_sigreturn(CPUOpenRISCState *env)
3801 d962783e Jia Liu
{
3802 d962783e Jia Liu
3803 d962783e Jia Liu
    qemu_log("do_sigreturn: not implemented\n");
3804 d962783e Jia Liu
    return -TARGET_ENOSYS;
3805 d962783e Jia Liu
}
3806 d962783e Jia Liu
3807 d962783e Jia Liu
long do_rt_sigreturn(CPUOpenRISCState *env)
3808 d962783e Jia Liu
{
3809 d962783e Jia Liu
    qemu_log("do_rt_sigreturn: not implemented\n");
3810 d962783e Jia Liu
    return -TARGET_ENOSYS;
3811 d962783e Jia Liu
}
3812 d962783e Jia Liu
/* TARGET_OPENRISC */
3813 d962783e Jia Liu
3814 a4c075f1 Ulrich Hecht
#elif defined(TARGET_S390X)
3815 a4c075f1 Ulrich Hecht
3816 a4c075f1 Ulrich Hecht
#define __NUM_GPRS 16
3817 a4c075f1 Ulrich Hecht
#define __NUM_FPRS 16
3818 a4c075f1 Ulrich Hecht
#define __NUM_ACRS 16
3819 a4c075f1 Ulrich Hecht
3820 a4c075f1 Ulrich Hecht
#define S390_SYSCALL_SIZE   2
3821 a4c075f1 Ulrich Hecht
#define __SIGNAL_FRAMESIZE      160 /* FIXME: 31-bit mode -> 96 */
3822 a4c075f1 Ulrich Hecht
3823 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG        64
3824 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */
3825 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
3826 a4c075f1 Ulrich Hecht
#define _SIGMASK_COPY_SIZE    (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
3827 a4c075f1 Ulrich Hecht
#define PSW_ADDR_AMODE            0x0000000000000000UL /* 0x80000000UL for 31-bit */
3828 a4c075f1 Ulrich Hecht
#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
3829 a4c075f1 Ulrich Hecht
3830 a4c075f1 Ulrich Hecht
typedef struct {
3831 a4c075f1 Ulrich Hecht
    target_psw_t psw;
3832 a4c075f1 Ulrich Hecht
    target_ulong gprs[__NUM_GPRS];
3833 a4c075f1 Ulrich Hecht
    unsigned int acrs[__NUM_ACRS];
3834 a4c075f1 Ulrich Hecht
} target_s390_regs_common;
3835 a4c075f1 Ulrich Hecht
3836 a4c075f1 Ulrich Hecht
typedef struct {
3837 a4c075f1 Ulrich Hecht
    unsigned int fpc;
3838 a4c075f1 Ulrich Hecht
    double   fprs[__NUM_FPRS];
3839 a4c075f1 Ulrich Hecht
} target_s390_fp_regs;
3840 a4c075f1 Ulrich Hecht
3841 a4c075f1 Ulrich Hecht
typedef struct {
3842 a4c075f1 Ulrich Hecht
    target_s390_regs_common regs;
3843 a4c075f1 Ulrich Hecht
    target_s390_fp_regs     fpregs;
3844 a4c075f1 Ulrich Hecht
} target_sigregs;
3845 a4c075f1 Ulrich Hecht
3846 a4c075f1 Ulrich Hecht
struct target_sigcontext {
3847 a4c075f1 Ulrich Hecht
    target_ulong   oldmask[_SIGCONTEXT_NSIG_WORDS];
3848 a4c075f1 Ulrich Hecht
    target_sigregs *sregs;
3849 a4c075f1 Ulrich Hecht
};
3850 a4c075f1 Ulrich Hecht
3851 a4c075f1 Ulrich Hecht
typedef struct {
3852 a4c075f1 Ulrich Hecht
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3853 a4c075f1 Ulrich Hecht
    struct target_sigcontext sc;
3854 a4c075f1 Ulrich Hecht
    target_sigregs sregs;
3855 a4c075f1 Ulrich Hecht
    int signo;
3856 a4c075f1 Ulrich Hecht
    uint8_t retcode[S390_SYSCALL_SIZE];
3857 a4c075f1 Ulrich Hecht
} sigframe;
3858 a4c075f1 Ulrich Hecht
3859 a4c075f1 Ulrich Hecht
struct target_ucontext {
3860 6fea2ea4 Peter Maydell
    target_ulong tuc_flags;
3861 6fea2ea4 Peter Maydell
    struct target_ucontext *tuc_link;
3862 6fea2ea4 Peter Maydell
    target_stack_t tuc_stack;
3863 6fea2ea4 Peter Maydell
    target_sigregs tuc_mcontext;
3864 6fea2ea4 Peter Maydell
    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
3865 a4c075f1 Ulrich Hecht
};
3866 a4c075f1 Ulrich Hecht
3867 a4c075f1 Ulrich Hecht
typedef struct {
3868 a4c075f1 Ulrich Hecht
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3869 a4c075f1 Ulrich Hecht
    uint8_t retcode[S390_SYSCALL_SIZE];
3870 a4c075f1 Ulrich Hecht
    struct target_siginfo info;
3871 a4c075f1 Ulrich Hecht
    struct target_ucontext uc;
3872 a4c075f1 Ulrich Hecht
} rt_sigframe;
3873 a4c075f1 Ulrich Hecht
3874 a4c075f1 Ulrich Hecht
static inline abi_ulong
3875 05390248 Andreas Färber
get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
3876 a4c075f1 Ulrich Hecht
{
3877 a4c075f1 Ulrich Hecht
    abi_ulong sp;
3878 a4c075f1 Ulrich Hecht
3879 a4c075f1 Ulrich Hecht
    /* Default to using normal stack */
3880 a4c075f1 Ulrich Hecht
    sp = env->regs[15];
3881 a4c075f1 Ulrich Hecht
3882 a4c075f1 Ulrich Hecht
    /* This is the X/Open sanctioned signal stack switching.  */
3883 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_ONSTACK) {
3884 a4c075f1 Ulrich Hecht
        if (!sas_ss_flags(sp)) {
3885 a4c075f1 Ulrich Hecht
            sp = target_sigaltstack_used.ss_sp +
3886 a4c075f1 Ulrich Hecht
                 target_sigaltstack_used.ss_size;
3887 a4c075f1 Ulrich Hecht
        }
3888 a4c075f1 Ulrich Hecht
    }
3889 a4c075f1 Ulrich Hecht
3890 a4c075f1 Ulrich Hecht
    /* This is the legacy signal stack switching. */
3891 a4c075f1 Ulrich Hecht
    else if (/* FIXME !user_mode(regs) */ 0 &&
3892 a4c075f1 Ulrich Hecht
             !(ka->sa_flags & TARGET_SA_RESTORER) &&
3893 a4c075f1 Ulrich Hecht
             ka->sa_restorer) {
3894 a4c075f1 Ulrich Hecht
        sp = (abi_ulong) ka->sa_restorer;
3895 a4c075f1 Ulrich Hecht
    }
3896 a4c075f1 Ulrich Hecht
3897 a4c075f1 Ulrich Hecht
    return (sp - frame_size) & -8ul;
3898 a4c075f1 Ulrich Hecht
}
3899 a4c075f1 Ulrich Hecht
3900 05390248 Andreas Färber
static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
3901 a4c075f1 Ulrich Hecht
{
3902 a4c075f1 Ulrich Hecht
    int i;
3903 a4c075f1 Ulrich Hecht
    //save_access_regs(current->thread.acrs); FIXME
3904 a4c075f1 Ulrich Hecht
3905 a4c075f1 Ulrich Hecht
    /* Copy a 'clean' PSW mask to the user to avoid leaking
3906 a4c075f1 Ulrich Hecht
       information about whether PER is currently on.  */
3907 a4c075f1 Ulrich Hecht
    __put_user(env->psw.mask, &sregs->regs.psw.mask);
3908 a4c075f1 Ulrich Hecht
    __put_user(env->psw.addr, &sregs->regs.psw.addr);
3909 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3910 a4c075f1 Ulrich Hecht
        __put_user(env->regs[i], &sregs->regs.gprs[i]);
3911 a4c075f1 Ulrich Hecht
    }
3912 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3913 a4c075f1 Ulrich Hecht
        __put_user(env->aregs[i], &sregs->regs.acrs[i]);
3914 a4c075f1 Ulrich Hecht
    }
3915 a4c075f1 Ulrich Hecht
    /*
3916 a4c075f1 Ulrich Hecht
     * We have to store the fp registers to current->thread.fp_regs
3917 a4c075f1 Ulrich Hecht
     * to merge them with the emulated registers.
3918 a4c075f1 Ulrich Hecht
     */
3919 a4c075f1 Ulrich Hecht
    //save_fp_regs(&current->thread.fp_regs); FIXME
3920 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3921 a4c075f1 Ulrich Hecht
        __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]);
3922 a4c075f1 Ulrich Hecht
    }
3923 a4c075f1 Ulrich Hecht
}
3924 a4c075f1 Ulrich Hecht
3925 a4c075f1 Ulrich Hecht
static void setup_frame(int sig, struct target_sigaction *ka,
3926 05390248 Andreas Färber
                        target_sigset_t *set, CPUS390XState *env)
3927 a4c075f1 Ulrich Hecht
{
3928 a4c075f1 Ulrich Hecht
    sigframe *frame;
3929 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr;
3930 a4c075f1 Ulrich Hecht
3931 a4c075f1 Ulrich Hecht
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3932 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3933 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
3934 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3935 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
3936 a4c075f1 Ulrich Hecht
    }
3937 a4c075f1 Ulrich Hecht
3938 a4c075f1 Ulrich Hecht
    qemu_log("%s: 1\n", __FUNCTION__);
3939 a4c075f1 Ulrich Hecht
    if (__put_user(set->sig[0], &frame->sc.oldmask[0])) {
3940 a4c075f1 Ulrich Hecht
              goto give_sigsegv;
3941 a4c075f1 Ulrich Hecht
    }
3942 a4c075f1 Ulrich Hecht
3943 a4c075f1 Ulrich Hecht
    save_sigregs(env, &frame->sregs);
3944 a4c075f1 Ulrich Hecht
3945 a4c075f1 Ulrich Hecht
    __put_user((abi_ulong)(unsigned long)&frame->sregs,
3946 a4c075f1 Ulrich Hecht
               (abi_ulong *)&frame->sc.sregs);
3947 a4c075f1 Ulrich Hecht
3948 a4c075f1 Ulrich Hecht
    /* Set up to return from userspace.  If provided, use a stub
3949 a4c075f1 Ulrich Hecht
       already in userspace.  */
3950 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3951 a4c075f1 Ulrich Hecht
            env->regs[14] = (unsigned long)
3952 a4c075f1 Ulrich Hecht
                    ka->sa_restorer | PSW_ADDR_AMODE;
3953 a4c075f1 Ulrich Hecht
    } else {
3954 a4c075f1 Ulrich Hecht
            env->regs[14] = (unsigned long)
3955 a4c075f1 Ulrich Hecht
                    frame->retcode | PSW_ADDR_AMODE;
3956 a4c075f1 Ulrich Hecht
            if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
3957 a4c075f1 Ulrich Hecht
                           (uint16_t *)(frame->retcode)))
3958 a4c075f1 Ulrich Hecht
                    goto give_sigsegv;
3959 a4c075f1 Ulrich Hecht
    }
3960 a4c075f1 Ulrich Hecht
3961 a4c075f1 Ulrich Hecht
    /* Set up backchain. */
3962 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
3963 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
3964 a4c075f1 Ulrich Hecht
    }
3965 a4c075f1 Ulrich Hecht
3966 a4c075f1 Ulrich Hecht
    /* Set up registers for signal handler */
3967 cb9c6268 Edgar E. Iglesias
    env->regs[15] = frame_addr;
3968 a4c075f1 Ulrich Hecht
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
3969 a4c075f1 Ulrich Hecht
3970 a4c075f1 Ulrich Hecht
    env->regs[2] = sig; //map_signal(sig);
3971 cb9c6268 Edgar E. Iglesias
    env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
3972 a4c075f1 Ulrich Hecht
3973 a4c075f1 Ulrich Hecht
    /* We forgot to include these in the sigcontext.
3974 a4c075f1 Ulrich Hecht
       To avoid breaking binary compatibility, they are passed as args. */
3975 a4c075f1 Ulrich Hecht
    env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
3976 a4c075f1 Ulrich Hecht
    env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
3977 a4c075f1 Ulrich Hecht
3978 a4c075f1 Ulrich Hecht
    /* Place signal number on stack to allow backtrace from handler.  */
3979 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[2], (int *) &frame->signo)) {
3980 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
3981 a4c075f1 Ulrich Hecht
    }
3982 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
3983 a4c075f1 Ulrich Hecht
    return;
3984 a4c075f1 Ulrich Hecht
3985 a4c075f1 Ulrich Hecht
give_sigsegv:
3986 a4c075f1 Ulrich Hecht
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
3987 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
3988 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
3989 a4c075f1 Ulrich Hecht
}
3990 a4c075f1 Ulrich Hecht
3991 a4c075f1 Ulrich Hecht
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3992 a4c075f1 Ulrich Hecht
                           target_siginfo_t *info,
3993 05390248 Andreas Färber
                           target_sigset_t *set, CPUS390XState *env)
3994 a4c075f1 Ulrich Hecht
{
3995 a4c075f1 Ulrich Hecht
    int i;
3996 a4c075f1 Ulrich Hecht
    rt_sigframe *frame;
3997 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr;
3998 a4c075f1 Ulrich Hecht
3999 a4c075f1 Ulrich Hecht
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4000 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4001 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4002 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4003 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4004 a4c075f1 Ulrich Hecht
    }
4005 a4c075f1 Ulrich Hecht
4006 a4c075f1 Ulrich Hecht
    qemu_log("%s: 1\n", __FUNCTION__);
4007 a4c075f1 Ulrich Hecht
    if (copy_siginfo_to_user(&frame->info, info)) {
4008 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4009 a4c075f1 Ulrich Hecht
    }
4010 a4c075f1 Ulrich Hecht
4011 a4c075f1 Ulrich Hecht
    /* Create the ucontext.  */
4012 6fea2ea4 Peter Maydell
    __put_user(0, &frame->uc.tuc_flags);
4013 6fea2ea4 Peter Maydell
    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4014 6fea2ea4 Peter Maydell
    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4015 a4c075f1 Ulrich Hecht
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
4016 6fea2ea4 Peter Maydell
                      &frame->uc.tuc_stack.ss_flags);
4017 6fea2ea4 Peter Maydell
    __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4018 6fea2ea4 Peter Maydell
    save_sigregs(env, &frame->uc.tuc_mcontext);
4019 a4c075f1 Ulrich Hecht
    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4020 a4c075f1 Ulrich Hecht
        __put_user((abi_ulong)set->sig[i],
4021 6fea2ea4 Peter Maydell
        (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4022 a4c075f1 Ulrich Hecht
    }
4023 a4c075f1 Ulrich Hecht
4024 a4c075f1 Ulrich Hecht
    /* Set up to return from userspace.  If provided, use a stub
4025 a4c075f1 Ulrich Hecht
       already in userspace.  */
4026 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_RESTORER) {
4027 a4c075f1 Ulrich Hecht
        env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4028 a4c075f1 Ulrich Hecht
    } else {
4029 a4c075f1 Ulrich Hecht
        env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
4030 a4c075f1 Ulrich Hecht
        if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4031 a4c075f1 Ulrich Hecht
                       (uint16_t *)(frame->retcode))) {
4032 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
4033 a4c075f1 Ulrich Hecht
        }
4034 a4c075f1 Ulrich Hecht
    }
4035 a4c075f1 Ulrich Hecht
4036 a4c075f1 Ulrich Hecht
    /* Set up backchain. */
4037 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
4038 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4039 a4c075f1 Ulrich Hecht
    }
4040 a4c075f1 Ulrich Hecht
4041 a4c075f1 Ulrich Hecht
    /* Set up registers for signal handler */
4042 cb9c6268 Edgar E. Iglesias
    env->regs[15] = frame_addr;
4043 a4c075f1 Ulrich Hecht
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4044 a4c075f1 Ulrich Hecht
4045 a4c075f1 Ulrich Hecht
    env->regs[2] = sig; //map_signal(sig);
4046 cb9c6268 Edgar E. Iglesias
    env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4047 cb9c6268 Edgar E. Iglesias
    env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
4048 a4c075f1 Ulrich Hecht
    return;
4049 a4c075f1 Ulrich Hecht
4050 a4c075f1 Ulrich Hecht
give_sigsegv:
4051 a4c075f1 Ulrich Hecht
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
4052 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
4053 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4054 a4c075f1 Ulrich Hecht
}
4055 a4c075f1 Ulrich Hecht
4056 a4c075f1 Ulrich Hecht
static int
4057 05390248 Andreas Färber
restore_sigregs(CPUS390XState *env, target_sigregs *sc)
4058 a4c075f1 Ulrich Hecht
{
4059 a4c075f1 Ulrich Hecht
    int err = 0;
4060 a4c075f1 Ulrich Hecht
    int i;
4061 a4c075f1 Ulrich Hecht
4062 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4063 a4c075f1 Ulrich Hecht
        err |= __get_user(env->regs[i], &sc->regs.gprs[i]);
4064 a4c075f1 Ulrich Hecht
    }
4065 a4c075f1 Ulrich Hecht
4066 a4c075f1 Ulrich Hecht
    err |= __get_user(env->psw.mask, &sc->regs.psw.mask);
4067 a4c075f1 Ulrich Hecht
    qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
4068 a4c075f1 Ulrich Hecht
             __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
4069 a4c075f1 Ulrich Hecht
             (unsigned long long)env->psw.addr);
4070 a4c075f1 Ulrich Hecht
    err |= __get_user(env->psw.addr, &sc->regs.psw.addr);
4071 a4c075f1 Ulrich Hecht
    /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4072 a4c075f1 Ulrich Hecht
4073 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4074 a4c075f1 Ulrich Hecht
        err |= __get_user(env->aregs[i], &sc->regs.acrs[i]);
4075 a4c075f1 Ulrich Hecht
    }
4076 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4077 a4c075f1 Ulrich Hecht
        err |= __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]);
4078 a4c075f1 Ulrich Hecht
    }
4079 a4c075f1 Ulrich Hecht
4080 a4c075f1 Ulrich Hecht
    return err;
4081 a4c075f1 Ulrich Hecht
}
4082 a4c075f1 Ulrich Hecht
4083 05390248 Andreas Färber
long do_sigreturn(CPUS390XState *env)
4084 a4c075f1 Ulrich Hecht
{
4085 a4c075f1 Ulrich Hecht
    sigframe *frame;
4086 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr = env->regs[15];
4087 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4088 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4089 a4c075f1 Ulrich Hecht
    target_sigset_t target_set;
4090 a4c075f1 Ulrich Hecht
    sigset_t set;
4091 a4c075f1 Ulrich Hecht
4092 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4093 a4c075f1 Ulrich Hecht
        goto badframe;
4094 a4c075f1 Ulrich Hecht
    }
4095 a4c075f1 Ulrich Hecht
    if (__get_user(target_set.sig[0], &frame->sc.oldmask[0])) {
4096 a4c075f1 Ulrich Hecht
        goto badframe;
4097 a4c075f1 Ulrich Hecht
    }
4098 a4c075f1 Ulrich Hecht
4099 a4c075f1 Ulrich Hecht
    target_to_host_sigset_internal(&set, &target_set);
4100 a4c075f1 Ulrich Hecht
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
4101 a4c075f1 Ulrich Hecht
4102 a4c075f1 Ulrich Hecht
    if (restore_sigregs(env, &frame->sregs)) {
4103 a4c075f1 Ulrich Hecht
        goto badframe;
4104 a4c075f1 Ulrich Hecht
    }
4105 a4c075f1 Ulrich Hecht
4106 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4107 a4c075f1 Ulrich Hecht
    return env->regs[2];
4108 a4c075f1 Ulrich Hecht
4109 a4c075f1 Ulrich Hecht
badframe:
4110 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4111 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4112 a4c075f1 Ulrich Hecht
    return 0;
4113 a4c075f1 Ulrich Hecht
}
4114 a4c075f1 Ulrich Hecht
4115 05390248 Andreas Färber
long do_rt_sigreturn(CPUS390XState *env)
4116 a4c075f1 Ulrich Hecht
{
4117 a4c075f1 Ulrich Hecht
    rt_sigframe *frame;
4118 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr = env->regs[15];
4119 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4120 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4121 a4c075f1 Ulrich Hecht
    sigset_t set;
4122 a4c075f1 Ulrich Hecht
4123 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4124 a4c075f1 Ulrich Hecht
        goto badframe;
4125 a4c075f1 Ulrich Hecht
    }
4126 6fea2ea4 Peter Maydell
    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4127 a4c075f1 Ulrich Hecht
4128 a4c075f1 Ulrich Hecht
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
4129 a4c075f1 Ulrich Hecht
4130 6fea2ea4 Peter Maydell
    if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
4131 a4c075f1 Ulrich Hecht
        goto badframe;
4132 a4c075f1 Ulrich Hecht
    }
4133 a4c075f1 Ulrich Hecht
4134 6fea2ea4 Peter Maydell
    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
4135 a4c075f1 Ulrich Hecht
                       get_sp_from_cpustate(env)) == -EFAULT) {
4136 a4c075f1 Ulrich Hecht
        goto badframe;
4137 a4c075f1 Ulrich Hecht
    }
4138 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4139 a4c075f1 Ulrich Hecht
    return env->regs[2];
4140 a4c075f1 Ulrich Hecht
4141 a4c075f1 Ulrich Hecht
badframe:
4142 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4143 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4144 a4c075f1 Ulrich Hecht
    return 0;
4145 a4c075f1 Ulrich Hecht
}
4146 a4c075f1 Ulrich Hecht
4147 bcd4933a Nathan Froyd
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
4148 bcd4933a Nathan Froyd
4149 bcd4933a Nathan Froyd
/* FIXME: Many of the structures are defined for both PPC and PPC64, but
4150 bcd4933a Nathan Froyd
   the signal handling is different enough that we haven't implemented
4151 bcd4933a Nathan Froyd
   support for PPC64 yet.  Hence the restriction above.
4152 bcd4933a Nathan Froyd

4153 bcd4933a Nathan Froyd
   There are various #if'd blocks for code for TARGET_PPC64.  These
4154 bcd4933a Nathan Froyd
   blocks should go away so that we can successfully run 32-bit and
4155 bcd4933a Nathan Froyd
   64-bit binaries on a QEMU configured for PPC64.  */
4156 bcd4933a Nathan Froyd
4157 bcd4933a Nathan Froyd
/* Size of dummy stack frame allocated when calling signal handler.
4158 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h.  */
4159 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4160 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 128
4161 bcd4933a Nathan Froyd
#else
4162 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 64
4163 bcd4933a Nathan Froyd
#endif
4164 bcd4933a Nathan Froyd
4165 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/sigcontext.h.  */
4166 bcd4933a Nathan Froyd
struct target_sigcontext {
4167 bcd4933a Nathan Froyd
    target_ulong _unused[4];
4168 bcd4933a Nathan Froyd
    int32_t signal;
4169 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4170 bcd4933a Nathan Froyd
    int32_t pad0;
4171 bcd4933a Nathan Froyd
#endif
4172 bcd4933a Nathan Froyd
    target_ulong handler;
4173 bcd4933a Nathan Froyd
    target_ulong oldmask;
4174 bcd4933a Nathan Froyd
    target_ulong regs;      /* struct pt_regs __user * */
4175 bcd4933a Nathan Froyd
    /* TODO: PPC64 includes extra bits here.  */
4176 bcd4933a Nathan Froyd
};
4177 bcd4933a Nathan Froyd
4178 bcd4933a Nathan Froyd
/* Indices for target_mcontext.mc_gregs, below.
4179 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h for details.  */
4180 bcd4933a Nathan Froyd
enum {
4181 bcd4933a Nathan Froyd
    TARGET_PT_R0 = 0,
4182 bcd4933a Nathan Froyd
    TARGET_PT_R1 = 1,
4183 bcd4933a Nathan Froyd
    TARGET_PT_R2 = 2,
4184 bcd4933a Nathan Froyd
    TARGET_PT_R3 = 3,
4185 bcd4933a Nathan Froyd
    TARGET_PT_R4 = 4,
4186 bcd4933a Nathan Froyd
    TARGET_PT_R5 = 5,
4187 bcd4933a Nathan Froyd
    TARGET_PT_R6 = 6,
4188 bcd4933a Nathan Froyd
    TARGET_PT_R7 = 7,
4189 bcd4933a Nathan Froyd
    TARGET_PT_R8 = 8,
4190 bcd4933a Nathan Froyd
    TARGET_PT_R9 = 9,
4191 bcd4933a Nathan Froyd
    TARGET_PT_R10 = 10,
4192 bcd4933a Nathan Froyd
    TARGET_PT_R11 = 11,
4193 bcd4933a Nathan Froyd
    TARGET_PT_R12 = 12,
4194 bcd4933a Nathan Froyd
    TARGET_PT_R13 = 13,
4195 bcd4933a Nathan Froyd
    TARGET_PT_R14 = 14,
4196 bcd4933a Nathan Froyd
    TARGET_PT_R15 = 15,
4197 bcd4933a Nathan Froyd
    TARGET_PT_R16 = 16,
4198 bcd4933a Nathan Froyd
    TARGET_PT_R17 = 17,
4199 bcd4933a Nathan Froyd
    TARGET_PT_R18 = 18,
4200 bcd4933a Nathan Froyd
    TARGET_PT_R19 = 19,
4201 bcd4933a Nathan Froyd
    TARGET_PT_R20 = 20,
4202 bcd4933a Nathan Froyd
    TARGET_PT_R21 = 21,
4203 bcd4933a Nathan Froyd
    TARGET_PT_R22 = 22,
4204 bcd4933a Nathan Froyd
    TARGET_PT_R23 = 23,
4205 bcd4933a Nathan Froyd
    TARGET_PT_R24 = 24,
4206 bcd4933a Nathan Froyd
    TARGET_PT_R25 = 25,
4207 bcd4933a Nathan Froyd
    TARGET_PT_R26 = 26,
4208 bcd4933a Nathan Froyd
    TARGET_PT_R27 = 27,
4209 bcd4933a Nathan Froyd
    TARGET_PT_R28 = 28,
4210 bcd4933a Nathan Froyd
    TARGET_PT_R29 = 29,
4211 bcd4933a Nathan Froyd
    TARGET_PT_R30 = 30,
4212 bcd4933a Nathan Froyd
    TARGET_PT_R31 = 31,
4213 bcd4933a Nathan Froyd
    TARGET_PT_NIP = 32,
4214 bcd4933a Nathan Froyd
    TARGET_PT_MSR = 33,
4215 bcd4933a Nathan Froyd
    TARGET_PT_ORIG_R3 = 34,
4216 bcd4933a Nathan Froyd
    TARGET_PT_CTR = 35,
4217 bcd4933a Nathan Froyd
    TARGET_PT_LNK = 36,
4218 bcd4933a Nathan Froyd
    TARGET_PT_XER = 37,
4219 bcd4933a Nathan Froyd
    TARGET_PT_CCR = 38,
4220 bcd4933a Nathan Froyd
    /* Yes, there are two registers with #39.  One is 64-bit only.  */
4221 bcd4933a Nathan Froyd
    TARGET_PT_MQ = 39,
4222 bcd4933a Nathan Froyd
    TARGET_PT_SOFTE = 39,
4223 bcd4933a Nathan Froyd
    TARGET_PT_TRAP = 40,
4224 bcd4933a Nathan Froyd
    TARGET_PT_DAR = 41,
4225 bcd4933a Nathan Froyd
    TARGET_PT_DSISR = 42,
4226 bcd4933a Nathan Froyd
    TARGET_PT_RESULT = 43,
4227 bcd4933a Nathan Froyd
    TARGET_PT_REGS_COUNT = 44
4228 bcd4933a Nathan Froyd
};
4229 bcd4933a Nathan Froyd
4230 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
4231 bcd4933a Nathan Froyd
   on 64-bit PPC, sigcontext and mcontext are one and the same.  */
4232 bcd4933a Nathan Froyd
struct target_mcontext {
4233 bcd4933a Nathan Froyd
    target_ulong mc_gregs[48];
4234 bcd4933a Nathan Froyd
    /* Includes fpscr.  */
4235 bcd4933a Nathan Froyd
    uint64_t mc_fregs[33];
4236 bcd4933a Nathan Froyd
    target_ulong mc_pad[2];
4237 bcd4933a Nathan Froyd
    /* We need to handle Altivec and SPE at the same time, which no
4238 bcd4933a Nathan Froyd
       kernel needs to do.  Fortunately, the kernel defines this bit to
4239 bcd4933a Nathan Froyd
       be Altivec-register-large all the time, rather than trying to
4240 bcd4933a Nathan Froyd
       twiddle it based on the specific platform.  */
4241 bcd4933a Nathan Froyd
    union {
4242 bcd4933a Nathan Froyd
        /* SPE vector registers.  One extra for SPEFSCR.  */
4243 bcd4933a Nathan Froyd
        uint32_t spe[33];
4244 bcd4933a Nathan Froyd
        /* Altivec vector registers.  The packing of VSCR and VRSAVE
4245 bcd4933a Nathan Froyd
           varies depending on whether we're PPC64 or not: PPC64 splits
4246 bcd4933a Nathan Froyd
           them apart; PPC32 stuffs them together.  */
4247 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4248 3efa9a67 malc
#define QEMU_NVRREG 34
4249 bcd4933a Nathan Froyd
#else
4250 3efa9a67 malc
#define QEMU_NVRREG 33
4251 bcd4933a Nathan Froyd
#endif
4252 c227f099 Anthony Liguori
        ppc_avr_t altivec[QEMU_NVRREG];
4253 3efa9a67 malc
#undef QEMU_NVRREG
4254 bcd4933a Nathan Froyd
    } mc_vregs __attribute__((__aligned__(16)));
4255 bcd4933a Nathan Froyd
};
4256 bcd4933a Nathan Froyd
4257 bcd4933a Nathan Froyd
struct target_ucontext {
4258 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
4259 60e99246 Aurelien Jarno
    target_ulong tuc_link;    /* struct ucontext __user * */
4260 60e99246 Aurelien Jarno
    struct target_sigaltstack tuc_stack;
4261 bcd4933a Nathan Froyd
#if !defined(TARGET_PPC64)
4262 60e99246 Aurelien Jarno
    int32_t tuc_pad[7];
4263 60e99246 Aurelien Jarno
    target_ulong tuc_regs;    /* struct mcontext __user *
4264 bcd4933a Nathan Froyd
                                points to uc_mcontext field */
4265 bcd4933a Nathan Froyd
#endif
4266 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4267 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4268 c227f099 Anthony Liguori
    target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
4269 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
4270 bcd4933a Nathan Froyd
#else
4271 60e99246 Aurelien Jarno
    int32_t tuc_maskext[30];
4272 60e99246 Aurelien Jarno
    int32_t tuc_pad2[3];
4273 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
4274 bcd4933a Nathan Froyd
#endif
4275 bcd4933a Nathan Froyd
};
4276 bcd4933a Nathan Froyd
4277 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
4278 bcd4933a Nathan Froyd
struct target_sigframe {
4279 bcd4933a Nathan Froyd
    struct target_sigcontext sctx;
4280 bcd4933a Nathan Froyd
    struct target_mcontext mctx;
4281 bcd4933a Nathan Froyd
    int32_t abigap[56];
4282 bcd4933a Nathan Froyd
};
4283 bcd4933a Nathan Froyd
4284 bcd4933a Nathan Froyd
struct target_rt_sigframe {
4285 bcd4933a Nathan Froyd
    struct target_siginfo info;
4286 bcd4933a Nathan Froyd
    struct target_ucontext uc;
4287 bcd4933a Nathan Froyd
    int32_t abigap[56];
4288 bcd4933a Nathan Froyd
};
4289 bcd4933a Nathan Froyd
4290 bcd4933a Nathan Froyd
/* We use the mc_pad field for the signal return trampoline.  */
4291 bcd4933a Nathan Froyd
#define tramp mc_pad
4292 bcd4933a Nathan Froyd
4293 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal.c.  */
4294 bcd4933a Nathan Froyd
static target_ulong get_sigframe(struct target_sigaction *ka,
4295 05390248 Andreas Färber
                                 CPUPPCState *env,
4296 bcd4933a Nathan Froyd
                                 int frame_size)
4297 bcd4933a Nathan Froyd
{
4298 bcd4933a Nathan Froyd
    target_ulong oldsp, newsp;
4299 bcd4933a Nathan Froyd
4300 bcd4933a Nathan Froyd
    oldsp = env->gpr[1];
4301 bcd4933a Nathan Froyd
4302 bcd4933a Nathan Froyd
    if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
4303 32a2003a Alex Barcelo
        (sas_ss_flags(oldsp) == 0)) {
4304 bcd4933a Nathan Froyd
        oldsp = (target_sigaltstack_used.ss_sp
4305 bcd4933a Nathan Froyd
                 + target_sigaltstack_used.ss_size);
4306 bcd4933a Nathan Froyd
    }
4307 bcd4933a Nathan Froyd
4308 bcd4933a Nathan Froyd
    newsp = (oldsp - frame_size) & ~0xFUL;
4309 bcd4933a Nathan Froyd
4310 bcd4933a Nathan Froyd
    return newsp;
4311 bcd4933a Nathan Froyd
}
4312 bcd4933a Nathan Froyd
4313 05390248 Andreas Färber
static int save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
4314 bcd4933a Nathan Froyd
                          int sigret)
4315 bcd4933a Nathan Froyd
{
4316 bcd4933a Nathan Froyd
    target_ulong msr = env->msr;
4317 bcd4933a Nathan Froyd
    int i;
4318 bcd4933a Nathan Froyd
    target_ulong ccr = 0;
4319 bcd4933a Nathan Froyd
4320 bcd4933a Nathan Froyd
    /* In general, the kernel attempts to be intelligent about what it
4321 bcd4933a Nathan Froyd
       needs to save for Altivec/FP/SPE registers.  We don't care that
4322 bcd4933a Nathan Froyd
       much, so we just go ahead and save everything.  */
4323 bcd4933a Nathan Froyd
4324 bcd4933a Nathan Froyd
    /* Save general registers.  */
4325 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4326 bcd4933a Nathan Froyd
        if (__put_user(env->gpr[i], &frame->mc_gregs[i])) {
4327 bcd4933a Nathan Froyd
            return 1;
4328 bcd4933a Nathan Froyd
        }
4329 bcd4933a Nathan Froyd
    }
4330 bcd4933a Nathan Froyd
    if (__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
4331 bcd4933a Nathan Froyd
        || __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
4332 bcd4933a Nathan Froyd
        || __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
4333 bcd4933a Nathan Froyd
        || __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
4334 bcd4933a Nathan Froyd
        return 1;
4335 bcd4933a Nathan Froyd
4336 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4337 bcd4933a Nathan Froyd
        ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4338 bcd4933a Nathan Froyd
    }
4339 bcd4933a Nathan Froyd
    if (__put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
4340 bcd4933a Nathan Froyd
        return 1;
4341 bcd4933a Nathan Froyd
4342 bcd4933a Nathan Froyd
    /* Save Altivec registers if necessary.  */
4343 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
4344 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
4345 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
4346 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
4347 bcd4933a Nathan Froyd
4348 bcd4933a Nathan Froyd
            if (__put_user(avr->u64[0], &vreg->u64[0]) ||
4349 bcd4933a Nathan Froyd
                __put_user(avr->u64[1], &vreg->u64[1])) {
4350 bcd4933a Nathan Froyd
                return 1;
4351 bcd4933a Nathan Froyd
            }
4352 bcd4933a Nathan Froyd
        }
4353 bcd4933a Nathan Froyd
        /* Set MSR_VR in the saved MSR value to indicate that
4354 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4355 bcd4933a Nathan Froyd
        msr |= MSR_VR;
4356 bcd4933a Nathan Froyd
        if (__put_user((uint32_t)env->spr[SPR_VRSAVE],
4357 bcd4933a Nathan Froyd
                       &frame->mc_vregs.altivec[32].u32[3]))
4358 bcd4933a Nathan Froyd
            return 1;
4359 bcd4933a Nathan Froyd
    }
4360 bcd4933a Nathan Froyd
4361 bcd4933a Nathan Froyd
    /* Save floating point registers.  */
4362 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
4363 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
4364 bcd4933a Nathan Froyd
            if (__put_user(env->fpr[i], &frame->mc_fregs[i])) {
4365 bcd4933a Nathan Froyd
                return 1;
4366 bcd4933a Nathan Froyd
            }
4367 bcd4933a Nathan Froyd
        }
4368 bcd4933a Nathan Froyd
        if (__put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]))
4369 bcd4933a Nathan Froyd
            return 1;
4370 bcd4933a Nathan Froyd
    }
4371 bcd4933a Nathan Froyd
4372 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
4373 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
4374 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4375 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4376 bcd4933a Nathan Froyd
            if (__put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i])) {
4377 bcd4933a Nathan Froyd
                return 1;
4378 bcd4933a Nathan Froyd
            }
4379 bcd4933a Nathan Froyd
        }
4380 bcd4933a Nathan Froyd
#else
4381 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
4382 bcd4933a Nathan Froyd
            if (__put_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
4383 bcd4933a Nathan Froyd
                return 1;
4384 bcd4933a Nathan Froyd
            }
4385 bcd4933a Nathan Froyd
        }
4386 bcd4933a Nathan Froyd
#endif
4387 bcd4933a Nathan Froyd
        /* Set MSR_SPE in the saved MSR value to indicate that
4388 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4389 bcd4933a Nathan Froyd
        msr |= MSR_SPE;
4390 bcd4933a Nathan Froyd
        if (__put_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
4391 bcd4933a Nathan Froyd
            return 1;
4392 bcd4933a Nathan Froyd
    }
4393 bcd4933a Nathan Froyd
4394 bcd4933a Nathan Froyd
    /* Store MSR.  */
4395 bcd4933a Nathan Froyd
    if (__put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
4396 bcd4933a Nathan Froyd
        return 1;
4397 bcd4933a Nathan Froyd
4398 bcd4933a Nathan Froyd
    /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
4399 bcd4933a Nathan Froyd
    if (sigret) {
4400 bcd4933a Nathan Froyd
        if (__put_user(0x38000000UL | sigret, &frame->tramp[0]) ||
4401 bcd4933a Nathan Froyd
            __put_user(0x44000002UL, &frame->tramp[1])) {
4402 bcd4933a Nathan Froyd
            return 1;
4403 bcd4933a Nathan Froyd
        }
4404 bcd4933a Nathan Froyd
    }
4405 bcd4933a Nathan Froyd
4406 bcd4933a Nathan Froyd
    return 0;
4407 bcd4933a Nathan Froyd
}
4408 bcd4933a Nathan Froyd
4409 05390248 Andreas Färber
static int restore_user_regs(CPUPPCState *env,
4410 bcd4933a Nathan Froyd
                             struct target_mcontext *frame, int sig)
4411 bcd4933a Nathan Froyd
{
4412 bcd4933a Nathan Froyd
    target_ulong save_r2 = 0;
4413 bcd4933a Nathan Froyd
    target_ulong msr;
4414 bcd4933a Nathan Froyd
    target_ulong ccr;
4415 bcd4933a Nathan Froyd
4416 bcd4933a Nathan Froyd
    int i;
4417 bcd4933a Nathan Froyd
4418 bcd4933a Nathan Froyd
    if (!sig) {
4419 bcd4933a Nathan Froyd
        save_r2 = env->gpr[2];
4420 bcd4933a Nathan Froyd
    }
4421 bcd4933a Nathan Froyd
4422 bcd4933a Nathan Froyd
    /* Restore general registers.  */
4423 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4424 bcd4933a Nathan Froyd
        if (__get_user(env->gpr[i], &frame->mc_gregs[i])) {
4425 bcd4933a Nathan Froyd
            return 1;
4426 bcd4933a Nathan Froyd
        }
4427 bcd4933a Nathan Froyd
    }
4428 bcd4933a Nathan Froyd
    if (__get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
4429 bcd4933a Nathan Froyd
        || __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
4430 bcd4933a Nathan Froyd
        || __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
4431 bcd4933a Nathan Froyd
        || __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
4432 bcd4933a Nathan Froyd
        return 1;
4433 bcd4933a Nathan Froyd
    if (__get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
4434 bcd4933a Nathan Froyd
        return 1;
4435 bcd4933a Nathan Froyd
4436 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4437 bcd4933a Nathan Froyd
        env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4438 bcd4933a Nathan Froyd
    }
4439 bcd4933a Nathan Froyd
4440 bcd4933a Nathan Froyd
    if (!sig) {
4441 bcd4933a Nathan Froyd
        env->gpr[2] = save_r2;
4442 bcd4933a Nathan Froyd
    }
4443 bcd4933a Nathan Froyd
    /* Restore MSR.  */
4444 bcd4933a Nathan Froyd
    if (__get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
4445 bcd4933a Nathan Froyd
        return 1;
4446 bcd4933a Nathan Froyd
4447 bcd4933a Nathan Froyd
    /* If doing signal return, restore the previous little-endian mode.  */
4448 bcd4933a Nathan Froyd
    if (sig)
4449 bcd4933a Nathan Froyd
        env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4450 bcd4933a Nathan Froyd
4451 bcd4933a Nathan Froyd
    /* Restore Altivec registers if necessary.  */
4452 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
4453 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
4454 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
4455 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
4456 bcd4933a Nathan Froyd
4457 bcd4933a Nathan Froyd
            if (__get_user(avr->u64[0], &vreg->u64[0]) ||
4458 bcd4933a Nathan Froyd
                __get_user(avr->u64[1], &vreg->u64[1])) {
4459 bcd4933a Nathan Froyd
                return 1;
4460 bcd4933a Nathan Froyd
            }
4461 bcd4933a Nathan Froyd
        }
4462 bcd4933a Nathan Froyd
        /* Set MSR_VEC in the saved MSR value to indicate that
4463 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4464 bcd4933a Nathan Froyd
        if (__get_user(env->spr[SPR_VRSAVE],
4465 bcd4933a Nathan Froyd
                       (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])))
4466 bcd4933a Nathan Froyd
            return 1;
4467 bcd4933a Nathan Froyd
    }
4468 bcd4933a Nathan Froyd
4469 bcd4933a Nathan Froyd
    /* Restore floating point registers.  */
4470 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
4471 bcd4933a Nathan Froyd
        uint64_t fpscr;
4472 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
4473 bcd4933a Nathan Froyd
            if (__get_user(env->fpr[i], &frame->mc_fregs[i])) {
4474 bcd4933a Nathan Froyd
                return 1;
4475 bcd4933a Nathan Froyd
            }
4476 bcd4933a Nathan Froyd
        }
4477 bcd4933a Nathan Froyd
        if (__get_user(fpscr, &frame->mc_fregs[32]))
4478 bcd4933a Nathan Froyd
            return 1;
4479 bcd4933a Nathan Froyd
        env->fpscr = (uint32_t) fpscr;
4480 bcd4933a Nathan Froyd
    }
4481 bcd4933a Nathan Froyd
4482 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
4483 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
4484 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4485 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4486 bcd4933a Nathan Froyd
            uint32_t hi;
4487 bcd4933a Nathan Froyd
4488 bcd4933a Nathan Froyd
            if (__get_user(hi, &frame->mc_vregs.spe[i])) {
4489 bcd4933a Nathan Froyd
                return 1;
4490 bcd4933a Nathan Froyd
            }
4491 bcd4933a Nathan Froyd
            env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4492 bcd4933a Nathan Froyd
        }
4493 bcd4933a Nathan Froyd
#else
4494 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
4495 bcd4933a Nathan Froyd
            if (__get_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
4496 bcd4933a Nathan Froyd
                return 1;
4497 bcd4933a Nathan Froyd
            }
4498 bcd4933a Nathan Froyd
        }
4499 bcd4933a Nathan Froyd
#endif
4500 bcd4933a Nathan Froyd
        if (__get_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
4501 bcd4933a Nathan Froyd
            return 1;
4502 bcd4933a Nathan Froyd
    }
4503 bcd4933a Nathan Froyd
4504 bcd4933a Nathan Froyd
    return 0;
4505 bcd4933a Nathan Froyd
}
4506 bcd4933a Nathan Froyd
4507 bcd4933a Nathan Froyd
static void setup_frame(int sig, struct target_sigaction *ka,
4508 05390248 Andreas Färber
                        target_sigset_t *set, CPUPPCState *env)
4509 bcd4933a Nathan Froyd
{
4510 bcd4933a Nathan Froyd
    struct target_sigframe *frame;
4511 bcd4933a Nathan Froyd
    struct target_sigcontext *sc;
4512 bcd4933a Nathan Froyd
    target_ulong frame_addr, newsp;
4513 bcd4933a Nathan Froyd
    int err = 0;
4514 bcd4933a Nathan Froyd
    int signal;
4515 bcd4933a Nathan Froyd
4516 bcd4933a Nathan Froyd
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
4517 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4518 bcd4933a Nathan Froyd
        goto sigsegv;
4519 bcd4933a Nathan Froyd
    sc = &frame->sctx;
4520 bcd4933a Nathan Froyd
4521 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
4522 bcd4933a Nathan Froyd
4523 beb526b1 Samuel Seay
    err |= __put_user(ka->_sa_handler, &sc->handler);
4524 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0], &sc->oldmask);
4525 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4526 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
4527 bcd4933a Nathan Froyd
#else
4528 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[1], &sc->_unused[3]);
4529 bcd4933a Nathan Froyd
#endif
4530 bcd4933a Nathan Froyd
    err |= __put_user(h2g(&frame->mctx), &sc->regs);
4531 bcd4933a Nathan Froyd
    err |= __put_user(sig, &sc->signal);
4532 bcd4933a Nathan Froyd
4533 bcd4933a Nathan Froyd
    /* Save user regs.  */
4534 bcd4933a Nathan Froyd
    err |= save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
4535 bcd4933a Nathan Froyd
4536 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4537 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4538 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->mctx.tramp);
4539 bcd4933a Nathan Froyd
4540 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4541 bcd4933a Nathan Froyd
    env->fpscr = 0;
4542 bcd4933a Nathan Froyd
4543 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4544 bcd4933a Nathan Froyd
    newsp = frame_addr - SIGNAL_FRAMESIZE;
4545 beb526b1 Samuel Seay
    err |= put_user(env->gpr[1], newsp, target_ulong);
4546 bcd4933a Nathan Froyd
4547 bcd4933a Nathan Froyd
    if (err)
4548 bcd4933a Nathan Froyd
        goto sigsegv;
4549 bcd4933a Nathan Froyd
4550 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4551 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4552 bcd4933a Nathan Froyd
    env->gpr[3] = signal;
4553 61993a67 Samuel Seay
    env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
4554 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4555 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4556 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4557 bcd4933a Nathan Froyd
4558 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4559 bcd4933a Nathan Froyd
    return;
4560 bcd4933a Nathan Froyd
4561 bcd4933a Nathan Froyd
sigsegv:
4562 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4563 eeacee4d Blue Swirl
    qemu_log("segfaulting from setup_frame\n");
4564 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4565 bcd4933a Nathan Froyd
}
4566 bcd4933a Nathan Froyd
4567 bcd4933a Nathan Froyd
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4568 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4569 05390248 Andreas Färber
                           target_sigset_t *set, CPUPPCState *env)
4570 bcd4933a Nathan Froyd
{
4571 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf;
4572 bcd4933a Nathan Froyd
    struct target_mcontext *frame;
4573 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr, newsp = 0;
4574 bcd4933a Nathan Froyd
    int i, err = 0;
4575 bcd4933a Nathan Froyd
    int signal;
4576 bcd4933a Nathan Froyd
4577 bcd4933a Nathan Froyd
    rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4578 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4579 bcd4933a Nathan Froyd
        goto sigsegv;
4580 bcd4933a Nathan Froyd
4581 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
4582 bcd4933a Nathan Froyd
4583 bcd4933a Nathan Froyd
    err |= copy_siginfo_to_user(&rt_sf->info, info);
4584 bcd4933a Nathan Froyd
4585 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_flags);
4586 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_link);
4587 bcd4933a Nathan Froyd
    err |= __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4588 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_sp);
4589 bcd4933a Nathan Froyd
    err |= __put_user(sas_ss_flags(env->gpr[1]),
4590 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_flags);
4591 bcd4933a Nathan Froyd
    err |= __put_user(target_sigaltstack_used.ss_size,
4592 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_size);
4593 60e99246 Aurelien Jarno
    err |= __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4594 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_regs);
4595 bcd4933a Nathan Froyd
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
4596 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
4597 bcd4933a Nathan Froyd
    }
4598 bcd4933a Nathan Froyd
4599 60e99246 Aurelien Jarno
    frame = &rt_sf->uc.tuc_mcontext;
4600 bcd4933a Nathan Froyd
    err |= save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
4601 bcd4933a Nathan Froyd
4602 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4603 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4604 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->tramp);
4605 bcd4933a Nathan Froyd
4606 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4607 bcd4933a Nathan Froyd
    env->fpscr = 0;
4608 bcd4933a Nathan Froyd
4609 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4610 bcd4933a Nathan Froyd
    newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
4611 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
4612 bcd4933a Nathan Froyd
4613 bcd4933a Nathan Froyd
    if (err)
4614 bcd4933a Nathan Froyd
        goto sigsegv;
4615 bcd4933a Nathan Froyd
4616 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4617 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4618 bcd4933a Nathan Froyd
    env->gpr[3] = (target_ulong) signal;
4619 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4620 bcd4933a Nathan Froyd
    env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4621 bcd4933a Nathan Froyd
    env->gpr[6] = (target_ulong) h2g(rt_sf);
4622 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4623 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4624 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4625 bcd4933a Nathan Froyd
4626 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4627 bcd4933a Nathan Froyd
    return;
4628 bcd4933a Nathan Froyd
4629 bcd4933a Nathan Froyd
sigsegv:
4630 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4631 eeacee4d Blue Swirl
    qemu_log("segfaulting from setup_rt_frame\n");
4632 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4633 bcd4933a Nathan Froyd
4634 bcd4933a Nathan Froyd
}
4635 bcd4933a Nathan Froyd
4636 05390248 Andreas Färber
long do_sigreturn(CPUPPCState *env)
4637 bcd4933a Nathan Froyd
{
4638 bcd4933a Nathan Froyd
    struct target_sigcontext *sc = NULL;
4639 bcd4933a Nathan Froyd
    struct target_mcontext *sr = NULL;
4640 bcd4933a Nathan Froyd
    target_ulong sr_addr, sc_addr;
4641 bcd4933a Nathan Froyd
    sigset_t blocked;
4642 c227f099 Anthony Liguori
    target_sigset_t set;
4643 bcd4933a Nathan Froyd
4644 bcd4933a Nathan Froyd
    sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4645 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4646 bcd4933a Nathan Froyd
        goto sigsegv;
4647 bcd4933a Nathan Froyd
4648 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4649 bcd4933a Nathan Froyd
    set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
4650 bcd4933a Nathan Froyd
#else
4651 bcd4933a Nathan Froyd
    if(__get_user(set.sig[0], &sc->oldmask) ||
4652 bcd4933a Nathan Froyd
       __get_user(set.sig[1], &sc->_unused[3]))
4653 bcd4933a Nathan Froyd
       goto sigsegv;
4654 bcd4933a Nathan Froyd
#endif
4655 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4656 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4657 bcd4933a Nathan Froyd
4658 bcd4933a Nathan Froyd
    if (__get_user(sr_addr, &sc->regs))
4659 bcd4933a Nathan Froyd
        goto sigsegv;
4660 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4661 bcd4933a Nathan Froyd
        goto sigsegv;
4662 bcd4933a Nathan Froyd
    if (restore_user_regs(env, sr, 1))
4663 bcd4933a Nathan Froyd
        goto sigsegv;
4664 bcd4933a Nathan Froyd
4665 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4666 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4667 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4668 bcd4933a Nathan Froyd
4669 bcd4933a Nathan Froyd
sigsegv:
4670 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4671 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4672 eeacee4d Blue Swirl
    qemu_log("segfaulting from do_sigreturn\n");
4673 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4674 bcd4933a Nathan Froyd
    return 0;
4675 bcd4933a Nathan Froyd
}
4676 bcd4933a Nathan Froyd
4677 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
4678 05390248 Andreas Färber
static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
4679 bcd4933a Nathan Froyd
{
4680 bcd4933a Nathan Froyd
    struct target_mcontext *mcp;
4681 bcd4933a Nathan Froyd
    target_ulong mcp_addr;
4682 bcd4933a Nathan Froyd
    sigset_t blocked;
4683 c227f099 Anthony Liguori
    target_sigset_t set;
4684 bcd4933a Nathan Froyd
4685 60e99246 Aurelien Jarno
    if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
4686 bcd4933a Nathan Froyd
                       sizeof (set)))
4687 bcd4933a Nathan Froyd
        return 1;
4688 bcd4933a Nathan Froyd
4689 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4690 bcd4933a Nathan Froyd
    fprintf (stderr, "do_setcontext: not implemented\n");
4691 bcd4933a Nathan Froyd
    return 0;
4692 bcd4933a Nathan Froyd
#else
4693 60e99246 Aurelien Jarno
    if (__get_user(mcp_addr, &ucp->tuc_regs))
4694 bcd4933a Nathan Froyd
        return 1;
4695 bcd4933a Nathan Froyd
4696 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4697 bcd4933a Nathan Froyd
        return 1;
4698 bcd4933a Nathan Froyd
4699 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4700 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4701 bcd4933a Nathan Froyd
    if (restore_user_regs(env, mcp, sig))
4702 bcd4933a Nathan Froyd
        goto sigsegv;
4703 bcd4933a Nathan Froyd
4704 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4705 bcd4933a Nathan Froyd
    return 0;
4706 bcd4933a Nathan Froyd
4707 bcd4933a Nathan Froyd
sigsegv:
4708 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4709 bcd4933a Nathan Froyd
    return 1;
4710 bcd4933a Nathan Froyd
#endif
4711 bcd4933a Nathan Froyd
}
4712 bcd4933a Nathan Froyd
4713 05390248 Andreas Färber
long do_rt_sigreturn(CPUPPCState *env)
4714 bcd4933a Nathan Froyd
{
4715 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf = NULL;
4716 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr;
4717 bcd4933a Nathan Froyd
4718 bcd4933a Nathan Froyd
    rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4719 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4720 bcd4933a Nathan Froyd
        goto sigsegv;
4721 bcd4933a Nathan Froyd
4722 bcd4933a Nathan Froyd
    if (do_setcontext(&rt_sf->uc, env, 1))
4723 bcd4933a Nathan Froyd
        goto sigsegv;
4724 bcd4933a Nathan Froyd
4725 bcd4933a Nathan Froyd
    do_sigaltstack(rt_sf_addr
4726 60e99246 Aurelien Jarno
                   + offsetof(struct target_rt_sigframe, uc.tuc_stack),
4727 bcd4933a Nathan Froyd
                   0, env->gpr[1]);
4728 bcd4933a Nathan Froyd
4729 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4730 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4731 bcd4933a Nathan Froyd
4732 bcd4933a Nathan Froyd
sigsegv:
4733 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4734 eeacee4d Blue Swirl
    qemu_log("segfaulting from do_rt_sigreturn\n");
4735 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4736 bcd4933a Nathan Froyd
    return 0;
4737 bcd4933a Nathan Froyd
}
4738 bcd4933a Nathan Froyd
4739 492a8744 Laurent Vivier
#elif defined(TARGET_M68K)
4740 492a8744 Laurent Vivier
4741 492a8744 Laurent Vivier
struct target_sigcontext {
4742 492a8744 Laurent Vivier
    abi_ulong  sc_mask;
4743 492a8744 Laurent Vivier
    abi_ulong  sc_usp;
4744 492a8744 Laurent Vivier
    abi_ulong  sc_d0;
4745 492a8744 Laurent Vivier
    abi_ulong  sc_d1;
4746 492a8744 Laurent Vivier
    abi_ulong  sc_a0;
4747 492a8744 Laurent Vivier
    abi_ulong  sc_a1;
4748 492a8744 Laurent Vivier
    unsigned short sc_sr;
4749 492a8744 Laurent Vivier
    abi_ulong  sc_pc;
4750 492a8744 Laurent Vivier
};
4751 492a8744 Laurent Vivier
4752 492a8744 Laurent Vivier
struct target_sigframe
4753 492a8744 Laurent Vivier
{
4754 492a8744 Laurent Vivier
    abi_ulong pretcode;
4755 492a8744 Laurent Vivier
    int sig;
4756 492a8744 Laurent Vivier
    int code;
4757 492a8744 Laurent Vivier
    abi_ulong psc;
4758 492a8744 Laurent Vivier
    char retcode[8];
4759 492a8744 Laurent Vivier
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
4760 492a8744 Laurent Vivier
    struct target_sigcontext sc;
4761 492a8744 Laurent Vivier
};
4762 7181155d Laurent Vivier
 
4763 c227f099 Anthony Liguori
typedef int target_greg_t;
4764 7181155d Laurent Vivier
#define TARGET_NGREG 18
4765 c227f099 Anthony Liguori
typedef target_greg_t target_gregset_t[TARGET_NGREG];
4766 7181155d Laurent Vivier
4767 7181155d Laurent Vivier
typedef struct target_fpregset {
4768 7181155d Laurent Vivier
    int f_fpcntl[3];
4769 7181155d Laurent Vivier
    int f_fpregs[8*3];
4770 c227f099 Anthony Liguori
} target_fpregset_t;
4771 7181155d Laurent Vivier
4772 7181155d Laurent Vivier
struct target_mcontext {
4773 7181155d Laurent Vivier
    int version;
4774 c227f099 Anthony Liguori
    target_gregset_t gregs;
4775 c227f099 Anthony Liguori
    target_fpregset_t fpregs;
4776 7181155d Laurent Vivier
};
4777 7181155d Laurent Vivier
4778 7181155d Laurent Vivier
#define TARGET_MCONTEXT_VERSION 2
4779 7181155d Laurent Vivier
4780 7181155d Laurent Vivier
struct target_ucontext {
4781 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
4782 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
4783 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
4784 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
4785 60e99246 Aurelien Jarno
    abi_long tuc_filler[80];
4786 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4787 7181155d Laurent Vivier
};
4788 7181155d Laurent Vivier
4789 7181155d Laurent Vivier
struct target_rt_sigframe
4790 7181155d Laurent Vivier
{
4791 7181155d Laurent Vivier
    abi_ulong pretcode;
4792 7181155d Laurent Vivier
    int sig;
4793 7181155d Laurent Vivier
    abi_ulong pinfo;
4794 7181155d Laurent Vivier
    abi_ulong puc;
4795 7181155d Laurent Vivier
    char retcode[8];
4796 7181155d Laurent Vivier
    struct target_siginfo info;
4797 7181155d Laurent Vivier
    struct target_ucontext uc;
4798 7181155d Laurent Vivier
};
4799 492a8744 Laurent Vivier
4800 492a8744 Laurent Vivier
static int
4801 05390248 Andreas Färber
setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
4802 05390248 Andreas Färber
                 abi_ulong mask)
4803 492a8744 Laurent Vivier
{
4804 492a8744 Laurent Vivier
    int err = 0;
4805 492a8744 Laurent Vivier
4806 492a8744 Laurent Vivier
    err |= __put_user(mask, &sc->sc_mask);
4807 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[7], &sc->sc_usp);
4808 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[0], &sc->sc_d0);
4809 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[1], &sc->sc_d1);
4810 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[0], &sc->sc_a0);
4811 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[1], &sc->sc_a1);
4812 492a8744 Laurent Vivier
    err |= __put_user(env->sr, &sc->sc_sr);
4813 492a8744 Laurent Vivier
    err |= __put_user(env->pc, &sc->sc_pc);
4814 492a8744 Laurent Vivier
4815 492a8744 Laurent Vivier
    return err;
4816 492a8744 Laurent Vivier
}
4817 492a8744 Laurent Vivier
4818 492a8744 Laurent Vivier
static int
4819 05390248 Andreas Färber
restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
4820 492a8744 Laurent Vivier
{
4821 492a8744 Laurent Vivier
    int err = 0;
4822 492a8744 Laurent Vivier
    int temp;
4823 492a8744 Laurent Vivier
4824 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[7], &sc->sc_usp);
4825 492a8744 Laurent Vivier
    err |= __get_user(env->dregs[1], &sc->sc_d1);
4826 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[0], &sc->sc_a0);
4827 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[1], &sc->sc_a1);
4828 492a8744 Laurent Vivier
    err |= __get_user(env->pc, &sc->sc_pc);
4829 492a8744 Laurent Vivier
    err |= __get_user(temp, &sc->sc_sr);
4830 492a8744 Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4831 492a8744 Laurent Vivier
4832 492a8744 Laurent Vivier
    *pd0 = tswapl(sc->sc_d0);
4833 492a8744 Laurent Vivier
4834 492a8744 Laurent Vivier
    return err;
4835 492a8744 Laurent Vivier
}
4836 492a8744 Laurent Vivier
4837 492a8744 Laurent Vivier
/*
4838 492a8744 Laurent Vivier
 * Determine which stack to use..
4839 492a8744 Laurent Vivier
 */
4840 492a8744 Laurent Vivier
static inline abi_ulong
4841 05390248 Andreas Färber
get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
4842 05390248 Andreas Färber
             size_t frame_size)
4843 492a8744 Laurent Vivier
{
4844 492a8744 Laurent Vivier
    unsigned long sp;
4845 492a8744 Laurent Vivier
4846 492a8744 Laurent Vivier
    sp = regs->aregs[7];
4847 492a8744 Laurent Vivier
4848 492a8744 Laurent Vivier
    /* This is the X/Open sanctioned signal stack switching.  */
4849 492a8744 Laurent Vivier
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
4850 492a8744 Laurent Vivier
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4851 492a8744 Laurent Vivier
    }
4852 492a8744 Laurent Vivier
4853 492a8744 Laurent Vivier
    return ((sp - frame_size) & -8UL);
4854 492a8744 Laurent Vivier
}
4855 492a8744 Laurent Vivier
4856 492a8744 Laurent Vivier
static void setup_frame(int sig, struct target_sigaction *ka,
4857 05390248 Andreas Färber
                        target_sigset_t *set, CPUM68KState *env)
4858 492a8744 Laurent Vivier
{
4859 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4860 492a8744 Laurent Vivier
    abi_ulong frame_addr;
4861 492a8744 Laurent Vivier
    abi_ulong retcode_addr;
4862 492a8744 Laurent Vivier
    abi_ulong sc_addr;
4863 492a8744 Laurent Vivier
    int err = 0;
4864 492a8744 Laurent Vivier
    int i;
4865 492a8744 Laurent Vivier
4866 492a8744 Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4867 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4868 492a8744 Laurent Vivier
        goto give_sigsegv;
4869 492a8744 Laurent Vivier
4870 492a8744 Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4871 492a8744 Laurent Vivier
4872 492a8744 Laurent Vivier
    sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
4873 492a8744 Laurent Vivier
    err |= __put_user(sc_addr, &frame->psc);
4874 492a8744 Laurent Vivier
4875 492a8744 Laurent Vivier
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
4876 492a8744 Laurent Vivier
    if (err)
4877 492a8744 Laurent Vivier
        goto give_sigsegv;
4878 492a8744 Laurent Vivier
4879 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4880 492a8744 Laurent Vivier
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
4881 492a8744 Laurent Vivier
            goto give_sigsegv;
4882 492a8744 Laurent Vivier
    }
4883 492a8744 Laurent Vivier
4884 492a8744 Laurent Vivier
    /* Set up to return from userspace.  */
4885 492a8744 Laurent Vivier
4886 492a8744 Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4887 492a8744 Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4888 492a8744 Laurent Vivier
4889 492a8744 Laurent Vivier
    /* moveq #,d0; trap #0 */
4890 492a8744 Laurent Vivier
4891 492a8744 Laurent Vivier
    err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
4892 492a8744 Laurent Vivier
                      (long *)(frame->retcode));
4893 492a8744 Laurent Vivier
4894 492a8744 Laurent Vivier
    if (err)
4895 492a8744 Laurent Vivier
        goto give_sigsegv;
4896 492a8744 Laurent Vivier
4897 492a8744 Laurent Vivier
    /* Set up to return from userspace */
4898 492a8744 Laurent Vivier
4899 492a8744 Laurent Vivier
    env->aregs[7] = frame_addr;
4900 492a8744 Laurent Vivier
    env->pc = ka->_sa_handler;
4901 492a8744 Laurent Vivier
4902 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4903 492a8744 Laurent Vivier
    return;
4904 492a8744 Laurent Vivier
4905 492a8744 Laurent Vivier
give_sigsegv:
4906 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4907 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4908 492a8744 Laurent Vivier
}
4909 492a8744 Laurent Vivier
4910 7181155d Laurent Vivier
static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
4911 05390248 Andreas Färber
                                           CPUM68KState *env)
4912 7181155d Laurent Vivier
{
4913 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
4914 7181155d Laurent Vivier
    int err;
4915 7181155d Laurent Vivier
4916 60e99246 Aurelien Jarno
    err = __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4917 7181155d Laurent Vivier
    err |= __put_user(env->dregs[0], &gregs[0]);
4918 7181155d Laurent Vivier
    err |= __put_user(env->dregs[1], &gregs[1]);
4919 7181155d Laurent Vivier
    err |= __put_user(env->dregs[2], &gregs[2]);
4920 7181155d Laurent Vivier
    err |= __put_user(env->dregs[3], &gregs[3]);
4921 7181155d Laurent Vivier
    err |= __put_user(env->dregs[4], &gregs[4]);
4922 7181155d Laurent Vivier
    err |= __put_user(env->dregs[5], &gregs[5]);
4923 7181155d Laurent Vivier
    err |= __put_user(env->dregs[6], &gregs[6]);
4924 7181155d Laurent Vivier
    err |= __put_user(env->dregs[7], &gregs[7]);
4925 7181155d Laurent Vivier
    err |= __put_user(env->aregs[0], &gregs[8]);
4926 7181155d Laurent Vivier
    err |= __put_user(env->aregs[1], &gregs[9]);
4927 7181155d Laurent Vivier
    err |= __put_user(env->aregs[2], &gregs[10]);
4928 7181155d Laurent Vivier
    err |= __put_user(env->aregs[3], &gregs[11]);
4929 7181155d Laurent Vivier
    err |= __put_user(env->aregs[4], &gregs[12]);
4930 7181155d Laurent Vivier
    err |= __put_user(env->aregs[5], &gregs[13]);
4931 7181155d Laurent Vivier
    err |= __put_user(env->aregs[6], &gregs[14]);
4932 7181155d Laurent Vivier
    err |= __put_user(env->aregs[7], &gregs[15]);
4933 7181155d Laurent Vivier
    err |= __put_user(env->pc, &gregs[16]);
4934 7181155d Laurent Vivier
    err |= __put_user(env->sr, &gregs[17]);
4935 7181155d Laurent Vivier
4936 7181155d Laurent Vivier
    return err;
4937 7181155d Laurent Vivier
}
4938 7181155d Laurent Vivier
 
4939 05390248 Andreas Färber
static inline int target_rt_restore_ucontext(CPUM68KState *env,
4940 7181155d Laurent Vivier
                                             struct target_ucontext *uc,
4941 7181155d Laurent Vivier
                                             int *pd0)
4942 7181155d Laurent Vivier
{
4943 7181155d Laurent Vivier
    int temp;
4944 7181155d Laurent Vivier
    int err;
4945 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
4946 7181155d Laurent Vivier
    
4947 60e99246 Aurelien Jarno
    err = __get_user(temp, &uc->tuc_mcontext.version);
4948 7181155d Laurent Vivier
    if (temp != TARGET_MCONTEXT_VERSION)
4949 7181155d Laurent Vivier
        goto badframe;
4950 7181155d Laurent Vivier
4951 7181155d Laurent Vivier
    /* restore passed registers */
4952 7181155d Laurent Vivier
    err |= __get_user(env->dregs[0], &gregs[0]);
4953 7181155d Laurent Vivier
    err |= __get_user(env->dregs[1], &gregs[1]);
4954 7181155d Laurent Vivier
    err |= __get_user(env->dregs[2], &gregs[2]);
4955 7181155d Laurent Vivier
    err |= __get_user(env->dregs[3], &gregs[3]);
4956 7181155d Laurent Vivier
    err |= __get_user(env->dregs[4], &gregs[4]);
4957 7181155d Laurent Vivier
    err |= __get_user(env->dregs[5], &gregs[5]);
4958 7181155d Laurent Vivier
    err |= __get_user(env->dregs[6], &gregs[6]);
4959 7181155d Laurent Vivier
    err |= __get_user(env->dregs[7], &gregs[7]);
4960 7181155d Laurent Vivier
    err |= __get_user(env->aregs[0], &gregs[8]);
4961 7181155d Laurent Vivier
    err |= __get_user(env->aregs[1], &gregs[9]);
4962 7181155d Laurent Vivier
    err |= __get_user(env->aregs[2], &gregs[10]);
4963 7181155d Laurent Vivier
    err |= __get_user(env->aregs[3], &gregs[11]);
4964 7181155d Laurent Vivier
    err |= __get_user(env->aregs[4], &gregs[12]);
4965 7181155d Laurent Vivier
    err |= __get_user(env->aregs[5], &gregs[13]);
4966 7181155d Laurent Vivier
    err |= __get_user(env->aregs[6], &gregs[14]);
4967 7181155d Laurent Vivier
    err |= __get_user(env->aregs[7], &gregs[15]);
4968 7181155d Laurent Vivier
    err |= __get_user(env->pc, &gregs[16]);
4969 7181155d Laurent Vivier
    err |= __get_user(temp, &gregs[17]);
4970 7181155d Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4971 7181155d Laurent Vivier
4972 7181155d Laurent Vivier
    *pd0 = env->dregs[0];
4973 7181155d Laurent Vivier
    return err;
4974 7181155d Laurent Vivier
4975 7181155d Laurent Vivier
badframe:
4976 7181155d Laurent Vivier
    return 1;
4977 7181155d Laurent Vivier
}
4978 7181155d Laurent Vivier
4979 492a8744 Laurent Vivier
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4980 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4981 05390248 Andreas Färber
                           target_sigset_t *set, CPUM68KState *env)
4982 492a8744 Laurent Vivier
{
4983 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
4984 7181155d Laurent Vivier
    abi_ulong frame_addr;
4985 7181155d Laurent Vivier
    abi_ulong retcode_addr;
4986 7181155d Laurent Vivier
    abi_ulong info_addr;
4987 7181155d Laurent Vivier
    abi_ulong uc_addr;
4988 7181155d Laurent Vivier
    int err = 0;
4989 7181155d Laurent Vivier
    int i;
4990 7181155d Laurent Vivier
4991 7181155d Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4992 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4993 7181155d Laurent Vivier
        goto give_sigsegv;
4994 7181155d Laurent Vivier
4995 7181155d Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4996 7181155d Laurent Vivier
4997 7181155d Laurent Vivier
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
4998 7181155d Laurent Vivier
    err |= __put_user(info_addr, &frame->pinfo);
4999 7181155d Laurent Vivier
5000 7181155d Laurent Vivier
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
5001 7181155d Laurent Vivier
    err |= __put_user(uc_addr, &frame->puc);
5002 7181155d Laurent Vivier
5003 7181155d Laurent Vivier
    err |= copy_siginfo_to_user(&frame->info, info);
5004 7181155d Laurent Vivier
5005 7181155d Laurent Vivier
    /* Create the ucontext */
5006 7181155d Laurent Vivier
5007 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
5008 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
5009 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_sp,
5010 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
5011 7181155d Laurent Vivier
    err |= __put_user(sas_ss_flags(env->aregs[7]),
5012 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
5013 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_size,
5014 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
5015 7181155d Laurent Vivier
    err |= target_rt_setup_ucontext(&frame->uc, env);
5016 7181155d Laurent Vivier
5017 7181155d Laurent Vivier
    if (err)
5018 7181155d Laurent Vivier
            goto give_sigsegv;
5019 7181155d Laurent Vivier
5020 7181155d Laurent Vivier
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
5021 60e99246 Aurelien Jarno
        if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
5022 7181155d Laurent Vivier
            goto give_sigsegv;
5023 7181155d Laurent Vivier
    }
5024 7181155d Laurent Vivier
5025 7181155d Laurent Vivier
    /* Set up to return from userspace.  */
5026 7181155d Laurent Vivier
5027 7181155d Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
5028 7181155d Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
5029 7181155d Laurent Vivier
5030 7181155d Laurent Vivier
    /* moveq #,d0; notb d0; trap #0 */
5031 7181155d Laurent Vivier
5032 7181155d Laurent Vivier
    err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
5033 7181155d Laurent Vivier
                      (long *)(frame->retcode + 0));
5034 7181155d Laurent Vivier
    err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
5035 7181155d Laurent Vivier
5036 7181155d Laurent Vivier
    if (err)
5037 7181155d Laurent Vivier
        goto give_sigsegv;
5038 7181155d Laurent Vivier
5039 7181155d Laurent Vivier
    /* Set up to return from userspace */
5040 7181155d Laurent Vivier
5041 7181155d Laurent Vivier
    env->aregs[7] = frame_addr;
5042 7181155d Laurent Vivier
    env->pc = ka->_sa_handler;
5043 7181155d Laurent Vivier
5044 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
5045 7181155d Laurent Vivier
    return;
5046 7181155d Laurent Vivier
5047 7181155d Laurent Vivier
give_sigsegv:
5048 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
5049 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
5050 492a8744 Laurent Vivier
}
5051 492a8744 Laurent Vivier
5052 05390248 Andreas Färber
long do_sigreturn(CPUM68KState *env)
5053 492a8744 Laurent Vivier
{
5054 492a8744 Laurent Vivier
    struct target_sigframe *frame;
5055 492a8744 Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
5056 c227f099 Anthony Liguori
    target_sigset_t target_set;
5057 492a8744 Laurent Vivier
    sigset_t set;
5058 492a8744 Laurent Vivier
    int d0, i;
5059 492a8744 Laurent Vivier
5060 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5061 492a8744 Laurent Vivier
        goto badframe;
5062 492a8744 Laurent Vivier
5063 492a8744 Laurent Vivier
    /* set blocked signals */
5064 492a8744 Laurent Vivier
5065 492a8744 Laurent Vivier
    if (__get_user(target_set.sig[0], &frame->sc.sc_mask))
5066 492a8744 Laurent Vivier
        goto badframe;
5067 492a8744 Laurent Vivier
5068 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
5069 492a8744 Laurent Vivier
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
5070 492a8744 Laurent Vivier
            goto badframe;
5071 492a8744 Laurent Vivier
    }
5072 492a8744 Laurent Vivier
5073 492a8744 Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
5074 492a8744 Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
5075 492a8744 Laurent Vivier
5076 492a8744 Laurent Vivier
    /* restore registers */
5077 492a8744 Laurent Vivier
5078 492a8744 Laurent Vivier
    if (restore_sigcontext(env, &frame->sc, &d0))
5079 492a8744 Laurent Vivier
        goto badframe;
5080 492a8744 Laurent Vivier
5081 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5082 492a8744 Laurent Vivier
    return d0;
5083 492a8744 Laurent Vivier
5084 492a8744 Laurent Vivier
badframe:
5085 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5086 492a8744 Laurent Vivier
    force_sig(TARGET_SIGSEGV);
5087 492a8744 Laurent Vivier
    return 0;
5088 492a8744 Laurent Vivier
}
5089 492a8744 Laurent Vivier
5090 05390248 Andreas Färber
long do_rt_sigreturn(CPUM68KState *env)
5091 492a8744 Laurent Vivier
{
5092 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
5093 7181155d Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
5094 c227f099 Anthony Liguori
    target_sigset_t target_set;
5095 7181155d Laurent Vivier
    sigset_t set;
5096 7181155d Laurent Vivier
    int d0;
5097 7181155d Laurent Vivier
5098 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5099 7181155d Laurent Vivier
        goto badframe;
5100 7181155d Laurent Vivier
5101 7181155d Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
5102 7181155d Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
5103 7181155d Laurent Vivier
5104 7181155d Laurent Vivier
    /* restore registers */
5105 7181155d Laurent Vivier
5106 7181155d Laurent Vivier
    if (target_rt_restore_ucontext(env, &frame->uc, &d0))
5107 7181155d Laurent Vivier
        goto badframe;
5108 7181155d Laurent Vivier
5109 7181155d Laurent Vivier
    if (do_sigaltstack(frame_addr +
5110 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
5111 7181155d Laurent Vivier
                       0, get_sp_from_cpustate(env)) == -EFAULT)
5112 7181155d Laurent Vivier
        goto badframe;
5113 7181155d Laurent Vivier
5114 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5115 7181155d Laurent Vivier
    return d0;
5116 7181155d Laurent Vivier
5117 7181155d Laurent Vivier
badframe:
5118 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5119 7181155d Laurent Vivier
    force_sig(TARGET_SIGSEGV);
5120 7181155d Laurent Vivier
    return 0;
5121 492a8744 Laurent Vivier
}
5122 492a8744 Laurent Vivier
5123 6049f4f8 Richard Henderson
#elif defined(TARGET_ALPHA)
5124 6049f4f8 Richard Henderson
5125 6049f4f8 Richard Henderson
struct target_sigcontext {
5126 6049f4f8 Richard Henderson
    abi_long sc_onstack;
5127 6049f4f8 Richard Henderson
    abi_long sc_mask;
5128 6049f4f8 Richard Henderson
    abi_long sc_pc;
5129 6049f4f8 Richard Henderson
    abi_long sc_ps;
5130 6049f4f8 Richard Henderson
    abi_long sc_regs[32];
5131 6049f4f8 Richard Henderson
    abi_long sc_ownedfp;
5132 6049f4f8 Richard Henderson
    abi_long sc_fpregs[32];
5133 6049f4f8 Richard Henderson
    abi_ulong sc_fpcr;
5134 6049f4f8 Richard Henderson
    abi_ulong sc_fp_control;
5135 6049f4f8 Richard Henderson
    abi_ulong sc_reserved1;
5136 6049f4f8 Richard Henderson
    abi_ulong sc_reserved2;
5137 6049f4f8 Richard Henderson
    abi_ulong sc_ssize;
5138 6049f4f8 Richard Henderson
    abi_ulong sc_sbase;
5139 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a0;
5140 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a1;
5141 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a2;
5142 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trap_pc;
5143 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_sum;
5144 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_inst;
5145 6049f4f8 Richard Henderson
};
5146 6049f4f8 Richard Henderson
5147 6049f4f8 Richard Henderson
struct target_ucontext {
5148 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
5149 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
5150 60e99246 Aurelien Jarno
    abi_ulong tuc_osf_sigmask;
5151 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
5152 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
5153 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
5154 6049f4f8 Richard Henderson
};
5155 6049f4f8 Richard Henderson
5156 6049f4f8 Richard Henderson
struct target_sigframe {
5157 6049f4f8 Richard Henderson
    struct target_sigcontext sc;
5158 6049f4f8 Richard Henderson
    unsigned int retcode[3];
5159 6049f4f8 Richard Henderson
};
5160 6049f4f8 Richard Henderson
5161 6049f4f8 Richard Henderson
struct target_rt_sigframe {
5162 6049f4f8 Richard Henderson
    target_siginfo_t info;
5163 6049f4f8 Richard Henderson
    struct target_ucontext uc;
5164 6049f4f8 Richard Henderson
    unsigned int retcode[3];
5165 6049f4f8 Richard Henderson
};
5166 6049f4f8 Richard Henderson
5167 6049f4f8 Richard Henderson
#define INSN_MOV_R30_R16        0x47fe0410
5168 6049f4f8 Richard Henderson
#define INSN_LDI_R0             0x201f0000
5169 6049f4f8 Richard Henderson
#define INSN_CALLSYS            0x00000083
5170 6049f4f8 Richard Henderson
5171 05390248 Andreas Färber
static int setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
5172 6049f4f8 Richard Henderson
                            abi_ulong frame_addr, target_sigset_t *set)
5173 6049f4f8 Richard Henderson
{
5174 6049f4f8 Richard Henderson
    int i, err = 0;
5175 6049f4f8 Richard Henderson
5176 6049f4f8 Richard Henderson
    err |= __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5177 6049f4f8 Richard Henderson
    err |= __put_user(set->sig[0], &sc->sc_mask);
5178 6049f4f8 Richard Henderson
    err |= __put_user(env->pc, &sc->sc_pc);
5179 6049f4f8 Richard Henderson
    err |= __put_user(8, &sc->sc_ps);
5180 6049f4f8 Richard Henderson
5181 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5182 6049f4f8 Richard Henderson
        err |= __put_user(env->ir[i], &sc->sc_regs[i]);
5183 6049f4f8 Richard Henderson
    }
5184 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_regs[31]);
5185 6049f4f8 Richard Henderson
5186 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5187 6049f4f8 Richard Henderson
        err |= __put_user(env->fir[i], &sc->sc_fpregs[i]);
5188 6049f4f8 Richard Henderson
    }
5189 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_fpregs[31]);
5190 6049f4f8 Richard Henderson
    err |= __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
5191 6049f4f8 Richard Henderson
5192 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5193 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5194 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a2); /* FIXME */
5195 6049f4f8 Richard Henderson
5196 6049f4f8 Richard Henderson
    return err;
5197 6049f4f8 Richard Henderson
}
5198 6049f4f8 Richard Henderson
5199 05390248 Andreas Färber
static int restore_sigcontext(CPUAlphaState *env,
5200 05390248 Andreas Färber
                              struct target_sigcontext *sc)
5201 6049f4f8 Richard Henderson
{
5202 6049f4f8 Richard Henderson
    uint64_t fpcr;
5203 6049f4f8 Richard Henderson
    int i, err = 0;
5204 6049f4f8 Richard Henderson
5205 6049f4f8 Richard Henderson
    err |= __get_user(env->pc, &sc->sc_pc);
5206 6049f4f8 Richard Henderson
5207 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5208 6049f4f8 Richard Henderson
        err |= __get_user(env->ir[i], &sc->sc_regs[i]);
5209 6049f4f8 Richard Henderson
    }
5210 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5211 6049f4f8 Richard Henderson
        err |= __get_user(env->fir[i], &sc->sc_fpregs[i]);
5212 6049f4f8 Richard Henderson
    }
5213 6049f4f8 Richard Henderson
5214 6049f4f8 Richard Henderson
    err |= __get_user(fpcr, &sc->sc_fpcr);
5215 6049f4f8 Richard Henderson
    cpu_alpha_store_fpcr(env, fpcr);
5216 6049f4f8 Richard Henderson
5217 6049f4f8 Richard Henderson
    return err;
5218 6049f4f8 Richard Henderson
}
5219 6049f4f8 Richard Henderson
5220 6049f4f8 Richard Henderson
static inline abi_ulong get_sigframe(struct target_sigaction *sa,
5221 05390248 Andreas Färber
                                     CPUAlphaState *env,
5222 05390248 Andreas Färber
                                     unsigned long framesize)
5223 6049f4f8 Richard Henderson
{
5224 6049f4f8 Richard Henderson
    abi_ulong sp = env->ir[IR_SP];
5225 6049f4f8 Richard Henderson
5226 6049f4f8 Richard Henderson
    /* This is the X/Open sanctioned signal stack switching.  */
5227 6049f4f8 Richard Henderson
    if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5228 6049f4f8 Richard Henderson
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5229 6049f4f8 Richard Henderson
    }
5230 6049f4f8 Richard Henderson
    return (sp - framesize) & -32;
5231 6049f4f8 Richard Henderson
}
5232 6049f4f8 Richard Henderson
5233 6049f4f8 Richard Henderson
static void setup_frame(int sig, struct target_sigaction *ka,
5234 05390248 Andreas Färber
                        target_sigset_t *set, CPUAlphaState *env)
5235 6049f4f8 Richard Henderson
{
5236 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
5237 6049f4f8 Richard Henderson
    struct target_sigframe *frame;
5238 6049f4f8 Richard Henderson
    int err = 0;
5239 6049f4f8 Richard Henderson
5240 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
5241 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5242 6049f4f8 Richard Henderson
        goto give_sigsegv;
5243 6049f4f8 Richard Henderson
    }
5244 6049f4f8 Richard Henderson
5245 6049f4f8 Richard Henderson
    err |= setup_sigcontext(&frame->sc, env, frame_addr, set);
5246 6049f4f8 Richard Henderson
5247 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
5248 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
5249 6049f4f8 Richard Henderson
    } else {
5250 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5251 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5252 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
5253 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
5254 6049f4f8 Richard Henderson
        /* imb() */
5255 6049f4f8 Richard Henderson
        r26 = frame_addr;
5256 6049f4f8 Richard Henderson
    }
5257 6049f4f8 Richard Henderson
5258 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 1);
5259 6049f4f8 Richard Henderson
5260 6049f4f8 Richard Henderson
    if (err) {
5261 6049f4f8 Richard Henderson
    give_sigsegv:
5262 6049f4f8 Richard Henderson
        if (sig == TARGET_SIGSEGV) {
5263 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
5264 6049f4f8 Richard Henderson
        }
5265 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
5266 6049f4f8 Richard Henderson
    }
5267 6049f4f8 Richard Henderson
5268 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
5269 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
5270 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
5271 6049f4f8 Richard Henderson
    env->ir[IR_A1] = 0;
5272 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5273 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
5274 6049f4f8 Richard Henderson
}
5275 6049f4f8 Richard Henderson
5276 6049f4f8 Richard Henderson
static void setup_rt_frame(int sig, struct target_sigaction *ka,
5277 6049f4f8 Richard Henderson
                           target_siginfo_t *info,
5278 05390248 Andreas Färber
                           target_sigset_t *set, CPUAlphaState *env)
5279 6049f4f8 Richard Henderson
{
5280 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
5281 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
5282 6049f4f8 Richard Henderson
    int i, err = 0;
5283 6049f4f8 Richard Henderson
5284 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
5285 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5286 6049f4f8 Richard Henderson
        goto give_sigsegv;
5287 6049f4f8 Richard Henderson
    }
5288 6049f4f8 Richard Henderson
5289 6049f4f8 Richard Henderson
    err |= copy_siginfo_to_user(&frame->info, info);
5290 6049f4f8 Richard Henderson
5291 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
5292 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
5293 60e99246 Aurelien Jarno
    err |= __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5294 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_sp,
5295 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
5296 6049f4f8 Richard Henderson
    err |= __put_user(sas_ss_flags(env->ir[IR_SP]),
5297 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
5298 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_size,
5299 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
5300 60e99246 Aurelien Jarno
    err |= setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
5301 6049f4f8 Richard Henderson
    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
5302 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
5303 6049f4f8 Richard Henderson
    }
5304 6049f4f8 Richard Henderson
5305 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
5306 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
5307 6049f4f8 Richard Henderson
    } else {
5308 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5309 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5310 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
5311 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
5312 6049f4f8 Richard Henderson
        /* imb(); */
5313 6049f4f8 Richard Henderson
        r26 = frame_addr;
5314 6049f4f8 Richard Henderson
    }
5315 6049f4f8 Richard Henderson
5316 6049f4f8 Richard Henderson
    if (err) {
5317 6049f4f8 Richard Henderson
    give_sigsegv:
5318 6049f4f8 Richard Henderson
       if (sig == TARGET_SIGSEGV) {
5319 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
5320 6049f4f8 Richard Henderson
        }
5321 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
5322 6049f4f8 Richard Henderson
    }
5323 6049f4f8 Richard Henderson
5324 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
5325 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
5326 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
5327 6049f4f8 Richard Henderson
    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5328 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5329 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
5330 6049f4f8 Richard Henderson
}
5331 6049f4f8 Richard Henderson
5332 05390248 Andreas Färber
long do_sigreturn(CPUAlphaState *env)
5333 6049f4f8 Richard Henderson
{
5334 6049f4f8 Richard Henderson
    struct target_sigcontext *sc;
5335 6049f4f8 Richard Henderson
    abi_ulong sc_addr = env->ir[IR_A0];
5336 6049f4f8 Richard Henderson
    target_sigset_t target_set;
5337 6049f4f8 Richard Henderson
    sigset_t set;
5338 6049f4f8 Richard Henderson
5339 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5340 6049f4f8 Richard Henderson
        goto badframe;
5341 6049f4f8 Richard Henderson
    }
5342 6049f4f8 Richard Henderson
5343 6049f4f8 Richard Henderson
    target_sigemptyset(&target_set);
5344 6049f4f8 Richard Henderson
    if (__get_user(target_set.sig[0], &sc->sc_mask)) {
5345 6049f4f8 Richard Henderson
        goto badframe;
5346 6049f4f8 Richard Henderson
    }
5347 6049f4f8 Richard Henderson
5348 6049f4f8 Richard Henderson
    target_to_host_sigset_internal(&set, &target_set);
5349 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
5350 6049f4f8 Richard Henderson
5351 6049f4f8 Richard Henderson
    if (restore_sigcontext(env, sc)) {
5352 6049f4f8 Richard Henderson
        goto badframe;
5353 6049f4f8 Richard Henderson
    }
5354 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
5355 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
5356 6049f4f8 Richard Henderson
5357 6049f4f8 Richard Henderson
 badframe:
5358 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
5359 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
5360 6049f4f8 Richard Henderson
}
5361 6049f4f8 Richard Henderson
5362 05390248 Andreas Färber
long do_rt_sigreturn(CPUAlphaState *env)
5363 6049f4f8 Richard Henderson
{
5364 6049f4f8 Richard Henderson
    abi_ulong frame_addr = env->ir[IR_A0];
5365 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
5366 6049f4f8 Richard Henderson
    sigset_t set;
5367 6049f4f8 Richard Henderson
5368 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5369 6049f4f8 Richard Henderson
        goto badframe;
5370 6049f4f8 Richard Henderson
    }
5371 60e99246 Aurelien Jarno
    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
5372 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
5373 6049f4f8 Richard Henderson
5374 60e99246 Aurelien Jarno
    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
5375 6049f4f8 Richard Henderson
        goto badframe;
5376 6049f4f8 Richard Henderson
    }
5377 6049f4f8 Richard Henderson
    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5378 60e99246 Aurelien Jarno
                                             uc.tuc_stack),
5379 6049f4f8 Richard Henderson
                       0, env->ir[IR_SP]) == -EFAULT) {
5380 6049f4f8 Richard Henderson
        goto badframe;
5381 6049f4f8 Richard Henderson
    }
5382 6049f4f8 Richard Henderson
5383 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
5384 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
5385 6049f4f8 Richard Henderson
5386 6049f4f8 Richard Henderson
5387 6049f4f8 Richard Henderson
 badframe:
5388 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
5389 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
5390 6049f4f8 Richard Henderson
}
5391 6049f4f8 Richard Henderson
5392 b346ff46 bellard
#else
5393 b346ff46 bellard
5394 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
5395 9349b4f9 Andreas Färber
                        target_sigset_t *set, CPUArchState *env)
5396 b346ff46 bellard
{
5397 b346ff46 bellard
    fprintf(stderr, "setup_frame: not implemented\n");
5398 b346ff46 bellard
}
5399 b346ff46 bellard
5400 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
5401 c227f099 Anthony Liguori
                           target_siginfo_t *info,
5402 9349b4f9 Andreas Färber
                           target_sigset_t *set, CPUArchState *env)
5403 b346ff46 bellard
{
5404 b346ff46 bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
5405 b346ff46 bellard
}
5406 b346ff46 bellard
5407 9349b4f9 Andreas Färber
long do_sigreturn(CPUArchState *env)
5408 b346ff46 bellard
{
5409 b346ff46 bellard
    fprintf(stderr, "do_sigreturn: not implemented\n");
5410 f8b0aa25 bellard
    return -TARGET_ENOSYS;
5411 b346ff46 bellard
}
5412 b346ff46 bellard
5413 9349b4f9 Andreas Färber
long do_rt_sigreturn(CPUArchState *env)
5414 b346ff46 bellard
{
5415 b346ff46 bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
5416 f8b0aa25 bellard
    return -TARGET_ENOSYS;
5417 b346ff46 bellard
}
5418 b346ff46 bellard
5419 66fb9763 bellard
#endif
5420 66fb9763 bellard
5421 9349b4f9 Andreas Färber
void process_pending_signals(CPUArchState *cpu_env)
5422 66fb9763 bellard
{
5423 66fb9763 bellard
    int sig;
5424 992f48a0 blueswir1
    abi_ulong handler;
5425 9de5e440 bellard
    sigset_t set, old_set;
5426 c227f099 Anthony Liguori
    target_sigset_t target_old_set;
5427 624f7979 pbrook
    struct emulated_sigtable *k;
5428 624f7979 pbrook
    struct target_sigaction *sa;
5429 66fb9763 bellard
    struct sigqueue *q;
5430 624f7979 pbrook
    TaskState *ts = cpu_env->opaque;
5431 3b46e624 ths
5432 624f7979 pbrook
    if (!ts->signal_pending)
5433 31e31b8a bellard
        return;
5434 31e31b8a bellard
5435 624f7979 pbrook
    /* FIXME: This is not threadsafe.  */
5436 624f7979 pbrook
    k = ts->sigtab;
5437 66fb9763 bellard
    for(sig = 1; sig <= TARGET_NSIG; sig++) {
5438 66fb9763 bellard
        if (k->pending)
5439 31e31b8a bellard
            goto handle_signal;
5440 66fb9763 bellard
        k++;
5441 31e31b8a bellard
    }
5442 31e31b8a bellard
    /* if no signal is pending, just return */
5443 624f7979 pbrook
    ts->signal_pending = 0;
5444 31e31b8a bellard
    return;
5445 66fb9763 bellard
5446 31e31b8a bellard
 handle_signal:
5447 66fb9763 bellard
#ifdef DEBUG_SIGNAL
5448 bc8a22cc bellard
    fprintf(stderr, "qemu: process signal %d\n", sig);
5449 66fb9763 bellard
#endif
5450 66fb9763 bellard
    /* dequeue signal */
5451 66fb9763 bellard
    q = k->first;
5452 66fb9763 bellard
    k->first = q->next;
5453 66fb9763 bellard
    if (!k->first)
5454 66fb9763 bellard
        k->pending = 0;
5455 3b46e624 ths
5456 1fddef4b bellard
    sig = gdb_handlesig (cpu_env, sig);
5457 1fddef4b bellard
    if (!sig) {
5458 ca587a8e aurel32
        sa = NULL;
5459 ca587a8e aurel32
        handler = TARGET_SIG_IGN;
5460 ca587a8e aurel32
    } else {
5461 ca587a8e aurel32
        sa = &sigact_table[sig - 1];
5462 ca587a8e aurel32
        handler = sa->_sa_handler;
5463 1fddef4b bellard
    }
5464 66fb9763 bellard
5465 66fb9763 bellard
    if (handler == TARGET_SIG_DFL) {
5466 ca587a8e aurel32
        /* default handler : ignore some signal. The other are job control or fatal */
5467 ca587a8e aurel32
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5468 ca587a8e aurel32
            kill(getpid(),SIGSTOP);
5469 ca587a8e aurel32
        } else if (sig != TARGET_SIGCHLD &&
5470 ca587a8e aurel32
                   sig != TARGET_SIGURG &&
5471 ca587a8e aurel32
                   sig != TARGET_SIGWINCH &&
5472 ca587a8e aurel32
                   sig != TARGET_SIGCONT) {
5473 66fb9763 bellard
            force_sig(sig);
5474 66fb9763 bellard
        }
5475 66fb9763 bellard
    } else if (handler == TARGET_SIG_IGN) {
5476 66fb9763 bellard
        /* ignore sig */
5477 66fb9763 bellard
    } else if (handler == TARGET_SIG_ERR) {
5478 66fb9763 bellard
        force_sig(sig);
5479 66fb9763 bellard
    } else {
5480 9de5e440 bellard
        /* compute the blocked signals during the handler execution */
5481 624f7979 pbrook
        target_to_host_sigset(&set, &sa->sa_mask);
5482 9de5e440 bellard
        /* SA_NODEFER indicates that the current signal should not be
5483 9de5e440 bellard
           blocked during the handler */
5484 624f7979 pbrook
        if (!(sa->sa_flags & TARGET_SA_NODEFER))
5485 9de5e440 bellard
            sigaddset(&set, target_to_host_signal(sig));
5486 3b46e624 ths
5487 9de5e440 bellard
        /* block signals in the handler using Linux */
5488 9de5e440 bellard
        sigprocmask(SIG_BLOCK, &set, &old_set);
5489 9de5e440 bellard
        /* save the previous blocked signal state to restore it at the
5490 9de5e440 bellard
           end of the signal execution (see do_sigreturn) */
5491 9231944d bellard
        host_to_target_sigset_internal(&target_old_set, &old_set);
5492 9de5e440 bellard
5493 bc8a22cc bellard
        /* if the CPU is in VM86 mode, we restore the 32 bit values */
5494 84409ddb j_mayer
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
5495 bc8a22cc bellard
        {
5496 bc8a22cc bellard
            CPUX86State *env = cpu_env;
5497 bc8a22cc bellard
            if (env->eflags & VM_MASK)
5498 bc8a22cc bellard
                save_v86_state(env);
5499 bc8a22cc bellard
        }
5500 bc8a22cc bellard
#endif
5501 9de5e440 bellard
        /* prepare the stack frame of the virtual CPU */
5502 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_SIGINFO)
5503 624f7979 pbrook
            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5504 66fb9763 bellard
        else
5505 624f7979 pbrook
            setup_frame(sig, sa, &target_old_set, cpu_env);
5506 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_RESETHAND)
5507 624f7979 pbrook
            sa->_sa_handler = TARGET_SIG_DFL;
5508 31e31b8a bellard
    }
5509 66fb9763 bellard
    if (q != &k->info)
5510 624f7979 pbrook
        free_sigqueue(cpu_env, q);
5511 66fb9763 bellard
}