1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 22c020ed8SCatalin Marinas /* 32c020ed8SCatalin Marinas * Based on arch/arm/kernel/signal.c 42c020ed8SCatalin Marinas * 52c020ed8SCatalin Marinas * Copyright (C) 1995-2009 Russell King 62c020ed8SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 72c020ed8SCatalin Marinas */ 82c020ed8SCatalin Marinas 994b07c1fSDave Martin #include <linux/cache.h> 10fd92d4a5SAKASHI Takahiro #include <linux/compat.h> 112c020ed8SCatalin Marinas #include <linux/errno.h> 1220987de3SDave Martin #include <linux/kernel.h> 132c020ed8SCatalin Marinas #include <linux/signal.h> 142c020ed8SCatalin Marinas #include <linux/freezer.h> 1547ccb028SDave Martin #include <linux/stddef.h> 162c020ed8SCatalin Marinas #include <linux/uaccess.h> 1733f08261SDave Martin #include <linux/sizes.h> 18bb4891a6SDave Martin #include <linux/string.h> 1903248addSEric W. Biederman #include <linux/resume_user_mode.h> 202c020ed8SCatalin Marinas #include <linux/ratelimit.h> 21cf7de27aSThomas Garnier #include <linux/syscalls.h> 222c020ed8SCatalin Marinas 238d66772eSJames Morse #include <asm/daifflags.h> 242c020ed8SCatalin Marinas #include <asm/debug-monitors.h> 252c020ed8SCatalin Marinas #include <asm/elf.h> 262c020ed8SCatalin Marinas #include <asm/cacheflush.h> 272c020ed8SCatalin Marinas #include <asm/ucontext.h> 282c020ed8SCatalin Marinas #include <asm/unistd.h> 292c020ed8SCatalin Marinas #include <asm/fpsimd.h> 3017c28958SDave Martin #include <asm/ptrace.h> 31e30e8d46SMark Rutland #include <asm/syscall.h> 322c020ed8SCatalin Marinas #include <asm/signal32.h> 33f71016a8SWill Deacon #include <asm/traps.h> 342c020ed8SCatalin Marinas #include <asm/vdso.h> 352c020ed8SCatalin Marinas 362c020ed8SCatalin Marinas /* 372c020ed8SCatalin Marinas * Do a signal return; undo the signal stack. These are aligned to 128-bit. 382c020ed8SCatalin Marinas */ 392c020ed8SCatalin Marinas struct rt_sigframe { 402c020ed8SCatalin Marinas struct siginfo info; 412c020ed8SCatalin Marinas struct ucontext uc; 4220987de3SDave Martin }; 4320987de3SDave Martin 4420987de3SDave Martin struct frame_record { 45304ef4e8SWill Deacon u64 fp; 46304ef4e8SWill Deacon u64 lr; 472c020ed8SCatalin Marinas }; 482c020ed8SCatalin Marinas 4920987de3SDave Martin struct rt_sigframe_user_layout { 5020987de3SDave Martin struct rt_sigframe __user *sigframe; 5120987de3SDave Martin struct frame_record __user *next_frame; 52bb4891a6SDave Martin 53bb4891a6SDave Martin unsigned long size; /* size of allocated sigframe data */ 54bb4891a6SDave Martin unsigned long limit; /* largest allowed size */ 55bb4891a6SDave Martin 56bb4891a6SDave Martin unsigned long fpsimd_offset; 57bb4891a6SDave Martin unsigned long esr_offset; 588cd969d2SDave Martin unsigned long sve_offset; 5939e54499SMark Brown unsigned long tpidr2_offset; 6039782210SMark Brown unsigned long za_offset; 61ee072cf7SMark Brown unsigned long zt_offset; 6233f08261SDave Martin unsigned long extra_offset; 63bb4891a6SDave Martin unsigned long end_offset; 6420987de3SDave Martin }; 6520987de3SDave Martin 6633f08261SDave Martin #define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16) 6733f08261SDave Martin #define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16) 6833f08261SDave Martin #define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16) 6933f08261SDave Martin 70bb4891a6SDave Martin static void init_user_layout(struct rt_sigframe_user_layout *user) 71bb4891a6SDave Martin { 7233f08261SDave Martin const size_t reserved_size = 7333f08261SDave Martin sizeof(user->sigframe->uc.uc_mcontext.__reserved); 7433f08261SDave Martin 75bb4891a6SDave Martin memset(user, 0, sizeof(*user)); 76bb4891a6SDave Martin user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved); 77bb4891a6SDave Martin 7833f08261SDave Martin user->limit = user->size + reserved_size; 7933f08261SDave Martin 8033f08261SDave Martin user->limit -= TERMINATOR_SIZE; 8133f08261SDave Martin user->limit -= EXTRA_CONTEXT_SIZE; 8233f08261SDave Martin /* Reserve space for extension and terminator ^ */ 83bb4891a6SDave Martin } 84bb4891a6SDave Martin 85bb4891a6SDave Martin static size_t sigframe_size(struct rt_sigframe_user_layout const *user) 86bb4891a6SDave Martin { 87bb4891a6SDave Martin return round_up(max(user->size, sizeof(struct rt_sigframe)), 16); 88bb4891a6SDave Martin } 89bb4891a6SDave Martin 90bb4322f7SDave Martin /* 9133f08261SDave Martin * Sanity limit on the approximate maximum size of signal frame we'll 9233f08261SDave Martin * try to generate. Stack alignment padding and the frame record are 9333f08261SDave Martin * not taken into account. This limit is not a guarantee and is 9433f08261SDave Martin * NOT ABI. 9533f08261SDave Martin */ 967ddcaf78SMark Brown #define SIGFRAME_MAXSZ SZ_256K 9733f08261SDave Martin 9833f08261SDave Martin static int __sigframe_alloc(struct rt_sigframe_user_layout *user, 9933f08261SDave Martin unsigned long *offset, size_t size, bool extend) 10033f08261SDave Martin { 10133f08261SDave Martin size_t padded_size = round_up(size, 16); 10233f08261SDave Martin 10333f08261SDave Martin if (padded_size > user->limit - user->size && 10433f08261SDave Martin !user->extra_offset && 10533f08261SDave Martin extend) { 10633f08261SDave Martin int ret; 10733f08261SDave Martin 10833f08261SDave Martin user->limit += EXTRA_CONTEXT_SIZE; 10933f08261SDave Martin ret = __sigframe_alloc(user, &user->extra_offset, 11033f08261SDave Martin sizeof(struct extra_context), false); 11133f08261SDave Martin if (ret) { 11233f08261SDave Martin user->limit -= EXTRA_CONTEXT_SIZE; 11333f08261SDave Martin return ret; 11433f08261SDave Martin } 11533f08261SDave Martin 11633f08261SDave Martin /* Reserve space for the __reserved[] terminator */ 11733f08261SDave Martin user->size += TERMINATOR_SIZE; 11833f08261SDave Martin 11933f08261SDave Martin /* 12033f08261SDave Martin * Allow expansion up to SIGFRAME_MAXSZ, ensuring space for 12133f08261SDave Martin * the terminator: 12233f08261SDave Martin */ 12333f08261SDave Martin user->limit = SIGFRAME_MAXSZ - TERMINATOR_SIZE; 12433f08261SDave Martin } 12533f08261SDave Martin 12633f08261SDave Martin /* Still not enough space? Bad luck! */ 12733f08261SDave Martin if (padded_size > user->limit - user->size) 12833f08261SDave Martin return -ENOMEM; 12933f08261SDave Martin 13033f08261SDave Martin *offset = user->size; 13133f08261SDave Martin user->size += padded_size; 13233f08261SDave Martin 13333f08261SDave Martin return 0; 13433f08261SDave Martin } 13533f08261SDave Martin 13633f08261SDave Martin /* 137bb4322f7SDave Martin * Allocate space for an optional record of <size> bytes in the user 138bb4322f7SDave Martin * signal frame. The offset from the signal frame base address to the 139bb4322f7SDave Martin * allocated block is assigned to *offset. 140bb4322f7SDave Martin */ 141bb4322f7SDave Martin static int sigframe_alloc(struct rt_sigframe_user_layout *user, 142bb4322f7SDave Martin unsigned long *offset, size_t size) 143bb4322f7SDave Martin { 14433f08261SDave Martin return __sigframe_alloc(user, offset, size, true); 14533f08261SDave Martin } 146bb4322f7SDave Martin 14733f08261SDave Martin /* Allocate the null terminator record and prevent further allocations */ 14833f08261SDave Martin static int sigframe_alloc_end(struct rt_sigframe_user_layout *user) 14933f08261SDave Martin { 15033f08261SDave Martin int ret; 151bb4322f7SDave Martin 15233f08261SDave Martin /* Un-reserve the space reserved for the terminator: */ 15333f08261SDave Martin user->limit += TERMINATOR_SIZE; 15433f08261SDave Martin 15533f08261SDave Martin ret = sigframe_alloc(user, &user->end_offset, 15633f08261SDave Martin sizeof(struct _aarch64_ctx)); 15733f08261SDave Martin if (ret) 15833f08261SDave Martin return ret; 15933f08261SDave Martin 16033f08261SDave Martin /* Prevent further allocation: */ 16133f08261SDave Martin user->limit = user->size; 162bb4322f7SDave Martin return 0; 163bb4322f7SDave Martin } 164bb4322f7SDave Martin 165bb4891a6SDave Martin static void __user *apply_user_offset( 166bb4891a6SDave Martin struct rt_sigframe_user_layout const *user, unsigned long offset) 167bb4891a6SDave Martin { 168bb4891a6SDave Martin char __user *base = (char __user *)user->sigframe; 169bb4891a6SDave Martin 170bb4891a6SDave Martin return base + offset; 171bb4891a6SDave Martin } 172bb4891a6SDave Martin 1734e4e9304SMark Brown struct user_ctxs { 1744e4e9304SMark Brown struct fpsimd_context __user *fpsimd; 175b57682b3SMark Brown u32 fpsimd_size; 1764e4e9304SMark Brown struct sve_context __user *sve; 177b57682b3SMark Brown u32 sve_size; 1784e4e9304SMark Brown struct tpidr2_context __user *tpidr2; 179b57682b3SMark Brown u32 tpidr2_size; 1804e4e9304SMark Brown struct za_context __user *za; 181b57682b3SMark Brown u32 za_size; 1824e4e9304SMark Brown struct zt_context __user *zt; 183b57682b3SMark Brown u32 zt_size; 1844e4e9304SMark Brown }; 1854e4e9304SMark Brown 1862c020ed8SCatalin Marinas static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) 1872c020ed8SCatalin Marinas { 18865896545SDave Martin struct user_fpsimd_state const *fpsimd = 18965896545SDave Martin ¤t->thread.uw.fpsimd_state; 1902c020ed8SCatalin Marinas int err; 1912c020ed8SCatalin Marinas 1922c020ed8SCatalin Marinas /* copy the FP and status/control registers */ 1932c020ed8SCatalin Marinas err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); 1942c020ed8SCatalin Marinas __put_user_error(fpsimd->fpsr, &ctx->fpsr, err); 1952c020ed8SCatalin Marinas __put_user_error(fpsimd->fpcr, &ctx->fpcr, err); 1962c020ed8SCatalin Marinas 1972c020ed8SCatalin Marinas /* copy the magic/size information */ 1982c020ed8SCatalin Marinas __put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err); 1992c020ed8SCatalin Marinas __put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err); 2002c020ed8SCatalin Marinas 2012c020ed8SCatalin Marinas return err ? -EFAULT : 0; 2022c020ed8SCatalin Marinas } 2032c020ed8SCatalin Marinas 2044e4e9304SMark Brown static int restore_fpsimd_context(struct user_ctxs *user) 2052c020ed8SCatalin Marinas { 2060abdeff5SDave Martin struct user_fpsimd_state fpsimd; 2072c020ed8SCatalin Marinas int err = 0; 2082c020ed8SCatalin Marinas 20992f14518SMark Brown /* check the size information */ 210b57682b3SMark Brown if (user->fpsimd_size != sizeof(struct fpsimd_context)) 2112c020ed8SCatalin Marinas return -EINVAL; 2122c020ed8SCatalin Marinas 2132c020ed8SCatalin Marinas /* copy the FP and status/control registers */ 2144e4e9304SMark Brown err = __copy_from_user(fpsimd.vregs, &(user->fpsimd->vregs), 2152c020ed8SCatalin Marinas sizeof(fpsimd.vregs)); 2164e4e9304SMark Brown __get_user_error(fpsimd.fpsr, &(user->fpsimd->fpsr), err); 2174e4e9304SMark Brown __get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err); 2182c020ed8SCatalin Marinas 2198cd969d2SDave Martin clear_thread_flag(TIF_SVE); 220baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 2218cd969d2SDave Martin 2222c020ed8SCatalin Marinas /* load the hardware registers from the fpsimd_state structure */ 223c51f9269SArd Biesheuvel if (!err) 224c51f9269SArd Biesheuvel fpsimd_update_current_state(&fpsimd); 2252c020ed8SCatalin Marinas 2262c020ed8SCatalin Marinas return err ? -EFAULT : 0; 2272c020ed8SCatalin Marinas } 2282c020ed8SCatalin Marinas 2298cd969d2SDave Martin 2308cd969d2SDave Martin #ifdef CONFIG_ARM64_SVE 2318cd969d2SDave Martin 2328cd969d2SDave Martin static int preserve_sve_context(struct sve_context __user *ctx) 2338cd969d2SDave Martin { 2348cd969d2SDave Martin int err = 0; 2358cd969d2SDave Martin u16 reserved[ARRAY_SIZE(ctx->__reserved)]; 23685ed24daSMark Brown u16 flags = 0; 2370423eedcSMark Brown unsigned int vl = task_get_sve_vl(current); 2388cd969d2SDave Martin unsigned int vq = 0; 2398cd969d2SDave Martin 24085ed24daSMark Brown if (thread_sm_enabled(¤t->thread)) { 24185ed24daSMark Brown vl = task_get_sme_vl(current); 2428cd969d2SDave Martin vq = sve_vq_from_vl(vl); 24385ed24daSMark Brown flags |= SVE_SIG_FLAG_SM; 24485ed24daSMark Brown } else if (test_thread_flag(TIF_SVE)) { 24585ed24daSMark Brown vq = sve_vq_from_vl(vl); 24685ed24daSMark Brown } 2478cd969d2SDave Martin 2488cd969d2SDave Martin memset(reserved, 0, sizeof(reserved)); 2498cd969d2SDave Martin 2508cd969d2SDave Martin __put_user_error(SVE_MAGIC, &ctx->head.magic, err); 2518cd969d2SDave Martin __put_user_error(round_up(SVE_SIG_CONTEXT_SIZE(vq), 16), 2528cd969d2SDave Martin &ctx->head.size, err); 2538cd969d2SDave Martin __put_user_error(vl, &ctx->vl, err); 25485ed24daSMark Brown __put_user_error(flags, &ctx->flags, err); 2558cd969d2SDave Martin BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved)); 2568cd969d2SDave Martin err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved)); 2578cd969d2SDave Martin 2588cd969d2SDave Martin if (vq) { 2598cd969d2SDave Martin /* 2608cd969d2SDave Martin * This assumes that the SVE state has already been saved to 26168a4c52eSJulien Grall * the task struct by calling the function 26268a4c52eSJulien Grall * fpsimd_signal_preserve_current_state(). 2638cd969d2SDave Martin */ 2648cd969d2SDave Martin err |= __copy_to_user((char __user *)ctx + SVE_SIG_REGS_OFFSET, 2658cd969d2SDave Martin current->thread.sve_state, 2668cd969d2SDave Martin SVE_SIG_REGS_SIZE(vq)); 2678cd969d2SDave Martin } 2688cd969d2SDave Martin 2698cd969d2SDave Martin return err ? -EFAULT : 0; 2708cd969d2SDave Martin } 2718cd969d2SDave Martin 2728cd969d2SDave Martin static int restore_sve_fpsimd_context(struct user_ctxs *user) 2738cd969d2SDave Martin { 274*f3ac48aaSMark Brown int err = 0; 27585ed24daSMark Brown unsigned int vl, vq; 2760abdeff5SDave Martin struct user_fpsimd_state fpsimd; 277*f3ac48aaSMark Brown u16 user_vl, flags; 2788cd969d2SDave Martin 279b57682b3SMark Brown if (user->sve_size < sizeof(*user->sve)) 280b57682b3SMark Brown return -EINVAL; 281b57682b3SMark Brown 282*f3ac48aaSMark Brown __get_user_error(user_vl, &(user->sve->vl), err); 283*f3ac48aaSMark Brown __get_user_error(flags, &(user->sve->flags), err); 284*f3ac48aaSMark Brown if (err) 285*f3ac48aaSMark Brown return err; 2868cd969d2SDave Martin 287*f3ac48aaSMark Brown if (flags & SVE_SIG_FLAG_SM) { 28885ed24daSMark Brown if (!system_supports_sme()) 28985ed24daSMark Brown return -EINVAL; 29085ed24daSMark Brown 29185ed24daSMark Brown vl = task_get_sme_vl(current); 29285ed24daSMark Brown } else { 293df07443fSMark Brown if (!system_supports_sve()) 294df07443fSMark Brown return -EINVAL; 295df07443fSMark Brown 29685ed24daSMark Brown vl = task_get_sve_vl(current); 29785ed24daSMark Brown } 29885ed24daSMark Brown 299*f3ac48aaSMark Brown if (user_vl != vl) 3008cd969d2SDave Martin return -EINVAL; 3018cd969d2SDave Martin 302b57682b3SMark Brown if (user->sve_size == sizeof(*user->sve)) { 3038cd969d2SDave Martin clear_thread_flag(TIF_SVE); 304ec0067a6SMark Brown current->thread.svcr &= ~SVCR_SM_MASK; 305baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 3068cd969d2SDave Martin goto fpsimd_only; 3078cd969d2SDave Martin } 3088cd969d2SDave Martin 309*f3ac48aaSMark Brown vq = sve_vq_from_vl(vl); 3108cd969d2SDave Martin 311b57682b3SMark Brown if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq)) 3128cd969d2SDave Martin return -EINVAL; 3138cd969d2SDave Martin 3148cd969d2SDave Martin /* 3158cd969d2SDave Martin * Careful: we are about __copy_from_user() directly into 3168cd969d2SDave Martin * thread.sve_state with preemption enabled, so protection is 3178cd969d2SDave Martin * needed to prevent a racing context switch from writing stale 3188cd969d2SDave Martin * registers back over the new data. 3198cd969d2SDave Martin */ 3208cd969d2SDave Martin 3218cd969d2SDave Martin fpsimd_flush_task_state(current); 3228cd969d2SDave Martin /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ 3238cd969d2SDave Martin 324826a4fddSMark Brown sve_alloc(current, true); 3257559b7d7SMark Brown if (!current->thread.sve_state) { 3267559b7d7SMark Brown clear_thread_flag(TIF_SVE); 3277559b7d7SMark Brown return -ENOMEM; 3287559b7d7SMark Brown } 3297559b7d7SMark Brown 3308cd969d2SDave Martin err = __copy_from_user(current->thread.sve_state, 3318cd969d2SDave Martin (char __user const *)user->sve + 3328cd969d2SDave Martin SVE_SIG_REGS_OFFSET, 3338cd969d2SDave Martin SVE_SIG_REGS_SIZE(vq)); 3348cd969d2SDave Martin if (err) 3358cd969d2SDave Martin return -EFAULT; 3368cd969d2SDave Martin 337*f3ac48aaSMark Brown if (flags & SVE_SIG_FLAG_SM) 338ec0067a6SMark Brown current->thread.svcr |= SVCR_SM_MASK; 33985ed24daSMark Brown else 3408cd969d2SDave Martin set_thread_flag(TIF_SVE); 341baa85152SMark Brown current->thread.fp_type = FP_STATE_SVE; 3428cd969d2SDave Martin 3438cd969d2SDave Martin fpsimd_only: 3448cd969d2SDave Martin /* copy the FP and status/control registers */ 3458cd969d2SDave Martin /* restore_sigframe() already checked that user->fpsimd != NULL. */ 3468cd969d2SDave Martin err = __copy_from_user(fpsimd.vregs, user->fpsimd->vregs, 3478cd969d2SDave Martin sizeof(fpsimd.vregs)); 3488cd969d2SDave Martin __get_user_error(fpsimd.fpsr, &user->fpsimd->fpsr, err); 3498cd969d2SDave Martin __get_user_error(fpsimd.fpcr, &user->fpsimd->fpcr, err); 3508cd969d2SDave Martin 3518cd969d2SDave Martin /* load the hardware registers from the fpsimd_state structure */ 3528cd969d2SDave Martin if (!err) 3538cd969d2SDave Martin fpsimd_update_current_state(&fpsimd); 3548cd969d2SDave Martin 3558cd969d2SDave Martin return err ? -EFAULT : 0; 3568cd969d2SDave Martin } 3578cd969d2SDave Martin 3588cd969d2SDave Martin #else /* ! CONFIG_ARM64_SVE */ 3598cd969d2SDave Martin 360df07443fSMark Brown static int restore_sve_fpsimd_context(struct user_ctxs *user) 361df07443fSMark Brown { 362df07443fSMark Brown WARN_ON_ONCE(1); 363df07443fSMark Brown return -EINVAL; 364df07443fSMark Brown } 365df07443fSMark Brown 366df07443fSMark Brown /* Turn any non-optimised out attempts to use this into a link error: */ 3678cd969d2SDave Martin extern int preserve_sve_context(void __user *ctx); 3688cd969d2SDave Martin 3698cd969d2SDave Martin #endif /* ! CONFIG_ARM64_SVE */ 3708cd969d2SDave Martin 37139782210SMark Brown #ifdef CONFIG_ARM64_SME 37239782210SMark Brown 37339e54499SMark Brown static int preserve_tpidr2_context(struct tpidr2_context __user *ctx) 37439e54499SMark Brown { 37539e54499SMark Brown int err = 0; 37639e54499SMark Brown 37739e54499SMark Brown current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0); 37839e54499SMark Brown 37939e54499SMark Brown __put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err); 38039e54499SMark Brown __put_user_error(sizeof(*ctx), &ctx->head.size, err); 38139e54499SMark Brown __put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err); 38239e54499SMark Brown 38339e54499SMark Brown return err; 38439e54499SMark Brown } 38539e54499SMark Brown 38639e54499SMark Brown static int restore_tpidr2_context(struct user_ctxs *user) 38739e54499SMark Brown { 38839e54499SMark Brown u64 tpidr2_el0; 38939e54499SMark Brown int err = 0; 39039e54499SMark Brown 391b57682b3SMark Brown if (user->tpidr2_size != sizeof(*user->tpidr2)) 392b57682b3SMark Brown return -EINVAL; 393b57682b3SMark Brown 39439e54499SMark Brown __get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err); 39539e54499SMark Brown if (!err) 39639e54499SMark Brown current->thread.tpidr2_el0 = tpidr2_el0; 39739e54499SMark Brown 39839e54499SMark Brown return err; 39939e54499SMark Brown } 40039e54499SMark Brown 40139782210SMark Brown static int preserve_za_context(struct za_context __user *ctx) 40239782210SMark Brown { 40339782210SMark Brown int err = 0; 40439782210SMark Brown u16 reserved[ARRAY_SIZE(ctx->__reserved)]; 40539782210SMark Brown unsigned int vl = task_get_sme_vl(current); 40639782210SMark Brown unsigned int vq; 40739782210SMark Brown 40839782210SMark Brown if (thread_za_enabled(¤t->thread)) 40939782210SMark Brown vq = sve_vq_from_vl(vl); 41039782210SMark Brown else 41139782210SMark Brown vq = 0; 41239782210SMark Brown 41339782210SMark Brown memset(reserved, 0, sizeof(reserved)); 41439782210SMark Brown 41539782210SMark Brown __put_user_error(ZA_MAGIC, &ctx->head.magic, err); 41639782210SMark Brown __put_user_error(round_up(ZA_SIG_CONTEXT_SIZE(vq), 16), 41739782210SMark Brown &ctx->head.size, err); 41839782210SMark Brown __put_user_error(vl, &ctx->vl, err); 41939782210SMark Brown BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved)); 42039782210SMark Brown err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved)); 42139782210SMark Brown 42239782210SMark Brown if (vq) { 42339782210SMark Brown /* 42439782210SMark Brown * This assumes that the ZA state has already been saved to 42539782210SMark Brown * the task struct by calling the function 42639782210SMark Brown * fpsimd_signal_preserve_current_state(). 42739782210SMark Brown */ 42839782210SMark Brown err |= __copy_to_user((char __user *)ctx + ZA_SIG_REGS_OFFSET, 429ce514000SMark Brown current->thread.sme_state, 43039782210SMark Brown ZA_SIG_REGS_SIZE(vq)); 43139782210SMark Brown } 43239782210SMark Brown 43339782210SMark Brown return err ? -EFAULT : 0; 43439782210SMark Brown } 43539782210SMark Brown 4361bec877bSCatalin Marinas static int restore_za_context(struct user_ctxs *user) 43739782210SMark Brown { 43839782210SMark Brown int err; 43939782210SMark Brown unsigned int vq; 44039782210SMark Brown struct za_context za; 44139782210SMark Brown 442b57682b3SMark Brown if (user->za_size < sizeof(*user->za)) 443b57682b3SMark Brown return -EINVAL; 444b57682b3SMark Brown 44539782210SMark Brown if (__copy_from_user(&za, user->za, sizeof(za))) 44639782210SMark Brown return -EFAULT; 44739782210SMark Brown 44839782210SMark Brown if (za.vl != task_get_sme_vl(current)) 44939782210SMark Brown return -EINVAL; 45039782210SMark Brown 451b57682b3SMark Brown if (user->za_size == sizeof(*user->za)) { 452ec0067a6SMark Brown current->thread.svcr &= ~SVCR_ZA_MASK; 45339782210SMark Brown return 0; 45439782210SMark Brown } 45539782210SMark Brown 45639782210SMark Brown vq = sve_vq_from_vl(za.vl); 45739782210SMark Brown 458b57682b3SMark Brown if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq)) 45939782210SMark Brown return -EINVAL; 46039782210SMark Brown 46139782210SMark Brown /* 46239782210SMark Brown * Careful: we are about __copy_from_user() directly into 463ce514000SMark Brown * thread.sme_state with preemption enabled, so protection is 46439782210SMark Brown * needed to prevent a racing context switch from writing stale 46539782210SMark Brown * registers back over the new data. 46639782210SMark Brown */ 46739782210SMark Brown 46839782210SMark Brown fpsimd_flush_task_state(current); 46939782210SMark Brown /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ 47039782210SMark Brown 47139782210SMark Brown sme_alloc(current); 472ce514000SMark Brown if (!current->thread.sme_state) { 473ec0067a6SMark Brown current->thread.svcr &= ~SVCR_ZA_MASK; 47439782210SMark Brown clear_thread_flag(TIF_SME); 47539782210SMark Brown return -ENOMEM; 47639782210SMark Brown } 47739782210SMark Brown 478ce514000SMark Brown err = __copy_from_user(current->thread.sme_state, 47939782210SMark Brown (char __user const *)user->za + 48039782210SMark Brown ZA_SIG_REGS_OFFSET, 48139782210SMark Brown ZA_SIG_REGS_SIZE(vq)); 48239782210SMark Brown if (err) 48339782210SMark Brown return -EFAULT; 48439782210SMark Brown 48539782210SMark Brown set_thread_flag(TIF_SME); 486ec0067a6SMark Brown current->thread.svcr |= SVCR_ZA_MASK; 48739782210SMark Brown 48839782210SMark Brown return 0; 48939782210SMark Brown } 490ee072cf7SMark Brown 491ee072cf7SMark Brown static int preserve_zt_context(struct zt_context __user *ctx) 492ee072cf7SMark Brown { 493ee072cf7SMark Brown int err = 0; 494ee072cf7SMark Brown u16 reserved[ARRAY_SIZE(ctx->__reserved)]; 495ee072cf7SMark Brown 496ee072cf7SMark Brown if (WARN_ON(!thread_za_enabled(¤t->thread))) 497ee072cf7SMark Brown return -EINVAL; 498ee072cf7SMark Brown 499ee072cf7SMark Brown memset(reserved, 0, sizeof(reserved)); 500ee072cf7SMark Brown 501ee072cf7SMark Brown __put_user_error(ZT_MAGIC, &ctx->head.magic, err); 502ee072cf7SMark Brown __put_user_error(round_up(ZT_SIG_CONTEXT_SIZE(1), 16), 503ee072cf7SMark Brown &ctx->head.size, err); 504ee072cf7SMark Brown __put_user_error(1, &ctx->nregs, err); 505ee072cf7SMark Brown BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved)); 506ee072cf7SMark Brown err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved)); 507ee072cf7SMark Brown 508ee072cf7SMark Brown /* 509ee072cf7SMark Brown * This assumes that the ZT state has already been saved to 510ee072cf7SMark Brown * the task struct by calling the function 511ee072cf7SMark Brown * fpsimd_signal_preserve_current_state(). 512ee072cf7SMark Brown */ 513ee072cf7SMark Brown err |= __copy_to_user((char __user *)ctx + ZT_SIG_REGS_OFFSET, 514ee072cf7SMark Brown thread_zt_state(¤t->thread), 515ee072cf7SMark Brown ZT_SIG_REGS_SIZE(1)); 516ee072cf7SMark Brown 517ee072cf7SMark Brown return err ? -EFAULT : 0; 518ee072cf7SMark Brown } 519ee072cf7SMark Brown 520ee072cf7SMark Brown static int restore_zt_context(struct user_ctxs *user) 521ee072cf7SMark Brown { 522ee072cf7SMark Brown int err; 523ee072cf7SMark Brown struct zt_context zt; 524ee072cf7SMark Brown 525ee072cf7SMark Brown /* ZA must be restored first for this check to be valid */ 526ee072cf7SMark Brown if (!thread_za_enabled(¤t->thread)) 527ee072cf7SMark Brown return -EINVAL; 528ee072cf7SMark Brown 529b57682b3SMark Brown if (user->zt_size != ZT_SIG_CONTEXT_SIZE(1)) 530b57682b3SMark Brown return -EINVAL; 531b57682b3SMark Brown 532ee072cf7SMark Brown if (__copy_from_user(&zt, user->zt, sizeof(zt))) 533ee072cf7SMark Brown return -EFAULT; 534ee072cf7SMark Brown 535ee072cf7SMark Brown if (zt.nregs != 1) 536ee072cf7SMark Brown return -EINVAL; 537ee072cf7SMark Brown 538ee072cf7SMark Brown /* 539ee072cf7SMark Brown * Careful: we are about __copy_from_user() directly into 540ee072cf7SMark Brown * thread.zt_state with preemption enabled, so protection is 541ee072cf7SMark Brown * needed to prevent a racing context switch from writing stale 542ee072cf7SMark Brown * registers back over the new data. 543ee072cf7SMark Brown */ 544ee072cf7SMark Brown 545ee072cf7SMark Brown fpsimd_flush_task_state(current); 546ee072cf7SMark Brown /* From now, fpsimd_thread_switch() won't touch ZT in thread state */ 547ee072cf7SMark Brown 548ee072cf7SMark Brown err = __copy_from_user(thread_zt_state(¤t->thread), 549ee072cf7SMark Brown (char __user const *)user->zt + 550ee072cf7SMark Brown ZT_SIG_REGS_OFFSET, 551ee072cf7SMark Brown ZT_SIG_REGS_SIZE(1)); 552ee072cf7SMark Brown if (err) 553ee072cf7SMark Brown return -EFAULT; 554ee072cf7SMark Brown 555ee072cf7SMark Brown return 0; 556ee072cf7SMark Brown } 557ee072cf7SMark Brown 55839782210SMark Brown #else /* ! CONFIG_ARM64_SME */ 55939782210SMark Brown 56039782210SMark Brown /* Turn any non-optimised out attempts to use these into a link error: */ 56139e54499SMark Brown extern int preserve_tpidr2_context(void __user *ctx); 56239e54499SMark Brown extern int restore_tpidr2_context(struct user_ctxs *user); 56339782210SMark Brown extern int preserve_za_context(void __user *ctx); 56439782210SMark Brown extern int restore_za_context(struct user_ctxs *user); 565ee072cf7SMark Brown extern int preserve_zt_context(void __user *ctx); 566ee072cf7SMark Brown extern int restore_zt_context(struct user_ctxs *user); 56739782210SMark Brown 56839782210SMark Brown #endif /* ! CONFIG_ARM64_SME */ 5698cd969d2SDave Martin 57047ccb028SDave Martin static int parse_user_sigframe(struct user_ctxs *user, 57147ccb028SDave Martin struct rt_sigframe __user *sf) 57247ccb028SDave Martin { 57347ccb028SDave Martin struct sigcontext __user *const sc = &sf->uc.uc_mcontext; 574bb4891a6SDave Martin struct _aarch64_ctx __user *head; 575bb4891a6SDave Martin char __user *base = (char __user *)&sc->__reserved; 57647ccb028SDave Martin size_t offset = 0; 577bb4891a6SDave Martin size_t limit = sizeof(sc->__reserved); 57833f08261SDave Martin bool have_extra_context = false; 57933f08261SDave Martin char const __user *const sfp = (char const __user *)sf; 58047ccb028SDave Martin 58147ccb028SDave Martin user->fpsimd = NULL; 5828cd969d2SDave Martin user->sve = NULL; 58339e54499SMark Brown user->tpidr2 = NULL; 58439782210SMark Brown user->za = NULL; 585ee072cf7SMark Brown user->zt = NULL; 58647ccb028SDave Martin 587bb4891a6SDave Martin if (!IS_ALIGNED((unsigned long)base, 16)) 58847ccb028SDave Martin goto invalid; 58947ccb028SDave Martin 590bb4891a6SDave Martin while (1) { 591bb4891a6SDave Martin int err = 0; 592bb4891a6SDave Martin u32 magic, size; 59333f08261SDave Martin char const __user *userp; 59433f08261SDave Martin struct extra_context const __user *extra; 59533f08261SDave Martin u64 extra_datap; 59633f08261SDave Martin u32 extra_size; 59733f08261SDave Martin struct _aarch64_ctx const __user *end; 59833f08261SDave Martin u32 end_magic, end_size; 599bb4891a6SDave Martin 600bb4891a6SDave Martin if (limit - offset < sizeof(*head)) 601bb4891a6SDave Martin goto invalid; 602bb4891a6SDave Martin 603bb4891a6SDave Martin if (!IS_ALIGNED(offset, 16)) 604bb4891a6SDave Martin goto invalid; 605bb4891a6SDave Martin 606bb4891a6SDave Martin head = (struct _aarch64_ctx __user *)(base + offset); 60747ccb028SDave Martin __get_user_error(magic, &head->magic, err); 60847ccb028SDave Martin __get_user_error(size, &head->size, err); 60947ccb028SDave Martin if (err) 61047ccb028SDave Martin return err; 61147ccb028SDave Martin 612bb4891a6SDave Martin if (limit - offset < size) 613bb4891a6SDave Martin goto invalid; 614bb4891a6SDave Martin 61547ccb028SDave Martin switch (magic) { 61647ccb028SDave Martin case 0: 61747ccb028SDave Martin if (size) 61847ccb028SDave Martin goto invalid; 61947ccb028SDave Martin 62047ccb028SDave Martin goto done; 62147ccb028SDave Martin 62247ccb028SDave Martin case FPSIMD_MAGIC: 6236d502b6bSSuzuki K Poulose if (!system_supports_fpsimd()) 6246d502b6bSSuzuki K Poulose goto invalid; 62547ccb028SDave Martin if (user->fpsimd) 62647ccb028SDave Martin goto invalid; 62747ccb028SDave Martin 62847ccb028SDave Martin user->fpsimd = (struct fpsimd_context __user *)head; 629b57682b3SMark Brown user->fpsimd_size = size; 63047ccb028SDave Martin break; 63147ccb028SDave Martin 63247ccb028SDave Martin case ESR_MAGIC: 63347ccb028SDave Martin /* ignore */ 63447ccb028SDave Martin break; 63547ccb028SDave Martin 6368cd969d2SDave Martin case SVE_MAGIC: 63785ed24daSMark Brown if (!system_supports_sve() && !system_supports_sme()) 6388cd969d2SDave Martin goto invalid; 6398cd969d2SDave Martin 6408cd969d2SDave Martin if (user->sve) 6418cd969d2SDave Martin goto invalid; 6428cd969d2SDave Martin 6438cd969d2SDave Martin user->sve = (struct sve_context __user *)head; 644b57682b3SMark Brown user->sve_size = size; 6458cd969d2SDave Martin break; 6468cd969d2SDave Martin 64739e54499SMark Brown case TPIDR2_MAGIC: 64839e54499SMark Brown if (!system_supports_sme()) 64939e54499SMark Brown goto invalid; 65039e54499SMark Brown 65139e54499SMark Brown if (user->tpidr2) 65239e54499SMark Brown goto invalid; 65339e54499SMark Brown 65439e54499SMark Brown user->tpidr2 = (struct tpidr2_context __user *)head; 655b57682b3SMark Brown user->tpidr2_size = size; 65639e54499SMark Brown break; 65739e54499SMark Brown 65839782210SMark Brown case ZA_MAGIC: 65939782210SMark Brown if (!system_supports_sme()) 66039782210SMark Brown goto invalid; 66139782210SMark Brown 66239782210SMark Brown if (user->za) 66339782210SMark Brown goto invalid; 66439782210SMark Brown 66539782210SMark Brown user->za = (struct za_context __user *)head; 666b57682b3SMark Brown user->za_size = size; 66739782210SMark Brown break; 66839782210SMark Brown 669ee072cf7SMark Brown case ZT_MAGIC: 670ee072cf7SMark Brown if (!system_supports_sme2()) 671ee072cf7SMark Brown goto invalid; 672ee072cf7SMark Brown 673ee072cf7SMark Brown if (user->zt) 674ee072cf7SMark Brown goto invalid; 675ee072cf7SMark Brown 676ee072cf7SMark Brown user->zt = (struct zt_context __user *)head; 677b57682b3SMark Brown user->zt_size = size; 678ee072cf7SMark Brown break; 679ee072cf7SMark Brown 68033f08261SDave Martin case EXTRA_MAGIC: 68133f08261SDave Martin if (have_extra_context) 68233f08261SDave Martin goto invalid; 68333f08261SDave Martin 68433f08261SDave Martin if (size < sizeof(*extra)) 68533f08261SDave Martin goto invalid; 68633f08261SDave Martin 68733f08261SDave Martin userp = (char const __user *)head; 68833f08261SDave Martin 68933f08261SDave Martin extra = (struct extra_context const __user *)userp; 69033f08261SDave Martin userp += size; 69133f08261SDave Martin 69233f08261SDave Martin __get_user_error(extra_datap, &extra->datap, err); 69333f08261SDave Martin __get_user_error(extra_size, &extra->size, err); 69433f08261SDave Martin if (err) 69533f08261SDave Martin return err; 69633f08261SDave Martin 69733f08261SDave Martin /* Check for the dummy terminator in __reserved[]: */ 69833f08261SDave Martin 69933f08261SDave Martin if (limit - offset - size < TERMINATOR_SIZE) 70033f08261SDave Martin goto invalid; 70133f08261SDave Martin 70233f08261SDave Martin end = (struct _aarch64_ctx const __user *)userp; 70333f08261SDave Martin userp += TERMINATOR_SIZE; 70433f08261SDave Martin 70533f08261SDave Martin __get_user_error(end_magic, &end->magic, err); 70633f08261SDave Martin __get_user_error(end_size, &end->size, err); 70733f08261SDave Martin if (err) 70833f08261SDave Martin return err; 70933f08261SDave Martin 71033f08261SDave Martin if (end_magic || end_size) 71133f08261SDave Martin goto invalid; 71233f08261SDave Martin 71333f08261SDave Martin /* Prevent looping/repeated parsing of extra_context */ 71433f08261SDave Martin have_extra_context = true; 71533f08261SDave Martin 71633f08261SDave Martin base = (__force void __user *)extra_datap; 71733f08261SDave Martin if (!IS_ALIGNED((unsigned long)base, 16)) 71833f08261SDave Martin goto invalid; 71933f08261SDave Martin 72033f08261SDave Martin if (!IS_ALIGNED(extra_size, 16)) 72133f08261SDave Martin goto invalid; 72233f08261SDave Martin 72333f08261SDave Martin if (base != userp) 72433f08261SDave Martin goto invalid; 72533f08261SDave Martin 72633f08261SDave Martin /* Reject "unreasonably large" frames: */ 72733f08261SDave Martin if (extra_size > sfp + SIGFRAME_MAXSZ - userp) 72833f08261SDave Martin goto invalid; 72933f08261SDave Martin 73033f08261SDave Martin /* 73133f08261SDave Martin * Ignore trailing terminator in __reserved[] 73233f08261SDave Martin * and start parsing extra data: 73333f08261SDave Martin */ 73433f08261SDave Martin offset = 0; 73533f08261SDave Martin limit = extra_size; 736abf73988SDave Martin 73796d4f267SLinus Torvalds if (!access_ok(base, limit)) 738abf73988SDave Martin goto invalid; 739abf73988SDave Martin 74033f08261SDave Martin continue; 74133f08261SDave Martin 74247ccb028SDave Martin default: 74347ccb028SDave Martin goto invalid; 74447ccb028SDave Martin } 74547ccb028SDave Martin 74647ccb028SDave Martin if (size < sizeof(*head)) 74747ccb028SDave Martin goto invalid; 74847ccb028SDave Martin 749bb4891a6SDave Martin if (limit - offset < size) 75047ccb028SDave Martin goto invalid; 75147ccb028SDave Martin 75247ccb028SDave Martin offset += size; 75347ccb028SDave Martin } 75447ccb028SDave Martin 75547ccb028SDave Martin done: 75647ccb028SDave Martin return 0; 75747ccb028SDave Martin 75847ccb028SDave Martin invalid: 75947ccb028SDave Martin return -EINVAL; 76047ccb028SDave Martin } 76147ccb028SDave Martin 7622c020ed8SCatalin Marinas static int restore_sigframe(struct pt_regs *regs, 7632c020ed8SCatalin Marinas struct rt_sigframe __user *sf) 7642c020ed8SCatalin Marinas { 7652c020ed8SCatalin Marinas sigset_t set; 7662c020ed8SCatalin Marinas int i, err; 76747ccb028SDave Martin struct user_ctxs user; 7682c020ed8SCatalin Marinas 7692c020ed8SCatalin Marinas err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); 7702c020ed8SCatalin Marinas if (err == 0) 7712c020ed8SCatalin Marinas set_current_blocked(&set); 7722c020ed8SCatalin Marinas 7732c020ed8SCatalin Marinas for (i = 0; i < 31; i++) 7742c020ed8SCatalin Marinas __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], 7752c020ed8SCatalin Marinas err); 7762c020ed8SCatalin Marinas __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); 7772c020ed8SCatalin Marinas __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); 7782c020ed8SCatalin Marinas __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); 7792c020ed8SCatalin Marinas 7802c020ed8SCatalin Marinas /* 7812c020ed8SCatalin Marinas * Avoid sys_rt_sigreturn() restarting. 7822c020ed8SCatalin Marinas */ 78317c28958SDave Martin forget_syscall(regs); 7842c020ed8SCatalin Marinas 785dbd4d7caSMark Rutland err |= !valid_user_regs(®s->user_regs, current); 78647ccb028SDave Martin if (err == 0) 78747ccb028SDave Martin err = parse_user_sigframe(&user, sf); 7882c020ed8SCatalin Marinas 7896d502b6bSSuzuki K Poulose if (err == 0 && system_supports_fpsimd()) { 7908cd969d2SDave Martin if (!user.fpsimd) 7918cd969d2SDave Martin return -EINVAL; 7928cd969d2SDave Martin 793df07443fSMark Brown if (user.sve) 7948cd969d2SDave Martin err = restore_sve_fpsimd_context(&user); 795df07443fSMark Brown else 7964e4e9304SMark Brown err = restore_fpsimd_context(&user); 7978cd969d2SDave Martin } 7982c020ed8SCatalin Marinas 79939e54499SMark Brown if (err == 0 && system_supports_sme() && user.tpidr2) 80039e54499SMark Brown err = restore_tpidr2_context(&user); 80139e54499SMark Brown 80239782210SMark Brown if (err == 0 && system_supports_sme() && user.za) 80339782210SMark Brown err = restore_za_context(&user); 80439782210SMark Brown 805ee072cf7SMark Brown if (err == 0 && system_supports_sme2() && user.zt) 806ee072cf7SMark Brown err = restore_zt_context(&user); 807ee072cf7SMark Brown 8082c020ed8SCatalin Marinas return err; 8092c020ed8SCatalin Marinas } 8102c020ed8SCatalin Marinas 811bf4ce5ccSMark Rutland SYSCALL_DEFINE0(rt_sigreturn) 8122c020ed8SCatalin Marinas { 8133085e164SMark Rutland struct pt_regs *regs = current_pt_regs(); 8142c020ed8SCatalin Marinas struct rt_sigframe __user *frame; 8152c020ed8SCatalin Marinas 8162c020ed8SCatalin Marinas /* Always make any pending restarted system calls return -EINTR */ 817f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall; 8182c020ed8SCatalin Marinas 8192c020ed8SCatalin Marinas /* 8202c020ed8SCatalin Marinas * Since we stacked the signal on a 128-bit boundary, then 'sp' should 8212c020ed8SCatalin Marinas * be word aligned here. 8222c020ed8SCatalin Marinas */ 8232c020ed8SCatalin Marinas if (regs->sp & 15) 8242c020ed8SCatalin Marinas goto badframe; 8252c020ed8SCatalin Marinas 8262c020ed8SCatalin Marinas frame = (struct rt_sigframe __user *)regs->sp; 8272c020ed8SCatalin Marinas 82896d4f267SLinus Torvalds if (!access_ok(frame, sizeof (*frame))) 8292c020ed8SCatalin Marinas goto badframe; 8302c020ed8SCatalin Marinas 8312c020ed8SCatalin Marinas if (restore_sigframe(regs, frame)) 8322c020ed8SCatalin Marinas goto badframe; 8332c020ed8SCatalin Marinas 834207bdae4SAl Viro if (restore_altstack(&frame->uc.uc_stack)) 8352c020ed8SCatalin Marinas goto badframe; 8362c020ed8SCatalin Marinas 8372c020ed8SCatalin Marinas return regs->regs[0]; 8382c020ed8SCatalin Marinas 8392c020ed8SCatalin Marinas badframe: 840f71016a8SWill Deacon arm64_notify_segfault(regs->sp); 8412c020ed8SCatalin Marinas return 0; 8422c020ed8SCatalin Marinas } 8432c020ed8SCatalin Marinas 84494b07c1fSDave Martin /* 84594b07c1fSDave Martin * Determine the layout of optional records in the signal frame 84694b07c1fSDave Martin * 84794b07c1fSDave Martin * add_all: if true, lays out the biggest possible signal frame for 84894b07c1fSDave Martin * this task; otherwise, generates a layout for the current state 84994b07c1fSDave Martin * of the task. 85094b07c1fSDave Martin */ 85194b07c1fSDave Martin static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, 85294b07c1fSDave Martin bool add_all) 853bb4891a6SDave Martin { 854bb4322f7SDave Martin int err; 855bb4322f7SDave Martin 8560a32c88dSDavid Engraf if (system_supports_fpsimd()) { 857bb4322f7SDave Martin err = sigframe_alloc(user, &user->fpsimd_offset, 858bb4322f7SDave Martin sizeof(struct fpsimd_context)); 859bb4322f7SDave Martin if (err) 860bb4322f7SDave Martin return err; 8610a32c88dSDavid Engraf } 862bb4891a6SDave Martin 863bb4891a6SDave Martin /* fault information, if valid */ 86494b07c1fSDave Martin if (add_all || current->thread.fault_code) { 865bb4322f7SDave Martin err = sigframe_alloc(user, &user->esr_offset, 866bb4322f7SDave Martin sizeof(struct esr_context)); 867bb4322f7SDave Martin if (err) 868bb4322f7SDave Martin return err; 869bb4891a6SDave Martin } 870bb4891a6SDave Martin 8718cd969d2SDave Martin if (system_supports_sve()) { 8728cd969d2SDave Martin unsigned int vq = 0; 8738cd969d2SDave Martin 87485ed24daSMark Brown if (add_all || test_thread_flag(TIF_SVE) || 87585ed24daSMark Brown thread_sm_enabled(¤t->thread)) { 87685ed24daSMark Brown int vl = max(sve_max_vl(), sme_max_vl()); 87794b07c1fSDave Martin 87894b07c1fSDave Martin if (!add_all) 87985ed24daSMark Brown vl = thread_get_cur_vl(¤t->thread); 88094b07c1fSDave Martin 88194b07c1fSDave Martin vq = sve_vq_from_vl(vl); 88294b07c1fSDave Martin } 8838cd969d2SDave Martin 8848cd969d2SDave Martin err = sigframe_alloc(user, &user->sve_offset, 8858cd969d2SDave Martin SVE_SIG_CONTEXT_SIZE(vq)); 8868cd969d2SDave Martin if (err) 8878cd969d2SDave Martin return err; 8888cd969d2SDave Martin } 8898cd969d2SDave Martin 89039782210SMark Brown if (system_supports_sme()) { 89139782210SMark Brown unsigned int vl; 89239782210SMark Brown unsigned int vq = 0; 89339782210SMark Brown 89439782210SMark Brown if (add_all) 89539782210SMark Brown vl = sme_max_vl(); 89639782210SMark Brown else 89739782210SMark Brown vl = task_get_sme_vl(current); 89839782210SMark Brown 89939e54499SMark Brown err = sigframe_alloc(user, &user->tpidr2_offset, 90039e54499SMark Brown sizeof(struct tpidr2_context)); 90139e54499SMark Brown if (err) 90239e54499SMark Brown return err; 90339e54499SMark Brown 90439782210SMark Brown if (thread_za_enabled(¤t->thread)) 90539782210SMark Brown vq = sve_vq_from_vl(vl); 90639782210SMark Brown 90739782210SMark Brown err = sigframe_alloc(user, &user->za_offset, 90839782210SMark Brown ZA_SIG_CONTEXT_SIZE(vq)); 90939782210SMark Brown if (err) 91039782210SMark Brown return err; 91139782210SMark Brown } 91239782210SMark Brown 913ee072cf7SMark Brown if (system_supports_sme2()) { 914ee072cf7SMark Brown if (add_all || thread_za_enabled(¤t->thread)) { 915ee072cf7SMark Brown err = sigframe_alloc(user, &user->zt_offset, 916ee072cf7SMark Brown ZT_SIG_CONTEXT_SIZE(1)); 917ee072cf7SMark Brown if (err) 918ee072cf7SMark Brown return err; 919ee072cf7SMark Brown } 920ee072cf7SMark Brown } 921ee072cf7SMark Brown 92233f08261SDave Martin return sigframe_alloc_end(user); 923bb4891a6SDave Martin } 924bb4891a6SDave Martin 92520987de3SDave Martin static int setup_sigframe(struct rt_sigframe_user_layout *user, 9262c020ed8SCatalin Marinas struct pt_regs *regs, sigset_t *set) 9272c020ed8SCatalin Marinas { 9282c020ed8SCatalin Marinas int i, err = 0; 92920987de3SDave Martin struct rt_sigframe __user *sf = user->sigframe; 9302c020ed8SCatalin Marinas 931304ef4e8SWill Deacon /* set up the stack frame for unwinding */ 93220987de3SDave Martin __put_user_error(regs->regs[29], &user->next_frame->fp, err); 93320987de3SDave Martin __put_user_error(regs->regs[30], &user->next_frame->lr, err); 934304ef4e8SWill Deacon 9352c020ed8SCatalin Marinas for (i = 0; i < 31; i++) 9362c020ed8SCatalin Marinas __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], 9372c020ed8SCatalin Marinas err); 9382c020ed8SCatalin Marinas __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); 9392c020ed8SCatalin Marinas __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); 9402c020ed8SCatalin Marinas __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); 9412c020ed8SCatalin Marinas 9422c020ed8SCatalin Marinas __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); 9432c020ed8SCatalin Marinas 9442c020ed8SCatalin Marinas err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 9452c020ed8SCatalin Marinas 9466d502b6bSSuzuki K Poulose if (err == 0 && system_supports_fpsimd()) { 947bb4891a6SDave Martin struct fpsimd_context __user *fpsimd_ctx = 948bb4891a6SDave Martin apply_user_offset(user, user->fpsimd_offset); 9490e0276d1SCatalin Marinas err |= preserve_fpsimd_context(fpsimd_ctx); 9500e0276d1SCatalin Marinas } 9512c020ed8SCatalin Marinas 95215af1942SCatalin Marinas /* fault information, if valid */ 953bb4891a6SDave Martin if (err == 0 && user->esr_offset) { 954bb4891a6SDave Martin struct esr_context __user *esr_ctx = 955bb4891a6SDave Martin apply_user_offset(user, user->esr_offset); 956bb4891a6SDave Martin 95715af1942SCatalin Marinas __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err); 95815af1942SCatalin Marinas __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err); 95915af1942SCatalin Marinas __put_user_error(current->thread.fault_code, &esr_ctx->esr, err); 96015af1942SCatalin Marinas } 96115af1942SCatalin Marinas 96285ed24daSMark Brown /* Scalable Vector Extension state (including streaming), if present */ 96385ed24daSMark Brown if ((system_supports_sve() || system_supports_sme()) && 96485ed24daSMark Brown err == 0 && user->sve_offset) { 9658cd969d2SDave Martin struct sve_context __user *sve_ctx = 9668cd969d2SDave Martin apply_user_offset(user, user->sve_offset); 9678cd969d2SDave Martin err |= preserve_sve_context(sve_ctx); 9688cd969d2SDave Martin } 9698cd969d2SDave Martin 97039e54499SMark Brown /* TPIDR2 if supported */ 97139e54499SMark Brown if (system_supports_sme() && err == 0) { 97239e54499SMark Brown struct tpidr2_context __user *tpidr2_ctx = 97339e54499SMark Brown apply_user_offset(user, user->tpidr2_offset); 97439e54499SMark Brown err |= preserve_tpidr2_context(tpidr2_ctx); 97539e54499SMark Brown } 97639e54499SMark Brown 97739782210SMark Brown /* ZA state if present */ 97839782210SMark Brown if (system_supports_sme() && err == 0 && user->za_offset) { 97939782210SMark Brown struct za_context __user *za_ctx = 98039782210SMark Brown apply_user_offset(user, user->za_offset); 98139782210SMark Brown err |= preserve_za_context(za_ctx); 98239782210SMark Brown } 98339782210SMark Brown 984ee072cf7SMark Brown /* ZT state if present */ 985ee072cf7SMark Brown if (system_supports_sme2() && err == 0 && user->zt_offset) { 986ee072cf7SMark Brown struct zt_context __user *zt_ctx = 987ee072cf7SMark Brown apply_user_offset(user, user->zt_offset); 988ee072cf7SMark Brown err |= preserve_zt_context(zt_ctx); 989ee072cf7SMark Brown } 990ee072cf7SMark Brown 99133f08261SDave Martin if (err == 0 && user->extra_offset) { 99233f08261SDave Martin char __user *sfp = (char __user *)user->sigframe; 99333f08261SDave Martin char __user *userp = 99433f08261SDave Martin apply_user_offset(user, user->extra_offset); 99533f08261SDave Martin 99633f08261SDave Martin struct extra_context __user *extra; 99733f08261SDave Martin struct _aarch64_ctx __user *end; 99833f08261SDave Martin u64 extra_datap; 99933f08261SDave Martin u32 extra_size; 100033f08261SDave Martin 100133f08261SDave Martin extra = (struct extra_context __user *)userp; 100233f08261SDave Martin userp += EXTRA_CONTEXT_SIZE; 100333f08261SDave Martin 100433f08261SDave Martin end = (struct _aarch64_ctx __user *)userp; 100533f08261SDave Martin userp += TERMINATOR_SIZE; 100633f08261SDave Martin 100733f08261SDave Martin /* 100833f08261SDave Martin * extra_datap is just written to the signal frame. 100933f08261SDave Martin * The value gets cast back to a void __user * 101033f08261SDave Martin * during sigreturn. 101133f08261SDave Martin */ 101233f08261SDave Martin extra_datap = (__force u64)userp; 101333f08261SDave Martin extra_size = sfp + round_up(user->size, 16) - userp; 101433f08261SDave Martin 101533f08261SDave Martin __put_user_error(EXTRA_MAGIC, &extra->head.magic, err); 101633f08261SDave Martin __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err); 101733f08261SDave Martin __put_user_error(extra_datap, &extra->datap, err); 101833f08261SDave Martin __put_user_error(extra_size, &extra->size, err); 101933f08261SDave Martin 102033f08261SDave Martin /* Add the terminator */ 102133f08261SDave Martin __put_user_error(0, &end->magic, err); 102233f08261SDave Martin __put_user_error(0, &end->size, err); 102333f08261SDave Martin } 102433f08261SDave Martin 10252c020ed8SCatalin Marinas /* set the "end" magic */ 1026bb4891a6SDave Martin if (err == 0) { 1027bb4891a6SDave Martin struct _aarch64_ctx __user *end = 1028bb4891a6SDave Martin apply_user_offset(user, user->end_offset); 1029bb4891a6SDave Martin 10300e0276d1SCatalin Marinas __put_user_error(0, &end->magic, err); 10310e0276d1SCatalin Marinas __put_user_error(0, &end->size, err); 1032bb4891a6SDave Martin } 10332c020ed8SCatalin Marinas 10342c020ed8SCatalin Marinas return err; 10352c020ed8SCatalin Marinas } 10362c020ed8SCatalin Marinas 103720987de3SDave Martin static int get_sigframe(struct rt_sigframe_user_layout *user, 103820987de3SDave Martin struct ksignal *ksig, struct pt_regs *regs) 10392c020ed8SCatalin Marinas { 10402c020ed8SCatalin Marinas unsigned long sp, sp_top; 1041bb4891a6SDave Martin int err; 1042bb4891a6SDave Martin 1043bb4891a6SDave Martin init_user_layout(user); 104494b07c1fSDave Martin err = setup_sigframe_layout(user, false); 1045bb4891a6SDave Martin if (err) 1046bb4891a6SDave Martin return err; 10472c020ed8SCatalin Marinas 104838a7be3cSRichard Weinberger sp = sp_top = sigsp(regs->sp, ksig); 10492c020ed8SCatalin Marinas 105020987de3SDave Martin sp = round_down(sp - sizeof(struct frame_record), 16); 105120987de3SDave Martin user->next_frame = (struct frame_record __user *)sp; 105220987de3SDave Martin 1053bb4891a6SDave Martin sp = round_down(sp, 16) - sigframe_size(user); 105420987de3SDave Martin user->sigframe = (struct rt_sigframe __user *)sp; 10552c020ed8SCatalin Marinas 10562c020ed8SCatalin Marinas /* 10572c020ed8SCatalin Marinas * Check that we can actually write to the signal frame. 10582c020ed8SCatalin Marinas */ 105996d4f267SLinus Torvalds if (!access_ok(user->sigframe, sp_top - sp)) 106020987de3SDave Martin return -EFAULT; 10612c020ed8SCatalin Marinas 106220987de3SDave Martin return 0; 10632c020ed8SCatalin Marinas } 10642c020ed8SCatalin Marinas 1065304ef4e8SWill Deacon static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, 106620987de3SDave Martin struct rt_sigframe_user_layout *user, int usig) 10672c020ed8SCatalin Marinas { 10682c020ed8SCatalin Marinas __sigrestore_t sigtramp; 10692c020ed8SCatalin Marinas 10702c020ed8SCatalin Marinas regs->regs[0] = usig; 107120987de3SDave Martin regs->sp = (unsigned long)user->sigframe; 107220987de3SDave Martin regs->regs[29] = (unsigned long)&user->next_frame->fp; 10732c020ed8SCatalin Marinas regs->pc = (unsigned long)ka->sa.sa_handler; 10742c020ed8SCatalin Marinas 10758ef8f360SDave Martin /* 10768ef8f360SDave Martin * Signal delivery is a (wacky) indirect function call in 10778ef8f360SDave Martin * userspace, so simulate the same setting of BTYPE as a BLR 10788ef8f360SDave Martin * <register containing the signal handler entry point>. 10798ef8f360SDave Martin * Signal delivery to a location in a PROT_BTI guarded page 10808ef8f360SDave Martin * that is not a function entry point will now trigger a 10818ef8f360SDave Martin * SIGILL in userspace. 10828ef8f360SDave Martin * 10838ef8f360SDave Martin * If the signal handler entry point is not in a PROT_BTI 10848ef8f360SDave Martin * guarded page, this is harmless. 10858ef8f360SDave Martin */ 10868ef8f360SDave Martin if (system_supports_bti()) { 10878ef8f360SDave Martin regs->pstate &= ~PSR_BTYPE_MASK; 10888ef8f360SDave Martin regs->pstate |= PSR_BTYPE_C; 10898ef8f360SDave Martin } 10908ef8f360SDave Martin 1091637ec831SVincenzo Frascino /* TCO (Tag Check Override) always cleared for signal handlers */ 1092637ec831SVincenzo Frascino regs->pstate &= ~PSR_TCO_BIT; 1093637ec831SVincenzo Frascino 109440a8e87bSMark Brown /* Signal handlers are invoked with ZA and streaming mode disabled */ 109540a8e87bSMark Brown if (system_supports_sme()) { 1096ea64baacSMark Brown /* 1097ea64baacSMark Brown * If we were in streaming mode the saved register 1098ea64baacSMark Brown * state was SVE but we will exit SM and use the 1099ea64baacSMark Brown * FPSIMD register state - flush the saved FPSIMD 1100ea64baacSMark Brown * register state in case it gets loaded. 1101ea64baacSMark Brown */ 1102baa85152SMark Brown if (current->thread.svcr & SVCR_SM_MASK) { 1103ea64baacSMark Brown memset(¤t->thread.uw.fpsimd_state, 0, 1104ea64baacSMark Brown sizeof(current->thread.uw.fpsimd_state)); 1105baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 1106baa85152SMark Brown } 1107ea64baacSMark Brown 1108ec0067a6SMark Brown current->thread.svcr &= ~(SVCR_ZA_MASK | 1109ec0067a6SMark Brown SVCR_SM_MASK); 111040a8e87bSMark Brown sme_smstop(); 111140a8e87bSMark Brown } 111240a8e87bSMark Brown 11132c020ed8SCatalin Marinas if (ka->sa.sa_flags & SA_RESTORER) 11142c020ed8SCatalin Marinas sigtramp = ka->sa.sa_restorer; 11152c020ed8SCatalin Marinas else 11162c020ed8SCatalin Marinas sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); 11172c020ed8SCatalin Marinas 11182c020ed8SCatalin Marinas regs->regs[30] = (unsigned long)sigtramp; 11192c020ed8SCatalin Marinas } 11202c020ed8SCatalin Marinas 112100554fa4SRichard Weinberger static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, 112200554fa4SRichard Weinberger struct pt_regs *regs) 11232c020ed8SCatalin Marinas { 112420987de3SDave Martin struct rt_sigframe_user_layout user; 11252c020ed8SCatalin Marinas struct rt_sigframe __user *frame; 11262c020ed8SCatalin Marinas int err = 0; 11272c020ed8SCatalin Marinas 11288cd969d2SDave Martin fpsimd_signal_preserve_current_state(); 11298cd969d2SDave Martin 113020987de3SDave Martin if (get_sigframe(&user, ksig, regs)) 11312c020ed8SCatalin Marinas return 1; 11322c020ed8SCatalin Marinas 113320987de3SDave Martin frame = user.sigframe; 113420987de3SDave Martin 11352c020ed8SCatalin Marinas __put_user_error(0, &frame->uc.uc_flags, err); 11362c020ed8SCatalin Marinas __put_user_error(NULL, &frame->uc.uc_link, err); 11372c020ed8SCatalin Marinas 1138207bdae4SAl Viro err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 113920987de3SDave Martin err |= setup_sigframe(&user, regs, set); 1140304ef4e8SWill Deacon if (err == 0) { 114120987de3SDave Martin setup_return(regs, &ksig->ka, &user, usig); 114200554fa4SRichard Weinberger if (ksig->ka.sa.sa_flags & SA_SIGINFO) { 114300554fa4SRichard Weinberger err |= copy_siginfo_to_user(&frame->info, &ksig->info); 11442c020ed8SCatalin Marinas regs->regs[1] = (unsigned long)&frame->info; 11452c020ed8SCatalin Marinas regs->regs[2] = (unsigned long)&frame->uc; 11462c020ed8SCatalin Marinas } 1147304ef4e8SWill Deacon } 11482c020ed8SCatalin Marinas 11492c020ed8SCatalin Marinas return err; 11502c020ed8SCatalin Marinas } 11512c020ed8SCatalin Marinas 11522c020ed8SCatalin Marinas static void setup_restart_syscall(struct pt_regs *regs) 11532c020ed8SCatalin Marinas { 11542c020ed8SCatalin Marinas if (is_compat_task()) 11552c020ed8SCatalin Marinas compat_setup_restart_syscall(regs); 11562c020ed8SCatalin Marinas else 11572c020ed8SCatalin Marinas regs->regs[8] = __NR_restart_syscall; 11582c020ed8SCatalin Marinas } 11592c020ed8SCatalin Marinas 11602c020ed8SCatalin Marinas /* 11612c020ed8SCatalin Marinas * OK, we're invoking a handler 11622c020ed8SCatalin Marinas */ 116300554fa4SRichard Weinberger static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 11642c020ed8SCatalin Marinas { 11652c020ed8SCatalin Marinas sigset_t *oldset = sigmask_to_save(); 116600554fa4SRichard Weinberger int usig = ksig->sig; 11672c020ed8SCatalin Marinas int ret; 11682c020ed8SCatalin Marinas 1169409d5db4SWill Deacon rseq_signal_deliver(ksig, regs); 1170409d5db4SWill Deacon 11712c020ed8SCatalin Marinas /* 11722c020ed8SCatalin Marinas * Set up the stack frame 11732c020ed8SCatalin Marinas */ 11742c020ed8SCatalin Marinas if (is_compat_task()) { 117500554fa4SRichard Weinberger if (ksig->ka.sa.sa_flags & SA_SIGINFO) 117600554fa4SRichard Weinberger ret = compat_setup_rt_frame(usig, ksig, oldset, regs); 11772c020ed8SCatalin Marinas else 117800554fa4SRichard Weinberger ret = compat_setup_frame(usig, ksig, oldset, regs); 11792c020ed8SCatalin Marinas } else { 118000554fa4SRichard Weinberger ret = setup_rt_frame(usig, ksig, oldset, regs); 11812c020ed8SCatalin Marinas } 11822c020ed8SCatalin Marinas 11832c020ed8SCatalin Marinas /* 11842c020ed8SCatalin Marinas * Check that the resulting registers are actually sane. 11852c020ed8SCatalin Marinas */ 1186dbd4d7caSMark Rutland ret |= !valid_user_regs(®s->user_regs, current); 11872c020ed8SCatalin Marinas 1188ac2081cdSWill Deacon /* Step into the signal handler if we are stepping */ 1189ac2081cdSWill Deacon signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); 11902c020ed8SCatalin Marinas } 11912c020ed8SCatalin Marinas 11922c020ed8SCatalin Marinas /* 11932c020ed8SCatalin Marinas * Note that 'init' is a special process: it doesn't get signals it doesn't 11942c020ed8SCatalin Marinas * want to handle. Thus you cannot kill init even with a SIGKILL even by 11952c020ed8SCatalin Marinas * mistake. 11962c020ed8SCatalin Marinas * 11972c020ed8SCatalin Marinas * Note that we go through the signals twice: once to check the signals that 11982c020ed8SCatalin Marinas * the kernel can handle, and then we build all the user-level signal handling 11992c020ed8SCatalin Marinas * stack-frames in one go after that. 12002c020ed8SCatalin Marinas */ 12012c020ed8SCatalin Marinas static void do_signal(struct pt_regs *regs) 12022c020ed8SCatalin Marinas { 12032c020ed8SCatalin Marinas unsigned long continue_addr = 0, restart_addr = 0; 120400554fa4SRichard Weinberger int retval = 0; 120500554fa4SRichard Weinberger struct ksignal ksig; 12060fe42512SDave Martin bool syscall = in_syscall(regs); 12072c020ed8SCatalin Marinas 12082c020ed8SCatalin Marinas /* 12092c020ed8SCatalin Marinas * If we were from a system call, check for system call restarting... 12102c020ed8SCatalin Marinas */ 12110fe42512SDave Martin if (syscall) { 12122c020ed8SCatalin Marinas continue_addr = regs->pc; 12132c020ed8SCatalin Marinas restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); 12142c020ed8SCatalin Marinas retval = regs->regs[0]; 12152c020ed8SCatalin Marinas 12162c020ed8SCatalin Marinas /* 12172c020ed8SCatalin Marinas * Avoid additional syscall restarting via ret_to_user. 12182c020ed8SCatalin Marinas */ 121917c28958SDave Martin forget_syscall(regs); 12202c020ed8SCatalin Marinas 12212c020ed8SCatalin Marinas /* 12222c020ed8SCatalin Marinas * Prepare for system call restart. We do this here so that a 12232c020ed8SCatalin Marinas * debugger will see the already changed PC. 12242c020ed8SCatalin Marinas */ 12252c020ed8SCatalin Marinas switch (retval) { 12262c020ed8SCatalin Marinas case -ERESTARTNOHAND: 12272c020ed8SCatalin Marinas case -ERESTARTSYS: 12282c020ed8SCatalin Marinas case -ERESTARTNOINTR: 12292c020ed8SCatalin Marinas case -ERESTART_RESTARTBLOCK: 12302c020ed8SCatalin Marinas regs->regs[0] = regs->orig_x0; 12312c020ed8SCatalin Marinas regs->pc = restart_addr; 12322c020ed8SCatalin Marinas break; 12332c020ed8SCatalin Marinas } 12342c020ed8SCatalin Marinas } 12352c020ed8SCatalin Marinas 12362c020ed8SCatalin Marinas /* 12372c020ed8SCatalin Marinas * Get the signal to deliver. When running under ptrace, at this point 12382c020ed8SCatalin Marinas * the debugger may change all of our registers. 12392c020ed8SCatalin Marinas */ 124000554fa4SRichard Weinberger if (get_signal(&ksig)) { 12412c020ed8SCatalin Marinas /* 12422c020ed8SCatalin Marinas * Depending on the signal settings, we may need to revert the 12432c020ed8SCatalin Marinas * decision to restart the system call, but skip this if a 12442c020ed8SCatalin Marinas * debugger has chosen to restart at a different PC. 12452c020ed8SCatalin Marinas */ 12462c020ed8SCatalin Marinas if (regs->pc == restart_addr && 12472c020ed8SCatalin Marinas (retval == -ERESTARTNOHAND || 12482c020ed8SCatalin Marinas retval == -ERESTART_RESTARTBLOCK || 12492c020ed8SCatalin Marinas (retval == -ERESTARTSYS && 125000554fa4SRichard Weinberger !(ksig.ka.sa.sa_flags & SA_RESTART)))) { 1251e30e8d46SMark Rutland syscall_set_return_value(current, regs, -EINTR, 0); 12522c020ed8SCatalin Marinas regs->pc = continue_addr; 12532c020ed8SCatalin Marinas } 12542c020ed8SCatalin Marinas 125500554fa4SRichard Weinberger handle_signal(&ksig, regs); 12562c020ed8SCatalin Marinas return; 12572c020ed8SCatalin Marinas } 12582c020ed8SCatalin Marinas 12592c020ed8SCatalin Marinas /* 12602c020ed8SCatalin Marinas * Handle restarting a different system call. As above, if a debugger 12612c020ed8SCatalin Marinas * has chosen to restart at a different PC, ignore the restart. 12622c020ed8SCatalin Marinas */ 12630fe42512SDave Martin if (syscall && regs->pc == restart_addr) { 12642c020ed8SCatalin Marinas if (retval == -ERESTART_RESTARTBLOCK) 12652c020ed8SCatalin Marinas setup_restart_syscall(regs); 12662c020ed8SCatalin Marinas user_rewind_single_step(current); 12672c020ed8SCatalin Marinas } 12682c020ed8SCatalin Marinas 12692c020ed8SCatalin Marinas restore_saved_sigmask(); 12702c020ed8SCatalin Marinas } 12712c020ed8SCatalin Marinas 12724d1c2ee2SMark Rutland void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags) 12732c020ed8SCatalin Marinas { 1274a2048e34SThomas Garnier do { 1275421dd6faSChris Metcalf if (thread_flags & _TIF_NEED_RESCHED) { 12768d66772eSJames Morse /* Unmask Debug and SError for the next task */ 12778d66772eSJames Morse local_daif_restore(DAIF_PROCCTX_NOIRQ); 12788d66772eSJames Morse 1279421dd6faSChris Metcalf schedule(); 1280421dd6faSChris Metcalf } else { 12818d66772eSJames Morse local_daif_restore(DAIF_PROCCTX); 1282421dd6faSChris Metcalf 12839842ceaeSPratyush Anand if (thread_flags & _TIF_UPROBE) 12849842ceaeSPratyush Anand uprobe_notify_resume(regs); 12859842ceaeSPratyush Anand 1286637ec831SVincenzo Frascino if (thread_flags & _TIF_MTE_ASYNC_FAULT) { 1287637ec831SVincenzo Frascino clear_thread_flag(TIF_MTE_ASYNC_FAULT); 1288637ec831SVincenzo Frascino send_sig_fault(SIGSEGV, SEGV_MTEAERR, 1289637ec831SVincenzo Frascino (void __user *)NULL, current); 1290637ec831SVincenzo Frascino } 1291637ec831SVincenzo Frascino 1292192caabdSJens Axboe if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) 12932c020ed8SCatalin Marinas do_signal(regs); 12942c020ed8SCatalin Marinas 1295a68de80fSSean Christopherson if (thread_flags & _TIF_NOTIFY_RESUME) 129603248addSEric W. Biederman resume_user_mode_work(regs); 1297005f78cdSArd Biesheuvel 1298005f78cdSArd Biesheuvel if (thread_flags & _TIF_FOREIGN_FPSTATE) 1299005f78cdSArd Biesheuvel fpsimd_restore_current_state(); 1300421dd6faSChris Metcalf } 1301005f78cdSArd Biesheuvel 13028d66772eSJames Morse local_daif_mask(); 1303342b3808SMark Rutland thread_flags = read_thread_flags(); 1304421dd6faSChris Metcalf } while (thread_flags & _TIF_WORK_MASK); 13052c020ed8SCatalin Marinas } 130694b07c1fSDave Martin 130794b07c1fSDave Martin unsigned long __ro_after_init signal_minsigstksz; 130894b07c1fSDave Martin 130994b07c1fSDave Martin /* 131094b07c1fSDave Martin * Determine the stack space required for guaranteed signal devliery. 131194b07c1fSDave Martin * This function is used to populate AT_MINSIGSTKSZ at process startup. 131294b07c1fSDave Martin * cpufeatures setup is assumed to be complete. 131394b07c1fSDave Martin */ 131494b07c1fSDave Martin void __init minsigstksz_setup(void) 131594b07c1fSDave Martin { 131694b07c1fSDave Martin struct rt_sigframe_user_layout user; 131794b07c1fSDave Martin 131894b07c1fSDave Martin init_user_layout(&user); 131994b07c1fSDave Martin 132094b07c1fSDave Martin /* 132194b07c1fSDave Martin * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't 132294b07c1fSDave Martin * be big enough, but it's our best guess: 132394b07c1fSDave Martin */ 132494b07c1fSDave Martin if (WARN_ON(setup_sigframe_layout(&user, true))) 132594b07c1fSDave Martin return; 132694b07c1fSDave Martin 132794b07c1fSDave Martin signal_minsigstksz = sigframe_size(&user) + 132894b07c1fSDave Martin round_up(sizeof(struct frame_record), 16) + 132994b07c1fSDave Martin 16; /* max alignment padding */ 133094b07c1fSDave Martin } 1331726e337bSMarco Elver 1332726e337bSMarco Elver /* 1333726e337bSMarco Elver * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as 1334726e337bSMarco Elver * changes likely come with new fields that should be added below. 1335726e337bSMarco Elver */ 1336726e337bSMarco Elver static_assert(NSIGILL == 11); 1337726e337bSMarco Elver static_assert(NSIGFPE == 15); 1338726e337bSMarco Elver static_assert(NSIGSEGV == 9); 1339726e337bSMarco Elver static_assert(NSIGBUS == 5); 1340726e337bSMarco Elver static_assert(NSIGTRAP == 6); 1341726e337bSMarco Elver static_assert(NSIGCHLD == 6); 1342726e337bSMarco Elver static_assert(NSIGSYS == 2); 134350ae8130SEric W. Biederman static_assert(sizeof(siginfo_t) == 128); 134450ae8130SEric W. Biederman static_assert(__alignof__(siginfo_t) == 8); 1345726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_signo) == 0x00); 1346726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_errno) == 0x04); 1347726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_code) == 0x08); 1348726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pid) == 0x10); 1349726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_uid) == 0x14); 1350726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_tid) == 0x10); 1351726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_overrun) == 0x14); 1352726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_status) == 0x18); 1353726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_utime) == 0x20); 1354726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_stime) == 0x28); 1355726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_value) == 0x18); 1356726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_int) == 0x18); 1357726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_ptr) == 0x18); 1358726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr) == 0x10); 1359726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x18); 1360726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_lower) == 0x20); 1361726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_upper) == 0x28); 1362726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pkey) == 0x20); 1363726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_data) == 0x18); 1364726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_type) == 0x20); 136578ed93d7SMarco Elver static_assert(offsetof(siginfo_t, si_perf_flags) == 0x24); 1366726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_band) == 0x10); 1367726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_fd) == 0x18); 1368726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_call_addr) == 0x10); 1369726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_syscall) == 0x18); 1370726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_arch) == 0x1c); 1371