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 */ 199340eddaSLaurent Vivier #include "qemu/osdep.h" 209340eddaSLaurent Vivier #include "qemu.h" 213b249d26SPeter Maydell #include "user-internals.h" 229340eddaSLaurent Vivier #include "signal-common.h" 239340eddaSLaurent Vivier #include "linux-user/trace.h" 249340eddaSLaurent Vivier 259340eddaSLaurent Vivier /* Size of dummy stack frame allocated when calling signal handler. 269340eddaSLaurent Vivier See arch/powerpc/include/asm/ptrace.h. */ 279340eddaSLaurent Vivier #if defined(TARGET_PPC64) 289340eddaSLaurent Vivier #define SIGNAL_FRAMESIZE 128 299340eddaSLaurent Vivier #else 309340eddaSLaurent Vivier #define SIGNAL_FRAMESIZE 64 319340eddaSLaurent Vivier #endif 329340eddaSLaurent Vivier 339340eddaSLaurent Vivier /* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC; 349340eddaSLaurent Vivier on 64-bit PPC, sigcontext and mcontext are one and the same. */ 359340eddaSLaurent Vivier struct target_mcontext { 369340eddaSLaurent Vivier target_ulong mc_gregs[48]; 379340eddaSLaurent Vivier /* Includes fpscr. */ 389340eddaSLaurent Vivier uint64_t mc_fregs[33]; 395da5f47eSRichard Henderson 409340eddaSLaurent Vivier #if defined(TARGET_PPC64) 419340eddaSLaurent Vivier /* Pointer to the vector regs */ 429340eddaSLaurent Vivier target_ulong v_regs; 435da5f47eSRichard Henderson /* 445da5f47eSRichard Henderson * On ppc64, this mcontext structure is naturally *unaligned*, 455da5f47eSRichard Henderson * or rather it is aligned on a 8 bytes boundary but not on 465da5f47eSRichard Henderson * a 16 byte boundary. This pad fixes it up. This is why we 475da5f47eSRichard Henderson * cannot use ppc_avr_t, which would force alignment. This is 485da5f47eSRichard Henderson * also why the vector regs are referenced in the ABI by the 495da5f47eSRichard Henderson * v_regs pointer above so any amount of padding can be added here. 505da5f47eSRichard Henderson */ 515da5f47eSRichard Henderson target_ulong pad; 525da5f47eSRichard Henderson /* VSCR and VRSAVE are saved separately. Also reserve space for VSX. */ 535da5f47eSRichard Henderson struct { 545da5f47eSRichard Henderson uint64_t altivec[34 + 16][2]; 555da5f47eSRichard Henderson } mc_vregs; 569340eddaSLaurent Vivier #else 579340eddaSLaurent Vivier target_ulong mc_pad[2]; 585da5f47eSRichard Henderson 599340eddaSLaurent Vivier /* We need to handle Altivec and SPE at the same time, which no 609340eddaSLaurent Vivier kernel needs to do. Fortunately, the kernel defines this bit to 619340eddaSLaurent Vivier be Altivec-register-large all the time, rather than trying to 629340eddaSLaurent Vivier twiddle it based on the specific platform. */ 639340eddaSLaurent Vivier union { 649340eddaSLaurent Vivier /* SPE vector registers. One extra for SPEFSCR. */ 659340eddaSLaurent Vivier uint32_t spe[33]; 665da5f47eSRichard Henderson /* 675da5f47eSRichard Henderson * Altivec vector registers. One extra for VRSAVE. 685da5f47eSRichard Henderson * On ppc32, we are already aligned to 16 bytes. We could 695da5f47eSRichard Henderson * use ppc_avr_t, but choose to share the same type as ppc64. 709340eddaSLaurent Vivier */ 715da5f47eSRichard Henderson uint64_t altivec[33][2]; 729340eddaSLaurent Vivier } mc_vregs; 735da5f47eSRichard Henderson #endif 749340eddaSLaurent Vivier }; 759340eddaSLaurent Vivier 769340eddaSLaurent Vivier /* See arch/powerpc/include/asm/sigcontext.h. */ 779340eddaSLaurent Vivier struct target_sigcontext { 789340eddaSLaurent Vivier target_ulong _unused[4]; 799340eddaSLaurent Vivier int32_t signal; 809340eddaSLaurent Vivier #if defined(TARGET_PPC64) 819340eddaSLaurent Vivier int32_t pad0; 829340eddaSLaurent Vivier #endif 839340eddaSLaurent Vivier target_ulong handler; 849340eddaSLaurent Vivier target_ulong oldmask; 859340eddaSLaurent Vivier target_ulong regs; /* struct pt_regs __user * */ 869340eddaSLaurent Vivier #if defined(TARGET_PPC64) 879340eddaSLaurent Vivier struct target_mcontext mcontext; 889340eddaSLaurent Vivier #endif 899340eddaSLaurent Vivier }; 909340eddaSLaurent Vivier 919340eddaSLaurent Vivier /* Indices for target_mcontext.mc_gregs, below. 929340eddaSLaurent Vivier See arch/powerpc/include/asm/ptrace.h for details. */ 939340eddaSLaurent Vivier enum { 949340eddaSLaurent Vivier TARGET_PT_R0 = 0, 959340eddaSLaurent Vivier TARGET_PT_R1 = 1, 969340eddaSLaurent Vivier TARGET_PT_R2 = 2, 979340eddaSLaurent Vivier TARGET_PT_R3 = 3, 989340eddaSLaurent Vivier TARGET_PT_R4 = 4, 999340eddaSLaurent Vivier TARGET_PT_R5 = 5, 1009340eddaSLaurent Vivier TARGET_PT_R6 = 6, 1019340eddaSLaurent Vivier TARGET_PT_R7 = 7, 1029340eddaSLaurent Vivier TARGET_PT_R8 = 8, 1039340eddaSLaurent Vivier TARGET_PT_R9 = 9, 1049340eddaSLaurent Vivier TARGET_PT_R10 = 10, 1059340eddaSLaurent Vivier TARGET_PT_R11 = 11, 1069340eddaSLaurent Vivier TARGET_PT_R12 = 12, 1079340eddaSLaurent Vivier TARGET_PT_R13 = 13, 1089340eddaSLaurent Vivier TARGET_PT_R14 = 14, 1099340eddaSLaurent Vivier TARGET_PT_R15 = 15, 1109340eddaSLaurent Vivier TARGET_PT_R16 = 16, 1119340eddaSLaurent Vivier TARGET_PT_R17 = 17, 1129340eddaSLaurent Vivier TARGET_PT_R18 = 18, 1139340eddaSLaurent Vivier TARGET_PT_R19 = 19, 1149340eddaSLaurent Vivier TARGET_PT_R20 = 20, 1159340eddaSLaurent Vivier TARGET_PT_R21 = 21, 1169340eddaSLaurent Vivier TARGET_PT_R22 = 22, 1179340eddaSLaurent Vivier TARGET_PT_R23 = 23, 1189340eddaSLaurent Vivier TARGET_PT_R24 = 24, 1199340eddaSLaurent Vivier TARGET_PT_R25 = 25, 1209340eddaSLaurent Vivier TARGET_PT_R26 = 26, 1219340eddaSLaurent Vivier TARGET_PT_R27 = 27, 1229340eddaSLaurent Vivier TARGET_PT_R28 = 28, 1239340eddaSLaurent Vivier TARGET_PT_R29 = 29, 1249340eddaSLaurent Vivier TARGET_PT_R30 = 30, 1259340eddaSLaurent Vivier TARGET_PT_R31 = 31, 1269340eddaSLaurent Vivier TARGET_PT_NIP = 32, 1279340eddaSLaurent Vivier TARGET_PT_MSR = 33, 1289340eddaSLaurent Vivier TARGET_PT_ORIG_R3 = 34, 1299340eddaSLaurent Vivier TARGET_PT_CTR = 35, 1309340eddaSLaurent Vivier TARGET_PT_LNK = 36, 1319340eddaSLaurent Vivier TARGET_PT_XER = 37, 1329340eddaSLaurent Vivier TARGET_PT_CCR = 38, 1339340eddaSLaurent Vivier /* Yes, there are two registers with #39. One is 64-bit only. */ 1349340eddaSLaurent Vivier TARGET_PT_MQ = 39, 1359340eddaSLaurent Vivier TARGET_PT_SOFTE = 39, 1369340eddaSLaurent Vivier TARGET_PT_TRAP = 40, 1379340eddaSLaurent Vivier TARGET_PT_DAR = 41, 1389340eddaSLaurent Vivier TARGET_PT_DSISR = 42, 1399340eddaSLaurent Vivier TARGET_PT_RESULT = 43, 1409340eddaSLaurent Vivier TARGET_PT_REGS_COUNT = 44 1419340eddaSLaurent Vivier }; 1429340eddaSLaurent Vivier 1439340eddaSLaurent Vivier 1449340eddaSLaurent Vivier struct target_ucontext { 1459340eddaSLaurent Vivier target_ulong tuc_flags; 1469340eddaSLaurent Vivier target_ulong tuc_link; /* ucontext_t __user * */ 1479340eddaSLaurent Vivier struct target_sigaltstack tuc_stack; 1489340eddaSLaurent Vivier #if !defined(TARGET_PPC64) 1499340eddaSLaurent Vivier int32_t tuc_pad[7]; 1509340eddaSLaurent Vivier target_ulong tuc_regs; /* struct mcontext __user * 1519340eddaSLaurent Vivier points to uc_mcontext field */ 1529340eddaSLaurent Vivier #endif 1539340eddaSLaurent Vivier target_sigset_t tuc_sigmask; 1549340eddaSLaurent Vivier #if defined(TARGET_PPC64) 1559340eddaSLaurent Vivier target_sigset_t unused[15]; /* Allow for uc_sigmask growth */ 1569340eddaSLaurent Vivier struct target_sigcontext tuc_sigcontext; 1579340eddaSLaurent Vivier #else 1589340eddaSLaurent Vivier int32_t tuc_maskext[30]; 1599340eddaSLaurent Vivier int32_t tuc_pad2[3]; 1609340eddaSLaurent Vivier struct target_mcontext tuc_mcontext; 1619340eddaSLaurent Vivier #endif 1629340eddaSLaurent Vivier }; 1639340eddaSLaurent Vivier 1649340eddaSLaurent Vivier /* See arch/powerpc/kernel/signal_32.c. */ 1659340eddaSLaurent Vivier struct target_sigframe { 1669340eddaSLaurent Vivier struct target_sigcontext sctx; 1679340eddaSLaurent Vivier struct target_mcontext mctx; 1689340eddaSLaurent Vivier int32_t abigap[56]; 1699340eddaSLaurent Vivier }; 1709340eddaSLaurent Vivier 1719340eddaSLaurent Vivier #if defined(TARGET_PPC64) 1729340eddaSLaurent Vivier 1739340eddaSLaurent Vivier #define TARGET_TRAMP_SIZE 6 1749340eddaSLaurent Vivier 1759340eddaSLaurent Vivier struct target_rt_sigframe { 1769340eddaSLaurent Vivier /* sys_rt_sigreturn requires the ucontext be the first field */ 1779340eddaSLaurent Vivier struct target_ucontext uc; 1789340eddaSLaurent Vivier target_ulong _unused[2]; 1799340eddaSLaurent Vivier uint32_t trampoline[TARGET_TRAMP_SIZE]; 1809340eddaSLaurent Vivier target_ulong pinfo; /* struct siginfo __user * */ 1819340eddaSLaurent Vivier target_ulong puc; /* void __user * */ 1829340eddaSLaurent Vivier struct target_siginfo info; 1839340eddaSLaurent Vivier /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ 1849340eddaSLaurent Vivier char abigap[288]; 1859340eddaSLaurent Vivier } __attribute__((aligned(16))); 1869340eddaSLaurent Vivier 1879340eddaSLaurent Vivier #else 1889340eddaSLaurent Vivier 1899340eddaSLaurent Vivier struct target_rt_sigframe { 1909340eddaSLaurent Vivier struct target_siginfo info; 1919340eddaSLaurent Vivier struct target_ucontext uc; 1929340eddaSLaurent Vivier int32_t abigap[56]; 1939340eddaSLaurent Vivier }; 1949340eddaSLaurent Vivier 1959340eddaSLaurent Vivier #endif 1969340eddaSLaurent Vivier 1979340eddaSLaurent Vivier #if defined(TARGET_PPC64) 1989340eddaSLaurent Vivier 1999340eddaSLaurent Vivier struct target_func_ptr { 2009340eddaSLaurent Vivier target_ulong entry; 2019340eddaSLaurent Vivier target_ulong toc; 2029340eddaSLaurent Vivier }; 2039340eddaSLaurent Vivier 2049340eddaSLaurent Vivier #endif 2059340eddaSLaurent Vivier 2069340eddaSLaurent Vivier /* See arch/powerpc/kernel/signal.c. */ 2079340eddaSLaurent Vivier static target_ulong get_sigframe(struct target_sigaction *ka, 2089340eddaSLaurent Vivier CPUPPCState *env, 2099340eddaSLaurent Vivier int frame_size) 2109340eddaSLaurent Vivier { 2119340eddaSLaurent Vivier target_ulong oldsp; 2129340eddaSLaurent Vivier 213465e237bSLaurent Vivier oldsp = target_sigsp(get_sp_from_cpustate(env), ka); 2149340eddaSLaurent Vivier 2159340eddaSLaurent Vivier return (oldsp - frame_size) & ~0xFUL; 2169340eddaSLaurent Vivier } 2179340eddaSLaurent Vivier 2189340eddaSLaurent Vivier #if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \ 2199340eddaSLaurent Vivier (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN))) 2209340eddaSLaurent Vivier #define PPC_VEC_HI 0 2219340eddaSLaurent Vivier #define PPC_VEC_LO 1 2229340eddaSLaurent Vivier #else 2239340eddaSLaurent Vivier #define PPC_VEC_HI 1 2249340eddaSLaurent Vivier #define PPC_VEC_LO 0 2259340eddaSLaurent Vivier #endif 2269340eddaSLaurent Vivier 2279340eddaSLaurent Vivier 2289340eddaSLaurent Vivier static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame) 2299340eddaSLaurent Vivier { 2309340eddaSLaurent Vivier target_ulong msr = env->msr; 2319340eddaSLaurent Vivier int i; 2329340eddaSLaurent Vivier target_ulong ccr = 0; 2339340eddaSLaurent Vivier 2349340eddaSLaurent Vivier /* In general, the kernel attempts to be intelligent about what it 2359340eddaSLaurent Vivier needs to save for Altivec/FP/SPE registers. We don't care that 2369340eddaSLaurent Vivier much, so we just go ahead and save everything. */ 2379340eddaSLaurent Vivier 2389340eddaSLaurent Vivier /* Save general registers. */ 2399340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 2409340eddaSLaurent Vivier __put_user(env->gpr[i], &frame->mc_gregs[i]); 2419340eddaSLaurent Vivier } 2429340eddaSLaurent Vivier __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]); 2439340eddaSLaurent Vivier __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]); 2449340eddaSLaurent Vivier __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]); 24566c6b40aSMatheus Ferst __put_user(cpu_read_xer(env), &frame->mc_gregs[TARGET_PT_XER]); 2469340eddaSLaurent Vivier 2479340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->crf); i++) { 2489340eddaSLaurent Vivier ccr |= env->crf[i] << (32 - ((i + 1) * 4)); 2499340eddaSLaurent Vivier } 2509340eddaSLaurent Vivier __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]); 2519340eddaSLaurent Vivier 2529340eddaSLaurent Vivier /* Save Altivec registers if necessary. */ 2539340eddaSLaurent Vivier if (env->insns_flags & PPC_ALTIVEC) { 2549340eddaSLaurent Vivier uint32_t *vrsave; 255ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 256ef96e3aeSMark Cave-Ayland ppc_avr_t *avr = cpu_avr_ptr(env, i); 2579340eddaSLaurent Vivier ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i]; 2589340eddaSLaurent Vivier 2599340eddaSLaurent Vivier __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]); 2609340eddaSLaurent Vivier __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]); 2619340eddaSLaurent Vivier } 2629340eddaSLaurent Vivier #if defined(TARGET_PPC64) 2639340eddaSLaurent Vivier vrsave = (uint32_t *)&frame->mc_vregs.altivec[33]; 2649340eddaSLaurent Vivier /* 64-bit needs to put a pointer to the vectors in the frame */ 2659340eddaSLaurent Vivier __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs); 2669340eddaSLaurent Vivier #else 2679340eddaSLaurent Vivier vrsave = (uint32_t *)&frame->mc_vregs.altivec[32]; 2689340eddaSLaurent Vivier #endif 2699340eddaSLaurent Vivier __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave); 2709340eddaSLaurent Vivier } 2719340eddaSLaurent Vivier 2725da5f47eSRichard Henderson #if defined(TARGET_PPC64) 2739340eddaSLaurent Vivier /* Save VSX second halves */ 2749340eddaSLaurent Vivier if (env->insns_flags2 & PPC2_VSX) { 2759340eddaSLaurent Vivier uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; 276ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 277ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(env, i); 278ef96e3aeSMark Cave-Ayland __put_user(*vsrl, &vsregs[i]); 2799340eddaSLaurent Vivier } 2809340eddaSLaurent Vivier } 2815da5f47eSRichard Henderson #endif 2829340eddaSLaurent Vivier 2839340eddaSLaurent Vivier /* Save floating point registers. */ 2849340eddaSLaurent Vivier if (env->insns_flags & PPC_FLOAT) { 285ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 286ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(env, i); 287ef96e3aeSMark Cave-Ayland __put_user(*fpr, &frame->mc_fregs[i]); 2889340eddaSLaurent Vivier } 2899340eddaSLaurent Vivier __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]); 2909340eddaSLaurent Vivier } 2919340eddaSLaurent Vivier 2925da5f47eSRichard Henderson #if !defined(TARGET_PPC64) 2939340eddaSLaurent Vivier /* Save SPE registers. The kernel only saves the high half. */ 2949340eddaSLaurent Vivier if (env->insns_flags & PPC_SPE) { 2959340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { 2969340eddaSLaurent Vivier __put_user(env->gprh[i], &frame->mc_vregs.spe[i]); 2979340eddaSLaurent Vivier } 2989340eddaSLaurent Vivier __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]); 2999340eddaSLaurent Vivier } 3005da5f47eSRichard Henderson #endif 3019340eddaSLaurent Vivier 3029340eddaSLaurent Vivier /* Store MSR. */ 3039340eddaSLaurent Vivier __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]); 3049340eddaSLaurent Vivier } 3059340eddaSLaurent Vivier 3069340eddaSLaurent Vivier static void encode_trampoline(int sigret, uint32_t *tramp) 3079340eddaSLaurent Vivier { 3089340eddaSLaurent Vivier /* Set up the sigreturn trampoline: li r0,sigret; sc. */ 3099340eddaSLaurent Vivier __put_user(0x38000000 | sigret, &tramp[0]); 3109340eddaSLaurent Vivier __put_user(0x44000002, &tramp[1]); 3119340eddaSLaurent Vivier } 3129340eddaSLaurent Vivier 3139340eddaSLaurent Vivier static void restore_user_regs(CPUPPCState *env, 3149340eddaSLaurent Vivier struct target_mcontext *frame, int sig) 3159340eddaSLaurent Vivier { 3169340eddaSLaurent Vivier target_ulong save_r2 = 0; 3179340eddaSLaurent Vivier target_ulong msr; 31866c6b40aSMatheus Ferst target_ulong xer; 3199340eddaSLaurent Vivier target_ulong ccr; 3209340eddaSLaurent Vivier 3219340eddaSLaurent Vivier int i; 3229340eddaSLaurent Vivier 3239340eddaSLaurent Vivier if (!sig) { 3249340eddaSLaurent Vivier save_r2 = env->gpr[2]; 3259340eddaSLaurent Vivier } 3269340eddaSLaurent Vivier 3279340eddaSLaurent Vivier /* Restore general registers. */ 3289340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 3299340eddaSLaurent Vivier __get_user(env->gpr[i], &frame->mc_gregs[i]); 3309340eddaSLaurent Vivier } 3319340eddaSLaurent Vivier __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]); 3329340eddaSLaurent Vivier __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]); 3339340eddaSLaurent Vivier __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]); 3349340eddaSLaurent Vivier 33566c6b40aSMatheus Ferst __get_user(xer, &frame->mc_gregs[TARGET_PT_XER]); 33666c6b40aSMatheus Ferst cpu_write_xer(env, xer); 33766c6b40aSMatheus Ferst 33866c6b40aSMatheus Ferst __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]); 3399340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->crf); i++) { 3409340eddaSLaurent Vivier env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf; 3419340eddaSLaurent Vivier } 3429340eddaSLaurent Vivier 3439340eddaSLaurent Vivier if (!sig) { 3449340eddaSLaurent Vivier env->gpr[2] = save_r2; 3459340eddaSLaurent Vivier } 3469340eddaSLaurent Vivier /* Restore MSR. */ 3479340eddaSLaurent Vivier __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]); 3489340eddaSLaurent Vivier 3499340eddaSLaurent Vivier /* If doing signal return, restore the previous little-endian mode. */ 35075da4997SRichard Henderson if (sig) { 35175da4997SRichard Henderson ppc_store_msr(env, ((env->msr & ~(1ull << MSR_LE)) | 35275da4997SRichard Henderson (msr & (1ull << MSR_LE)))); 35375da4997SRichard Henderson } 3549340eddaSLaurent Vivier 3559340eddaSLaurent Vivier /* Restore Altivec registers if necessary. */ 3569340eddaSLaurent Vivier if (env->insns_flags & PPC_ALTIVEC) { 3579340eddaSLaurent Vivier ppc_avr_t *v_regs; 3589340eddaSLaurent Vivier uint32_t *vrsave; 3599340eddaSLaurent Vivier #if defined(TARGET_PPC64) 3609340eddaSLaurent Vivier uint64_t v_addr; 3619340eddaSLaurent Vivier /* 64-bit needs to recover the pointer to the vectors from the frame */ 3629340eddaSLaurent Vivier __get_user(v_addr, &frame->v_regs); 3633e8f1628SRichard Henderson v_regs = g2h(env_cpu(env), v_addr); 3649340eddaSLaurent Vivier #else 3659340eddaSLaurent Vivier v_regs = (ppc_avr_t *)frame->mc_vregs.altivec; 3669340eddaSLaurent Vivier #endif 367ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 368ef96e3aeSMark Cave-Ayland ppc_avr_t *avr = cpu_avr_ptr(env, i); 3699340eddaSLaurent Vivier ppc_avr_t *vreg = &v_regs[i]; 3709340eddaSLaurent Vivier 3719340eddaSLaurent Vivier __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]); 3729340eddaSLaurent Vivier __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]); 3739340eddaSLaurent Vivier } 3749340eddaSLaurent Vivier #if defined(TARGET_PPC64) 3759340eddaSLaurent Vivier vrsave = (uint32_t *)&v_regs[33]; 3769340eddaSLaurent Vivier #else 3779340eddaSLaurent Vivier vrsave = (uint32_t *)&v_regs[32]; 3789340eddaSLaurent Vivier #endif 3799340eddaSLaurent Vivier __get_user(env->spr[SPR_VRSAVE], vrsave); 3809340eddaSLaurent Vivier } 3819340eddaSLaurent Vivier 3825da5f47eSRichard Henderson #if defined(TARGET_PPC64) 3839340eddaSLaurent Vivier /* Restore VSX second halves */ 3849340eddaSLaurent Vivier if (env->insns_flags2 & PPC2_VSX) { 3859340eddaSLaurent Vivier uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; 386ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 387ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(env, i); 388ef96e3aeSMark Cave-Ayland __get_user(*vsrl, &vsregs[i]); 3899340eddaSLaurent Vivier } 3909340eddaSLaurent Vivier } 3915da5f47eSRichard Henderson #endif 3929340eddaSLaurent Vivier 3939340eddaSLaurent Vivier /* Restore floating point registers. */ 3949340eddaSLaurent Vivier if (env->insns_flags & PPC_FLOAT) { 3959340eddaSLaurent Vivier uint64_t fpscr; 396ef96e3aeSMark Cave-Ayland for (i = 0; i < 32; i++) { 397ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(env, i); 398ef96e3aeSMark Cave-Ayland __get_user(*fpr, &frame->mc_fregs[i]); 3999340eddaSLaurent Vivier } 4009340eddaSLaurent Vivier __get_user(fpscr, &frame->mc_fregs[32]); 4019340eddaSLaurent Vivier env->fpscr = (uint32_t) fpscr; 4029340eddaSLaurent Vivier } 4039340eddaSLaurent Vivier 4045da5f47eSRichard Henderson #if !defined(TARGET_PPC64) 4059340eddaSLaurent Vivier /* Save SPE registers. The kernel only saves the high half. */ 4069340eddaSLaurent Vivier if (env->insns_flags & PPC_SPE) { 4079340eddaSLaurent Vivier for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { 4089340eddaSLaurent Vivier __get_user(env->gprh[i], &frame->mc_vregs.spe[i]); 4099340eddaSLaurent Vivier } 4109340eddaSLaurent Vivier __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]); 4119340eddaSLaurent Vivier } 4125da5f47eSRichard Henderson #endif 4139340eddaSLaurent Vivier } 4149340eddaSLaurent Vivier 4159340eddaSLaurent Vivier #if !defined(TARGET_PPC64) 4169340eddaSLaurent Vivier void setup_frame(int sig, struct target_sigaction *ka, 4179340eddaSLaurent Vivier target_sigset_t *set, CPUPPCState *env) 4189340eddaSLaurent Vivier { 4199340eddaSLaurent Vivier struct target_sigframe *frame; 4209340eddaSLaurent Vivier struct target_sigcontext *sc; 4219340eddaSLaurent Vivier target_ulong frame_addr, newsp; 4229340eddaSLaurent Vivier int err = 0; 4239340eddaSLaurent Vivier 4249340eddaSLaurent Vivier frame_addr = get_sigframe(ka, env, sizeof(*frame)); 4259340eddaSLaurent Vivier trace_user_setup_frame(env, frame_addr); 4269340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) 4279340eddaSLaurent Vivier goto sigsegv; 4289340eddaSLaurent Vivier sc = &frame->sctx; 4299340eddaSLaurent Vivier 4309340eddaSLaurent Vivier __put_user(ka->_sa_handler, &sc->handler); 4319340eddaSLaurent Vivier __put_user(set->sig[0], &sc->oldmask); 4329340eddaSLaurent Vivier __put_user(set->sig[1], &sc->_unused[3]); 4339340eddaSLaurent Vivier __put_user(h2g(&frame->mctx), &sc->regs); 4349340eddaSLaurent Vivier __put_user(sig, &sc->signal); 4359340eddaSLaurent Vivier 4369340eddaSLaurent Vivier /* Save user regs. */ 4379340eddaSLaurent Vivier save_user_regs(env, &frame->mctx); 4389340eddaSLaurent Vivier 439c790e4ebSRichard Henderson env->lr = default_sigreturn; 4409340eddaSLaurent Vivier 4419340eddaSLaurent Vivier /* Turn off all fp exceptions. */ 4429340eddaSLaurent Vivier env->fpscr = 0; 4439340eddaSLaurent Vivier 4449340eddaSLaurent Vivier /* Create a stack frame for the caller of the handler. */ 4459340eddaSLaurent Vivier newsp = frame_addr - SIGNAL_FRAMESIZE; 4469340eddaSLaurent Vivier err |= put_user(env->gpr[1], newsp, target_ulong); 4479340eddaSLaurent Vivier 4489340eddaSLaurent Vivier if (err) 4499340eddaSLaurent Vivier goto sigsegv; 4509340eddaSLaurent Vivier 4519340eddaSLaurent Vivier /* Set up registers for signal handler. */ 4529340eddaSLaurent Vivier env->gpr[1] = newsp; 4539340eddaSLaurent Vivier env->gpr[3] = sig; 4549340eddaSLaurent Vivier env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx); 4559340eddaSLaurent Vivier 4569340eddaSLaurent Vivier env->nip = (target_ulong) ka->_sa_handler; 4579340eddaSLaurent Vivier 4589340eddaSLaurent Vivier /* Signal handlers are entered in big-endian mode. */ 45975da4997SRichard Henderson ppc_store_msr(env, env->msr & ~(1ull << MSR_LE)); 4609340eddaSLaurent Vivier 4619340eddaSLaurent Vivier unlock_user_struct(frame, frame_addr, 1); 4629340eddaSLaurent Vivier return; 4639340eddaSLaurent Vivier 4649340eddaSLaurent Vivier sigsegv: 4659340eddaSLaurent Vivier unlock_user_struct(frame, frame_addr, 1); 4669340eddaSLaurent Vivier force_sigsegv(sig); 4679340eddaSLaurent Vivier } 4689340eddaSLaurent Vivier #endif /* !defined(TARGET_PPC64) */ 4699340eddaSLaurent Vivier 4709340eddaSLaurent Vivier void setup_rt_frame(int sig, struct target_sigaction *ka, 4719340eddaSLaurent Vivier target_siginfo_t *info, 4729340eddaSLaurent Vivier target_sigset_t *set, CPUPPCState *env) 4739340eddaSLaurent Vivier { 4749340eddaSLaurent Vivier struct target_rt_sigframe *rt_sf; 4759340eddaSLaurent Vivier struct target_mcontext *mctx = 0; 4769340eddaSLaurent Vivier target_ulong rt_sf_addr, newsp = 0; 4779340eddaSLaurent Vivier int i, err = 0; 4789340eddaSLaurent Vivier #if defined(TARGET_PPC64) 4799340eddaSLaurent Vivier struct target_sigcontext *sc = 0; 4809340eddaSLaurent Vivier struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; 4819340eddaSLaurent Vivier #endif 4829340eddaSLaurent Vivier 4839340eddaSLaurent Vivier rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf)); 4849340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1)) 4859340eddaSLaurent Vivier goto sigsegv; 4869340eddaSLaurent Vivier 4879340eddaSLaurent Vivier tswap_siginfo(&rt_sf->info, info); 4889340eddaSLaurent Vivier 4899340eddaSLaurent Vivier __put_user(0, &rt_sf->uc.tuc_flags); 4909340eddaSLaurent Vivier __put_user(0, &rt_sf->uc.tuc_link); 491465e237bSLaurent Vivier target_save_altstack(&rt_sf->uc.tuc_stack, env); 4929340eddaSLaurent Vivier #if !defined(TARGET_PPC64) 4939340eddaSLaurent Vivier __put_user(h2g (&rt_sf->uc.tuc_mcontext), 4949340eddaSLaurent Vivier &rt_sf->uc.tuc_regs); 4959340eddaSLaurent Vivier #endif 4969340eddaSLaurent Vivier for(i = 0; i < TARGET_NSIG_WORDS; i++) { 4979340eddaSLaurent Vivier __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]); 4989340eddaSLaurent Vivier } 4999340eddaSLaurent Vivier 5009340eddaSLaurent Vivier #if defined(TARGET_PPC64) 5019340eddaSLaurent Vivier mctx = &rt_sf->uc.tuc_sigcontext.mcontext; 5029340eddaSLaurent Vivier 5039340eddaSLaurent Vivier sc = &rt_sf->uc.tuc_sigcontext; 5049340eddaSLaurent Vivier __put_user(h2g(mctx), &sc->regs); 5059340eddaSLaurent Vivier __put_user(sig, &sc->signal); 5069340eddaSLaurent Vivier #else 5079340eddaSLaurent Vivier mctx = &rt_sf->uc.tuc_mcontext; 5089340eddaSLaurent Vivier #endif 5099340eddaSLaurent Vivier 5109340eddaSLaurent Vivier save_user_regs(env, mctx); 5119340eddaSLaurent Vivier 512c790e4ebSRichard Henderson env->lr = default_rt_sigreturn; 5139340eddaSLaurent Vivier 5149340eddaSLaurent Vivier /* Turn off all fp exceptions. */ 5159340eddaSLaurent Vivier env->fpscr = 0; 5169340eddaSLaurent Vivier 5179340eddaSLaurent Vivier /* Create a stack frame for the caller of the handler. */ 5189340eddaSLaurent Vivier newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16); 5199340eddaSLaurent Vivier err |= put_user(env->gpr[1], newsp, target_ulong); 5209340eddaSLaurent Vivier 5219340eddaSLaurent Vivier if (err) 5229340eddaSLaurent Vivier goto sigsegv; 5239340eddaSLaurent Vivier 5249340eddaSLaurent Vivier /* Set up registers for signal handler. */ 5259340eddaSLaurent Vivier env->gpr[1] = newsp; 5269340eddaSLaurent Vivier env->gpr[3] = (target_ulong) sig; 5279340eddaSLaurent Vivier env->gpr[4] = (target_ulong) h2g(&rt_sf->info); 5289340eddaSLaurent Vivier env->gpr[5] = (target_ulong) h2g(&rt_sf->uc); 5299340eddaSLaurent Vivier env->gpr[6] = (target_ulong) h2g(rt_sf); 5309340eddaSLaurent Vivier 531*74154d7eSThomas Huth #if defined(TARGET_PPC64) 5329340eddaSLaurent Vivier if (get_ppc64_abi(image) < 2) { 5339340eddaSLaurent Vivier /* ELFv1 PPC64 function pointers are pointers to OPD entries. */ 5349340eddaSLaurent Vivier struct target_func_ptr *handler = 5353e8f1628SRichard Henderson (struct target_func_ptr *)g2h(env_cpu(env), ka->_sa_handler); 5369340eddaSLaurent Vivier env->nip = tswapl(handler->entry); 5379340eddaSLaurent Vivier env->gpr[2] = tswapl(handler->toc); 5389340eddaSLaurent Vivier } else { 539feb39b62SVincent Fazio /* ELFv2 PPC64 function pointers are entry points. R12 must also be set. */ 540feb39b62SVincent Fazio env->gpr[12] = env->nip = ka->_sa_handler; 5419340eddaSLaurent Vivier } 5429340eddaSLaurent Vivier #else 5439340eddaSLaurent Vivier env->nip = (target_ulong) ka->_sa_handler; 5449340eddaSLaurent Vivier #endif 5459340eddaSLaurent Vivier 54675da4997SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN 5479340eddaSLaurent Vivier /* Signal handlers are entered in big-endian mode. */ 54875da4997SRichard Henderson ppc_store_msr(env, env->msr & ~(1ull << MSR_LE)); 54975da4997SRichard Henderson #else 55075da4997SRichard Henderson /* Signal handlers are entered in little-endian mode. */ 55175da4997SRichard Henderson ppc_store_msr(env, env->msr | (1ull << MSR_LE)); 55275da4997SRichard Henderson #endif 5539340eddaSLaurent Vivier 5549340eddaSLaurent Vivier unlock_user_struct(rt_sf, rt_sf_addr, 1); 5559340eddaSLaurent Vivier return; 5569340eddaSLaurent Vivier 5579340eddaSLaurent Vivier sigsegv: 5589340eddaSLaurent Vivier unlock_user_struct(rt_sf, rt_sf_addr, 1); 5599340eddaSLaurent Vivier force_sigsegv(sig); 5609340eddaSLaurent Vivier 5619340eddaSLaurent Vivier } 5629340eddaSLaurent Vivier 563*74154d7eSThomas Huth #if !defined(TARGET_PPC64) 5649340eddaSLaurent Vivier long do_sigreturn(CPUPPCState *env) 5659340eddaSLaurent Vivier { 5669340eddaSLaurent Vivier struct target_sigcontext *sc = NULL; 5679340eddaSLaurent Vivier struct target_mcontext *sr = NULL; 5689340eddaSLaurent Vivier target_ulong sr_addr = 0, sc_addr; 5699340eddaSLaurent Vivier sigset_t blocked; 5709340eddaSLaurent Vivier target_sigset_t set; 5719340eddaSLaurent Vivier 5729340eddaSLaurent Vivier sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE; 5739340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) 5749340eddaSLaurent Vivier goto sigsegv; 5759340eddaSLaurent Vivier 5769340eddaSLaurent Vivier __get_user(set.sig[0], &sc->oldmask); 5779340eddaSLaurent Vivier __get_user(set.sig[1], &sc->_unused[3]); 578*74154d7eSThomas Huth 5799340eddaSLaurent Vivier target_to_host_sigset_internal(&blocked, &set); 5809340eddaSLaurent Vivier set_sigmask(&blocked); 5819340eddaSLaurent Vivier 5829340eddaSLaurent Vivier __get_user(sr_addr, &sc->regs); 5839340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1)) 5849340eddaSLaurent Vivier goto sigsegv; 5859340eddaSLaurent Vivier restore_user_regs(env, sr, 1); 5869340eddaSLaurent Vivier 5879340eddaSLaurent Vivier unlock_user_struct(sr, sr_addr, 1); 5889340eddaSLaurent Vivier unlock_user_struct(sc, sc_addr, 1); 58957a0c938SRichard Henderson return -QEMU_ESIGRETURN; 5909340eddaSLaurent Vivier 5919340eddaSLaurent Vivier sigsegv: 5929340eddaSLaurent Vivier unlock_user_struct(sr, sr_addr, 1); 5939340eddaSLaurent Vivier unlock_user_struct(sc, sc_addr, 1); 5949340eddaSLaurent Vivier force_sig(TARGET_SIGSEGV); 59557a0c938SRichard Henderson return -QEMU_ESIGRETURN; 5969340eddaSLaurent Vivier } 5979340eddaSLaurent Vivier #endif /* !defined(TARGET_PPC64) */ 5989340eddaSLaurent Vivier 5999340eddaSLaurent Vivier /* See arch/powerpc/kernel/signal_32.c. */ 6009340eddaSLaurent Vivier static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) 6019340eddaSLaurent Vivier { 6029340eddaSLaurent Vivier struct target_mcontext *mcp; 6039340eddaSLaurent Vivier target_ulong mcp_addr; 6049340eddaSLaurent Vivier sigset_t blocked; 6059340eddaSLaurent Vivier target_sigset_t set; 6069340eddaSLaurent Vivier 6079340eddaSLaurent Vivier if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask), 6089340eddaSLaurent Vivier sizeof (set))) 6099340eddaSLaurent Vivier return 1; 6109340eddaSLaurent Vivier 6119340eddaSLaurent Vivier #if defined(TARGET_PPC64) 6129340eddaSLaurent Vivier mcp_addr = h2g(ucp) + 6139340eddaSLaurent Vivier offsetof(struct target_ucontext, tuc_sigcontext.mcontext); 6149340eddaSLaurent Vivier #else 6159340eddaSLaurent Vivier __get_user(mcp_addr, &ucp->tuc_regs); 6169340eddaSLaurent Vivier #endif 6179340eddaSLaurent Vivier 6189340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1)) 6199340eddaSLaurent Vivier return 1; 6209340eddaSLaurent Vivier 6219340eddaSLaurent Vivier target_to_host_sigset_internal(&blocked, &set); 6229340eddaSLaurent Vivier set_sigmask(&blocked); 6239340eddaSLaurent Vivier restore_user_regs(env, mcp, sig); 6249340eddaSLaurent Vivier 6259340eddaSLaurent Vivier unlock_user_struct(mcp, mcp_addr, 1); 6269340eddaSLaurent Vivier return 0; 6279340eddaSLaurent Vivier } 6289340eddaSLaurent Vivier 6299340eddaSLaurent Vivier long do_rt_sigreturn(CPUPPCState *env) 6309340eddaSLaurent Vivier { 6319340eddaSLaurent Vivier struct target_rt_sigframe *rt_sf = NULL; 6329340eddaSLaurent Vivier target_ulong rt_sf_addr; 6339340eddaSLaurent Vivier 6349340eddaSLaurent Vivier rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16; 6359340eddaSLaurent Vivier if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1)) 6369340eddaSLaurent Vivier goto sigsegv; 6379340eddaSLaurent Vivier 6389340eddaSLaurent Vivier if (do_setcontext(&rt_sf->uc, env, 1)) 6399340eddaSLaurent Vivier goto sigsegv; 6409340eddaSLaurent Vivier 641ddc3e74dSRichard Henderson target_restore_altstack(&rt_sf->uc.tuc_stack, env); 6429340eddaSLaurent Vivier 6439340eddaSLaurent Vivier unlock_user_struct(rt_sf, rt_sf_addr, 1); 64457a0c938SRichard Henderson return -QEMU_ESIGRETURN; 6459340eddaSLaurent Vivier 6469340eddaSLaurent Vivier sigsegv: 6479340eddaSLaurent Vivier unlock_user_struct(rt_sf, rt_sf_addr, 1); 6489340eddaSLaurent Vivier force_sig(TARGET_SIGSEGV); 64957a0c938SRichard Henderson return -QEMU_ESIGRETURN; 6509340eddaSLaurent Vivier } 651fa97e38eSRichard Henderson 652fa97e38eSRichard Henderson /* This syscall implements {get,set,swap}context for userland. */ 653fa97e38eSRichard Henderson abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx, 654fa97e38eSRichard Henderson abi_ulong unew_ctx, abi_long ctx_size) 655fa97e38eSRichard Henderson { 656fa97e38eSRichard Henderson struct target_ucontext *uctx; 657fa97e38eSRichard Henderson struct target_mcontext *mctx; 658fa97e38eSRichard Henderson 659fa97e38eSRichard Henderson /* For ppc32, ctx_size is "reserved for future use". 660fa97e38eSRichard Henderson * For ppc64, we do not yet support the VSX extension. 661fa97e38eSRichard Henderson */ 662fa97e38eSRichard Henderson if (ctx_size < sizeof(struct target_ucontext)) { 663fa97e38eSRichard Henderson return -TARGET_EINVAL; 664fa97e38eSRichard Henderson } 665fa97e38eSRichard Henderson 666fa97e38eSRichard Henderson if (uold_ctx) { 667fa97e38eSRichard Henderson TaskState *ts = (TaskState *)thread_cpu->opaque; 668fa97e38eSRichard Henderson 669fa97e38eSRichard Henderson if (!lock_user_struct(VERIFY_WRITE, uctx, uold_ctx, 1)) { 670fa97e38eSRichard Henderson return -TARGET_EFAULT; 671fa97e38eSRichard Henderson } 672fa97e38eSRichard Henderson 673fa97e38eSRichard Henderson #ifdef TARGET_PPC64 674fa97e38eSRichard Henderson mctx = &uctx->tuc_sigcontext.mcontext; 675fa97e38eSRichard Henderson #else 676fa97e38eSRichard Henderson /* ??? The kernel aligns the pointer down here into padding, but 677fa97e38eSRichard Henderson * in setup_rt_frame we don't. Be self-compatible for now. 678fa97e38eSRichard Henderson */ 679fa97e38eSRichard Henderson mctx = &uctx->tuc_mcontext; 680fa97e38eSRichard Henderson __put_user(h2g(mctx), &uctx->tuc_regs); 681fa97e38eSRichard Henderson #endif 682fa97e38eSRichard Henderson 683fa97e38eSRichard Henderson save_user_regs(env, mctx); 684fa97e38eSRichard Henderson host_to_target_sigset(&uctx->tuc_sigmask, &ts->signal_mask); 685fa97e38eSRichard Henderson 686fa97e38eSRichard Henderson unlock_user_struct(uctx, uold_ctx, 1); 687fa97e38eSRichard Henderson } 688fa97e38eSRichard Henderson 689fa97e38eSRichard Henderson if (unew_ctx) { 690fa97e38eSRichard Henderson int err; 691fa97e38eSRichard Henderson 692fa97e38eSRichard Henderson if (!lock_user_struct(VERIFY_READ, uctx, unew_ctx, 1)) { 693fa97e38eSRichard Henderson return -TARGET_EFAULT; 694fa97e38eSRichard Henderson } 695fa97e38eSRichard Henderson err = do_setcontext(uctx, env, 0); 696fa97e38eSRichard Henderson unlock_user_struct(uctx, unew_ctx, 1); 697fa97e38eSRichard Henderson 698fa97e38eSRichard Henderson if (err) { 699fa97e38eSRichard Henderson /* We cannot return to a partially updated context. */ 700fa97e38eSRichard Henderson force_sig(TARGET_SIGSEGV); 701fa97e38eSRichard Henderson } 70257a0c938SRichard Henderson return -QEMU_ESIGRETURN; 703fa97e38eSRichard Henderson } 704fa97e38eSRichard Henderson 705fa97e38eSRichard Henderson return 0; 706fa97e38eSRichard Henderson } 707c790e4ebSRichard Henderson 708c790e4ebSRichard Henderson void setup_sigtramp(abi_ulong sigtramp_page) 709c790e4ebSRichard Henderson { 710c790e4ebSRichard Henderson uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); 711c790e4ebSRichard Henderson assert(tramp != NULL); 712c790e4ebSRichard Henderson 713c790e4ebSRichard Henderson #ifdef TARGET_ARCH_HAS_SETUP_FRAME 714c790e4ebSRichard Henderson default_sigreturn = sigtramp_page; 715c790e4ebSRichard Henderson encode_trampoline(TARGET_NR_sigreturn, tramp + 0); 716c790e4ebSRichard Henderson #endif 717c790e4ebSRichard Henderson 718c790e4ebSRichard Henderson default_rt_sigreturn = sigtramp_page + 8; 719c790e4ebSRichard Henderson encode_trampoline(TARGET_NR_rt_sigreturn, tramp + 2); 720c790e4ebSRichard Henderson 721c790e4ebSRichard Henderson unlock_user(tramp, sigtramp_page, 2 * 8); 722c790e4ebSRichard Henderson } 723