1befb7447SLaurent Vivier /* 2befb7447SLaurent Vivier * Emulation of Linux signals 3befb7447SLaurent Vivier * 4befb7447SLaurent Vivier * Copyright (c) 2003 Fabrice Bellard 5befb7447SLaurent Vivier * 6befb7447SLaurent Vivier * This program is free software; you can redistribute it and/or modify 7befb7447SLaurent Vivier * it under the terms of the GNU General Public License as published by 8befb7447SLaurent Vivier * the Free Software Foundation; either version 2 of the License, or 9befb7447SLaurent Vivier * (at your option) any later version. 10befb7447SLaurent Vivier * 11befb7447SLaurent Vivier * This program is distributed in the hope that it will be useful, 12befb7447SLaurent Vivier * but WITHOUT ANY WARRANTY; without even the implied warranty of 13befb7447SLaurent Vivier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14befb7447SLaurent Vivier * GNU General Public License for more details. 15befb7447SLaurent Vivier * 16befb7447SLaurent Vivier * You should have received a copy of the GNU General Public License 17befb7447SLaurent Vivier * along with this program; if not, see <http://www.gnu.org/licenses/>. 18befb7447SLaurent Vivier */ 19a075f313SLaurent Vivier #include "qemu/osdep.h" 20a075f313SLaurent Vivier #include "qemu.h" 213b249d26SPeter Maydell #include "user-internals.h" 22a075f313SLaurent Vivier #include "signal-common.h" 23a075f313SLaurent Vivier #include "linux-user/trace.h" 24a075f313SLaurent Vivier 25a075f313SLaurent Vivier /* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */ 26a075f313SLaurent Vivier 27a075f313SLaurent Vivier struct target_fpreg { 28a075f313SLaurent Vivier uint16_t significand[4]; 29a075f313SLaurent Vivier uint16_t exponent; 30a075f313SLaurent Vivier }; 31a075f313SLaurent Vivier 32a075f313SLaurent Vivier struct target_fpxreg { 33a075f313SLaurent Vivier uint16_t significand[4]; 34a075f313SLaurent Vivier uint16_t exponent; 35a075f313SLaurent Vivier uint16_t padding[3]; 36a075f313SLaurent Vivier }; 37a075f313SLaurent Vivier 38a075f313SLaurent Vivier struct target_xmmreg { 39a075f313SLaurent Vivier uint32_t element[4]; 40a075f313SLaurent Vivier }; 41a075f313SLaurent Vivier 42a075f313SLaurent Vivier struct target_fpstate_32 { 43a075f313SLaurent Vivier /* Regular FPU environment */ 44a075f313SLaurent Vivier uint32_t cw; 45a075f313SLaurent Vivier uint32_t sw; 46a075f313SLaurent Vivier uint32_t tag; 47a075f313SLaurent Vivier uint32_t ipoff; 48a075f313SLaurent Vivier uint32_t cssel; 49a075f313SLaurent Vivier uint32_t dataoff; 50a075f313SLaurent Vivier uint32_t datasel; 51a075f313SLaurent Vivier struct target_fpreg st[8]; 52a075f313SLaurent Vivier uint16_t status; 53a075f313SLaurent Vivier uint16_t magic; /* 0xffff = regular FPU data only */ 54a075f313SLaurent Vivier 55a075f313SLaurent Vivier /* FXSR FPU environment */ 56a075f313SLaurent Vivier uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */ 57a075f313SLaurent Vivier uint32_t mxcsr; 58a075f313SLaurent Vivier uint32_t reserved; 59a075f313SLaurent Vivier struct target_fpxreg fxsr_st[8]; /* FXSR FPU reg data is ignored */ 60a075f313SLaurent Vivier struct target_xmmreg xmm[8]; 61a075f313SLaurent Vivier uint32_t padding[56]; 62a075f313SLaurent Vivier }; 63a075f313SLaurent Vivier 64a075f313SLaurent Vivier struct target_fpstate_64 { 65a075f313SLaurent Vivier /* FXSAVE format */ 66a075f313SLaurent Vivier uint16_t cw; 67a075f313SLaurent Vivier uint16_t sw; 68a075f313SLaurent Vivier uint16_t twd; 69a075f313SLaurent Vivier uint16_t fop; 70a075f313SLaurent Vivier uint64_t rip; 71a075f313SLaurent Vivier uint64_t rdp; 72a075f313SLaurent Vivier uint32_t mxcsr; 73a075f313SLaurent Vivier uint32_t mxcsr_mask; 74a075f313SLaurent Vivier uint32_t st_space[32]; 75a075f313SLaurent Vivier uint32_t xmm_space[64]; 76a075f313SLaurent Vivier uint32_t reserved[24]; 77a075f313SLaurent Vivier }; 78a075f313SLaurent Vivier 79a075f313SLaurent Vivier #ifndef TARGET_X86_64 80a075f313SLaurent Vivier # define target_fpstate target_fpstate_32 81a075f313SLaurent Vivier #else 82a075f313SLaurent Vivier # define target_fpstate target_fpstate_64 83a075f313SLaurent Vivier #endif 84a075f313SLaurent Vivier 85a075f313SLaurent Vivier struct target_sigcontext_32 { 86a075f313SLaurent Vivier uint16_t gs, __gsh; 87a075f313SLaurent Vivier uint16_t fs, __fsh; 88a075f313SLaurent Vivier uint16_t es, __esh; 89a075f313SLaurent Vivier uint16_t ds, __dsh; 90a075f313SLaurent Vivier uint32_t edi; 91a075f313SLaurent Vivier uint32_t esi; 92a075f313SLaurent Vivier uint32_t ebp; 93a075f313SLaurent Vivier uint32_t esp; 94a075f313SLaurent Vivier uint32_t ebx; 95a075f313SLaurent Vivier uint32_t edx; 96a075f313SLaurent Vivier uint32_t ecx; 97a075f313SLaurent Vivier uint32_t eax; 98a075f313SLaurent Vivier uint32_t trapno; 99a075f313SLaurent Vivier uint32_t err; 100a075f313SLaurent Vivier uint32_t eip; 101a075f313SLaurent Vivier uint16_t cs, __csh; 102a075f313SLaurent Vivier uint32_t eflags; 103a075f313SLaurent Vivier uint32_t esp_at_signal; 104a075f313SLaurent Vivier uint16_t ss, __ssh; 105a075f313SLaurent Vivier uint32_t fpstate; /* pointer */ 106a075f313SLaurent Vivier uint32_t oldmask; 107a075f313SLaurent Vivier uint32_t cr2; 108a075f313SLaurent Vivier }; 109a075f313SLaurent Vivier 110a075f313SLaurent Vivier struct target_sigcontext_64 { 111a075f313SLaurent Vivier uint64_t r8; 112a075f313SLaurent Vivier uint64_t r9; 113a075f313SLaurent Vivier uint64_t r10; 114a075f313SLaurent Vivier uint64_t r11; 115a075f313SLaurent Vivier uint64_t r12; 116a075f313SLaurent Vivier uint64_t r13; 117a075f313SLaurent Vivier uint64_t r14; 118a075f313SLaurent Vivier uint64_t r15; 119a075f313SLaurent Vivier 120a075f313SLaurent Vivier uint64_t rdi; 121a075f313SLaurent Vivier uint64_t rsi; 122a075f313SLaurent Vivier uint64_t rbp; 123a075f313SLaurent Vivier uint64_t rbx; 124a075f313SLaurent Vivier uint64_t rdx; 125a075f313SLaurent Vivier uint64_t rax; 126a075f313SLaurent Vivier uint64_t rcx; 127a075f313SLaurent Vivier uint64_t rsp; 128a075f313SLaurent Vivier uint64_t rip; 129a075f313SLaurent Vivier 130a075f313SLaurent Vivier uint64_t eflags; 131a075f313SLaurent Vivier 132a075f313SLaurent Vivier uint16_t cs; 133a075f313SLaurent Vivier uint16_t gs; 134a075f313SLaurent Vivier uint16_t fs; 135a075f313SLaurent Vivier uint16_t ss; 136a075f313SLaurent Vivier 137a075f313SLaurent Vivier uint64_t err; 138a075f313SLaurent Vivier uint64_t trapno; 139a075f313SLaurent Vivier uint64_t oldmask; 140a075f313SLaurent Vivier uint64_t cr2; 141a075f313SLaurent Vivier 142a075f313SLaurent Vivier uint64_t fpstate; /* pointer */ 143a075f313SLaurent Vivier uint64_t padding[8]; 144a075f313SLaurent Vivier }; 145a075f313SLaurent Vivier 146a075f313SLaurent Vivier #ifndef TARGET_X86_64 147a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_32 148a075f313SLaurent Vivier #else 149a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_64 150a075f313SLaurent Vivier #endif 151a075f313SLaurent Vivier 152a075f313SLaurent Vivier /* see Linux/include/uapi/asm-generic/ucontext.h */ 153a075f313SLaurent Vivier struct target_ucontext { 154a075f313SLaurent Vivier abi_ulong tuc_flags; 155a075f313SLaurent Vivier abi_ulong tuc_link; 156a075f313SLaurent Vivier target_stack_t tuc_stack; 157a075f313SLaurent Vivier struct target_sigcontext tuc_mcontext; 158a075f313SLaurent Vivier target_sigset_t tuc_sigmask; /* mask last for extensibility */ 159a075f313SLaurent Vivier }; 160a075f313SLaurent Vivier 161a075f313SLaurent Vivier #ifndef TARGET_X86_64 162a075f313SLaurent Vivier struct sigframe { 163a075f313SLaurent Vivier abi_ulong pretcode; 164a075f313SLaurent Vivier int sig; 165a075f313SLaurent Vivier struct target_sigcontext sc; 166a075f313SLaurent Vivier struct target_fpstate fpstate; 167a075f313SLaurent Vivier abi_ulong extramask[TARGET_NSIG_WORDS-1]; 168a075f313SLaurent Vivier char retcode[8]; 169a075f313SLaurent Vivier }; 170a075f313SLaurent Vivier 171a075f313SLaurent Vivier struct rt_sigframe { 172a075f313SLaurent Vivier abi_ulong pretcode; 173a075f313SLaurent Vivier int sig; 174a075f313SLaurent Vivier abi_ulong pinfo; 175a075f313SLaurent Vivier abi_ulong puc; 176a075f313SLaurent Vivier struct target_siginfo info; 177a075f313SLaurent Vivier struct target_ucontext uc; 178a075f313SLaurent Vivier struct target_fpstate fpstate; 179a075f313SLaurent Vivier char retcode[8]; 180a075f313SLaurent Vivier }; 181a075f313SLaurent Vivier 182a075f313SLaurent Vivier #else 183a075f313SLaurent Vivier 184a075f313SLaurent Vivier struct rt_sigframe { 185a075f313SLaurent Vivier abi_ulong pretcode; 186a075f313SLaurent Vivier struct target_ucontext uc; 187a075f313SLaurent Vivier struct target_siginfo info; 188a075f313SLaurent Vivier struct target_fpstate fpstate; 189a075f313SLaurent Vivier }; 190a075f313SLaurent Vivier 191a075f313SLaurent Vivier #endif 192a075f313SLaurent Vivier 193a075f313SLaurent Vivier /* 194a075f313SLaurent Vivier * Set up a signal frame. 195a075f313SLaurent Vivier */ 196a075f313SLaurent Vivier 197a075f313SLaurent Vivier /* XXX: save x87 state */ 198a075f313SLaurent Vivier static void setup_sigcontext(struct target_sigcontext *sc, 199a075f313SLaurent Vivier struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, 200a075f313SLaurent Vivier abi_ulong fpstate_addr) 201a075f313SLaurent Vivier { 2026aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 203a075f313SLaurent Vivier #ifndef TARGET_X86_64 204a075f313SLaurent Vivier uint16_t magic; 205a075f313SLaurent Vivier 206a075f313SLaurent Vivier /* already locked in setup_frame() */ 207a075f313SLaurent Vivier __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); 208a075f313SLaurent Vivier __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); 209a075f313SLaurent Vivier __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); 210a075f313SLaurent Vivier __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); 211a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->edi); 212a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->esi); 213a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->ebp); 214a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp); 215a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->ebx); 216a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->edx); 217a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->ecx); 218a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->eax); 219a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 220a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 221a075f313SLaurent Vivier __put_user(env->eip, &sc->eip); 222a075f313SLaurent Vivier __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); 223a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 224a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp_at_signal); 225a075f313SLaurent Vivier __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); 226a075f313SLaurent Vivier 227a075f313SLaurent Vivier cpu_x86_fsave(env, fpstate_addr, 1); 228a075f313SLaurent Vivier fpstate->status = fpstate->sw; 229a075f313SLaurent Vivier magic = 0xffff; 230a075f313SLaurent Vivier __put_user(magic, &fpstate->magic); 231a075f313SLaurent Vivier __put_user(fpstate_addr, &sc->fpstate); 232a075f313SLaurent Vivier 233a075f313SLaurent Vivier /* non-iBCS2 extensions.. */ 234a075f313SLaurent Vivier __put_user(mask, &sc->oldmask); 235a075f313SLaurent Vivier __put_user(env->cr[2], &sc->cr2); 236a075f313SLaurent Vivier #else 237a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->rdi); 238a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->rsi); 239a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->rbp); 240a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->rsp); 241a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->rbx); 242a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->rdx); 243a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->rcx); 244a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->rax); 245a075f313SLaurent Vivier 246a075f313SLaurent Vivier __put_user(env->regs[8], &sc->r8); 247a075f313SLaurent Vivier __put_user(env->regs[9], &sc->r9); 248a075f313SLaurent Vivier __put_user(env->regs[10], &sc->r10); 249a075f313SLaurent Vivier __put_user(env->regs[11], &sc->r11); 250a075f313SLaurent Vivier __put_user(env->regs[12], &sc->r12); 251a075f313SLaurent Vivier __put_user(env->regs[13], &sc->r13); 252a075f313SLaurent Vivier __put_user(env->regs[14], &sc->r14); 253a075f313SLaurent Vivier __put_user(env->regs[15], &sc->r15); 254a075f313SLaurent Vivier 255a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 256a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 257a075f313SLaurent Vivier __put_user(env->eip, &sc->rip); 258a075f313SLaurent Vivier 259a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 260a075f313SLaurent Vivier __put_user(env->segs[R_CS].selector, &sc->cs); 261a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->gs); 262a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->fs); 263a075f313SLaurent Vivier __put_user(env->segs[R_SS].selector, &sc->ss); 264a075f313SLaurent Vivier 265a075f313SLaurent Vivier __put_user(mask, &sc->oldmask); 266a075f313SLaurent Vivier __put_user(env->cr[2], &sc->cr2); 267a075f313SLaurent Vivier 268a075f313SLaurent Vivier /* fpstate_addr must be 16 byte aligned for fxsave */ 269a075f313SLaurent Vivier assert(!(fpstate_addr & 0xf)); 270a075f313SLaurent Vivier 271a075f313SLaurent Vivier cpu_x86_fxsave(env, fpstate_addr); 272a075f313SLaurent Vivier __put_user(fpstate_addr, &sc->fpstate); 273a075f313SLaurent Vivier #endif 274a075f313SLaurent Vivier } 275a075f313SLaurent Vivier 276a075f313SLaurent Vivier /* 277a075f313SLaurent Vivier * Determine which stack to use.. 278a075f313SLaurent Vivier */ 279a075f313SLaurent Vivier 280a075f313SLaurent Vivier static inline abi_ulong 281a075f313SLaurent Vivier get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size) 282a075f313SLaurent Vivier { 283a075f313SLaurent Vivier unsigned long esp; 284a075f313SLaurent Vivier 285a075f313SLaurent Vivier /* Default to using normal stack */ 286465e237bSLaurent Vivier esp = get_sp_from_cpustate(env); 287a075f313SLaurent Vivier #ifdef TARGET_X86_64 288a075f313SLaurent Vivier esp -= 128; /* this is the redzone */ 289a075f313SLaurent Vivier #endif 290a075f313SLaurent Vivier 291a075f313SLaurent Vivier /* This is the X/Open sanctioned signal stack switching. */ 292a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_ONSTACK) { 293465e237bSLaurent Vivier esp = target_sigsp(esp, ka); 294a075f313SLaurent Vivier } else { 295a075f313SLaurent Vivier #ifndef TARGET_X86_64 296a075f313SLaurent Vivier /* This is the legacy signal stack switching. */ 297a075f313SLaurent Vivier if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && 298a075f313SLaurent Vivier !(ka->sa_flags & TARGET_SA_RESTORER) && 299a075f313SLaurent Vivier ka->sa_restorer) { 300a075f313SLaurent Vivier esp = (unsigned long) ka->sa_restorer; 301a075f313SLaurent Vivier } 302a075f313SLaurent Vivier #endif 303a075f313SLaurent Vivier } 304a075f313SLaurent Vivier 305a075f313SLaurent Vivier #ifndef TARGET_X86_64 306a075f313SLaurent Vivier return (esp - frame_size) & -8ul; 307a075f313SLaurent Vivier #else 308a075f313SLaurent Vivier return ((esp - frame_size) & (~15ul)) - 8; 309a075f313SLaurent Vivier #endif 310a075f313SLaurent Vivier } 311a075f313SLaurent Vivier 312a075f313SLaurent Vivier #ifndef TARGET_X86_64 3138ee8a104SRichard Henderson static void install_sigtramp(void *tramp) 3148ee8a104SRichard Henderson { 3158ee8a104SRichard Henderson /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */ 3168ee8a104SRichard Henderson __put_user(0xb858, (uint16_t *)(tramp + 0)); 3178ee8a104SRichard Henderson __put_user(TARGET_NR_sigreturn, (int32_t *)(tramp + 2)); 3188ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 6)); 3198ee8a104SRichard Henderson } 3208ee8a104SRichard Henderson 3218ee8a104SRichard Henderson static void install_rt_sigtramp(void *tramp) 3228ee8a104SRichard Henderson { 3238ee8a104SRichard Henderson /* This is movl $syscall,%eax ; int $0x80 */ 3248ee8a104SRichard Henderson __put_user(0xb8, (uint8_t *)(tramp + 0)); 3258ee8a104SRichard Henderson __put_user(TARGET_NR_rt_sigreturn, (int32_t *)(tramp + 1)); 3268ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 5)); 3278ee8a104SRichard Henderson } 3288ee8a104SRichard Henderson 329a075f313SLaurent Vivier /* compare linux/arch/i386/kernel/signal.c:setup_frame() */ 330a075f313SLaurent Vivier void setup_frame(int sig, struct target_sigaction *ka, 331a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 332a075f313SLaurent Vivier { 333a075f313SLaurent Vivier abi_ulong frame_addr; 334a075f313SLaurent Vivier struct sigframe *frame; 335a075f313SLaurent Vivier int i; 336a075f313SLaurent Vivier 337a075f313SLaurent Vivier frame_addr = get_sigframe(ka, env, sizeof(*frame)); 338a075f313SLaurent Vivier trace_user_setup_frame(env, frame_addr); 339a075f313SLaurent Vivier 340a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) 341a075f313SLaurent Vivier goto give_sigsegv; 342a075f313SLaurent Vivier 343a075f313SLaurent Vivier __put_user(sig, &frame->sig); 344a075f313SLaurent Vivier 345a075f313SLaurent Vivier setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], 346a075f313SLaurent Vivier frame_addr + offsetof(struct sigframe, fpstate)); 347a075f313SLaurent Vivier 348a075f313SLaurent Vivier for(i = 1; i < TARGET_NSIG_WORDS; i++) { 349a075f313SLaurent Vivier __put_user(set->sig[i], &frame->extramask[i - 1]); 350a075f313SLaurent Vivier } 351a075f313SLaurent Vivier 352a075f313SLaurent Vivier /* Set up to return from userspace. If provided, use a stub 353a075f313SLaurent Vivier already in userspace. */ 354a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 355a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 356a075f313SLaurent Vivier } else { 3578ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 3588ee8a104SRichard Henderson install_sigtramp(frame->retcode); 3598ee8a104SRichard Henderson __put_user(default_sigreturn, &frame->pretcode); 360a075f313SLaurent Vivier } 361a075f313SLaurent Vivier 362a075f313SLaurent Vivier /* Set up registers for signal handler */ 363a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 364a075f313SLaurent Vivier env->eip = ka->_sa_handler; 365a075f313SLaurent Vivier 366a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, __USER_DS); 367a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, __USER_DS); 368a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, __USER_DS); 369a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 370a075f313SLaurent Vivier env->eflags &= ~TF_MASK; 371a075f313SLaurent Vivier 372a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 1); 373a075f313SLaurent Vivier 374a075f313SLaurent Vivier return; 375a075f313SLaurent Vivier 376a075f313SLaurent Vivier give_sigsegv: 377a075f313SLaurent Vivier force_sigsegv(sig); 378a075f313SLaurent Vivier } 379a075f313SLaurent Vivier #endif 380a075f313SLaurent Vivier 381a075f313SLaurent Vivier /* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */ 382a075f313SLaurent Vivier void setup_rt_frame(int sig, struct target_sigaction *ka, 383a075f313SLaurent Vivier target_siginfo_t *info, 384a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 385a075f313SLaurent Vivier { 386a075f313SLaurent Vivier abi_ulong frame_addr; 387a075f313SLaurent Vivier #ifndef TARGET_X86_64 388a075f313SLaurent Vivier abi_ulong addr; 389a075f313SLaurent Vivier #endif 390a075f313SLaurent Vivier struct rt_sigframe *frame; 391a075f313SLaurent Vivier int i; 392a075f313SLaurent Vivier 393a075f313SLaurent Vivier frame_addr = get_sigframe(ka, env, sizeof(*frame)); 394a075f313SLaurent Vivier trace_user_setup_rt_frame(env, frame_addr); 395a075f313SLaurent Vivier 396a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) 397a075f313SLaurent Vivier goto give_sigsegv; 398a075f313SLaurent Vivier 399a075f313SLaurent Vivier /* These fields are only in rt_sigframe on 32 bit */ 400a075f313SLaurent Vivier #ifndef TARGET_X86_64 401a075f313SLaurent Vivier __put_user(sig, &frame->sig); 402a075f313SLaurent Vivier addr = frame_addr + offsetof(struct rt_sigframe, info); 403a075f313SLaurent Vivier __put_user(addr, &frame->pinfo); 404a075f313SLaurent Vivier addr = frame_addr + offsetof(struct rt_sigframe, uc); 405a075f313SLaurent Vivier __put_user(addr, &frame->puc); 406a075f313SLaurent Vivier #endif 407a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_SIGINFO) { 408a075f313SLaurent Vivier tswap_siginfo(&frame->info, info); 409a075f313SLaurent Vivier } 410a075f313SLaurent Vivier 411a075f313SLaurent Vivier /* Create the ucontext. */ 412a075f313SLaurent Vivier __put_user(0, &frame->uc.tuc_flags); 413a075f313SLaurent Vivier __put_user(0, &frame->uc.tuc_link); 414465e237bSLaurent Vivier target_save_altstack(&frame->uc.tuc_stack, env); 415a075f313SLaurent Vivier setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, 416a075f313SLaurent Vivier set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); 417a075f313SLaurent Vivier 418a075f313SLaurent Vivier for(i = 0; i < TARGET_NSIG_WORDS; i++) { 419a075f313SLaurent Vivier __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); 420a075f313SLaurent Vivier } 421a075f313SLaurent Vivier 422a075f313SLaurent Vivier /* Set up to return from userspace. If provided, use a stub 423a075f313SLaurent Vivier already in userspace. */ 424a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 425a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 426a075f313SLaurent Vivier } else { 427*db205541SRichard Henderson #ifdef TARGET_X86_64 428*db205541SRichard Henderson /* For x86_64, SA_RESTORER is required ABI. */ 429*db205541SRichard Henderson goto give_sigsegv; 430*db205541SRichard Henderson #else 4318ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 4328ee8a104SRichard Henderson install_rt_sigtramp(frame->retcode); 4338ee8a104SRichard Henderson __put_user(default_rt_sigreturn, &frame->pretcode); 434a075f313SLaurent Vivier #endif 435*db205541SRichard Henderson } 436a075f313SLaurent Vivier 437a075f313SLaurent Vivier /* Set up registers for signal handler */ 438a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 439a075f313SLaurent Vivier env->eip = ka->_sa_handler; 440a075f313SLaurent Vivier 441a075f313SLaurent Vivier #ifndef TARGET_X86_64 442a075f313SLaurent Vivier env->regs[R_EAX] = sig; 4430c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, info); 4440c40c18eSIlya Leoshkevich env->regs[R_ECX] = frame_addr + offsetof(struct rt_sigframe, uc); 445a075f313SLaurent Vivier #else 446a075f313SLaurent Vivier env->regs[R_EAX] = 0; 447a075f313SLaurent Vivier env->regs[R_EDI] = sig; 4480c40c18eSIlya Leoshkevich env->regs[R_ESI] = frame_addr + offsetof(struct rt_sigframe, info); 4490c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, uc); 450a075f313SLaurent Vivier #endif 451a075f313SLaurent Vivier 452a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, __USER_DS); 453a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, __USER_DS); 454a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 455a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, __USER_DS); 456a075f313SLaurent Vivier env->eflags &= ~TF_MASK; 457a075f313SLaurent Vivier 458a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 1); 459a075f313SLaurent Vivier 460a075f313SLaurent Vivier return; 461a075f313SLaurent Vivier 462a075f313SLaurent Vivier give_sigsegv: 463a075f313SLaurent Vivier force_sigsegv(sig); 464a075f313SLaurent Vivier } 465a075f313SLaurent Vivier 466a075f313SLaurent Vivier static int 467a075f313SLaurent Vivier restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc) 468a075f313SLaurent Vivier { 469a075f313SLaurent Vivier unsigned int err = 0; 470a075f313SLaurent Vivier abi_ulong fpstate_addr; 471a075f313SLaurent Vivier unsigned int tmpflags; 472a075f313SLaurent Vivier 473a075f313SLaurent Vivier #ifndef TARGET_X86_64 474a075f313SLaurent Vivier cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); 475a075f313SLaurent Vivier cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); 476a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); 477a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); 478a075f313SLaurent Vivier 479a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->edi); 480a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->esi); 481a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->ebp); 482a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->esp); 483a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->ebx); 484a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->edx); 485a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->ecx); 486a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->eax); 487a075f313SLaurent Vivier 488a075f313SLaurent Vivier env->eip = tswapl(sc->eip); 489a075f313SLaurent Vivier #else 490a075f313SLaurent Vivier env->regs[8] = tswapl(sc->r8); 491a075f313SLaurent Vivier env->regs[9] = tswapl(sc->r9); 492a075f313SLaurent Vivier env->regs[10] = tswapl(sc->r10); 493a075f313SLaurent Vivier env->regs[11] = tswapl(sc->r11); 494a075f313SLaurent Vivier env->regs[12] = tswapl(sc->r12); 495a075f313SLaurent Vivier env->regs[13] = tswapl(sc->r13); 496a075f313SLaurent Vivier env->regs[14] = tswapl(sc->r14); 497a075f313SLaurent Vivier env->regs[15] = tswapl(sc->r15); 498a075f313SLaurent Vivier 499a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->rdi); 500a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->rsi); 501a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->rbp); 502a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->rbx); 503a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->rdx); 504a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->rax); 505a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->rcx); 506a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->rsp); 507a075f313SLaurent Vivier 508a075f313SLaurent Vivier env->eip = tswapl(sc->rip); 509a075f313SLaurent Vivier #endif 510a075f313SLaurent Vivier 511a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3); 512a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3); 513a075f313SLaurent Vivier 514a075f313SLaurent Vivier tmpflags = tswapl(sc->eflags); 515a075f313SLaurent Vivier env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); 516a075f313SLaurent Vivier // regs->orig_eax = -1; /* disable syscall checks */ 517a075f313SLaurent Vivier 518a075f313SLaurent Vivier fpstate_addr = tswapl(sc->fpstate); 519a075f313SLaurent Vivier if (fpstate_addr != 0) { 520c7169b02SRichard Henderson if (!access_ok(env_cpu(env), VERIFY_READ, fpstate_addr, 521c7169b02SRichard Henderson sizeof(struct target_fpstate))) { 522a075f313SLaurent Vivier goto badframe; 523c7169b02SRichard Henderson } 524a075f313SLaurent Vivier #ifndef TARGET_X86_64 525a075f313SLaurent Vivier cpu_x86_frstor(env, fpstate_addr, 1); 526a075f313SLaurent Vivier #else 527a075f313SLaurent Vivier cpu_x86_fxrstor(env, fpstate_addr); 528a075f313SLaurent Vivier #endif 529a075f313SLaurent Vivier } 530a075f313SLaurent Vivier 531a075f313SLaurent Vivier return err; 532a075f313SLaurent Vivier badframe: 533a075f313SLaurent Vivier return 1; 534a075f313SLaurent Vivier } 535a075f313SLaurent Vivier 536a075f313SLaurent Vivier /* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */ 537a075f313SLaurent Vivier #ifndef TARGET_X86_64 538a075f313SLaurent Vivier long do_sigreturn(CPUX86State *env) 539a075f313SLaurent Vivier { 540a075f313SLaurent Vivier struct sigframe *frame; 541a075f313SLaurent Vivier abi_ulong frame_addr = env->regs[R_ESP] - 8; 542a075f313SLaurent Vivier target_sigset_t target_set; 543a075f313SLaurent Vivier sigset_t set; 544a075f313SLaurent Vivier int i; 545a075f313SLaurent Vivier 546a075f313SLaurent Vivier trace_user_do_sigreturn(env, frame_addr); 547a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 548a075f313SLaurent Vivier goto badframe; 549a075f313SLaurent Vivier /* set blocked signals */ 550a075f313SLaurent Vivier __get_user(target_set.sig[0], &frame->sc.oldmask); 551a075f313SLaurent Vivier for(i = 1; i < TARGET_NSIG_WORDS; i++) { 552a075f313SLaurent Vivier __get_user(target_set.sig[i], &frame->extramask[i - 1]); 553a075f313SLaurent Vivier } 554a075f313SLaurent Vivier 555a075f313SLaurent Vivier target_to_host_sigset_internal(&set, &target_set); 556a075f313SLaurent Vivier set_sigmask(&set); 557a075f313SLaurent Vivier 558a075f313SLaurent Vivier /* restore registers */ 559a075f313SLaurent Vivier if (restore_sigcontext(env, &frame->sc)) 560a075f313SLaurent Vivier goto badframe; 561a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 562a075f313SLaurent Vivier return -TARGET_QEMU_ESIGRETURN; 563a075f313SLaurent Vivier 564a075f313SLaurent Vivier badframe: 565a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 566a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 567a075f313SLaurent Vivier return -TARGET_QEMU_ESIGRETURN; 568a075f313SLaurent Vivier } 569a075f313SLaurent Vivier #endif 570a075f313SLaurent Vivier 571a075f313SLaurent Vivier long do_rt_sigreturn(CPUX86State *env) 572a075f313SLaurent Vivier { 573a075f313SLaurent Vivier abi_ulong frame_addr; 574a075f313SLaurent Vivier struct rt_sigframe *frame; 575a075f313SLaurent Vivier sigset_t set; 576a075f313SLaurent Vivier 577a075f313SLaurent Vivier frame_addr = env->regs[R_ESP] - sizeof(abi_ulong); 578a075f313SLaurent Vivier trace_user_do_rt_sigreturn(env, frame_addr); 579a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 580a075f313SLaurent Vivier goto badframe; 581a075f313SLaurent Vivier target_to_host_sigset(&set, &frame->uc.tuc_sigmask); 582a075f313SLaurent Vivier set_sigmask(&set); 583a075f313SLaurent Vivier 584a075f313SLaurent Vivier if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) { 585a075f313SLaurent Vivier goto badframe; 586a075f313SLaurent Vivier } 587a075f313SLaurent Vivier 588ddc3e74dSRichard Henderson target_restore_altstack(&frame->uc.tuc_stack, env); 589a075f313SLaurent Vivier 590a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 591a075f313SLaurent Vivier return -TARGET_QEMU_ESIGRETURN; 592a075f313SLaurent Vivier 593a075f313SLaurent Vivier badframe: 594a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 595a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 596a075f313SLaurent Vivier return -TARGET_QEMU_ESIGRETURN; 597a075f313SLaurent Vivier } 5988ee8a104SRichard Henderson 5998ee8a104SRichard Henderson #ifndef TARGET_X86_64 6008ee8a104SRichard Henderson void setup_sigtramp(abi_ulong sigtramp_page) 6018ee8a104SRichard Henderson { 6028ee8a104SRichard Henderson uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); 6038ee8a104SRichard Henderson assert(tramp != NULL); 6048ee8a104SRichard Henderson 6058ee8a104SRichard Henderson default_sigreturn = sigtramp_page; 6068ee8a104SRichard Henderson install_sigtramp(tramp); 6078ee8a104SRichard Henderson 6088ee8a104SRichard Henderson default_rt_sigreturn = sigtramp_page + 8; 6098ee8a104SRichard Henderson install_rt_sigtramp(tramp + 8); 6108ee8a104SRichard Henderson 6118ee8a104SRichard Henderson unlock_user(tramp, sigtramp_page, 2 * 8); 6128ee8a104SRichard Henderson } 6138ee8a104SRichard Henderson #endif 614