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
)
54 __put_user(env
->iaoq_f
, &sc
->sc_iaoq
[0]);
55 __put_user(env
->iaoq_b
, &sc
->sc_iaoq
[1]);
56 __put_user(0, &sc
->sc_iasq
[0]);
57 __put_user(0, &sc
->sc_iasq
[1]);
58 __put_user(0, &sc
->sc_flags
);
60 __put_user(cpu_hppa_get_psw(env
), &sc
->sc_gr
[0]);
61 for (i
= 1; i
< 32; ++i
) {
62 __put_user(env
->gr
[i
], &sc
->sc_gr
[i
]);
65 __put_user((uint64_t)env
->fr0_shadow
<< 32, &sc
->sc_fr
[0]);
66 for (i
= 1; i
< 32; ++i
) {
67 __put_user(env
->fr
[i
], &sc
->sc_fr
[i
]);
70 __put_user(env
->cr
[CR_SAR
], &sc
->sc_sar
);
73 static void restore_sigcontext(CPUArchState
*env
, struct target_sigcontext
*sc
)
78 __get_user(psw
, &sc
->sc_gr
[0]);
79 cpu_hppa_put_psw(env
, psw
);
81 for (i
= 1; i
< 32; ++i
) {
82 __get_user(env
->gr
[i
], &sc
->sc_gr
[i
]);
84 for (i
= 0; i
< 32; ++i
) {
85 __get_user(env
->fr
[i
], &sc
->sc_fr
[i
]);
87 cpu_hppa_loaded_fr0(env
);
89 __get_user(env
->iaoq_f
, &sc
->sc_iaoq
[0]);
90 __get_user(env
->iaoq_b
, &sc
->sc_iaoq
[1]);
91 __get_user(env
->cr
[CR_SAR
], &sc
->sc_sar
);
94 #if TARGET_ABI_BITS == 32
96 #define FUNCTIONCALLFRAME 48
99 #define FUNCTIONCALLFRAME 96
101 #define PARISC_RT_SIGFRAME_SIZE32 \
102 ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
104 void setup_rt_frame(int sig
, struct target_sigaction
*ka
,
105 target_siginfo_t
*info
,
106 target_sigset_t
*set
, CPUArchState
*env
)
108 abi_ulong frame_addr
, sp
, haddr
;
109 struct target_rt_sigframe
*frame
;
111 TaskState
*ts
= (TaskState
*)thread_cpu
->opaque
;
113 sp
= get_sp_from_cpustate(env
);
114 if ((ka
->sa_flags
& TARGET_SA_ONSTACK
) && !sas_ss_flags(sp
)) {
115 sp
= (ts
->sigaltstack_used
.ss_sp
+ 0x7f) & ~0x3f;
117 frame_addr
= QEMU_ALIGN_UP(sp
, SIGFRAME
);
118 sp
= frame_addr
+ PARISC_RT_SIGFRAME_SIZE32
;
120 trace_user_setup_rt_frame(env
, frame_addr
);
122 if (!lock_user_struct(VERIFY_WRITE
, frame
, frame_addr
, 0)) {
126 tswap_siginfo(&frame
->info
, info
);
127 frame
->uc
.tuc_flags
= 0;
128 frame
->uc
.tuc_link
= 0;
130 target_save_altstack(&frame
->uc
.tuc_stack
, env
);
132 for (i
= 0; i
< TARGET_NSIG_WORDS
; i
++) {
133 __put_user(set
->sig
[i
], &frame
->uc
.tuc_sigmask
.sig
[i
]);
136 setup_sigcontext(&frame
->uc
.tuc_mcontext
, env
);
138 unlock_user_struct(frame
, frame_addr
, 1);
140 env
->gr
[2] = default_rt_sigreturn
;
143 env
->gr
[25] = h2g(&frame
->info
);
144 env
->gr
[24] = h2g(&frame
->uc
);
146 haddr
= ka
->_sa_handler
;
148 /* Function descriptor. */
149 target_ulong
*fdesc
, dest
;
152 if (!lock_user_struct(VERIFY_READ
, fdesc
, haddr
, 1)) {
155 __get_user(dest
, fdesc
);
156 __get_user(env
->gr
[19], fdesc
+ 1);
157 unlock_user_struct(fdesc
, haddr
, 1);
161 env
->iaoq_b
= haddr
+ 4;
168 long do_rt_sigreturn(CPUArchState
*env
)
170 abi_ulong frame_addr
= env
->gr
[30] - PARISC_RT_SIGFRAME_SIZE32
;
171 struct target_rt_sigframe
*frame
;
174 trace_user_do_rt_sigreturn(env
, frame_addr
);
175 if (!lock_user_struct(VERIFY_READ
, frame
, frame_addr
, 1)) {
178 target_to_host_sigset(&set
, &frame
->uc
.tuc_sigmask
);
181 restore_sigcontext(env
, &frame
->uc
.tuc_mcontext
);
182 target_restore_altstack(&frame
->uc
.tuc_stack
, env
);
184 unlock_user_struct(frame
, frame_addr
, 0);
185 return -QEMU_ESIGRETURN
;
188 force_sig(TARGET_SIGSEGV
);
189 return -QEMU_ESIGRETURN
;
192 void setup_sigtramp(abi_ulong sigtramp_page
)
194 uint32_t *tramp
= lock_user(VERIFY_WRITE
, sigtramp_page
, 6*4, 0);
195 abi_ulong SIGFRAME_CONTEXT_REGS32
;
196 assert(tramp
!= NULL
);
198 SIGFRAME_CONTEXT_REGS32
= offsetof(struct target_rt_sigframe
, uc
.tuc_mcontext
);
199 SIGFRAME_CONTEXT_REGS32
-= PARISC_RT_SIGFRAME_SIZE32
;
201 __put_user(SIGFRAME_CONTEXT_REGS32
, tramp
+ 0);
202 __put_user(0x08000240, tramp
+ 1); /* nop - b/c dwarf2 unwind routines */
203 __put_user(0x34190000, tramp
+ 2); /* ldi 0, %r25 (in_syscall=0) */
204 __put_user(0x3414015a, tramp
+ 3); /* ldi __NR_rt_sigreturn, %r20 */
205 __put_user(0xe4008200, tramp
+ 4); /* ble 0x100(%sr2, %r0) */
206 __put_user(0x08000240, tramp
+ 5); /* nop */
208 default_rt_sigreturn
= (sigtramp_page
+ 8) | 3;
209 unlock_user(tramp
, sigtramp_page
, 6*4);