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" 2482723866SPhilippe Mathieu-Daudé #include "user/tswap-target.h" 25a075f313SLaurent Vivier 26a075f313SLaurent Vivier /* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */ 27a075f313SLaurent Vivier 285d245678SPaolo Bonzini #define TARGET_FP_XSTATE_MAGIC1 0x46505853U /* FPXS */ 295d245678SPaolo Bonzini #define TARGET_FP_XSTATE_MAGIC2 0x46505845U /* FPXE */ 305d245678SPaolo Bonzini #define TARGET_FP_XSTATE_MAGIC2_SIZE 4 315d245678SPaolo Bonzini 32a075f313SLaurent Vivier struct target_fpreg { 33a075f313SLaurent Vivier uint16_t significand[4]; 34a075f313SLaurent Vivier uint16_t exponent; 35a075f313SLaurent Vivier }; 36a075f313SLaurent Vivier 37a075f313SLaurent Vivier struct target_fpxreg { 38a075f313SLaurent Vivier uint16_t significand[4]; 39a075f313SLaurent Vivier uint16_t exponent; 40a075f313SLaurent Vivier uint16_t padding[3]; 41a075f313SLaurent Vivier }; 42a075f313SLaurent Vivier 43a075f313SLaurent Vivier struct target_xmmreg { 44a075f313SLaurent Vivier uint32_t element[4]; 45a075f313SLaurent Vivier }; 46a075f313SLaurent Vivier 475d245678SPaolo Bonzini struct target_fpx_sw_bytes { 485d245678SPaolo Bonzini uint32_t magic1; 495d245678SPaolo Bonzini uint32_t extended_size; 505d245678SPaolo Bonzini uint64_t xfeatures; 515d245678SPaolo Bonzini uint32_t xstate_size; 525d245678SPaolo Bonzini uint32_t reserved[7]; 535d245678SPaolo Bonzini }; 545d245678SPaolo Bonzini QEMU_BUILD_BUG_ON(sizeof(struct target_fpx_sw_bytes) != 12*4); 555d245678SPaolo Bonzini 562796f290SPaolo Bonzini struct target_fpstate_fxsave { 57a075f313SLaurent Vivier /* FXSAVE format */ 58a075f313SLaurent Vivier uint16_t cw; 59a075f313SLaurent Vivier uint16_t sw; 60a075f313SLaurent Vivier uint16_t twd; 61a075f313SLaurent Vivier uint16_t fop; 62a075f313SLaurent Vivier uint64_t rip; 63a075f313SLaurent Vivier uint64_t rdp; 64a075f313SLaurent Vivier uint32_t mxcsr; 65a075f313SLaurent Vivier uint32_t mxcsr_mask; 66a075f313SLaurent Vivier uint32_t st_space[32]; 67a075f313SLaurent Vivier uint32_t xmm_space[64]; 685d245678SPaolo Bonzini uint32_t hw_reserved[12]; 695d245678SPaolo Bonzini struct target_fpx_sw_bytes sw_reserved; 705d245678SPaolo Bonzini uint8_t xfeatures[]; 71a075f313SLaurent Vivier }; 722796f290SPaolo Bonzini #define TARGET_FXSAVE_SIZE sizeof(struct target_fpstate_fxsave) 732796f290SPaolo Bonzini QEMU_BUILD_BUG_ON(TARGET_FXSAVE_SIZE != 512); 745d245678SPaolo Bonzini QEMU_BUILD_BUG_ON(offsetof(struct target_fpstate_fxsave, sw_reserved) != 464); 752796f290SPaolo Bonzini 762796f290SPaolo Bonzini struct target_fpstate_32 { 772796f290SPaolo Bonzini /* Regular FPU environment */ 782796f290SPaolo Bonzini uint32_t cw; 792796f290SPaolo Bonzini uint32_t sw; 802796f290SPaolo Bonzini uint32_t tag; 812796f290SPaolo Bonzini uint32_t ipoff; 822796f290SPaolo Bonzini uint32_t cssel; 832796f290SPaolo Bonzini uint32_t dataoff; 842796f290SPaolo Bonzini uint32_t datasel; 852796f290SPaolo Bonzini struct target_fpreg st[8]; 862796f290SPaolo Bonzini uint16_t status; 872796f290SPaolo Bonzini uint16_t magic; /* 0xffff = regular FPU data only */ 882796f290SPaolo Bonzini struct target_fpstate_fxsave fxsave; 892796f290SPaolo Bonzini }; 902796f290SPaolo Bonzini 912796f290SPaolo Bonzini /* 922796f290SPaolo Bonzini * For simplicity, setup_frame aligns struct target_fpstate_32 to 932796f290SPaolo Bonzini * 16 bytes, so ensure that the FXSAVE area is also aligned. 942796f290SPaolo Bonzini */ 952796f290SPaolo Bonzini QEMU_BUILD_BUG_ON(offsetof(struct target_fpstate_32, fxsave) & 15); 96a075f313SLaurent Vivier 97a075f313SLaurent Vivier #ifndef TARGET_X86_64 98a075f313SLaurent Vivier # define target_fpstate target_fpstate_32 992796f290SPaolo Bonzini # define TARGET_FPSTATE_FXSAVE_OFFSET offsetof(struct target_fpstate_32, fxsave) 100a075f313SLaurent Vivier #else 1012796f290SPaolo Bonzini # define target_fpstate target_fpstate_fxsave 1022796f290SPaolo Bonzini # define TARGET_FPSTATE_FXSAVE_OFFSET 0 103a075f313SLaurent Vivier #endif 104a075f313SLaurent Vivier 105a075f313SLaurent Vivier struct target_sigcontext_32 { 106a075f313SLaurent Vivier uint16_t gs, __gsh; 107a075f313SLaurent Vivier uint16_t fs, __fsh; 108a075f313SLaurent Vivier uint16_t es, __esh; 109a075f313SLaurent Vivier uint16_t ds, __dsh; 110a075f313SLaurent Vivier uint32_t edi; 111a075f313SLaurent Vivier uint32_t esi; 112a075f313SLaurent Vivier uint32_t ebp; 113a075f313SLaurent Vivier uint32_t esp; 114a075f313SLaurent Vivier uint32_t ebx; 115a075f313SLaurent Vivier uint32_t edx; 116a075f313SLaurent Vivier uint32_t ecx; 117a075f313SLaurent Vivier uint32_t eax; 118a075f313SLaurent Vivier uint32_t trapno; 119a075f313SLaurent Vivier uint32_t err; 120a075f313SLaurent Vivier uint32_t eip; 121a075f313SLaurent Vivier uint16_t cs, __csh; 122a075f313SLaurent Vivier uint32_t eflags; 123a075f313SLaurent Vivier uint32_t esp_at_signal; 124a075f313SLaurent Vivier uint16_t ss, __ssh; 125a075f313SLaurent Vivier uint32_t fpstate; /* pointer */ 126a075f313SLaurent Vivier uint32_t oldmask; 127a075f313SLaurent Vivier uint32_t cr2; 128a075f313SLaurent Vivier }; 129a075f313SLaurent Vivier 130a075f313SLaurent Vivier struct target_sigcontext_64 { 131a075f313SLaurent Vivier uint64_t r8; 132a075f313SLaurent Vivier uint64_t r9; 133a075f313SLaurent Vivier uint64_t r10; 134a075f313SLaurent Vivier uint64_t r11; 135a075f313SLaurent Vivier uint64_t r12; 136a075f313SLaurent Vivier uint64_t r13; 137a075f313SLaurent Vivier uint64_t r14; 138a075f313SLaurent Vivier uint64_t r15; 139a075f313SLaurent Vivier 140a075f313SLaurent Vivier uint64_t rdi; 141a075f313SLaurent Vivier uint64_t rsi; 142a075f313SLaurent Vivier uint64_t rbp; 143a075f313SLaurent Vivier uint64_t rbx; 144a075f313SLaurent Vivier uint64_t rdx; 145a075f313SLaurent Vivier uint64_t rax; 146a075f313SLaurent Vivier uint64_t rcx; 147a075f313SLaurent Vivier uint64_t rsp; 148a075f313SLaurent Vivier uint64_t rip; 149a075f313SLaurent Vivier 150a075f313SLaurent Vivier uint64_t eflags; 151a075f313SLaurent Vivier 152a075f313SLaurent Vivier uint16_t cs; 153a075f313SLaurent Vivier uint16_t gs; 154a075f313SLaurent Vivier uint16_t fs; 155a075f313SLaurent Vivier uint16_t ss; 156a075f313SLaurent Vivier 157a075f313SLaurent Vivier uint64_t err; 158a075f313SLaurent Vivier uint64_t trapno; 159a075f313SLaurent Vivier uint64_t oldmask; 160a075f313SLaurent Vivier uint64_t cr2; 161a075f313SLaurent Vivier 162a075f313SLaurent Vivier uint64_t fpstate; /* pointer */ 163a075f313SLaurent Vivier uint64_t padding[8]; 164a075f313SLaurent Vivier }; 165a075f313SLaurent Vivier 166a075f313SLaurent Vivier #ifndef TARGET_X86_64 167a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_32 168a075f313SLaurent Vivier #else 169a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_64 170a075f313SLaurent Vivier #endif 171a075f313SLaurent Vivier 172a075f313SLaurent Vivier /* see Linux/include/uapi/asm-generic/ucontext.h */ 173a075f313SLaurent Vivier struct target_ucontext { 174a075f313SLaurent Vivier abi_ulong tuc_flags; 175a075f313SLaurent Vivier abi_ulong tuc_link; 176a075f313SLaurent Vivier target_stack_t tuc_stack; 177a075f313SLaurent Vivier struct target_sigcontext tuc_mcontext; 178a075f313SLaurent Vivier target_sigset_t tuc_sigmask; /* mask last for extensibility */ 179a075f313SLaurent Vivier }; 180a075f313SLaurent Vivier 181a075f313SLaurent Vivier #ifndef TARGET_X86_64 182a075f313SLaurent Vivier struct sigframe { 183a075f313SLaurent Vivier abi_ulong pretcode; 184a075f313SLaurent Vivier int sig; 185a075f313SLaurent Vivier struct target_sigcontext sc; 1865154d35bSPaolo Bonzini /* 1875154d35bSPaolo Bonzini * The actual fpstate is placed after retcode[] below, to make 1885154d35bSPaolo Bonzini * room for the variable-sized xsave data. The older unused fpstate 1895154d35bSPaolo Bonzini * has to be kept to avoid changing the offset of extramask[], which 1905154d35bSPaolo Bonzini * is part of the ABI. 1915154d35bSPaolo Bonzini */ 1925154d35bSPaolo Bonzini struct target_fpstate fpstate_unused; 193a075f313SLaurent Vivier abi_ulong extramask[TARGET_NSIG_WORDS-1]; 194a075f313SLaurent Vivier char retcode[8]; 1952796f290SPaolo Bonzini 1962796f290SPaolo Bonzini /* 1972796f290SPaolo Bonzini * This field will be 16-byte aligned in memory. Applying QEMU_ALIGNED 1982796f290SPaolo Bonzini * to it ensures that the base of the frame has an appropriate alignment 1992796f290SPaolo Bonzini * too. 2002796f290SPaolo Bonzini */ 2012796f290SPaolo Bonzini struct target_fpstate fpstate QEMU_ALIGNED(8); 202a075f313SLaurent Vivier }; 2032796f290SPaolo Bonzini #define TARGET_SIGFRAME_FXSAVE_OFFSET ( \ 2042796f290SPaolo Bonzini offsetof(struct sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) 205a075f313SLaurent Vivier 206a075f313SLaurent Vivier struct rt_sigframe { 207a075f313SLaurent Vivier abi_ulong pretcode; 208a075f313SLaurent Vivier int sig; 209a075f313SLaurent Vivier abi_ulong pinfo; 210a075f313SLaurent Vivier abi_ulong puc; 211a075f313SLaurent Vivier struct target_siginfo info; 212a075f313SLaurent Vivier struct target_ucontext uc; 213a075f313SLaurent Vivier char retcode[8]; 2142796f290SPaolo Bonzini struct target_fpstate fpstate QEMU_ALIGNED(8); 215a075f313SLaurent Vivier }; 2162796f290SPaolo Bonzini #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( \ 2172796f290SPaolo Bonzini offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) 218a1367443SRichard Henderson 219a1367443SRichard Henderson /* 220a1367443SRichard Henderson * Verify that vdso-asmoffset.h constants match. 221a1367443SRichard Henderson */ 222a1367443SRichard Henderson #include "i386/vdso-asmoffset.h" 223a1367443SRichard Henderson 224a1367443SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(struct sigframe, sc.eip) 225a1367443SRichard Henderson != SIGFRAME_SIGCONTEXT_eip); 226a1367443SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, uc.tuc_mcontext.eip) 227a1367443SRichard Henderson != RT_SIGFRAME_SIGCONTEXT_eip); 228a1367443SRichard Henderson 229a075f313SLaurent Vivier #else 230a075f313SLaurent Vivier 231a075f313SLaurent Vivier struct rt_sigframe { 232a075f313SLaurent Vivier abi_ulong pretcode; 233a075f313SLaurent Vivier struct target_ucontext uc; 234a075f313SLaurent Vivier struct target_siginfo info; 2352796f290SPaolo Bonzini struct target_fpstate fpstate QEMU_ALIGNED(16); 236a075f313SLaurent Vivier }; 2372796f290SPaolo Bonzini #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( \ 2382796f290SPaolo Bonzini offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) 239a075f313SLaurent Vivier #endif 240a075f313SLaurent Vivier 241a075f313SLaurent Vivier /* 242a075f313SLaurent Vivier * Set up a signal frame. 243a075f313SLaurent Vivier */ 244a075f313SLaurent Vivier 2455d245678SPaolo Bonzini static void xsave_sigcontext(CPUX86State *env, struct target_fpstate_fxsave *fxsave, 2462796f290SPaolo Bonzini abi_ulong fxsave_addr) 2472796f290SPaolo Bonzini { 2485d245678SPaolo Bonzini if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { 2492796f290SPaolo Bonzini /* fxsave_addr must be 16 byte aligned for fxsave */ 2502796f290SPaolo Bonzini assert(!(fxsave_addr & 0xf)); 2512796f290SPaolo Bonzini 2522796f290SPaolo Bonzini cpu_x86_fxsave(env, fxsave_addr); 2535d245678SPaolo Bonzini __put_user(0, &fxsave->sw_reserved.magic1); 2545d245678SPaolo Bonzini } else { 2555d245678SPaolo Bonzini uint32_t xstate_size = xsave_area_size(env->xcr0, false); 2565d245678SPaolo Bonzini 2575d245678SPaolo Bonzini /* 2585d245678SPaolo Bonzini * extended_size is the offset from fpstate_addr to right after the end 2595d245678SPaolo Bonzini * of the extended save states. On 32-bit that includes the legacy 2605d245678SPaolo Bonzini * FSAVE area. 2615d245678SPaolo Bonzini */ 2625d245678SPaolo Bonzini uint32_t extended_size = TARGET_FPSTATE_FXSAVE_OFFSET 2635d245678SPaolo Bonzini + xstate_size + TARGET_FP_XSTATE_MAGIC2_SIZE; 2645d245678SPaolo Bonzini 2655d245678SPaolo Bonzini /* fxsave_addr must be 64 byte aligned for xsave */ 2665d245678SPaolo Bonzini assert(!(fxsave_addr & 0x3f)); 2675d245678SPaolo Bonzini 2685d245678SPaolo Bonzini /* Zero the header, XSAVE *adds* features to an existing save state. */ 2695d245678SPaolo Bonzini memset(fxsave->xfeatures, 0, 64); 270a2d64d61SRichard Henderson cpu_x86_xsave(env, fxsave_addr, -1); 2715d245678SPaolo Bonzini __put_user(TARGET_FP_XSTATE_MAGIC1, &fxsave->sw_reserved.magic1); 2725d245678SPaolo Bonzini __put_user(extended_size, &fxsave->sw_reserved.extended_size); 2735d245678SPaolo Bonzini __put_user(env->xcr0, &fxsave->sw_reserved.xfeatures); 2745d245678SPaolo Bonzini __put_user(xstate_size, &fxsave->sw_reserved.xstate_size); 275*077c43ebSRichard Henderson __put_user(TARGET_FP_XSTATE_MAGIC2, 276*077c43ebSRichard Henderson (uint32_t *)((void *)fxsave + xstate_size)); 2775d245678SPaolo Bonzini } 2782796f290SPaolo Bonzini } 2792796f290SPaolo Bonzini 280a075f313SLaurent Vivier static void setup_sigcontext(struct target_sigcontext *sc, 281a075f313SLaurent Vivier struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, 282a075f313SLaurent Vivier abi_ulong fpstate_addr) 283a075f313SLaurent Vivier { 2846aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 285a075f313SLaurent Vivier #ifndef TARGET_X86_64 286a075f313SLaurent Vivier uint16_t magic; 287a075f313SLaurent Vivier 288a075f313SLaurent Vivier /* already locked in setup_frame() */ 289a075f313SLaurent Vivier __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); 290a075f313SLaurent Vivier __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); 291a075f313SLaurent Vivier __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); 292a075f313SLaurent Vivier __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); 293a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->edi); 294a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->esi); 295a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->ebp); 296a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp); 297a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->ebx); 298a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->edx); 299a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->ecx); 300a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->eax); 301a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 302a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 303a075f313SLaurent Vivier __put_user(env->eip, &sc->eip); 304a075f313SLaurent Vivier __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); 305a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 306a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp_at_signal); 307a075f313SLaurent Vivier __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); 308a075f313SLaurent Vivier 309a075f313SLaurent Vivier cpu_x86_fsave(env, fpstate_addr, 1); 310a075f313SLaurent Vivier fpstate->status = fpstate->sw; 3112796f290SPaolo Bonzini if (!(env->features[FEAT_1_EDX] & CPUID_FXSR)) { 312a075f313SLaurent Vivier magic = 0xffff; 3132796f290SPaolo Bonzini } else { 3145d245678SPaolo Bonzini xsave_sigcontext(env, &fpstate->fxsave, 3152796f290SPaolo Bonzini fpstate_addr + TARGET_FPSTATE_FXSAVE_OFFSET); 3162796f290SPaolo Bonzini magic = 0; 3172796f290SPaolo Bonzini } 318a075f313SLaurent Vivier __put_user(magic, &fpstate->magic); 319a075f313SLaurent Vivier #else 320a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->rdi); 321a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->rsi); 322a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->rbp); 323a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->rsp); 324a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->rbx); 325a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->rdx); 326a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->rcx); 327a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->rax); 328a075f313SLaurent Vivier 329a075f313SLaurent Vivier __put_user(env->regs[8], &sc->r8); 330a075f313SLaurent Vivier __put_user(env->regs[9], &sc->r9); 331a075f313SLaurent Vivier __put_user(env->regs[10], &sc->r10); 332a075f313SLaurent Vivier __put_user(env->regs[11], &sc->r11); 333a075f313SLaurent Vivier __put_user(env->regs[12], &sc->r12); 334a075f313SLaurent Vivier __put_user(env->regs[13], &sc->r13); 335a075f313SLaurent Vivier __put_user(env->regs[14], &sc->r14); 336a075f313SLaurent Vivier __put_user(env->regs[15], &sc->r15); 337a075f313SLaurent Vivier 338a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 339a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 340a075f313SLaurent Vivier __put_user(env->eip, &sc->rip); 341a075f313SLaurent Vivier 342a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 343a075f313SLaurent Vivier __put_user(env->segs[R_CS].selector, &sc->cs); 344a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->gs); 345a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->fs); 346a075f313SLaurent Vivier __put_user(env->segs[R_SS].selector, &sc->ss); 347a075f313SLaurent Vivier 3485d245678SPaolo Bonzini xsave_sigcontext(env, fpstate, fpstate_addr); 3492796f290SPaolo Bonzini #endif 3502796f290SPaolo Bonzini 3512796f290SPaolo Bonzini __put_user(fpstate_addr, &sc->fpstate); 3522796f290SPaolo Bonzini 3532796f290SPaolo Bonzini /* non-iBCS2 extensions.. */ 354a075f313SLaurent Vivier __put_user(mask, &sc->oldmask); 355a075f313SLaurent Vivier __put_user(env->cr[2], &sc->cr2); 356a075f313SLaurent Vivier } 357a075f313SLaurent Vivier 358a075f313SLaurent Vivier /* 359a075f313SLaurent Vivier * Determine which stack to use.. 360a075f313SLaurent Vivier */ 361a075f313SLaurent Vivier 362a075f313SLaurent Vivier static inline abi_ulong 3632796f290SPaolo Bonzini get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t fxsave_offset) 364a075f313SLaurent Vivier { 365a075f313SLaurent Vivier unsigned long esp; 366a075f313SLaurent Vivier 367a075f313SLaurent Vivier /* Default to using normal stack */ 368465e237bSLaurent Vivier esp = get_sp_from_cpustate(env); 369a075f313SLaurent Vivier #ifdef TARGET_X86_64 370a075f313SLaurent Vivier esp -= 128; /* this is the redzone */ 371a075f313SLaurent Vivier #endif 372a075f313SLaurent Vivier 373a075f313SLaurent Vivier /* This is the X/Open sanctioned signal stack switching. */ 374a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_ONSTACK) { 375465e237bSLaurent Vivier esp = target_sigsp(esp, ka); 376a075f313SLaurent Vivier } else { 377a075f313SLaurent Vivier #ifndef TARGET_X86_64 378a075f313SLaurent Vivier /* This is the legacy signal stack switching. */ 379a075f313SLaurent Vivier if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && 380a075f313SLaurent Vivier !(ka->sa_flags & TARGET_SA_RESTORER) && 381a075f313SLaurent Vivier ka->sa_restorer) { 382a075f313SLaurent Vivier esp = (unsigned long) ka->sa_restorer; 383a075f313SLaurent Vivier } 384a075f313SLaurent Vivier #endif 385a075f313SLaurent Vivier } 386a075f313SLaurent Vivier 3872796f290SPaolo Bonzini if (!(env->features[FEAT_1_EDX] & CPUID_FXSR)) { 3882796f290SPaolo Bonzini return (esp - (fxsave_offset + TARGET_FXSAVE_SIZE)) & -8ul; 3895d245678SPaolo Bonzini } else if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { 3902796f290SPaolo Bonzini return ((esp - TARGET_FXSAVE_SIZE) & -16ul) - fxsave_offset; 3915d245678SPaolo Bonzini } else { 3925d245678SPaolo Bonzini size_t xstate_size = 3935d245678SPaolo Bonzini xsave_area_size(env->xcr0, false) + TARGET_FP_XSTATE_MAGIC2_SIZE; 3945d245678SPaolo Bonzini return ((esp - xstate_size) & -64ul) - fxsave_offset; 3952796f290SPaolo Bonzini } 396a075f313SLaurent Vivier } 397a075f313SLaurent Vivier 398a075f313SLaurent Vivier #ifndef TARGET_X86_64 3998ee8a104SRichard Henderson static void install_sigtramp(void *tramp) 4008ee8a104SRichard Henderson { 4018ee8a104SRichard Henderson /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */ 4028ee8a104SRichard Henderson __put_user(0xb858, (uint16_t *)(tramp + 0)); 4038ee8a104SRichard Henderson __put_user(TARGET_NR_sigreturn, (int32_t *)(tramp + 2)); 4048ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 6)); 4058ee8a104SRichard Henderson } 4068ee8a104SRichard Henderson 4078ee8a104SRichard Henderson static void install_rt_sigtramp(void *tramp) 4088ee8a104SRichard Henderson { 4098ee8a104SRichard Henderson /* This is movl $syscall,%eax ; int $0x80 */ 4108ee8a104SRichard Henderson __put_user(0xb8, (uint8_t *)(tramp + 0)); 4118ee8a104SRichard Henderson __put_user(TARGET_NR_rt_sigreturn, (int32_t *)(tramp + 1)); 4128ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 5)); 4138ee8a104SRichard Henderson } 4148ee8a104SRichard Henderson 415a075f313SLaurent Vivier /* compare linux/arch/i386/kernel/signal.c:setup_frame() */ 416a075f313SLaurent Vivier void setup_frame(int sig, struct target_sigaction *ka, 417a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 418a075f313SLaurent Vivier { 419a075f313SLaurent Vivier abi_ulong frame_addr; 420a075f313SLaurent Vivier struct sigframe *frame; 421a075f313SLaurent Vivier int i; 422a075f313SLaurent Vivier 4232796f290SPaolo Bonzini frame_addr = get_sigframe(ka, env, TARGET_SIGFRAME_FXSAVE_OFFSET); 424a075f313SLaurent Vivier trace_user_setup_frame(env, frame_addr); 425a075f313SLaurent Vivier 426a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) 427a075f313SLaurent Vivier goto give_sigsegv; 428a075f313SLaurent Vivier 429a075f313SLaurent Vivier __put_user(sig, &frame->sig); 430a075f313SLaurent Vivier 431a075f313SLaurent Vivier setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], 432a075f313SLaurent Vivier frame_addr + offsetof(struct sigframe, fpstate)); 433a075f313SLaurent Vivier 434a075f313SLaurent Vivier for (i = 1; i < TARGET_NSIG_WORDS; i++) { 435a075f313SLaurent Vivier __put_user(set->sig[i], &frame->extramask[i - 1]); 436a075f313SLaurent Vivier } 437a075f313SLaurent Vivier 438a075f313SLaurent Vivier /* Set up to return from userspace. If provided, use a stub 439a075f313SLaurent Vivier already in userspace. */ 440a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 441a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 442a075f313SLaurent Vivier } else { 4438ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 4448ee8a104SRichard Henderson install_sigtramp(frame->retcode); 4458ee8a104SRichard Henderson __put_user(default_sigreturn, &frame->pretcode); 446a075f313SLaurent Vivier } 447a075f313SLaurent Vivier 448a075f313SLaurent Vivier /* Set up registers for signal handler */ 449a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 450a075f313SLaurent Vivier env->eip = ka->_sa_handler; 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_SS, __USER_DS); 455a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 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 #endif 466a075f313SLaurent Vivier 467a075f313SLaurent Vivier /* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */ 468a075f313SLaurent Vivier void setup_rt_frame(int sig, struct target_sigaction *ka, 469a075f313SLaurent Vivier target_siginfo_t *info, 470a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 471a075f313SLaurent Vivier { 472a075f313SLaurent Vivier abi_ulong frame_addr; 473a075f313SLaurent Vivier #ifndef TARGET_X86_64 474a075f313SLaurent Vivier abi_ulong addr; 475a075f313SLaurent Vivier #endif 476a075f313SLaurent Vivier struct rt_sigframe *frame; 477a075f313SLaurent Vivier int i; 478a075f313SLaurent Vivier 4792796f290SPaolo Bonzini frame_addr = get_sigframe(ka, env, TARGET_RT_SIGFRAME_FXSAVE_OFFSET); 480a075f313SLaurent Vivier trace_user_setup_rt_frame(env, frame_addr); 481a075f313SLaurent Vivier 482a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) 483a075f313SLaurent Vivier goto give_sigsegv; 484a075f313SLaurent Vivier 485a075f313SLaurent Vivier /* These fields are only in rt_sigframe on 32 bit */ 486a075f313SLaurent Vivier #ifndef TARGET_X86_64 487a075f313SLaurent Vivier __put_user(sig, &frame->sig); 488a075f313SLaurent Vivier addr = frame_addr + offsetof(struct rt_sigframe, info); 489a075f313SLaurent Vivier __put_user(addr, &frame->pinfo); 490a075f313SLaurent Vivier addr = frame_addr + offsetof(struct rt_sigframe, uc); 491a075f313SLaurent Vivier __put_user(addr, &frame->puc); 492a075f313SLaurent Vivier #endif 493a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_SIGINFO) { 4944d6d8a05SGustavo Romero frame->info = *info; 495a075f313SLaurent Vivier } 496a075f313SLaurent Vivier 497a075f313SLaurent Vivier /* Create the ucontext. */ 4985d245678SPaolo Bonzini if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) { 4995d245678SPaolo Bonzini __put_user(1, &frame->uc.tuc_flags); 5005d245678SPaolo Bonzini } else { 501a075f313SLaurent Vivier __put_user(0, &frame->uc.tuc_flags); 5025d245678SPaolo Bonzini } 503a075f313SLaurent Vivier __put_user(0, &frame->uc.tuc_link); 504465e237bSLaurent Vivier target_save_altstack(&frame->uc.tuc_stack, env); 505a075f313SLaurent Vivier setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, 506a075f313SLaurent Vivier set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); 507a075f313SLaurent Vivier 508a075f313SLaurent Vivier for (i = 0; i < TARGET_NSIG_WORDS; i++) { 509a075f313SLaurent Vivier __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); 510a075f313SLaurent Vivier } 511a075f313SLaurent Vivier 512a075f313SLaurent Vivier /* Set up to return from userspace. If provided, use a stub 513a075f313SLaurent Vivier already in userspace. */ 514a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 515a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 516a075f313SLaurent Vivier } else { 517db205541SRichard Henderson #ifdef TARGET_X86_64 518db205541SRichard Henderson /* For x86_64, SA_RESTORER is required ABI. */ 519db205541SRichard Henderson goto give_sigsegv; 520db205541SRichard Henderson #else 5218ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 5228ee8a104SRichard Henderson install_rt_sigtramp(frame->retcode); 5238ee8a104SRichard Henderson __put_user(default_rt_sigreturn, &frame->pretcode); 524a075f313SLaurent Vivier #endif 525db205541SRichard Henderson } 526a075f313SLaurent Vivier 527a075f313SLaurent Vivier /* Set up registers for signal handler */ 528a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 529a075f313SLaurent Vivier env->eip = ka->_sa_handler; 530a075f313SLaurent Vivier 531a075f313SLaurent Vivier #ifndef TARGET_X86_64 532a075f313SLaurent Vivier env->regs[R_EAX] = sig; 5330c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, info); 5340c40c18eSIlya Leoshkevich env->regs[R_ECX] = frame_addr + offsetof(struct rt_sigframe, uc); 535a075f313SLaurent Vivier #else 536a075f313SLaurent Vivier env->regs[R_EAX] = 0; 537a075f313SLaurent Vivier env->regs[R_EDI] = sig; 5380c40c18eSIlya Leoshkevich env->regs[R_ESI] = frame_addr + offsetof(struct rt_sigframe, info); 5390c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, uc); 540a075f313SLaurent Vivier #endif 541a075f313SLaurent Vivier 542a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, __USER_DS); 543a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, __USER_DS); 544a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 545a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, __USER_DS); 546a075f313SLaurent Vivier env->eflags &= ~TF_MASK; 547a075f313SLaurent Vivier 548a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 1); 549a075f313SLaurent Vivier 550a075f313SLaurent Vivier return; 551a075f313SLaurent Vivier 552a075f313SLaurent Vivier give_sigsegv: 553a075f313SLaurent Vivier force_sigsegv(sig); 554a075f313SLaurent Vivier } 555a075f313SLaurent Vivier 5565d245678SPaolo Bonzini static int xrstor_sigcontext(CPUX86State *env, struct target_fpstate_fxsave *fxsave, 5575d245678SPaolo Bonzini abi_ulong fxsave_addr) 5585d245678SPaolo Bonzini { 5595d245678SPaolo Bonzini if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) { 5605d245678SPaolo Bonzini uint32_t extended_size = tswapl(fxsave->sw_reserved.extended_size); 5615d245678SPaolo Bonzini uint32_t xstate_size = tswapl(fxsave->sw_reserved.xstate_size); 5625d245678SPaolo Bonzini 5635d245678SPaolo Bonzini /* Linux checks MAGIC2 using xstate_size, not extended_size. */ 5645d245678SPaolo Bonzini if (tswapl(fxsave->sw_reserved.magic1) == TARGET_FP_XSTATE_MAGIC1 && 5655d245678SPaolo Bonzini extended_size >= TARGET_FPSTATE_FXSAVE_OFFSET + xstate_size + TARGET_FP_XSTATE_MAGIC2_SIZE) { 5665d245678SPaolo Bonzini if (!access_ok(env_cpu(env), VERIFY_READ, fxsave_addr, 5675d245678SPaolo Bonzini extended_size - TARGET_FPSTATE_FXSAVE_OFFSET)) { 5685d245678SPaolo Bonzini return 1; 5695d245678SPaolo Bonzini } 570*077c43ebSRichard Henderson if (tswapl(*(uint32_t *)((void *)fxsave + xstate_size)) == TARGET_FP_XSTATE_MAGIC2) { 571a2d64d61SRichard Henderson cpu_x86_xrstor(env, fxsave_addr, -1); 5725d245678SPaolo Bonzini return 0; 5735d245678SPaolo Bonzini } 5745d245678SPaolo Bonzini } 5755d245678SPaolo Bonzini /* fall through to fxrstor */ 5765d245678SPaolo Bonzini } 5775d245678SPaolo Bonzini 5785d245678SPaolo Bonzini cpu_x86_fxrstor(env, fxsave_addr); 5795d245678SPaolo Bonzini return 0; 5805d245678SPaolo Bonzini } 5815d245678SPaolo Bonzini 582a075f313SLaurent Vivier static int 583a075f313SLaurent Vivier restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc) 584a075f313SLaurent Vivier { 5855d245678SPaolo Bonzini int err = 1; 586a075f313SLaurent Vivier abi_ulong fpstate_addr; 587a075f313SLaurent Vivier unsigned int tmpflags; 588a075f313SLaurent Vivier 589a075f313SLaurent Vivier #ifndef TARGET_X86_64 590a075f313SLaurent Vivier cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); 591a075f313SLaurent Vivier cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); 592a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); 593a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); 594a075f313SLaurent Vivier 595a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->edi); 596a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->esi); 597a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->ebp); 598a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->esp); 599a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->ebx); 600a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->edx); 601a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->ecx); 602a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->eax); 603a075f313SLaurent Vivier 604a075f313SLaurent Vivier env->eip = tswapl(sc->eip); 605a075f313SLaurent Vivier #else 606a075f313SLaurent Vivier env->regs[8] = tswapl(sc->r8); 607a075f313SLaurent Vivier env->regs[9] = tswapl(sc->r9); 608a075f313SLaurent Vivier env->regs[10] = tswapl(sc->r10); 609a075f313SLaurent Vivier env->regs[11] = tswapl(sc->r11); 610a075f313SLaurent Vivier env->regs[12] = tswapl(sc->r12); 611a075f313SLaurent Vivier env->regs[13] = tswapl(sc->r13); 612a075f313SLaurent Vivier env->regs[14] = tswapl(sc->r14); 613a075f313SLaurent Vivier env->regs[15] = tswapl(sc->r15); 614a075f313SLaurent Vivier 615a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->rdi); 616a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->rsi); 617a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->rbp); 618a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->rbx); 619a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->rdx); 620a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->rax); 621a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->rcx); 622a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->rsp); 623a075f313SLaurent Vivier 624a075f313SLaurent Vivier env->eip = tswapl(sc->rip); 625a075f313SLaurent Vivier #endif 626a075f313SLaurent Vivier 627a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3); 628a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3); 629a075f313SLaurent Vivier 630a075f313SLaurent Vivier tmpflags = tswapl(sc->eflags); 631a075f313SLaurent Vivier env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); 632a075f313SLaurent Vivier // regs->orig_eax = -1; /* disable syscall checks */ 633a075f313SLaurent Vivier 634a075f313SLaurent Vivier fpstate_addr = tswapl(sc->fpstate); 635a075f313SLaurent Vivier if (fpstate_addr != 0) { 6365d245678SPaolo Bonzini struct target_fpstate *fpstate; 6375d245678SPaolo Bonzini if (!lock_user_struct(VERIFY_READ, fpstate, fpstate_addr, 638c7169b02SRichard Henderson sizeof(struct target_fpstate))) { 6395d245678SPaolo Bonzini return err; 640c7169b02SRichard Henderson } 641a075f313SLaurent Vivier #ifndef TARGET_X86_64 6422796f290SPaolo Bonzini if (!(env->features[FEAT_1_EDX] & CPUID_FXSR)) { 643a075f313SLaurent Vivier cpu_x86_frstor(env, fpstate_addr, 1); 6445d245678SPaolo Bonzini err = 0; 6452796f290SPaolo Bonzini } else { 6465d245678SPaolo Bonzini err = xrstor_sigcontext(env, &fpstate->fxsave, 6475d245678SPaolo Bonzini fpstate_addr + TARGET_FPSTATE_FXSAVE_OFFSET); 6482796f290SPaolo Bonzini } 649a075f313SLaurent Vivier #else 6505d245678SPaolo Bonzini err = xrstor_sigcontext(env, fpstate, fpstate_addr); 651a075f313SLaurent Vivier #endif 6525d245678SPaolo Bonzini unlock_user_struct(fpstate, fpstate_addr, 0); 6535d245678SPaolo Bonzini } else { 6545d245678SPaolo Bonzini err = 0; 655a075f313SLaurent Vivier } 656a075f313SLaurent Vivier 657a075f313SLaurent Vivier return err; 658a075f313SLaurent Vivier } 659a075f313SLaurent Vivier 660a075f313SLaurent Vivier /* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */ 661a075f313SLaurent Vivier #ifndef TARGET_X86_64 662a075f313SLaurent Vivier long do_sigreturn(CPUX86State *env) 663a075f313SLaurent Vivier { 664a075f313SLaurent Vivier struct sigframe *frame; 665a075f313SLaurent Vivier abi_ulong frame_addr = env->regs[R_ESP] - 8; 666a075f313SLaurent Vivier target_sigset_t target_set; 667a075f313SLaurent Vivier sigset_t set; 668a075f313SLaurent Vivier int i; 669a075f313SLaurent Vivier 670a075f313SLaurent Vivier trace_user_do_sigreturn(env, frame_addr); 671a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 672a075f313SLaurent Vivier goto badframe; 673a075f313SLaurent Vivier /* set blocked signals */ 674a075f313SLaurent Vivier __get_user(target_set.sig[0], &frame->sc.oldmask); 675a075f313SLaurent Vivier for(i = 1; i < TARGET_NSIG_WORDS; i++) { 676a075f313SLaurent Vivier __get_user(target_set.sig[i], &frame->extramask[i - 1]); 677a075f313SLaurent Vivier } 678a075f313SLaurent Vivier 679a075f313SLaurent Vivier target_to_host_sigset_internal(&set, &target_set); 680a075f313SLaurent Vivier set_sigmask(&set); 681a075f313SLaurent Vivier 682a075f313SLaurent Vivier /* restore registers */ 683a075f313SLaurent Vivier if (restore_sigcontext(env, &frame->sc)) 684a075f313SLaurent Vivier goto badframe; 685a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 68657a0c938SRichard Henderson return -QEMU_ESIGRETURN; 687a075f313SLaurent Vivier 688a075f313SLaurent Vivier badframe: 689a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 690a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 69157a0c938SRichard Henderson return -QEMU_ESIGRETURN; 692a075f313SLaurent Vivier } 693a075f313SLaurent Vivier #endif 694a075f313SLaurent Vivier 695a075f313SLaurent Vivier long do_rt_sigreturn(CPUX86State *env) 696a075f313SLaurent Vivier { 697a075f313SLaurent Vivier abi_ulong frame_addr; 698a075f313SLaurent Vivier struct rt_sigframe *frame; 699a075f313SLaurent Vivier sigset_t set; 700a075f313SLaurent Vivier 701a075f313SLaurent Vivier frame_addr = env->regs[R_ESP] - sizeof(abi_ulong); 702a075f313SLaurent Vivier trace_user_do_rt_sigreturn(env, frame_addr); 703a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 704a075f313SLaurent Vivier goto badframe; 705a075f313SLaurent Vivier target_to_host_sigset(&set, &frame->uc.tuc_sigmask); 706a075f313SLaurent Vivier set_sigmask(&set); 707a075f313SLaurent Vivier 708a075f313SLaurent Vivier if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) { 709a075f313SLaurent Vivier goto badframe; 710a075f313SLaurent Vivier } 711a075f313SLaurent Vivier 712ddc3e74dSRichard Henderson target_restore_altstack(&frame->uc.tuc_stack, env); 713a075f313SLaurent Vivier 714a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 71557a0c938SRichard Henderson return -QEMU_ESIGRETURN; 716a075f313SLaurent Vivier 717a075f313SLaurent Vivier badframe: 718a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 719a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 72057a0c938SRichard Henderson return -QEMU_ESIGRETURN; 721a075f313SLaurent Vivier } 7228ee8a104SRichard Henderson 7238ee8a104SRichard Henderson #ifndef TARGET_X86_64 7248ee8a104SRichard Henderson void setup_sigtramp(abi_ulong sigtramp_page) 7258ee8a104SRichard Henderson { 7268ee8a104SRichard Henderson uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); 7278ee8a104SRichard Henderson assert(tramp != NULL); 7288ee8a104SRichard Henderson 7298ee8a104SRichard Henderson default_sigreturn = sigtramp_page; 7308ee8a104SRichard Henderson install_sigtramp(tramp); 7318ee8a104SRichard Henderson 7328ee8a104SRichard Henderson default_rt_sigreturn = sigtramp_page + 8; 7338ee8a104SRichard Henderson install_rt_sigtramp(tramp + 8); 7348ee8a104SRichard Henderson 7358ee8a104SRichard Henderson unlock_user(tramp, sigtramp_page, 2 * 8); 7368ee8a104SRichard Henderson } 7378ee8a104SRichard Henderson #endif 738