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
{
38 struct target_ucontext
{
41 target_stack_t tuc_stack
;
42 struct target_sigcontext tuc_mcontext
;
43 target_sigset_t tuc_sigmask
;
46 struct target_rt_sigframe
{
47 target_siginfo_t info
;
48 struct target_ucontext uc
;
54 static abi_ulong
get_sigframe(struct target_sigaction
*sa
,
56 unsigned long framesize
)
60 sp
= target_sigsp(get_sp_from_cpustate(env
), sa
);
62 return (sp
- framesize
) & -16;
65 static int flush_window_regs(CPUXtensaState
*env
)
67 uint32_t wb
= env
->sregs
[WINDOW_BASE
];
68 uint32_t ws
= xtensa_replicate_windowstart(env
) >> (wb
+ 1);
69 unsigned d
= ctz32(ws
) + 1;
73 for (i
= d
; i
< env
->config
->nareg
/ 4; i
+= d
) {
78 xtensa_rotate_window(env
, d
);
83 } else if (ws
& 0x2) {
85 ret
|= get_user_ual(osp
, env
->regs
[1] - 12);
88 } else if (ws
& 0x4) {
90 ret
|= get_user_ual(osp
, env
->regs
[1] - 12);
94 g_assert_not_reached();
97 for (j
= 0; j
< 4; ++j
) {
98 ret
|= put_user_ual(env
->regs
[j
], ssp
- 16 + j
* 4);
100 for (j
= 4; j
< d
* 4; ++j
) {
101 ret
|= put_user_ual(env
->regs
[j
], osp
- 16 + j
* 4);
104 xtensa_rotate_window(env
, d
);
105 g_assert(env
->sregs
[WINDOW_BASE
] == wb
);
109 static int setup_sigcontext(struct target_rt_sigframe
*frame
,
112 struct target_sigcontext
*sc
= &frame
->uc
.tuc_mcontext
;
115 __put_user(env
->pc
, &sc
->sc_pc
);
116 __put_user(env
->sregs
[PS
], &sc
->sc_ps
);
117 __put_user(env
->sregs
[LBEG
], &sc
->sc_lbeg
);
118 __put_user(env
->sregs
[LEND
], &sc
->sc_lend
);
119 __put_user(env
->sregs
[LCOUNT
], &sc
->sc_lcount
);
120 if (!flush_window_regs(env
)) {
123 for (i
= 0; i
< 16; ++i
) {
124 __put_user(env
->regs
[i
], sc
->sc_a
+ i
);
126 __put_user(0, &sc
->sc_xtregs
);
131 static void install_sigtramp(uint8_t *tramp
)
133 #if TARGET_BIG_ENDIAN
134 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
135 __put_user(0x22, &tramp
[0]);
136 __put_user(0x0a, &tramp
[1]);
137 __put_user(TARGET_NR_rt_sigreturn
, &tramp
[2]);
138 /* Generate instruction: SYSCALL */
139 __put_user(0x00, &tramp
[3]);
140 __put_user(0x05, &tramp
[4]);
141 __put_user(0x00, &tramp
[5]);
143 /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
144 __put_user(0x22, &tramp
[0]);
145 __put_user(0xa0, &tramp
[1]);
146 __put_user(TARGET_NR_rt_sigreturn
, &tramp
[2]);
147 /* Generate instruction: SYSCALL */
148 __put_user(0x00, &tramp
[3]);
149 __put_user(0x50, &tramp
[4]);
150 __put_user(0x00, &tramp
[5]);
154 void setup_rt_frame(int sig
, struct target_sigaction
*ka
,
155 target_siginfo_t
*info
,
156 target_sigset_t
*set
, CPUXtensaState
*env
)
158 abi_ulong frame_addr
;
159 struct target_rt_sigframe
*frame
;
160 int is_fdpic
= info_is_fdpic(get_task_state(thread_cpu
)->info
);
161 abi_ulong handler
= 0;
162 abi_ulong handler_fdpic_GOT
= 0;
168 frame_addr
= get_sigframe(ka
, env
, sizeof(*frame
));
169 trace_user_setup_rt_frame(env
, frame_addr
);
172 abi_ulong funcdesc_ptr
= ka
->_sa_handler
;
174 if (get_user_ual(handler
, funcdesc_ptr
)
175 || get_user_ual(handler_fdpic_GOT
, funcdesc_ptr
+ 4)) {
179 handler
= ka
->_sa_handler
;
182 if (!lock_user_struct(VERIFY_WRITE
, frame
, frame_addr
, 0)) {
186 if (ka
->sa_flags
& SA_SIGINFO
) {
190 __put_user(0, &frame
->uc
.tuc_flags
);
191 __put_user(0, &frame
->uc
.tuc_link
);
192 target_save_altstack(&frame
->uc
.tuc_stack
, env
);
193 if (!setup_sigcontext(frame
, env
)) {
194 unlock_user_struct(frame
, frame_addr
, 0);
197 for (i
= 0; i
< TARGET_NSIG_WORDS
; ++i
) {
198 __put_user(set
->sig
[i
], &frame
->uc
.tuc_sigmask
.sig
[i
]);
201 if (ka
->sa_flags
& TARGET_SA_RESTORER
) {
203 if (get_user_ual(ra
, ka
->sa_restorer
)) {
204 unlock_user_struct(frame
, frame_addr
, 0);
208 ra
= ka
->sa_restorer
;
211 /* Not used, but retain for ABI compatibility. */
212 install_sigtramp(frame
->retcode
);
213 ra
= default_rt_sigreturn
;
215 memset(env
->regs
, 0, sizeof(env
->regs
));
217 env
->regs
[1] = frame_addr
;
218 env
->sregs
[WINDOW_BASE
] = 0;
219 env
->sregs
[WINDOW_START
] = 1;
221 abi_call0
= (env
->sregs
[PS
] & PS_WOE
) == 0;
222 env
->sregs
[PS
] = PS_UM
| (3 << PS_RING_SHIFT
);
226 env
->regs
[base
] = ra
;
228 env
->sregs
[PS
] |= PS_WOE
| (1 << PS_CALLINC_SHIFT
);
230 env
->regs
[base
] = (ra
& 0x3fffffff) | 0x40000000;
232 env
->regs
[base
+ 2] = sig
;
233 env
->regs
[base
+ 3] = frame_addr
+ offsetof(struct target_rt_sigframe
,
235 env
->regs
[base
+ 4] = frame_addr
+ offsetof(struct target_rt_sigframe
, uc
);
237 env
->regs
[base
+ 11] = handler_fdpic_GOT
;
239 unlock_user_struct(frame
, frame_addr
, 1);
247 static void restore_sigcontext(CPUXtensaState
*env
,
248 struct target_rt_sigframe
*frame
)
250 struct target_sigcontext
*sc
= &frame
->uc
.tuc_mcontext
;
254 __get_user(env
->pc
, &sc
->sc_pc
);
255 __get_user(ps
, &sc
->sc_ps
);
256 __get_user(env
->sregs
[LBEG
], &sc
->sc_lbeg
);
257 __get_user(env
->sregs
[LEND
], &sc
->sc_lend
);
258 __get_user(env
->sregs
[LCOUNT
], &sc
->sc_lcount
);
260 env
->sregs
[WINDOW_BASE
] = 0;
261 env
->sregs
[WINDOW_START
] = 1;
262 env
->sregs
[PS
] = deposit32(env
->sregs
[PS
],
265 extract32(ps
, PS_CALLINC_SHIFT
,
267 for (i
= 0; i
< 16; ++i
) {
268 __get_user(env
->regs
[i
], sc
->sc_a
+ i
);
273 long do_rt_sigreturn(CPUXtensaState
*env
)
275 abi_ulong frame_addr
= env
->regs
[1];
276 struct target_rt_sigframe
*frame
;
279 trace_user_do_rt_sigreturn(env
, frame_addr
);
280 if (!lock_user_struct(VERIFY_READ
, frame
, frame_addr
, 1)) {
283 target_to_host_sigset(&set
, &frame
->uc
.tuc_sigmask
);
286 restore_sigcontext(env
, frame
);
287 target_restore_altstack(&frame
->uc
.tuc_stack
, env
);
289 unlock_user_struct(frame
, frame_addr
, 0);
290 return -QEMU_ESIGRETURN
;
293 unlock_user_struct(frame
, frame_addr
, 0);
294 force_sig(TARGET_SIGSEGV
);
295 return -QEMU_ESIGRETURN
;
298 void setup_sigtramp(abi_ulong sigtramp_page
)
300 uint8_t *tramp
= lock_user(VERIFY_WRITE
, sigtramp_page
, 6, 0);
301 assert(tramp
!= NULL
);
303 default_rt_sigreturn
= sigtramp_page
;
304 install_sigtramp(tramp
);
305 unlock_user(tramp
, sigtramp_page
, 6);