1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * LoongArch emulation of Linux signals 4 * 5 * Copyright (c) 2021 Loongson Technology Corporation Limited 6 */ 7 8 #include "qemu/osdep.h" 9 #include "qemu.h" 10 #include "user-internals.h" 11 #include "signal-common.h" 12 #include "linux-user/trace.h" 13 #include "target/loongarch/internals.h" 14 #include "target/loongarch/vec.h" 15 #include "vdso-asmoffset.h" 16 17 /* FP context was used */ 18 #define SC_USED_FP (1 << 0) 19 20 struct target_sigcontext { 21 uint64_t sc_pc; 22 uint64_t sc_regs[32]; 23 uint32_t sc_flags; 24 uint64_t sc_extcontext[0] QEMU_ALIGNED(16); 25 }; 26 27 QEMU_BUILD_BUG_ON(sizeof(struct target_sigcontext) != sizeof_sigcontext); 28 QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_pc) 29 != offsetof_sigcontext_pc); 30 QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_regs) 31 != offsetof_sigcontext_gr); 32 33 #define FPU_CTX_MAGIC 0x46505501 34 #define FPU_CTX_ALIGN 8 35 struct target_fpu_context { 36 uint64_t regs[32]; 37 uint64_t fcc; 38 uint32_t fcsr; 39 } QEMU_ALIGNED(FPU_CTX_ALIGN); 40 41 QEMU_BUILD_BUG_ON(offsetof(struct target_fpu_context, regs) 42 != offsetof_fpucontext_fr); 43 44 #define CONTEXT_INFO_ALIGN 16 45 struct target_sctx_info { 46 uint32_t magic; 47 uint32_t size; 48 uint64_t padding; 49 } QEMU_ALIGNED(CONTEXT_INFO_ALIGN); 50 51 QEMU_BUILD_BUG_ON(sizeof(struct target_sctx_info) != sizeof_sctx_info); 52 53 struct target_ucontext { 54 abi_ulong tuc_flags; 55 abi_ptr tuc_link; 56 target_stack_t tuc_stack; 57 target_sigset_t tuc_sigmask; 58 uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)]; 59 struct target_sigcontext tuc_mcontext; 60 }; 61 62 struct target_rt_sigframe { 63 struct target_siginfo rs_info; 64 struct target_ucontext rs_uc; 65 }; 66 67 QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe) 68 != sizeof_rt_sigframe); 69 QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, rs_uc.tuc_mcontext) 70 != offsetof_sigcontext); 71 72 /* 73 * These two structures are not present in guest memory, are private 74 * to the signal implementation, but are largely copied from the 75 * kernel's signal implementation. 76 */ 77 struct ctx_layout { 78 void *haddr; 79 abi_ptr gaddr; 80 unsigned int size; 81 }; 82 83 struct extctx_layout { 84 unsigned int size; 85 unsigned int flags; 86 struct ctx_layout fpu; 87 struct ctx_layout end; 88 }; 89 90 static abi_ptr extframe_alloc(struct extctx_layout *extctx, 91 struct ctx_layout *sctx, unsigned size, 92 unsigned align, abi_ptr orig_sp) 93 { 94 abi_ptr sp = orig_sp; 95 96 sp -= sizeof(struct target_sctx_info) + size; 97 align = MAX(align, CONTEXT_INFO_ALIGN); 98 sp = ROUND_DOWN(sp, align); 99 sctx->gaddr = sp; 100 101 size = orig_sp - sp; 102 sctx->size = size; 103 extctx->size += size; 104 105 return sp; 106 } 107 108 static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp) 109 { 110 memset(extctx, 0, sizeof(struct extctx_layout)); 111 112 /* Grow down, alloc "end" context info first. */ 113 sp = extframe_alloc(extctx, &extctx->end, 0, CONTEXT_INFO_ALIGN, sp); 114 115 /* For qemu, there is no lazy fp context switch, so fp always present. */ 116 extctx->flags = SC_USED_FP; 117 sp = extframe_alloc(extctx, &extctx->fpu, 118 sizeof(struct target_rt_sigframe), FPU_CTX_ALIGN, sp); 119 120 return sp; 121 } 122 123 static void setup_sigframe(CPULoongArchState *env, 124 struct target_sigcontext *sc, 125 struct extctx_layout *extctx) 126 { 127 struct target_sctx_info *info; 128 struct target_fpu_context *fpu_ctx; 129 int i; 130 131 __put_user(extctx->flags, &sc->sc_flags); 132 __put_user(env->pc, &sc->sc_pc); 133 __put_user(0, &sc->sc_regs[0]); 134 for (i = 1; i < 32; ++i) { 135 __put_user(env->gpr[i], &sc->sc_regs[i]); 136 } 137 138 /* 139 * Set fpu context 140 */ 141 info = extctx->fpu.haddr; 142 __put_user(FPU_CTX_MAGIC, &info->magic); 143 __put_user(extctx->fpu.size, &info->size); 144 145 fpu_ctx = (struct target_fpu_context *)(info + 1); 146 for (i = 0; i < 32; ++i) { 147 __put_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]); 148 } 149 __put_user(read_fcc(env), &fpu_ctx->fcc); 150 __put_user(env->fcsr0, &fpu_ctx->fcsr); 151 152 /* 153 * Set end context 154 */ 155 info = extctx->end.haddr; 156 __put_user(0, &info->magic); 157 __put_user(extctx->end.size, &info->size); 158 } 159 160 static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame) 161 { 162 memset(extctx, 0, sizeof(*extctx)); 163 164 while (1) { 165 uint32_t magic, size; 166 167 if (get_user_u32(magic, frame) || get_user_u32(size, frame + 4)) { 168 return false; 169 } 170 171 switch (magic) { 172 case 0: /* END */ 173 extctx->end.gaddr = frame; 174 extctx->end.size = size; 175 extctx->size += size; 176 return true; 177 178 case FPU_CTX_MAGIC: 179 if (size < (sizeof(struct target_sctx_info) + 180 sizeof(struct target_fpu_context))) { 181 return false; 182 } 183 extctx->fpu.gaddr = frame; 184 extctx->fpu.size = size; 185 extctx->size += size; 186 break; 187 default: 188 return false; 189 } 190 191 frame += size; 192 } 193 } 194 195 static void restore_sigframe(CPULoongArchState *env, 196 struct target_sigcontext *sc, 197 struct extctx_layout *extctx) 198 { 199 int i; 200 201 __get_user(env->pc, &sc->sc_pc); 202 for (i = 1; i < 32; ++i) { 203 __get_user(env->gpr[i], &sc->sc_regs[i]); 204 } 205 206 if (extctx->fpu.haddr) { 207 struct target_fpu_context *fpu_ctx = 208 extctx->fpu.haddr + sizeof(struct target_sctx_info); 209 uint64_t fcc; 210 211 for (i = 0; i < 32; ++i) { 212 __get_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]); 213 } 214 __get_user(fcc, &fpu_ctx->fcc); 215 write_fcc(env, fcc); 216 __get_user(env->fcsr0, &fpu_ctx->fcsr); 217 restore_fp_status(env); 218 } 219 } 220 221 /* 222 * Determine which stack to use. 223 */ 224 static abi_ptr get_sigframe(struct target_sigaction *ka, 225 CPULoongArchState *env, 226 struct extctx_layout *extctx) 227 { 228 abi_ulong sp; 229 230 sp = target_sigsp(get_sp_from_cpustate(env), ka); 231 sp = ROUND_DOWN(sp, 16); 232 sp = setup_extcontext(extctx, sp); 233 sp -= sizeof(struct target_rt_sigframe); 234 235 assert(QEMU_IS_ALIGNED(sp, 16)); 236 237 return sp; 238 } 239 240 void setup_rt_frame(int sig, struct target_sigaction *ka, 241 target_siginfo_t *info, 242 target_sigset_t *set, CPULoongArchState *env) 243 { 244 struct target_rt_sigframe *frame; 245 struct extctx_layout extctx; 246 abi_ptr frame_addr; 247 int i; 248 249 frame_addr = get_sigframe(ka, env, &extctx); 250 trace_user_setup_rt_frame(env, frame_addr); 251 252 frame = lock_user(VERIFY_WRITE, frame_addr, 253 sizeof(*frame) + extctx.size, 0); 254 if (!frame) { 255 force_sigsegv(sig); 256 return; 257 } 258 extctx.fpu.haddr = (void *)frame + (extctx.fpu.gaddr - frame_addr); 259 extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); 260 261 tswap_siginfo(&frame->rs_info, info); 262 263 __put_user(0, &frame->rs_uc.tuc_flags); 264 __put_user(0, &frame->rs_uc.tuc_link); 265 target_save_altstack(&frame->rs_uc.tuc_stack, env); 266 267 setup_sigframe(env, &frame->rs_uc.tuc_mcontext, &extctx); 268 269 for (i = 0; i < TARGET_NSIG_WORDS; i++) { 270 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); 271 } 272 273 env->gpr[4] = sig; 274 env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); 275 env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); 276 env->gpr[3] = frame_addr; 277 env->gpr[1] = default_rt_sigreturn; 278 279 env->pc = ka->_sa_handler; 280 unlock_user(frame, frame_addr, sizeof(*frame) + extctx.size); 281 } 282 283 long do_rt_sigreturn(CPULoongArchState *env) 284 { 285 struct target_rt_sigframe *frame; 286 struct extctx_layout extctx; 287 abi_ulong frame_addr; 288 sigset_t blocked; 289 290 frame_addr = env->gpr[3]; 291 trace_user_do_rt_sigreturn(env, frame_addr); 292 293 if (!parse_extcontext(&extctx, frame_addr + sizeof(*frame))) { 294 goto badframe; 295 } 296 297 frame = lock_user(VERIFY_READ, frame_addr, 298 sizeof(*frame) + extctx.size, 1); 299 if (!frame) { 300 goto badframe; 301 } 302 if (extctx.fpu.gaddr) { 303 extctx.fpu.haddr = (void *)frame + (extctx.fpu.gaddr - frame_addr); 304 } 305 306 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); 307 set_sigmask(&blocked); 308 309 restore_sigframe(env, &frame->rs_uc.tuc_mcontext, &extctx); 310 311 target_restore_altstack(&frame->rs_uc.tuc_stack, env); 312 313 unlock_user(frame, frame_addr, 0); 314 return -QEMU_ESIGRETURN; 315 316 badframe: 317 force_sig(TARGET_SIGSEGV); 318 return -QEMU_ESIGRETURN; 319 } 320 321 void setup_sigtramp(abi_ulong sigtramp_page) 322 { 323 uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); 324 assert(tramp != NULL); 325 326 __put_user(0x03822c0b, tramp + 0); /* ori a7, zero, 0x8b */ 327 __put_user(0x002b0000, tramp + 1); /* syscall 0 */ 328 329 default_rt_sigreturn = sigtramp_page; 330 unlock_user(tramp, sigtramp_page, 8); 331 } 332