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 "user-internals.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
{
44 abi_uint tramp
[2]; /* syscall restart return address */
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 #if TARGET_ABI_BITS == 32
106 #define FUNCTIONCALLFRAME 48
109 #define FUNCTIONCALLFRAME 96
111 #define PARISC_RT_SIGFRAME_SIZE32 \
112 ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
114 void setup_rt_frame(int sig
, struct target_sigaction
*ka
,
115 target_siginfo_t
*info
,
116 target_sigset_t
*set
, CPUArchState
*env
)
118 abi_ulong frame_addr
, sp
, haddr
;
119 struct target_rt_sigframe
*frame
;
121 TaskState
*ts
= (TaskState
*)thread_cpu
->opaque
;
123 sp
= get_sp_from_cpustate(env
);
124 if ((ka
->sa_flags
& TARGET_SA_ONSTACK
) && !sas_ss_flags(sp
)) {
125 sp
= (ts
->sigaltstack_used
.ss_sp
+ 0x7f) & ~0x3f;
127 frame_addr
= QEMU_ALIGN_UP(sp
, SIGFRAME
);
128 sp
= frame_addr
+ PARISC_RT_SIGFRAME_SIZE32
;
130 trace_user_setup_rt_frame(env
, frame_addr
);
132 if (!lock_user_struct(VERIFY_WRITE
, frame
, frame_addr
, 0)) {
136 tswap_siginfo(&frame
->info
, info
);
137 frame
->uc
.tuc_flags
= 0;
138 frame
->uc
.tuc_link
= 0;
140 target_save_altstack(&frame
->uc
.tuc_stack
, env
);
142 for (i
= 0; i
< TARGET_NSIG_WORDS
; i
++) {
143 __put_user(set
->sig
[i
], &frame
->uc
.tuc_sigmask
.sig
[i
]);
146 setup_sigcontext(&frame
->uc
.tuc_mcontext
, env
);
148 unlock_user_struct(frame
, frame_addr
, 1);
150 env
->gr
[2] = default_rt_sigreturn
;
153 env
->gr
[25] = h2g(&frame
->info
);
154 env
->gr
[24] = h2g(&frame
->uc
);
156 haddr
= ka
->_sa_handler
;
158 /* Function descriptor. */
159 target_ulong
*fdesc
, dest
;
162 if (!lock_user_struct(VERIFY_READ
, fdesc
, haddr
, 1)) {
165 __get_user(dest
, fdesc
);
166 __get_user(env
->gr
[19], fdesc
+ 1);
167 unlock_user_struct(fdesc
, haddr
, 1);
171 env
->iaoq_b
= haddr
+ 4;
178 long do_rt_sigreturn(CPUArchState
*env
)
180 abi_ulong frame_addr
= env
->gr
[30] - PARISC_RT_SIGFRAME_SIZE32
;
181 struct target_rt_sigframe
*frame
;
184 trace_user_do_rt_sigreturn(env
, frame_addr
);
185 if (!lock_user_struct(VERIFY_READ
, frame
, frame_addr
, 1)) {
188 target_to_host_sigset(&set
, &frame
->uc
.tuc_sigmask
);
191 restore_sigcontext(env
, &frame
->uc
.tuc_mcontext
);
192 target_restore_altstack(&frame
->uc
.tuc_stack
, env
);
194 unlock_user_struct(frame
, frame_addr
, 0);
195 return -QEMU_ESIGRETURN
;
198 force_sig(TARGET_SIGSEGV
);
199 return -QEMU_ESIGRETURN
;
202 void setup_sigtramp(abi_ulong sigtramp_page
)
204 uint32_t *tramp
= lock_user(VERIFY_WRITE
, sigtramp_page
, 6*4, 0);
205 abi_ulong SIGFRAME_CONTEXT_REGS32
;
206 assert(tramp
!= NULL
);
208 SIGFRAME_CONTEXT_REGS32
= offsetof(struct target_rt_sigframe
, uc
.tuc_mcontext
);
209 SIGFRAME_CONTEXT_REGS32
-= PARISC_RT_SIGFRAME_SIZE32
;
211 __put_user(SIGFRAME_CONTEXT_REGS32
, tramp
+ 0);
212 __put_user(0x08000240, tramp
+ 1); /* nop - b/c dwarf2 unwind routines */
213 __put_user(0x34190000, tramp
+ 2); /* ldi 0, %r25 (in_syscall=0) */
214 __put_user(0x3414015a, tramp
+ 3); /* ldi __NR_rt_sigreturn, %r20 */
215 __put_user(0xe4008200, tramp
+ 4); /* ble 0x100(%sr2, %r0) */
216 __put_user(0x08000240, tramp
+ 5); /* nop */
218 default_rt_sigreturn
= (sigtramp_page
+ 8) | 3;
219 unlock_user(tramp
, sigtramp_page
, 6*4);