2 * Emulation of Linux signals
4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "target_signal.h"
22 #include "signal-common.h"
23 #include "linux-user/trace.h"
25 struct target_sigcontext
{
34 struct target_ucontext
{
37 target_stack_t tuc_stack
;
39 struct target_sigcontext tuc_mcontext
;
40 target_sigset_t tuc_sigmask
;
43 struct target_rt_sigframe
{
45 target_siginfo_t info
;
46 struct target_ucontext uc
;
47 /* hidden location of upper halves of pa2.0 64-bit gregs */
50 static void setup_sigcontext(struct target_sigcontext
*sc
, CPUArchState
*env
)
55 /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
57 if (env
->iaoq_f
< TARGET_PAGE_SIZE
) {
58 /* In the gateway page, executing a syscall. */
59 flags
|= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
60 __put_user(env
->gr
[31], &sc
->sc_iaoq
[0]);
61 __put_user(env
->gr
[31] + 4, &sc
->sc_iaoq
[1]);
63 __put_user(env
->iaoq_f
, &sc
->sc_iaoq
[0]);
64 __put_user(env
->iaoq_b
, &sc
->sc_iaoq
[1]);
66 __put_user(0, &sc
->sc_iasq
[0]);
67 __put_user(0, &sc
->sc_iasq
[1]);
68 __put_user(flags
, &sc
->sc_flags
);
70 __put_user(cpu_hppa_get_psw(env
), &sc
->sc_gr
[0]);
71 for (i
= 1; i
< 32; ++i
) {
72 __put_user(env
->gr
[i
], &sc
->sc_gr
[i
]);
75 __put_user((uint64_t)env
->fr0_shadow
<< 32, &sc
->sc_fr
[0]);
76 for (i
= 1; i
< 32; ++i
) {
77 __put_user(env
->fr
[i
], &sc
->sc_fr
[i
]);
80 __put_user(env
->cr
[CR_SAR
], &sc
->sc_sar
);
83 static void restore_sigcontext(CPUArchState
*env
, struct target_sigcontext
*sc
)
88 __get_user(psw
, &sc
->sc_gr
[0]);
89 cpu_hppa_put_psw(env
, psw
);
91 for (i
= 1; i
< 32; ++i
) {
92 __get_user(env
->gr
[i
], &sc
->sc_gr
[i
]);
94 for (i
= 0; i
< 32; ++i
) {
95 __get_user(env
->fr
[i
], &sc
->sc_fr
[i
]);
97 cpu_hppa_loaded_fr0(env
);
99 __get_user(env
->iaoq_f
, &sc
->sc_iaoq
[0]);
100 __get_user(env
->iaoq_b
, &sc
->sc_iaoq
[1]);
101 __get_user(env
->cr
[CR_SAR
], &sc
->sc_sar
);
104 /* No, this doesn't look right, but it's copied straight from the kernel. */
105 #define PARISC_RT_SIGFRAME_SIZE32 \
106 ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
108 void setup_rt_frame(int sig
, struct target_sigaction
*ka
,
109 target_siginfo_t
*info
,
110 target_sigset_t
*set
, CPUArchState
*env
)
112 abi_ulong frame_addr
, sp
, haddr
;
113 struct target_rt_sigframe
*frame
;
116 sp
= get_sp_from_cpustate(env
);
117 if ((ka
->sa_flags
& TARGET_SA_ONSTACK
) && !sas_ss_flags(sp
)) {
118 sp
= (target_sigaltstack_used
.ss_sp
+ 0x7f) & ~0x3f;
120 frame_addr
= QEMU_ALIGN_UP(sp
, 64);
121 sp
= frame_addr
+ PARISC_RT_SIGFRAME_SIZE32
;
123 trace_user_setup_rt_frame(env
, frame_addr
);
125 if (!lock_user_struct(VERIFY_WRITE
, frame
, frame_addr
, 0)) {
129 tswap_siginfo(&frame
->info
, info
);
130 frame
->uc
.tuc_flags
= 0;
131 frame
->uc
.tuc_link
= 0;
133 target_save_altstack(&frame
->uc
.tuc_stack
, env
);
135 for (i
= 0; i
< TARGET_NSIG_WORDS
; i
++) {
136 __put_user(set
->sig
[i
], &frame
->uc
.tuc_sigmask
.sig
[i
]);
139 setup_sigcontext(&frame
->uc
.tuc_mcontext
, env
);
141 __put_user(0x34190000, frame
->tramp
+ 0); /* ldi 0,%r25 */
142 __put_user(0x3414015a, frame
->tramp
+ 1); /* ldi __NR_rt_sigreturn,%r20 */
143 __put_user(0xe4008200, frame
->tramp
+ 2); /* be,l 0x100(%sr2,%r0) */
144 __put_user(0x08000240, frame
->tramp
+ 3); /* nop */
146 unlock_user_struct(frame
, frame_addr
, 1);
148 env
->gr
[2] = h2g(frame
->tramp
);
151 env
->gr
[25] = h2g(&frame
->info
);
152 env
->gr
[24] = h2g(&frame
->uc
);
154 haddr
= ka
->_sa_handler
;
156 /* Function descriptor. */
157 target_ulong
*fdesc
, dest
;
160 if (!lock_user_struct(VERIFY_READ
, fdesc
, haddr
, 1)) {
163 __get_user(dest
, fdesc
);
164 __get_user(env
->gr
[19], fdesc
+ 1);
165 unlock_user_struct(fdesc
, haddr
, 1);
169 env
->iaoq_b
= haddr
+ 4;
176 long do_rt_sigreturn(CPUArchState
*env
)
178 abi_ulong frame_addr
= env
->gr
[30] - PARISC_RT_SIGFRAME_SIZE32
;
179 struct target_rt_sigframe
*frame
;
182 trace_user_do_rt_sigreturn(env
, frame_addr
);
183 if (!lock_user_struct(VERIFY_READ
, frame
, frame_addr
, 1)) {
186 target_to_host_sigset(&set
, &frame
->uc
.tuc_sigmask
);
189 restore_sigcontext(env
, &frame
->uc
.tuc_mcontext
);
190 unlock_user_struct(frame
, frame_addr
, 0);
192 if (do_sigaltstack(frame_addr
+ offsetof(struct target_rt_sigframe
,
194 0, env
->gr
[30]) == -EFAULT
) {
198 unlock_user_struct(frame
, frame_addr
, 0);
199 return -TARGET_QEMU_ESIGRETURN
;
202 force_sig(TARGET_SIGSEGV
);
203 return -TARGET_QEMU_ESIGRETURN
;