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