qom: Use return values to check for error where that's simpler
[qemu/ar7.git] / linux-user / aarch64 / signal.c
blobcd521ee42d1784bdac6469b2fc88a77498287feb
1 /*
2 * Emulation of Linux signals
4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qemu.h"
21 #include "signal-common.h"
22 #include "linux-user/trace.h"
24 struct target_sigcontext {
25 uint64_t fault_address;
26 /* AArch64 registers */
27 uint64_t regs[31];
28 uint64_t sp;
29 uint64_t pc;
30 uint64_t pstate;
31 /* 4K reserved for FP/SIMD state and future expansion */
32 char __reserved[4096] __attribute__((__aligned__(16)));
35 struct target_ucontext {
36 abi_ulong tuc_flags;
37 abi_ulong tuc_link;
38 target_stack_t tuc_stack;
39 target_sigset_t tuc_sigmask;
40 /* glibc uses a 1024-bit sigset_t */
41 char __unused[1024 / 8 - sizeof(target_sigset_t)];
42 /* last for future expansion */
43 struct target_sigcontext tuc_mcontext;
47 * Header to be used at the beginning of structures extending the user
48 * context. Such structures must be placed after the rt_sigframe on the stack
49 * and be 16-byte aligned. The last structure must be a dummy one with the
50 * magic and size set to 0.
52 struct target_aarch64_ctx {
53 uint32_t magic;
54 uint32_t size;
57 #define TARGET_FPSIMD_MAGIC 0x46508001
59 struct target_fpsimd_context {
60 struct target_aarch64_ctx head;
61 uint32_t fpsr;
62 uint32_t fpcr;
63 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
66 #define TARGET_EXTRA_MAGIC 0x45585401
68 struct target_extra_context {
69 struct target_aarch64_ctx head;
70 uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
71 uint32_t size; /* size in bytes of the extra space */
72 uint32_t reserved[3];
75 #define TARGET_SVE_MAGIC 0x53564501
77 struct target_sve_context {
78 struct target_aarch64_ctx head;
79 uint16_t vl;
80 uint16_t reserved[3];
81 /* The actual SVE data immediately follows. It is layed out
82 * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
83 * the original struct pointer.
87 #define TARGET_SVE_VQ_BYTES 16
89 #define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
90 #define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
92 #define TARGET_SVE_SIG_REGS_OFFSET \
93 QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
94 #define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
95 (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
96 #define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
97 (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
98 #define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
99 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
100 #define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
101 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
103 struct target_rt_sigframe {
104 struct target_siginfo info;
105 struct target_ucontext uc;
108 struct target_rt_frame_record {
109 uint64_t fp;
110 uint64_t lr;
111 uint32_t tramp[2];
114 static void target_setup_general_frame(struct target_rt_sigframe *sf,
115 CPUARMState *env, target_sigset_t *set)
117 int i;
119 __put_user(0, &sf->uc.tuc_flags);
120 __put_user(0, &sf->uc.tuc_link);
122 target_save_altstack(&sf->uc.tuc_stack, env);
124 for (i = 0; i < 31; i++) {
125 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
127 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
128 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
129 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
131 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
133 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
134 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
138 static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
139 CPUARMState *env)
141 int i;
143 __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
144 __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
145 __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
146 __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
148 for (i = 0; i < 32; i++) {
149 uint64_t *q = aa64_vfp_qreg(env, i);
150 #ifdef TARGET_WORDS_BIGENDIAN
151 __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
152 __put_user(q[1], &fpsimd->vregs[i * 2]);
153 #else
154 __put_user(q[0], &fpsimd->vregs[i * 2]);
155 __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
156 #endif
160 static void target_setup_extra_record(struct target_extra_context *extra,
161 uint64_t datap, uint32_t extra_size)
163 __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
164 __put_user(sizeof(struct target_extra_context), &extra->head.size);
165 __put_user(datap, &extra->datap);
166 __put_user(extra_size, &extra->size);
169 static void target_setup_end_record(struct target_aarch64_ctx *end)
171 __put_user(0, &end->magic);
172 __put_user(0, &end->size);
175 static void target_setup_sve_record(struct target_sve_context *sve,
176 CPUARMState *env, int vq, int size)
178 int i, j;
180 __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
181 __put_user(size, &sve->head.size);
182 __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
184 /* Note that SVE regs are stored as a byte stream, with each byte element
185 * at a subsequent address. This corresponds to a little-endian store
186 * of our 64-bit hunks.
188 for (i = 0; i < 32; ++i) {
189 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
190 for (j = 0; j < vq * 2; ++j) {
191 __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
194 for (i = 0; i <= 16; ++i) {
195 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
196 for (j = 0; j < vq; ++j) {
197 uint64_t r = env->vfp.pregs[i].p[j >> 2];
198 __put_user_e(r >> ((j & 3) * 16), p + j, le);
203 static void target_restore_general_frame(CPUARMState *env,
204 struct target_rt_sigframe *sf)
206 sigset_t set;
207 uint64_t pstate;
208 int i;
210 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
211 set_sigmask(&set);
213 for (i = 0; i < 31; i++) {
214 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
217 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
218 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
219 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
220 pstate_write(env, pstate);
223 static void target_restore_fpsimd_record(CPUARMState *env,
224 struct target_fpsimd_context *fpsimd)
226 uint32_t fpsr, fpcr;
227 int i;
229 __get_user(fpsr, &fpsimd->fpsr);
230 vfp_set_fpsr(env, fpsr);
231 __get_user(fpcr, &fpsimd->fpcr);
232 vfp_set_fpcr(env, fpcr);
234 for (i = 0; i < 32; i++) {
235 uint64_t *q = aa64_vfp_qreg(env, i);
236 #ifdef TARGET_WORDS_BIGENDIAN
237 __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
238 __get_user(q[1], &fpsimd->vregs[i * 2]);
239 #else
240 __get_user(q[0], &fpsimd->vregs[i * 2]);
241 __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
242 #endif
246 static void target_restore_sve_record(CPUARMState *env,
247 struct target_sve_context *sve, int vq)
249 int i, j;
251 /* Note that SVE regs are stored as a byte stream, with each byte element
252 * at a subsequent address. This corresponds to a little-endian load
253 * of our 64-bit hunks.
255 for (i = 0; i < 32; ++i) {
256 uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
257 for (j = 0; j < vq * 2; ++j) {
258 __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
261 for (i = 0; i <= 16; ++i) {
262 uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
263 for (j = 0; j < vq; ++j) {
264 uint16_t r;
265 __get_user_e(r, p + j, le);
266 if (j & 3) {
267 env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
268 } else {
269 env->vfp.pregs[i].p[j >> 2] = r;
275 static int target_restore_sigframe(CPUARMState *env,
276 struct target_rt_sigframe *sf)
278 struct target_aarch64_ctx *ctx, *extra = NULL;
279 struct target_fpsimd_context *fpsimd = NULL;
280 struct target_sve_context *sve = NULL;
281 uint64_t extra_datap = 0;
282 bool used_extra = false;
283 bool err = false;
284 int vq = 0, sve_size = 0;
286 target_restore_general_frame(env, sf);
288 ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
289 while (ctx) {
290 uint32_t magic, size, extra_size;
292 __get_user(magic, &ctx->magic);
293 __get_user(size, &ctx->size);
294 switch (magic) {
295 case 0:
296 if (size != 0) {
297 err = true;
298 goto exit;
300 if (used_extra) {
301 ctx = NULL;
302 } else {
303 ctx = extra;
304 used_extra = true;
306 continue;
308 case TARGET_FPSIMD_MAGIC:
309 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
310 err = true;
311 goto exit;
313 fpsimd = (struct target_fpsimd_context *)ctx;
314 break;
316 case TARGET_SVE_MAGIC:
317 if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
318 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
319 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
320 if (!sve && size == sve_size) {
321 sve = (struct target_sve_context *)ctx;
322 break;
325 err = true;
326 goto exit;
328 case TARGET_EXTRA_MAGIC:
329 if (extra || size != sizeof(struct target_extra_context)) {
330 err = true;
331 goto exit;
333 __get_user(extra_datap,
334 &((struct target_extra_context *)ctx)->datap);
335 __get_user(extra_size,
336 &((struct target_extra_context *)ctx)->size);
337 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
338 break;
340 default:
341 /* Unknown record -- we certainly didn't generate it.
342 * Did we in fact get out of sync?
344 err = true;
345 goto exit;
347 ctx = (void *)ctx + size;
350 /* Require FPSIMD always. */
351 if (fpsimd) {
352 target_restore_fpsimd_record(env, fpsimd);
353 } else {
354 err = true;
357 /* SVE data, if present, overwrites FPSIMD data. */
358 if (sve) {
359 target_restore_sve_record(env, sve, vq);
362 exit:
363 unlock_user(extra, extra_datap, 0);
364 return err;
367 static abi_ulong get_sigframe(struct target_sigaction *ka,
368 CPUARMState *env, int size)
370 abi_ulong sp;
372 sp = target_sigsp(get_sp_from_cpustate(env), ka);
374 sp = (sp - size) & ~15;
376 return sp;
379 typedef struct {
380 int total_size;
381 int extra_base;
382 int extra_size;
383 int std_end_ofs;
384 int extra_ofs;
385 int extra_end_ofs;
386 } target_sigframe_layout;
388 static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
390 /* Make sure there will always be space for the end marker. */
391 const int std_size = sizeof(struct target_rt_sigframe)
392 - sizeof(struct target_aarch64_ctx);
393 int this_loc = l->total_size;
395 if (l->extra_base) {
396 /* Once we have begun an extra space, all allocations go there. */
397 l->extra_size += this_size;
398 } else if (this_size + this_loc > std_size) {
399 /* This allocation does not fit in the standard space. */
400 /* Allocate the extra record. */
401 l->extra_ofs = this_loc;
402 l->total_size += sizeof(struct target_extra_context);
404 /* Allocate the standard end record. */
405 l->std_end_ofs = l->total_size;
406 l->total_size += sizeof(struct target_aarch64_ctx);
408 /* Allocate the requested record. */
409 l->extra_base = this_loc = l->total_size;
410 l->extra_size = this_size;
412 l->total_size += this_size;
414 return this_loc;
417 static void target_setup_frame(int usig, struct target_sigaction *ka,
418 target_siginfo_t *info, target_sigset_t *set,
419 CPUARMState *env)
421 target_sigframe_layout layout = {
422 /* Begin with the size pointing to the reserved space. */
423 .total_size = offsetof(struct target_rt_sigframe,
424 uc.tuc_mcontext.__reserved),
426 int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
427 struct target_rt_sigframe *frame;
428 struct target_rt_frame_record *fr;
429 abi_ulong frame_addr, return_addr;
431 /* FPSIMD record is always in the standard space. */
432 fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
433 &layout);
435 /* SVE state needs saving only if it exists. */
436 if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
437 vq = (env->vfp.zcr_el[1] & 0xf) + 1;
438 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
439 sve_ofs = alloc_sigframe_space(sve_size, &layout);
442 if (layout.extra_ofs) {
443 /* Reserve space for the extra end marker. The standard end marker
444 * will have been allocated when we allocated the extra record.
446 layout.extra_end_ofs
447 = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
448 } else {
449 /* Reserve space for the standard end marker.
450 * Do not use alloc_sigframe_space because we cheat
451 * std_size therein to reserve space for this.
453 layout.std_end_ofs = layout.total_size;
454 layout.total_size += sizeof(struct target_aarch64_ctx);
457 /* We must always provide at least the standard 4K reserved space,
458 * even if we don't use all of it (this is part of the ABI)
460 layout.total_size = MAX(layout.total_size,
461 sizeof(struct target_rt_sigframe));
463 /* Reserve space for the return code. On a real system this would
464 * be within the VDSO. So, despite the name this is not a "real"
465 * record within the frame.
467 fr_ofs = layout.total_size;
468 layout.total_size += sizeof(struct target_rt_frame_record);
470 frame_addr = get_sigframe(ka, env, layout.total_size);
471 trace_user_setup_frame(env, frame_addr);
472 frame = lock_user(VERIFY_WRITE, frame_addr, layout.total_size, 0);
473 if (!frame) {
474 goto give_sigsegv;
477 target_setup_general_frame(frame, env, set);
478 target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
479 target_setup_end_record((void *)frame + layout.std_end_ofs);
480 if (layout.extra_ofs) {
481 target_setup_extra_record((void *)frame + layout.extra_ofs,
482 frame_addr + layout.extra_base,
483 layout.extra_size);
484 target_setup_end_record((void *)frame + layout.extra_end_ofs);
486 if (sve_ofs) {
487 target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
490 /* Set up the stack frame for unwinding. */
491 fr = (void *)frame + fr_ofs;
492 __put_user(env->xregs[29], &fr->fp);
493 __put_user(env->xregs[30], &fr->lr);
495 if (ka->sa_flags & TARGET_SA_RESTORER) {
496 return_addr = ka->sa_restorer;
497 } else {
499 * mov x8,#__NR_rt_sigreturn; svc #0
500 * Since these are instructions they need to be put as little-endian
501 * regardless of target default or current CPU endianness.
503 __put_user_e(0xd2801168, &fr->tramp[0], le);
504 __put_user_e(0xd4000001, &fr->tramp[1], le);
505 return_addr = frame_addr + fr_ofs
506 + offsetof(struct target_rt_frame_record, tramp);
508 env->xregs[0] = usig;
509 env->xregs[31] = frame_addr;
510 env->xregs[29] = frame_addr + fr_ofs;
511 env->pc = ka->_sa_handler;
512 env->xregs[30] = return_addr;
513 if (info) {
514 tswap_siginfo(&frame->info, info);
515 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
516 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
519 unlock_user(frame, frame_addr, layout.total_size);
520 return;
522 give_sigsegv:
523 unlock_user(frame, frame_addr, layout.total_size);
524 force_sigsegv(usig);
527 void setup_rt_frame(int sig, struct target_sigaction *ka,
528 target_siginfo_t *info, target_sigset_t *set,
529 CPUARMState *env)
531 target_setup_frame(sig, ka, info, set, env);
534 void setup_frame(int sig, struct target_sigaction *ka,
535 target_sigset_t *set, CPUARMState *env)
537 target_setup_frame(sig, ka, 0, set, env);
540 long do_rt_sigreturn(CPUARMState *env)
542 struct target_rt_sigframe *frame = NULL;
543 abi_ulong frame_addr = env->xregs[31];
545 trace_user_do_rt_sigreturn(env, frame_addr);
546 if (frame_addr & 15) {
547 goto badframe;
550 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
551 goto badframe;
554 if (target_restore_sigframe(env, frame)) {
555 goto badframe;
558 if (do_sigaltstack(frame_addr +
559 offsetof(struct target_rt_sigframe, uc.tuc_stack),
560 0, get_sp_from_cpustate(env)) == -EFAULT) {
561 goto badframe;
564 unlock_user_struct(frame, frame_addr, 0);
565 return -TARGET_QEMU_ESIGRETURN;
567 badframe:
568 unlock_user_struct(frame, frame_addr, 0);
569 force_sig(TARGET_SIGSEGV);
570 return -TARGET_QEMU_ESIGRETURN;
573 long do_sigreturn(CPUARMState *env)
575 return do_rt_sigreturn(env);