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 375cc77ebeSRichard Henderson /* Legacy x87 fpu state format for FSAVE/FRESTOR. */ 385cc77ebeSRichard Henderson struct target_fregs_state { 395cc77ebeSRichard Henderson uint32_t cwd; 405cc77ebeSRichard Henderson uint32_t swd; 415cc77ebeSRichard Henderson uint32_t twd; 425cc77ebeSRichard Henderson uint32_t fip; 435cc77ebeSRichard Henderson uint32_t fcs; 445cc77ebeSRichard Henderson uint32_t foo; 455cc77ebeSRichard Henderson uint32_t fos; 465cc77ebeSRichard Henderson struct target_fpreg st[8]; 475cc77ebeSRichard Henderson 485cc77ebeSRichard Henderson /* Software status information [not touched by FSAVE]. */ 495cc77ebeSRichard Henderson uint16_t status; 505cc77ebeSRichard Henderson uint16_t magic; /* 0xffff: FPU data only, 0x0000: FXSR FPU data */ 515cc77ebeSRichard Henderson }; 525cc77ebeSRichard Henderson QEMU_BUILD_BUG_ON(sizeof(struct target_fregs_state) != 32 + 80); 535cc77ebeSRichard Henderson 545d245678SPaolo Bonzini struct target_fpx_sw_bytes { 555d245678SPaolo Bonzini uint32_t magic1; 565d245678SPaolo Bonzini uint32_t extended_size; 575d245678SPaolo Bonzini uint64_t xfeatures; 585d245678SPaolo Bonzini uint32_t xstate_size; 595d245678SPaolo Bonzini uint32_t reserved[7]; 605d245678SPaolo Bonzini }; 615d245678SPaolo Bonzini QEMU_BUILD_BUG_ON(sizeof(struct target_fpx_sw_bytes) != 12*4); 625d245678SPaolo Bonzini 632796f290SPaolo Bonzini struct target_fpstate_32 { 645cc77ebeSRichard Henderson struct target_fregs_state fpstate; 655cc77ebeSRichard Henderson X86LegacyXSaveArea fxstate; 662796f290SPaolo Bonzini }; 672796f290SPaolo Bonzini 68a075f313SLaurent Vivier struct target_sigcontext_32 { 69a075f313SLaurent Vivier uint16_t gs, __gsh; 70a075f313SLaurent Vivier uint16_t fs, __fsh; 71a075f313SLaurent Vivier uint16_t es, __esh; 72a075f313SLaurent Vivier uint16_t ds, __dsh; 73a075f313SLaurent Vivier uint32_t edi; 74a075f313SLaurent Vivier uint32_t esi; 75a075f313SLaurent Vivier uint32_t ebp; 76a075f313SLaurent Vivier uint32_t esp; 77a075f313SLaurent Vivier uint32_t ebx; 78a075f313SLaurent Vivier uint32_t edx; 79a075f313SLaurent Vivier uint32_t ecx; 80a075f313SLaurent Vivier uint32_t eax; 81a075f313SLaurent Vivier uint32_t trapno; 82a075f313SLaurent Vivier uint32_t err; 83a075f313SLaurent Vivier uint32_t eip; 84a075f313SLaurent Vivier uint16_t cs, __csh; 85a075f313SLaurent Vivier uint32_t eflags; 86a075f313SLaurent Vivier uint32_t esp_at_signal; 87a075f313SLaurent Vivier uint16_t ss, __ssh; 88a075f313SLaurent Vivier uint32_t fpstate; /* pointer */ 89a075f313SLaurent Vivier uint32_t oldmask; 90a075f313SLaurent Vivier uint32_t cr2; 91a075f313SLaurent Vivier }; 92a075f313SLaurent Vivier 93a075f313SLaurent Vivier struct target_sigcontext_64 { 94a075f313SLaurent Vivier uint64_t r8; 95a075f313SLaurent Vivier uint64_t r9; 96a075f313SLaurent Vivier uint64_t r10; 97a075f313SLaurent Vivier uint64_t r11; 98a075f313SLaurent Vivier uint64_t r12; 99a075f313SLaurent Vivier uint64_t r13; 100a075f313SLaurent Vivier uint64_t r14; 101a075f313SLaurent Vivier uint64_t r15; 102a075f313SLaurent Vivier 103a075f313SLaurent Vivier uint64_t rdi; 104a075f313SLaurent Vivier uint64_t rsi; 105a075f313SLaurent Vivier uint64_t rbp; 106a075f313SLaurent Vivier uint64_t rbx; 107a075f313SLaurent Vivier uint64_t rdx; 108a075f313SLaurent Vivier uint64_t rax; 109a075f313SLaurent Vivier uint64_t rcx; 110a075f313SLaurent Vivier uint64_t rsp; 111a075f313SLaurent Vivier uint64_t rip; 112a075f313SLaurent Vivier 113a075f313SLaurent Vivier uint64_t eflags; 114a075f313SLaurent Vivier 115a075f313SLaurent Vivier uint16_t cs; 116a075f313SLaurent Vivier uint16_t gs; 117a075f313SLaurent Vivier uint16_t fs; 118a075f313SLaurent Vivier uint16_t ss; 119a075f313SLaurent Vivier 120a075f313SLaurent Vivier uint64_t err; 121a075f313SLaurent Vivier uint64_t trapno; 122a075f313SLaurent Vivier uint64_t oldmask; 123a075f313SLaurent Vivier uint64_t cr2; 124a075f313SLaurent Vivier 125a075f313SLaurent Vivier uint64_t fpstate; /* pointer */ 126a075f313SLaurent Vivier uint64_t padding[8]; 127a075f313SLaurent Vivier }; 128a075f313SLaurent Vivier 129a075f313SLaurent Vivier #ifndef TARGET_X86_64 130a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_32 131a075f313SLaurent Vivier #else 132a075f313SLaurent Vivier # define target_sigcontext target_sigcontext_64 133a075f313SLaurent Vivier #endif 134a075f313SLaurent Vivier 135a075f313SLaurent Vivier /* see Linux/include/uapi/asm-generic/ucontext.h */ 136a075f313SLaurent Vivier struct target_ucontext { 137a075f313SLaurent Vivier abi_ulong tuc_flags; 138a075f313SLaurent Vivier abi_ulong tuc_link; 139a075f313SLaurent Vivier target_stack_t tuc_stack; 140a075f313SLaurent Vivier struct target_sigcontext tuc_mcontext; 141a075f313SLaurent Vivier target_sigset_t tuc_sigmask; /* mask last for extensibility */ 142a075f313SLaurent Vivier }; 143a075f313SLaurent Vivier 144a075f313SLaurent Vivier #ifndef TARGET_X86_64 145a075f313SLaurent Vivier struct sigframe { 146a075f313SLaurent Vivier abi_ulong pretcode; 147a075f313SLaurent Vivier int sig; 148a075f313SLaurent Vivier struct target_sigcontext sc; 1495154d35bSPaolo Bonzini /* 150*a7365e98SRichard Henderson * The actual fpstate is placed after retcode[] below, to make room 151*a7365e98SRichard Henderson * for the variable-sized xsave data. The older unused fpstate has 152*a7365e98SRichard Henderson * to be kept to avoid changing the offset of extramask[], which 1535154d35bSPaolo Bonzini * is part of the ABI. 1545154d35bSPaolo Bonzini */ 155*a7365e98SRichard Henderson struct target_fpstate_32 fpstate_unused; 156a075f313SLaurent Vivier abi_ulong extramask[TARGET_NSIG_WORDS-1]; 157a075f313SLaurent Vivier char retcode[8]; 158*a7365e98SRichard Henderson /* fp state follows here */ 159a075f313SLaurent Vivier }; 160a075f313SLaurent Vivier 161a075f313SLaurent Vivier struct rt_sigframe { 162a075f313SLaurent Vivier abi_ulong pretcode; 163a075f313SLaurent Vivier int sig; 164a075f313SLaurent Vivier abi_ulong pinfo; 165a075f313SLaurent Vivier abi_ulong puc; 166a075f313SLaurent Vivier struct target_siginfo info; 167a075f313SLaurent Vivier struct target_ucontext uc; 168a075f313SLaurent Vivier char retcode[8]; 169*a7365e98SRichard Henderson /* fp state follows here */ 170a075f313SLaurent Vivier }; 171a1367443SRichard Henderson 172a1367443SRichard Henderson /* 173a1367443SRichard Henderson * Verify that vdso-asmoffset.h constants match. 174a1367443SRichard Henderson */ 175a1367443SRichard Henderson #include "i386/vdso-asmoffset.h" 176a1367443SRichard Henderson 177a1367443SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(struct sigframe, sc.eip) 178a1367443SRichard Henderson != SIGFRAME_SIGCONTEXT_eip); 179a1367443SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, uc.tuc_mcontext.eip) 180a1367443SRichard Henderson != RT_SIGFRAME_SIGCONTEXT_eip); 181a1367443SRichard Henderson 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; 188*a7365e98SRichard Henderson /* fp state follows here */ 189a075f313SLaurent Vivier }; 190a075f313SLaurent Vivier #endif 191a075f313SLaurent Vivier 192*a7365e98SRichard Henderson typedef enum { 193*a7365e98SRichard Henderson #ifndef TARGET_X86_64 194*a7365e98SRichard Henderson FPSTATE_FSAVE, 195*a7365e98SRichard Henderson #endif 196*a7365e98SRichard Henderson FPSTATE_FXSAVE, 197*a7365e98SRichard Henderson FPSTATE_XSAVE 198*a7365e98SRichard Henderson } FPStateKind; 199*a7365e98SRichard Henderson 200*a7365e98SRichard Henderson static FPStateKind get_fpstate_kind(CPUX86State *env) 201*a7365e98SRichard Henderson { 202*a7365e98SRichard Henderson if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) { 203*a7365e98SRichard Henderson return FPSTATE_XSAVE; 204*a7365e98SRichard Henderson } 205*a7365e98SRichard Henderson #ifdef TARGET_X86_64 206*a7365e98SRichard Henderson return FPSTATE_FXSAVE; 207*a7365e98SRichard Henderson #else 208*a7365e98SRichard Henderson if (env->features[FEAT_1_EDX] & CPUID_FXSR) { 209*a7365e98SRichard Henderson return FPSTATE_FXSAVE; 210*a7365e98SRichard Henderson } 211*a7365e98SRichard Henderson return FPSTATE_FSAVE; 212*a7365e98SRichard Henderson #endif 213*a7365e98SRichard Henderson } 214*a7365e98SRichard Henderson 215*a7365e98SRichard Henderson static unsigned get_fpstate_size(CPUX86State *env, FPStateKind fpkind) 216*a7365e98SRichard Henderson { 217*a7365e98SRichard Henderson /* 218*a7365e98SRichard Henderson * Kernel: 219*a7365e98SRichard Henderson * fpu__alloc_mathframe 220*a7365e98SRichard Henderson * xstate_sigframe_size(current->thread.fpu.fpstate); 221*a7365e98SRichard Henderson * size = fpstate->user_size 222*a7365e98SRichard Henderson * use_xsave() ? size + FP_XSTATE_MAGIC2_SIZE : size 223*a7365e98SRichard Henderson * where fpstate->user_size is computed at init in 224*a7365e98SRichard Henderson * fpu__init_system_xstate_size_legacy and 225*a7365e98SRichard Henderson * fpu__init_system_xstate. 226*a7365e98SRichard Henderson * 227*a7365e98SRichard Henderson * Here we have no place to pre-compute, so inline it all. 228*a7365e98SRichard Henderson */ 229*a7365e98SRichard Henderson switch (fpkind) { 230*a7365e98SRichard Henderson case FPSTATE_XSAVE: 231*a7365e98SRichard Henderson return (xsave_area_size(env->xcr0, false) 232*a7365e98SRichard Henderson + TARGET_FP_XSTATE_MAGIC2_SIZE); 233*a7365e98SRichard Henderson case FPSTATE_FXSAVE: 234*a7365e98SRichard Henderson return sizeof(X86LegacyXSaveArea); 235*a7365e98SRichard Henderson #ifndef TARGET_X86_64 236*a7365e98SRichard Henderson case FPSTATE_FSAVE: 237*a7365e98SRichard Henderson return sizeof(struct target_fregs_state); 238*a7365e98SRichard Henderson #endif 239*a7365e98SRichard Henderson } 240*a7365e98SRichard Henderson g_assert_not_reached(); 241*a7365e98SRichard Henderson } 242*a7365e98SRichard Henderson 243*a7365e98SRichard Henderson static abi_ptr get_sigframe(struct target_sigaction *ka, CPUX86State *env, 244*a7365e98SRichard Henderson unsigned frame_size, FPStateKind fpkind, 245*a7365e98SRichard Henderson abi_ptr *fpstate, abi_ptr *fxstate, abi_ptr *fpend) 246*a7365e98SRichard Henderson { 247*a7365e98SRichard Henderson abi_ptr sp; 248*a7365e98SRichard Henderson unsigned math_size; 249*a7365e98SRichard Henderson 250*a7365e98SRichard Henderson /* Default to using normal stack */ 251*a7365e98SRichard Henderson sp = get_sp_from_cpustate(env); 252*a7365e98SRichard Henderson #ifdef TARGET_X86_64 253*a7365e98SRichard Henderson sp -= 128; /* this is the redzone */ 254*a7365e98SRichard Henderson #endif 255*a7365e98SRichard Henderson 256*a7365e98SRichard Henderson /* This is the X/Open sanctioned signal stack switching. */ 257*a7365e98SRichard Henderson if (ka->sa_flags & TARGET_SA_ONSTACK) { 258*a7365e98SRichard Henderson sp = target_sigsp(sp, ka); 259*a7365e98SRichard Henderson } else { 260*a7365e98SRichard Henderson #ifndef TARGET_X86_64 261*a7365e98SRichard Henderson /* This is the legacy signal stack switching. */ 262*a7365e98SRichard Henderson if ((env->segs[R_SS].selector & 0xffff) != __USER_DS 263*a7365e98SRichard Henderson && !(ka->sa_flags & TARGET_SA_RESTORER) 264*a7365e98SRichard Henderson && ka->sa_restorer) { 265*a7365e98SRichard Henderson sp = ka->sa_restorer; 266*a7365e98SRichard Henderson } 267*a7365e98SRichard Henderson #endif 268*a7365e98SRichard Henderson } 269*a7365e98SRichard Henderson 270*a7365e98SRichard Henderson math_size = get_fpstate_size(env, fpkind); 271*a7365e98SRichard Henderson sp = ROUND_DOWN(sp - math_size, 64); 272*a7365e98SRichard Henderson *fpend = sp + math_size; 273*a7365e98SRichard Henderson *fxstate = sp; 274*a7365e98SRichard Henderson #ifndef TARGET_X86_64 275*a7365e98SRichard Henderson if (fpkind != FPSTATE_FSAVE) { 276*a7365e98SRichard Henderson sp -= sizeof(struct target_fregs_state); 277*a7365e98SRichard Henderson } 278*a7365e98SRichard Henderson #endif 279*a7365e98SRichard Henderson *fpstate = sp; 280*a7365e98SRichard Henderson 281*a7365e98SRichard Henderson sp -= frame_size; 282*a7365e98SRichard Henderson /* 283*a7365e98SRichard Henderson * Align the stack pointer according to the ABI, i.e. so that on 284*a7365e98SRichard Henderson * function entry ((sp + sizeof(return_addr)) & 15) == 0. 285*a7365e98SRichard Henderson */ 286*a7365e98SRichard Henderson sp += sizeof(target_ulong); 287*a7365e98SRichard Henderson sp = ROUND_DOWN(sp, 16); 288*a7365e98SRichard Henderson sp -= sizeof(target_ulong); 289*a7365e98SRichard Henderson 290*a7365e98SRichard Henderson return sp; 291*a7365e98SRichard Henderson } 292*a7365e98SRichard Henderson 293a075f313SLaurent Vivier /* 294a075f313SLaurent Vivier * Set up a signal frame. 295a075f313SLaurent Vivier */ 296a075f313SLaurent Vivier 297*a7365e98SRichard Henderson static void fxsave_sigcontext(CPUX86State *env, X86LegacyXSaveArea *fxstate, 298*a7365e98SRichard Henderson abi_ptr fxstate_addr) 2992796f290SPaolo Bonzini { 300*a7365e98SRichard Henderson struct target_fpx_sw_bytes *sw = (void *)&fxstate->sw_reserved; 3013b6e9491SRichard Henderson 302*a7365e98SRichard Henderson /* fxstate_addr must be 16 byte aligned for fxsave */ 303*a7365e98SRichard Henderson assert(!(fxstate_addr & 0xf)); 304*a7365e98SRichard Henderson cpu_x86_fxsave(env, fxstate_addr); 3053b6e9491SRichard Henderson __put_user(0, &sw->magic1); 306*a7365e98SRichard Henderson } 3075d245678SPaolo Bonzini 308*a7365e98SRichard Henderson static void xsave_sigcontext(CPUX86State *env, 309*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate, 310*a7365e98SRichard Henderson abi_ptr fpstate_addr, 311*a7365e98SRichard Henderson abi_ptr xstate_addr, 312*a7365e98SRichard Henderson abi_ptr fpend_addr) 313*a7365e98SRichard Henderson { 314*a7365e98SRichard Henderson struct target_fpx_sw_bytes *sw = (void *)&fxstate->sw_reserved; 3155d245678SPaolo Bonzini /* 316*a7365e98SRichard Henderson * extended_size is the offset from fpstate_addr to right after 317*a7365e98SRichard Henderson * the end of the extended save states. On 32-bit that includes 318*a7365e98SRichard Henderson * the legacy FSAVE area. 3195d245678SPaolo Bonzini */ 320*a7365e98SRichard Henderson uint32_t extended_size = fpend_addr - fpstate_addr; 321*a7365e98SRichard Henderson /* Recover xstate_size by removing magic2. */ 322*a7365e98SRichard Henderson uint32_t xstate_size = (fpend_addr - xstate_addr 323*a7365e98SRichard Henderson - TARGET_FP_XSTATE_MAGIC2_SIZE); 324*a7365e98SRichard Henderson /* magic2 goes just after xstate. */ 325*a7365e98SRichard Henderson uint32_t *magic2 = (void *)fxstate + xstate_size; 3265d245678SPaolo Bonzini 327*a7365e98SRichard Henderson /* xstate_addr must be 64 byte aligned for xsave */ 328*a7365e98SRichard Henderson assert(!(xstate_addr & 0x3f)); 3295d245678SPaolo Bonzini 3305d245678SPaolo Bonzini /* Zero the header, XSAVE *adds* features to an existing save state. */ 331*a7365e98SRichard Henderson memset(fxstate + 1, 0, sizeof(X86XSaveHeader)); 332*a7365e98SRichard Henderson cpu_x86_xsave(env, xstate_addr, -1); 333*a7365e98SRichard Henderson 3343b6e9491SRichard Henderson __put_user(TARGET_FP_XSTATE_MAGIC1, &sw->magic1); 3353b6e9491SRichard Henderson __put_user(extended_size, &sw->extended_size); 3363b6e9491SRichard Henderson __put_user(env->xcr0, &sw->xfeatures); 3373b6e9491SRichard Henderson __put_user(xstate_size, &sw->xstate_size); 338*a7365e98SRichard Henderson __put_user(TARGET_FP_XSTATE_MAGIC2, magic2); 3392796f290SPaolo Bonzini } 3402796f290SPaolo Bonzini 341*a7365e98SRichard Henderson static void setup_sigcontext(CPUX86State *env, 342*a7365e98SRichard Henderson struct target_sigcontext *sc, 343*a7365e98SRichard Henderson abi_ulong mask, FPStateKind fpkind, 344*a7365e98SRichard Henderson struct target_fregs_state *fpstate, 345*a7365e98SRichard Henderson abi_ptr fpstate_addr, 346*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate, 347*a7365e98SRichard Henderson abi_ptr fxstate_addr, 348*a7365e98SRichard Henderson abi_ptr fpend_addr) 349a075f313SLaurent Vivier { 3506aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 351*a7365e98SRichard Henderson 352a075f313SLaurent Vivier #ifndef TARGET_X86_64 353a075f313SLaurent Vivier uint16_t magic; 354a075f313SLaurent Vivier 355a075f313SLaurent Vivier /* already locked in setup_frame() */ 356*a7365e98SRichard Henderson __put_user(env->segs[R_GS].selector, (uint32_t *)&sc->gs); 357*a7365e98SRichard Henderson __put_user(env->segs[R_FS].selector, (uint32_t *)&sc->fs); 358*a7365e98SRichard Henderson __put_user(env->segs[R_ES].selector, (uint32_t *)&sc->es); 359*a7365e98SRichard Henderson __put_user(env->segs[R_DS].selector, (uint32_t *)&sc->ds); 360a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->edi); 361a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->esi); 362a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->ebp); 363a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp); 364a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->ebx); 365a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->edx); 366a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->ecx); 367a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->eax); 368a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 369a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 370a075f313SLaurent Vivier __put_user(env->eip, &sc->eip); 371*a7365e98SRichard Henderson __put_user(env->segs[R_CS].selector, (uint32_t *)&sc->cs); 372a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 373a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->esp_at_signal); 374*a7365e98SRichard Henderson __put_user(env->segs[R_SS].selector, (uint32_t *)&sc->ss); 375a075f313SLaurent Vivier 376a075f313SLaurent Vivier cpu_x86_fsave(env, fpstate_addr, 1); 377*a7365e98SRichard Henderson fpstate->status = fpstate->swd; 378*a7365e98SRichard Henderson magic = (fpkind == FPSTATE_FSAVE ? 0 : 0xffff); 379*a7365e98SRichard Henderson __put_user(magic, &fpstate->magic); 380a075f313SLaurent Vivier #else 381a075f313SLaurent Vivier __put_user(env->regs[R_EDI], &sc->rdi); 382a075f313SLaurent Vivier __put_user(env->regs[R_ESI], &sc->rsi); 383a075f313SLaurent Vivier __put_user(env->regs[R_EBP], &sc->rbp); 384a075f313SLaurent Vivier __put_user(env->regs[R_ESP], &sc->rsp); 385a075f313SLaurent Vivier __put_user(env->regs[R_EBX], &sc->rbx); 386a075f313SLaurent Vivier __put_user(env->regs[R_EDX], &sc->rdx); 387a075f313SLaurent Vivier __put_user(env->regs[R_ECX], &sc->rcx); 388a075f313SLaurent Vivier __put_user(env->regs[R_EAX], &sc->rax); 389a075f313SLaurent Vivier 390a075f313SLaurent Vivier __put_user(env->regs[8], &sc->r8); 391a075f313SLaurent Vivier __put_user(env->regs[9], &sc->r9); 392a075f313SLaurent Vivier __put_user(env->regs[10], &sc->r10); 393a075f313SLaurent Vivier __put_user(env->regs[11], &sc->r11); 394a075f313SLaurent Vivier __put_user(env->regs[12], &sc->r12); 395a075f313SLaurent Vivier __put_user(env->regs[13], &sc->r13); 396a075f313SLaurent Vivier __put_user(env->regs[14], &sc->r14); 397a075f313SLaurent Vivier __put_user(env->regs[15], &sc->r15); 398a075f313SLaurent Vivier 399a075f313SLaurent Vivier __put_user(cs->exception_index, &sc->trapno); 400a075f313SLaurent Vivier __put_user(env->error_code, &sc->err); 401a075f313SLaurent Vivier __put_user(env->eip, &sc->rip); 402a075f313SLaurent Vivier 403a075f313SLaurent Vivier __put_user(env->eflags, &sc->eflags); 404a075f313SLaurent Vivier __put_user(env->segs[R_CS].selector, &sc->cs); 405a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->gs); 406a075f313SLaurent Vivier __put_user((uint16_t)0, &sc->fs); 407a075f313SLaurent Vivier __put_user(env->segs[R_SS].selector, &sc->ss); 4082796f290SPaolo Bonzini #endif 4092796f290SPaolo Bonzini 410*a7365e98SRichard Henderson switch (fpkind) { 411*a7365e98SRichard Henderson case FPSTATE_XSAVE: 412*a7365e98SRichard Henderson xsave_sigcontext(env, fxstate, fpstate_addr, fxstate_addr, fpend_addr); 413*a7365e98SRichard Henderson break; 414*a7365e98SRichard Henderson case FPSTATE_FXSAVE: 415*a7365e98SRichard Henderson fxsave_sigcontext(env, fxstate, fxstate_addr); 416*a7365e98SRichard Henderson break; 417*a7365e98SRichard Henderson default: 418*a7365e98SRichard Henderson break; 419*a7365e98SRichard Henderson } 4202796f290SPaolo Bonzini 421*a7365e98SRichard Henderson __put_user(fpstate_addr, &sc->fpstate); 4222796f290SPaolo Bonzini /* non-iBCS2 extensions.. */ 423a075f313SLaurent Vivier __put_user(mask, &sc->oldmask); 424a075f313SLaurent Vivier __put_user(env->cr[2], &sc->cr2); 425a075f313SLaurent Vivier } 426a075f313SLaurent Vivier 427a075f313SLaurent Vivier #ifndef TARGET_X86_64 4288ee8a104SRichard Henderson static void install_sigtramp(void *tramp) 4298ee8a104SRichard Henderson { 4308ee8a104SRichard Henderson /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */ 4318ee8a104SRichard Henderson __put_user(0xb858, (uint16_t *)(tramp + 0)); 4328ee8a104SRichard Henderson __put_user(TARGET_NR_sigreturn, (int32_t *)(tramp + 2)); 4338ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 6)); 4348ee8a104SRichard Henderson } 4358ee8a104SRichard Henderson 4368ee8a104SRichard Henderson static void install_rt_sigtramp(void *tramp) 4378ee8a104SRichard Henderson { 4388ee8a104SRichard Henderson /* This is movl $syscall,%eax ; int $0x80 */ 4398ee8a104SRichard Henderson __put_user(0xb8, (uint8_t *)(tramp + 0)); 4408ee8a104SRichard Henderson __put_user(TARGET_NR_rt_sigreturn, (int32_t *)(tramp + 1)); 4418ee8a104SRichard Henderson __put_user(0x80cd, (uint16_t *)(tramp + 5)); 4428ee8a104SRichard Henderson } 4438ee8a104SRichard Henderson 444a075f313SLaurent Vivier /* compare linux/arch/i386/kernel/signal.c:setup_frame() */ 445a075f313SLaurent Vivier void setup_frame(int sig, struct target_sigaction *ka, 446a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 447a075f313SLaurent Vivier { 448*a7365e98SRichard Henderson abi_ptr frame_addr, fpstate_addr, fxstate_addr, fpend_addr; 449a075f313SLaurent Vivier struct sigframe *frame; 450*a7365e98SRichard Henderson struct target_fregs_state *fpstate; 451*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate; 452*a7365e98SRichard Henderson unsigned total_size; 453*a7365e98SRichard Henderson FPStateKind fpkind; 454a075f313SLaurent Vivier 455*a7365e98SRichard Henderson fpkind = get_fpstate_kind(env); 456*a7365e98SRichard Henderson frame_addr = get_sigframe(ka, env, sizeof(struct sigframe), fpkind, 457*a7365e98SRichard Henderson &fpstate_addr, &fxstate_addr, &fpend_addr); 458a075f313SLaurent Vivier trace_user_setup_frame(env, frame_addr); 459a075f313SLaurent Vivier 460*a7365e98SRichard Henderson total_size = fpend_addr - frame_addr; 461*a7365e98SRichard Henderson frame = lock_user(VERIFY_WRITE, frame_addr, total_size, 0); 462*a7365e98SRichard Henderson if (!frame) { 463*a7365e98SRichard Henderson force_sigsegv(sig); 464*a7365e98SRichard Henderson return; 465*a7365e98SRichard Henderson } 466a075f313SLaurent Vivier 467*a7365e98SRichard Henderson fxstate = (void *)frame + (fxstate_addr - frame_addr); 468*a7365e98SRichard Henderson #ifdef TARGET_X86_64 469*a7365e98SRichard Henderson fpstate = NULL; 470*a7365e98SRichard Henderson #else 471*a7365e98SRichard Henderson fpstate = (void *)frame + (fpstate_addr - frame_addr); 472*a7365e98SRichard Henderson #endif 473a075f313SLaurent Vivier 474*a7365e98SRichard Henderson setup_sigcontext(env, &frame->sc, set->sig[0], fpkind, 475*a7365e98SRichard Henderson fpstate, fpstate_addr, fxstate, fxstate_addr, fpend_addr); 476*a7365e98SRichard Henderson 477*a7365e98SRichard Henderson for (int i = 1; i < TARGET_NSIG_WORDS; i++) { 478a075f313SLaurent Vivier __put_user(set->sig[i], &frame->extramask[i - 1]); 479a075f313SLaurent Vivier } 480a075f313SLaurent Vivier 481a075f313SLaurent Vivier /* Set up to return from userspace. If provided, use a stub 482a075f313SLaurent Vivier already in userspace. */ 483a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 484a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 485a075f313SLaurent Vivier } else { 4868ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 4878ee8a104SRichard Henderson install_sigtramp(frame->retcode); 4888ee8a104SRichard Henderson __put_user(default_sigreturn, &frame->pretcode); 489a075f313SLaurent Vivier } 490*a7365e98SRichard Henderson unlock_user(frame, frame_addr, total_size); 491a075f313SLaurent Vivier 492a075f313SLaurent Vivier /* Set up registers for signal handler */ 493a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 494a075f313SLaurent Vivier env->eip = ka->_sa_handler; 495a075f313SLaurent Vivier 496bae0455cSRichard Henderson /* Store argument for both -mregparm=3 and standard. */ 497bae0455cSRichard Henderson env->regs[R_EAX] = sig; 498bae0455cSRichard Henderson __put_user(sig, &frame->sig); 499bae0455cSRichard Henderson /* The kernel clears EDX and ECX even though there is only one arg. */ 500bae0455cSRichard Henderson env->regs[R_EDX] = 0; 501bae0455cSRichard Henderson env->regs[R_ECX] = 0; 502bae0455cSRichard Henderson 503a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, __USER_DS); 504a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, __USER_DS); 505a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, __USER_DS); 506a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 507a075f313SLaurent Vivier env->eflags &= ~TF_MASK; 508a075f313SLaurent Vivier } 509a075f313SLaurent Vivier #endif 510a075f313SLaurent Vivier 511a075f313SLaurent Vivier /* compare linux/arch/x86/kernel/signal.c:setup_rt_frame() */ 512a075f313SLaurent Vivier void setup_rt_frame(int sig, struct target_sigaction *ka, 513a075f313SLaurent Vivier target_siginfo_t *info, 514a075f313SLaurent Vivier target_sigset_t *set, CPUX86State *env) 515a075f313SLaurent Vivier { 516*a7365e98SRichard Henderson abi_ptr frame_addr, fpstate_addr, fxstate_addr, fpend_addr; 517a075f313SLaurent Vivier struct rt_sigframe *frame; 518*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate; 519*a7365e98SRichard Henderson struct target_fregs_state *fpstate; 520*a7365e98SRichard Henderson unsigned total_size; 521*a7365e98SRichard Henderson FPStateKind fpkind; 522a075f313SLaurent Vivier 523*a7365e98SRichard Henderson fpkind = get_fpstate_kind(env); 524*a7365e98SRichard Henderson frame_addr = get_sigframe(ka, env, sizeof(struct rt_sigframe), fpkind, 525*a7365e98SRichard Henderson &fpstate_addr, &fxstate_addr, &fpend_addr); 526a075f313SLaurent Vivier trace_user_setup_rt_frame(env, frame_addr); 527a075f313SLaurent Vivier 528*a7365e98SRichard Henderson total_size = fpend_addr - frame_addr; 529*a7365e98SRichard Henderson frame = lock_user(VERIFY_WRITE, frame_addr, total_size, 0); 530*a7365e98SRichard Henderson if (!frame) { 531a075f313SLaurent Vivier goto give_sigsegv; 532*a7365e98SRichard Henderson } 533a075f313SLaurent Vivier 534a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_SIGINFO) { 5354d6d8a05SGustavo Romero frame->info = *info; 536a075f313SLaurent Vivier } 537a075f313SLaurent Vivier 538a075f313SLaurent Vivier /* Create the ucontext. */ 539*a7365e98SRichard Henderson __put_user(fpkind == FPSTATE_XSAVE, &frame->uc.tuc_flags); 540a075f313SLaurent Vivier __put_user(0, &frame->uc.tuc_link); 541465e237bSLaurent Vivier target_save_altstack(&frame->uc.tuc_stack, env); 542a075f313SLaurent Vivier 543*a7365e98SRichard Henderson fxstate = (void *)frame + (fxstate_addr - frame_addr); 544*a7365e98SRichard Henderson #ifdef TARGET_X86_64 545*a7365e98SRichard Henderson fpstate = NULL; 546*a7365e98SRichard Henderson #else 547*a7365e98SRichard Henderson fpstate = (void *)frame + (fpstate_addr - frame_addr); 548*a7365e98SRichard Henderson #endif 549*a7365e98SRichard Henderson 550*a7365e98SRichard Henderson setup_sigcontext(env, &frame->uc.tuc_mcontext, set->sig[0], fpkind, 551*a7365e98SRichard Henderson fpstate, fpstate_addr, fxstate, fxstate_addr, fpend_addr); 552*a7365e98SRichard Henderson 553*a7365e98SRichard Henderson for (int i = 0; i < TARGET_NSIG_WORDS; i++) { 554a075f313SLaurent Vivier __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); 555a075f313SLaurent Vivier } 556a075f313SLaurent Vivier 557*a7365e98SRichard Henderson /* 558*a7365e98SRichard Henderson * Set up to return from userspace. If provided, use a stub 559*a7365e98SRichard Henderson * already in userspace. 560*a7365e98SRichard Henderson */ 561a075f313SLaurent Vivier if (ka->sa_flags & TARGET_SA_RESTORER) { 562a075f313SLaurent Vivier __put_user(ka->sa_restorer, &frame->pretcode); 563a075f313SLaurent Vivier } else { 564db205541SRichard Henderson #ifdef TARGET_X86_64 565db205541SRichard Henderson /* For x86_64, SA_RESTORER is required ABI. */ 566db205541SRichard Henderson goto give_sigsegv; 567db205541SRichard Henderson #else 5688ee8a104SRichard Henderson /* This is no longer used, but is retained for ABI compatibility. */ 5698ee8a104SRichard Henderson install_rt_sigtramp(frame->retcode); 5708ee8a104SRichard Henderson __put_user(default_rt_sigreturn, &frame->pretcode); 571a075f313SLaurent Vivier #endif 572db205541SRichard Henderson } 573a075f313SLaurent Vivier 574a075f313SLaurent Vivier /* Set up registers for signal handler */ 575a075f313SLaurent Vivier env->regs[R_ESP] = frame_addr; 576a075f313SLaurent Vivier env->eip = ka->_sa_handler; 577a075f313SLaurent Vivier 578a075f313SLaurent Vivier #ifndef TARGET_X86_64 579bae0455cSRichard Henderson /* Store arguments for both -mregparm=3 and standard. */ 580a075f313SLaurent Vivier env->regs[R_EAX] = sig; 581bae0455cSRichard Henderson __put_user(sig, &frame->sig); 5820c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, info); 583bae0455cSRichard Henderson __put_user(env->regs[R_EDX], &frame->pinfo); 5840c40c18eSIlya Leoshkevich env->regs[R_ECX] = frame_addr + offsetof(struct rt_sigframe, uc); 585bae0455cSRichard Henderson __put_user(env->regs[R_ECX], &frame->puc); 586a075f313SLaurent Vivier #else 587a075f313SLaurent Vivier env->regs[R_EAX] = 0; 588a075f313SLaurent Vivier env->regs[R_EDI] = sig; 5890c40c18eSIlya Leoshkevich env->regs[R_ESI] = frame_addr + offsetof(struct rt_sigframe, info); 5900c40c18eSIlya Leoshkevich env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, uc); 591a075f313SLaurent Vivier #endif 592*a7365e98SRichard Henderson unlock_user(frame, frame_addr, total_size); 593a075f313SLaurent Vivier 594a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, __USER_DS); 595a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, __USER_DS); 596a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, __USER_CS); 597a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, __USER_DS); 598a075f313SLaurent Vivier env->eflags &= ~TF_MASK; 599a075f313SLaurent Vivier return; 600a075f313SLaurent Vivier 601a075f313SLaurent Vivier give_sigsegv: 602a075f313SLaurent Vivier force_sigsegv(sig); 603a075f313SLaurent Vivier } 604a075f313SLaurent Vivier 605*a7365e98SRichard Henderson /* 606*a7365e98SRichard Henderson * Restore a signal frame. 607*a7365e98SRichard Henderson */ 608*a7365e98SRichard Henderson 609*a7365e98SRichard Henderson static bool xrstor_sigcontext(CPUX86State *env, FPStateKind fpkind, 610*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate, 611*a7365e98SRichard Henderson abi_ptr fxstate_addr) 6125d245678SPaolo Bonzini { 613*a7365e98SRichard Henderson struct target_fpx_sw_bytes *sw = (void *)&fxstate->sw_reserved; 614*a7365e98SRichard Henderson uint32_t magic1, magic2; 615*a7365e98SRichard Henderson uint32_t extended_size, xstate_size, min_size, max_size; 6163b6e9491SRichard Henderson 617*a7365e98SRichard Henderson switch (fpkind) { 618*a7365e98SRichard Henderson case FPSTATE_XSAVE: 619*a7365e98SRichard Henderson magic1 = tswap32(sw->magic1); 620*a7365e98SRichard Henderson extended_size = tswap32(sw->extended_size); 621*a7365e98SRichard Henderson xstate_size = tswap32(sw->xstate_size); 622*a7365e98SRichard Henderson min_size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader); 623*a7365e98SRichard Henderson max_size = xsave_area_size(env->xcr0, false); 6245d245678SPaolo Bonzini 625*a7365e98SRichard Henderson /* Check for the first magic field and other error scenarios. */ 626*a7365e98SRichard Henderson if (magic1 != TARGET_FP_XSTATE_MAGIC1 || 627*a7365e98SRichard Henderson xstate_size < min_size || 628*a7365e98SRichard Henderson xstate_size > max_size || 629*a7365e98SRichard Henderson xstate_size > extended_size) { 630*a7365e98SRichard Henderson break; 631*a7365e98SRichard Henderson } 632*a7365e98SRichard Henderson if (!access_ok(env_cpu(env), VERIFY_READ, fxstate_addr, 633*a7365e98SRichard Henderson xstate_size + TARGET_FP_XSTATE_MAGIC2_SIZE)) { 6349e9b7d4cSRichard Henderson return false; 6355d245678SPaolo Bonzini } 636*a7365e98SRichard Henderson /* 637*a7365e98SRichard Henderson * Check for the presence of second magic word at the end of memory 638*a7365e98SRichard Henderson * layout. This detects the case where the user just copied the legacy 639*a7365e98SRichard Henderson * fpstate layout with out copying the extended state information 640*a7365e98SRichard Henderson * in the memory layout. 641*a7365e98SRichard Henderson */ 642*a7365e98SRichard Henderson if (get_user_u32(magic2, fxstate_addr + xstate_size)) { 643*a7365e98SRichard Henderson return false; 644*a7365e98SRichard Henderson } 645*a7365e98SRichard Henderson if (magic2 != TARGET_FP_XSTATE_MAGIC2) { 646*a7365e98SRichard Henderson break; 647*a7365e98SRichard Henderson } 648*a7365e98SRichard Henderson cpu_x86_xrstor(env, fxstate_addr, -1); 6499e9b7d4cSRichard Henderson return true; 650*a7365e98SRichard Henderson 651*a7365e98SRichard Henderson default: 652*a7365e98SRichard Henderson break; 6535d245678SPaolo Bonzini } 6545d245678SPaolo Bonzini 655*a7365e98SRichard Henderson cpu_x86_fxrstor(env, fxstate_addr); 6569e9b7d4cSRichard Henderson return true; 6575d245678SPaolo Bonzini } 6585d245678SPaolo Bonzini 659*a7365e98SRichard Henderson #ifndef TARGET_X86_64 660*a7365e98SRichard Henderson static bool frstor_sigcontext(CPUX86State *env, FPStateKind fpkind, 661*a7365e98SRichard Henderson struct target_fregs_state *fpstate, 662*a7365e98SRichard Henderson abi_ptr fpstate_addr, 663*a7365e98SRichard Henderson X86LegacyXSaveArea *fxstate, 664*a7365e98SRichard Henderson abi_ptr fxstate_addr) 665*a7365e98SRichard Henderson { 666*a7365e98SRichard Henderson switch (fpkind) { 667*a7365e98SRichard Henderson case FPSTATE_XSAVE: 668*a7365e98SRichard Henderson if (!xrstor_sigcontext(env, fpkind, fxstate, fxstate_addr)) { 669*a7365e98SRichard Henderson return false; 670*a7365e98SRichard Henderson } 671*a7365e98SRichard Henderson break; 672*a7365e98SRichard Henderson case FPSTATE_FXSAVE: 673*a7365e98SRichard Henderson cpu_x86_fxrstor(env, fxstate_addr); 674*a7365e98SRichard Henderson break; 675*a7365e98SRichard Henderson case FPSTATE_FSAVE: 676*a7365e98SRichard Henderson break; 677*a7365e98SRichard Henderson default: 678*a7365e98SRichard Henderson g_assert_not_reached(); 679*a7365e98SRichard Henderson } 680*a7365e98SRichard Henderson 681*a7365e98SRichard Henderson /* 682*a7365e98SRichard Henderson * Copy the legacy state because the FP portion of the FX frame has 683*a7365e98SRichard Henderson * to be ignored for histerical raisins. The kernel folds the two 684*a7365e98SRichard Henderson * states together and then performs a single load; here we perform 685*a7365e98SRichard Henderson * the merge within ENV by loading XSTATE/FXSTATE first, then 686*a7365e98SRichard Henderson * overriding with the FSTATE afterward. 687*a7365e98SRichard Henderson */ 688*a7365e98SRichard Henderson cpu_x86_frstor(env, fpstate_addr, 1); 689*a7365e98SRichard Henderson return true; 690*a7365e98SRichard Henderson } 691*a7365e98SRichard Henderson #endif 692*a7365e98SRichard Henderson 693c536f9b7SRichard Henderson static bool restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc) 694a075f313SLaurent Vivier { 695*a7365e98SRichard Henderson abi_ptr fpstate_addr; 696*a7365e98SRichard Henderson unsigned tmpflags, math_size; 697*a7365e98SRichard Henderson FPStateKind fpkind; 698*a7365e98SRichard Henderson void *fpstate; 699c536f9b7SRichard Henderson bool ok; 700a075f313SLaurent Vivier 701a075f313SLaurent Vivier #ifndef TARGET_X86_64 702a075f313SLaurent Vivier cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); 703a075f313SLaurent Vivier cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); 704a075f313SLaurent Vivier cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); 705a075f313SLaurent Vivier cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); 706a075f313SLaurent Vivier 707a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->edi); 708a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->esi); 709a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->ebp); 710a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->esp); 711a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->ebx); 712a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->edx); 713a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->ecx); 714a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->eax); 715a075f313SLaurent Vivier 716a075f313SLaurent Vivier env->eip = tswapl(sc->eip); 717a075f313SLaurent Vivier #else 718a075f313SLaurent Vivier env->regs[8] = tswapl(sc->r8); 719a075f313SLaurent Vivier env->regs[9] = tswapl(sc->r9); 720a075f313SLaurent Vivier env->regs[10] = tswapl(sc->r10); 721a075f313SLaurent Vivier env->regs[11] = tswapl(sc->r11); 722a075f313SLaurent Vivier env->regs[12] = tswapl(sc->r12); 723a075f313SLaurent Vivier env->regs[13] = tswapl(sc->r13); 724a075f313SLaurent Vivier env->regs[14] = tswapl(sc->r14); 725a075f313SLaurent Vivier env->regs[15] = tswapl(sc->r15); 726a075f313SLaurent Vivier 727a075f313SLaurent Vivier env->regs[R_EDI] = tswapl(sc->rdi); 728a075f313SLaurent Vivier env->regs[R_ESI] = tswapl(sc->rsi); 729a075f313SLaurent Vivier env->regs[R_EBP] = tswapl(sc->rbp); 730a075f313SLaurent Vivier env->regs[R_EBX] = tswapl(sc->rbx); 731a075f313SLaurent Vivier env->regs[R_EDX] = tswapl(sc->rdx); 732a075f313SLaurent Vivier env->regs[R_EAX] = tswapl(sc->rax); 733a075f313SLaurent Vivier env->regs[R_ECX] = tswapl(sc->rcx); 734a075f313SLaurent Vivier env->regs[R_ESP] = tswapl(sc->rsp); 735a075f313SLaurent Vivier 736a075f313SLaurent Vivier env->eip = tswapl(sc->rip); 737a075f313SLaurent Vivier #endif 738a075f313SLaurent Vivier 739a075f313SLaurent Vivier cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3); 740a075f313SLaurent Vivier cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3); 741a075f313SLaurent Vivier 742a075f313SLaurent Vivier tmpflags = tswapl(sc->eflags); 743a075f313SLaurent Vivier env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); 744a075f313SLaurent Vivier 745a075f313SLaurent Vivier fpstate_addr = tswapl(sc->fpstate); 746c536f9b7SRichard Henderson if (fpstate_addr == 0) { 747c536f9b7SRichard Henderson return true; 748c536f9b7SRichard Henderson } 749*a7365e98SRichard Henderson 750*a7365e98SRichard Henderson fpkind = get_fpstate_kind(env); 751*a7365e98SRichard Henderson math_size = get_fpstate_size(env, fpkind); 752*a7365e98SRichard Henderson #ifndef TARGET_X86_64 753*a7365e98SRichard Henderson if (fpkind != FPSTATE_FSAVE) { 754*a7365e98SRichard Henderson math_size += sizeof(struct target_fregs_state); 755*a7365e98SRichard Henderson } 756*a7365e98SRichard Henderson #endif 757*a7365e98SRichard Henderson fpstate = lock_user(VERIFY_READ, fpstate_addr, math_size, 1); 758*a7365e98SRichard Henderson if (!fpstate) { 759c536f9b7SRichard Henderson return false; 760c7169b02SRichard Henderson } 761a075f313SLaurent Vivier 762*a7365e98SRichard Henderson #ifdef TARGET_X86_64 763*a7365e98SRichard Henderson ok = xrstor_sigcontext(env, fpkind, fpstate, fpstate_addr); 764*a7365e98SRichard Henderson #else 765*a7365e98SRichard Henderson ok = frstor_sigcontext(env, fpkind, fpstate, fpstate_addr, 766*a7365e98SRichard Henderson fpstate + sizeof(struct target_fregs_state), 767*a7365e98SRichard Henderson fpstate_addr + sizeof(struct target_fregs_state)); 768*a7365e98SRichard Henderson #endif 769*a7365e98SRichard Henderson 770*a7365e98SRichard Henderson unlock_user(fpstate, fpstate_addr, 0); 771c536f9b7SRichard Henderson return ok; 772a075f313SLaurent Vivier } 773a075f313SLaurent Vivier 774a075f313SLaurent Vivier /* Note: there is no sigreturn on x86_64, there is only rt_sigreturn */ 775a075f313SLaurent Vivier #ifndef TARGET_X86_64 776a075f313SLaurent Vivier long do_sigreturn(CPUX86State *env) 777a075f313SLaurent Vivier { 778a075f313SLaurent Vivier struct sigframe *frame; 779a075f313SLaurent Vivier abi_ulong frame_addr = env->regs[R_ESP] - 8; 780a075f313SLaurent Vivier target_sigset_t target_set; 781a075f313SLaurent Vivier sigset_t set; 782a075f313SLaurent Vivier 783a075f313SLaurent Vivier trace_user_do_sigreturn(env, frame_addr); 784*a7365e98SRichard Henderson if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { 785*a7365e98SRichard Henderson force_sig(TARGET_SIGSEGV); 786*a7365e98SRichard Henderson return -QEMU_ESIGRETURN; 787a075f313SLaurent Vivier } 788a075f313SLaurent Vivier 789*a7365e98SRichard Henderson /* Set blocked signals. */ 790*a7365e98SRichard Henderson __get_user(target_set.sig[0], &frame->sc.oldmask); 791*a7365e98SRichard Henderson for (int i = 1; i < TARGET_NSIG_WORDS; i++) { 792*a7365e98SRichard Henderson __get_user(target_set.sig[i], &frame->extramask[i - 1]); 793*a7365e98SRichard Henderson } 794a075f313SLaurent Vivier target_to_host_sigset_internal(&set, &target_set); 795a075f313SLaurent Vivier set_sigmask(&set); 796a075f313SLaurent Vivier 797*a7365e98SRichard Henderson /* Restore registers */ 798c536f9b7SRichard Henderson if (!restore_sigcontext(env, &frame->sc)) { 799a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 800*a7365e98SRichard Henderson } 801*a7365e98SRichard Henderson 802*a7365e98SRichard Henderson unlock_user_struct(frame, frame_addr, 0); 80357a0c938SRichard Henderson return -QEMU_ESIGRETURN; 804a075f313SLaurent Vivier } 805a075f313SLaurent Vivier #endif 806a075f313SLaurent Vivier 807a075f313SLaurent Vivier long do_rt_sigreturn(CPUX86State *env) 808a075f313SLaurent Vivier { 809a075f313SLaurent Vivier abi_ulong frame_addr; 810a075f313SLaurent Vivier struct rt_sigframe *frame; 811a075f313SLaurent Vivier sigset_t set; 812a075f313SLaurent Vivier 813a075f313SLaurent Vivier frame_addr = env->regs[R_ESP] - sizeof(abi_ulong); 814a075f313SLaurent Vivier trace_user_do_rt_sigreturn(env, frame_addr); 815a075f313SLaurent Vivier if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 816a075f313SLaurent Vivier goto badframe; 817a075f313SLaurent Vivier target_to_host_sigset(&set, &frame->uc.tuc_sigmask); 818a075f313SLaurent Vivier set_sigmask(&set); 819a075f313SLaurent Vivier 820c536f9b7SRichard Henderson if (!restore_sigcontext(env, &frame->uc.tuc_mcontext)) { 821a075f313SLaurent Vivier goto badframe; 822a075f313SLaurent Vivier } 823a075f313SLaurent Vivier 824ddc3e74dSRichard Henderson target_restore_altstack(&frame->uc.tuc_stack, env); 825a075f313SLaurent Vivier 826a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 82757a0c938SRichard Henderson return -QEMU_ESIGRETURN; 828a075f313SLaurent Vivier 829a075f313SLaurent Vivier badframe: 830a075f313SLaurent Vivier unlock_user_struct(frame, frame_addr, 0); 831a075f313SLaurent Vivier force_sig(TARGET_SIGSEGV); 83257a0c938SRichard Henderson return -QEMU_ESIGRETURN; 833a075f313SLaurent Vivier } 8348ee8a104SRichard Henderson 8358ee8a104SRichard Henderson #ifndef TARGET_X86_64 8368ee8a104SRichard Henderson void setup_sigtramp(abi_ulong sigtramp_page) 8378ee8a104SRichard Henderson { 8388ee8a104SRichard Henderson uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); 8398ee8a104SRichard Henderson assert(tramp != NULL); 8408ee8a104SRichard Henderson 8418ee8a104SRichard Henderson default_sigreturn = sigtramp_page; 8428ee8a104SRichard Henderson install_sigtramp(tramp); 8438ee8a104SRichard Henderson 8448ee8a104SRichard Henderson default_rt_sigreturn = sigtramp_page + 8; 8458ee8a104SRichard Henderson install_rt_sigtramp(tramp + 8); 8468ee8a104SRichard Henderson 8478ee8a104SRichard Henderson unlock_user(tramp, sigtramp_page, 2 * 8); 8488ee8a104SRichard Henderson } 8498ee8a104SRichard Henderson #endif 850