xref: /openbmc/linux/arch/arm64/kernel/signal.c (revision 60480c6b)
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>
268ada7aabSArnd Bergmann #include <asm/exception.h>
272c020ed8SCatalin Marinas #include <asm/cacheflush.h>
282c020ed8SCatalin Marinas #include <asm/ucontext.h>
292c020ed8SCatalin Marinas #include <asm/unistd.h>
302c020ed8SCatalin Marinas #include <asm/fpsimd.h>
3117c28958SDave Martin #include <asm/ptrace.h>
32e30e8d46SMark Rutland #include <asm/syscall.h>
332c020ed8SCatalin Marinas #include <asm/signal32.h>
34f71016a8SWill Deacon #include <asm/traps.h>
352c020ed8SCatalin Marinas #include <asm/vdso.h>
362c020ed8SCatalin Marinas 
372c020ed8SCatalin Marinas /*
382c020ed8SCatalin Marinas  * Do a signal return; undo the signal stack. These are aligned to 128-bit.
392c020ed8SCatalin Marinas  */
402c020ed8SCatalin Marinas struct rt_sigframe {
412c020ed8SCatalin Marinas 	struct siginfo info;
422c020ed8SCatalin Marinas 	struct ucontext uc;
4320987de3SDave Martin };
4420987de3SDave Martin 
4520987de3SDave Martin struct frame_record {
46304ef4e8SWill Deacon 	u64 fp;
47304ef4e8SWill Deacon 	u64 lr;
482c020ed8SCatalin Marinas };
492c020ed8SCatalin Marinas 
5020987de3SDave Martin struct rt_sigframe_user_layout {
5120987de3SDave Martin 	struct rt_sigframe __user *sigframe;
5220987de3SDave Martin 	struct frame_record __user *next_frame;
53bb4891a6SDave Martin 
54bb4891a6SDave Martin 	unsigned long size;	/* size of allocated sigframe data */
55bb4891a6SDave Martin 	unsigned long limit;	/* largest allowed size */
56bb4891a6SDave Martin 
57bb4891a6SDave Martin 	unsigned long fpsimd_offset;
58bb4891a6SDave Martin 	unsigned long esr_offset;
598cd969d2SDave Martin 	unsigned long sve_offset;
6039e54499SMark Brown 	unsigned long tpidr2_offset;
6139782210SMark Brown 	unsigned long za_offset;
62ee072cf7SMark Brown 	unsigned long zt_offset;
6333f08261SDave Martin 	unsigned long extra_offset;
64bb4891a6SDave Martin 	unsigned long end_offset;
6520987de3SDave Martin };
6620987de3SDave Martin 
6733f08261SDave Martin #define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
6833f08261SDave Martin #define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
6933f08261SDave Martin #define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
7033f08261SDave Martin 
init_user_layout(struct rt_sigframe_user_layout * user)71bb4891a6SDave Martin static void init_user_layout(struct rt_sigframe_user_layout *user)
72bb4891a6SDave Martin {
7333f08261SDave Martin 	const size_t reserved_size =
7433f08261SDave Martin 		sizeof(user->sigframe->uc.uc_mcontext.__reserved);
7533f08261SDave Martin 
76bb4891a6SDave Martin 	memset(user, 0, sizeof(*user));
77bb4891a6SDave Martin 	user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved);
78bb4891a6SDave Martin 
7933f08261SDave Martin 	user->limit = user->size + reserved_size;
8033f08261SDave Martin 
8133f08261SDave Martin 	user->limit -= TERMINATOR_SIZE;
8233f08261SDave Martin 	user->limit -= EXTRA_CONTEXT_SIZE;
8333f08261SDave Martin 	/* Reserve space for extension and terminator ^ */
84bb4891a6SDave Martin }
85bb4891a6SDave Martin 
sigframe_size(struct rt_sigframe_user_layout const * user)86bb4891a6SDave Martin static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
87bb4891a6SDave Martin {
88bb4891a6SDave Martin 	return round_up(max(user->size, sizeof(struct rt_sigframe)), 16);
89bb4891a6SDave Martin }
90bb4891a6SDave Martin 
91bb4322f7SDave Martin /*
9233f08261SDave Martin  * Sanity limit on the approximate maximum size of signal frame we'll
9333f08261SDave Martin  * try to generate.  Stack alignment padding and the frame record are
9433f08261SDave Martin  * not taken into account.  This limit is not a guarantee and is
9533f08261SDave Martin  * NOT ABI.
9633f08261SDave Martin  */
977ddcaf78SMark Brown #define SIGFRAME_MAXSZ SZ_256K
9833f08261SDave Martin 
__sigframe_alloc(struct rt_sigframe_user_layout * user,unsigned long * offset,size_t size,bool extend)9933f08261SDave Martin static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
10033f08261SDave Martin 			    unsigned long *offset, size_t size, bool extend)
10133f08261SDave Martin {
10233f08261SDave Martin 	size_t padded_size = round_up(size, 16);
10333f08261SDave Martin 
10433f08261SDave Martin 	if (padded_size > user->limit - user->size &&
10533f08261SDave Martin 	    !user->extra_offset &&
10633f08261SDave Martin 	    extend) {
10733f08261SDave Martin 		int ret;
10833f08261SDave Martin 
10933f08261SDave Martin 		user->limit += EXTRA_CONTEXT_SIZE;
11033f08261SDave Martin 		ret = __sigframe_alloc(user, &user->extra_offset,
11133f08261SDave Martin 				       sizeof(struct extra_context), false);
11233f08261SDave Martin 		if (ret) {
11333f08261SDave Martin 			user->limit -= EXTRA_CONTEXT_SIZE;
11433f08261SDave Martin 			return ret;
11533f08261SDave Martin 		}
11633f08261SDave Martin 
11733f08261SDave Martin 		/* Reserve space for the __reserved[] terminator */
11833f08261SDave Martin 		user->size += TERMINATOR_SIZE;
11933f08261SDave Martin 
12033f08261SDave Martin 		/*
12133f08261SDave Martin 		 * Allow expansion up to SIGFRAME_MAXSZ, ensuring space for
12233f08261SDave Martin 		 * the terminator:
12333f08261SDave Martin 		 */
12433f08261SDave Martin 		user->limit = SIGFRAME_MAXSZ - TERMINATOR_SIZE;
12533f08261SDave Martin 	}
12633f08261SDave Martin 
12733f08261SDave Martin 	/* Still not enough space?  Bad luck! */
12833f08261SDave Martin 	if (padded_size > user->limit - user->size)
12933f08261SDave Martin 		return -ENOMEM;
13033f08261SDave Martin 
13133f08261SDave Martin 	*offset = user->size;
13233f08261SDave Martin 	user->size += padded_size;
13333f08261SDave Martin 
13433f08261SDave Martin 	return 0;
13533f08261SDave Martin }
13633f08261SDave Martin 
13733f08261SDave Martin /*
138bb4322f7SDave Martin  * Allocate space for an optional record of <size> bytes in the user
139bb4322f7SDave Martin  * signal frame.  The offset from the signal frame base address to the
140bb4322f7SDave Martin  * allocated block is assigned to *offset.
141bb4322f7SDave Martin  */
sigframe_alloc(struct rt_sigframe_user_layout * user,unsigned long * offset,size_t size)142bb4322f7SDave Martin static int sigframe_alloc(struct rt_sigframe_user_layout *user,
143bb4322f7SDave Martin 			  unsigned long *offset, size_t size)
144bb4322f7SDave Martin {
14533f08261SDave Martin 	return __sigframe_alloc(user, offset, size, true);
14633f08261SDave Martin }
147bb4322f7SDave Martin 
14833f08261SDave Martin /* Allocate the null terminator record and prevent further allocations */
sigframe_alloc_end(struct rt_sigframe_user_layout * user)14933f08261SDave Martin static int sigframe_alloc_end(struct rt_sigframe_user_layout *user)
15033f08261SDave Martin {
15133f08261SDave Martin 	int ret;
152bb4322f7SDave Martin 
15333f08261SDave Martin 	/* Un-reserve the space reserved for the terminator: */
15433f08261SDave Martin 	user->limit += TERMINATOR_SIZE;
15533f08261SDave Martin 
15633f08261SDave Martin 	ret = sigframe_alloc(user, &user->end_offset,
15733f08261SDave Martin 			     sizeof(struct _aarch64_ctx));
15833f08261SDave Martin 	if (ret)
15933f08261SDave Martin 		return ret;
16033f08261SDave Martin 
16133f08261SDave Martin 	/* Prevent further allocation: */
16233f08261SDave Martin 	user->limit = user->size;
163bb4322f7SDave Martin 	return 0;
164bb4322f7SDave Martin }
165bb4322f7SDave Martin 
apply_user_offset(struct rt_sigframe_user_layout const * user,unsigned long offset)166bb4891a6SDave Martin static void __user *apply_user_offset(
167bb4891a6SDave Martin 	struct rt_sigframe_user_layout const *user, unsigned long offset)
168bb4891a6SDave Martin {
169bb4891a6SDave Martin 	char __user *base = (char __user *)user->sigframe;
170bb4891a6SDave Martin 
171bb4891a6SDave Martin 	return base + offset;
172bb4891a6SDave Martin }
173bb4891a6SDave Martin 
1744e4e9304SMark Brown struct user_ctxs {
1754e4e9304SMark Brown 	struct fpsimd_context __user *fpsimd;
176b57682b3SMark Brown 	u32 fpsimd_size;
1774e4e9304SMark Brown 	struct sve_context __user *sve;
178b57682b3SMark Brown 	u32 sve_size;
1794e4e9304SMark Brown 	struct tpidr2_context __user *tpidr2;
180b57682b3SMark Brown 	u32 tpidr2_size;
1814e4e9304SMark Brown 	struct za_context __user *za;
182b57682b3SMark Brown 	u32 za_size;
1834e4e9304SMark Brown 	struct zt_context __user *zt;
184b57682b3SMark Brown 	u32 zt_size;
1854e4e9304SMark Brown };
1864e4e9304SMark Brown 
preserve_fpsimd_context(struct fpsimd_context __user * ctx)1872c020ed8SCatalin Marinas static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
1882c020ed8SCatalin Marinas {
18965896545SDave Martin 	struct user_fpsimd_state const *fpsimd =
19065896545SDave Martin 		&current->thread.uw.fpsimd_state;
1912c020ed8SCatalin Marinas 	int err;
1922c020ed8SCatalin Marinas 
1932c020ed8SCatalin Marinas 	/* copy the FP and status/control registers */
1942c020ed8SCatalin Marinas 	err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs));
1952c020ed8SCatalin Marinas 	__put_user_error(fpsimd->fpsr, &ctx->fpsr, err);
1962c020ed8SCatalin Marinas 	__put_user_error(fpsimd->fpcr, &ctx->fpcr, err);
1972c020ed8SCatalin Marinas 
1982c020ed8SCatalin Marinas 	/* copy the magic/size information */
1992c020ed8SCatalin Marinas 	__put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err);
2002c020ed8SCatalin Marinas 	__put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err);
2012c020ed8SCatalin Marinas 
2022c020ed8SCatalin Marinas 	return err ? -EFAULT : 0;
2032c020ed8SCatalin Marinas }
2042c020ed8SCatalin Marinas 
restore_fpsimd_context(struct user_ctxs * user)2054e4e9304SMark Brown static int restore_fpsimd_context(struct user_ctxs *user)
2062c020ed8SCatalin Marinas {
2070abdeff5SDave Martin 	struct user_fpsimd_state fpsimd;
2082c020ed8SCatalin Marinas 	int err = 0;
2092c020ed8SCatalin Marinas 
21092f14518SMark Brown 	/* check the size information */
211b57682b3SMark Brown 	if (user->fpsimd_size != sizeof(struct fpsimd_context))
2122c020ed8SCatalin Marinas 		return -EINVAL;
2132c020ed8SCatalin Marinas 
2142c020ed8SCatalin Marinas 	/* copy the FP and status/control registers */
2154e4e9304SMark Brown 	err = __copy_from_user(fpsimd.vregs, &(user->fpsimd->vregs),
2162c020ed8SCatalin Marinas 			       sizeof(fpsimd.vregs));
2174e4e9304SMark Brown 	__get_user_error(fpsimd.fpsr, &(user->fpsimd->fpsr), err);
2184e4e9304SMark Brown 	__get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err);
2192c020ed8SCatalin Marinas 
2208cd969d2SDave Martin 	clear_thread_flag(TIF_SVE);
221baa85152SMark Brown 	current->thread.fp_type = FP_STATE_FPSIMD;
2228cd969d2SDave Martin 
2232c020ed8SCatalin Marinas 	/* load the hardware registers from the fpsimd_state structure */
224c51f9269SArd Biesheuvel 	if (!err)
225c51f9269SArd Biesheuvel 		fpsimd_update_current_state(&fpsimd);
2262c020ed8SCatalin Marinas 
2272c020ed8SCatalin Marinas 	return err ? -EFAULT : 0;
2282c020ed8SCatalin Marinas }
2292c020ed8SCatalin Marinas 
2308cd969d2SDave Martin 
2318cd969d2SDave Martin #ifdef CONFIG_ARM64_SVE
2328cd969d2SDave Martin 
preserve_sve_context(struct sve_context __user * ctx)2338cd969d2SDave Martin static int preserve_sve_context(struct sve_context __user *ctx)
2348cd969d2SDave Martin {
2358cd969d2SDave Martin 	int err = 0;
2368cd969d2SDave Martin 	u16 reserved[ARRAY_SIZE(ctx->__reserved)];
23785ed24daSMark Brown 	u16 flags = 0;
2380423eedcSMark Brown 	unsigned int vl = task_get_sve_vl(current);
2398cd969d2SDave Martin 	unsigned int vq = 0;
2408cd969d2SDave Martin 
24185ed24daSMark Brown 	if (thread_sm_enabled(&current->thread)) {
24285ed24daSMark Brown 		vl = task_get_sme_vl(current);
2438cd969d2SDave Martin 		vq = sve_vq_from_vl(vl);
24485ed24daSMark Brown 		flags |= SVE_SIG_FLAG_SM;
245*60480c6bSMark Brown 	} else if (current->thread.fp_type == FP_STATE_SVE) {
24685ed24daSMark Brown 		vq = sve_vq_from_vl(vl);
24785ed24daSMark Brown 	}
2488cd969d2SDave Martin 
2498cd969d2SDave Martin 	memset(reserved, 0, sizeof(reserved));
2508cd969d2SDave Martin 
2518cd969d2SDave Martin 	__put_user_error(SVE_MAGIC, &ctx->head.magic, err);
2528cd969d2SDave Martin 	__put_user_error(round_up(SVE_SIG_CONTEXT_SIZE(vq), 16),
2538cd969d2SDave Martin 			 &ctx->head.size, err);
2548cd969d2SDave Martin 	__put_user_error(vl, &ctx->vl, err);
25585ed24daSMark Brown 	__put_user_error(flags, &ctx->flags, err);
2568cd969d2SDave Martin 	BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved));
2578cd969d2SDave Martin 	err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved));
2588cd969d2SDave Martin 
2598cd969d2SDave Martin 	if (vq) {
2608cd969d2SDave Martin 		/*
2618cd969d2SDave Martin 		 * This assumes that the SVE state has already been saved to
26268a4c52eSJulien Grall 		 * the task struct by calling the function
26368a4c52eSJulien Grall 		 * fpsimd_signal_preserve_current_state().
2648cd969d2SDave Martin 		 */
2658cd969d2SDave Martin 		err |= __copy_to_user((char __user *)ctx + SVE_SIG_REGS_OFFSET,
2668cd969d2SDave Martin 				      current->thread.sve_state,
2678cd969d2SDave Martin 				      SVE_SIG_REGS_SIZE(vq));
2688cd969d2SDave Martin 	}
2698cd969d2SDave Martin 
2708cd969d2SDave Martin 	return err ? -EFAULT : 0;
2718cd969d2SDave Martin }
2728cd969d2SDave Martin 
restore_sve_fpsimd_context(struct user_ctxs * user)2738cd969d2SDave Martin static int restore_sve_fpsimd_context(struct user_ctxs *user)
2748cd969d2SDave Martin {
275f3ac48aaSMark Brown 	int err = 0;
27685ed24daSMark Brown 	unsigned int vl, vq;
2770abdeff5SDave Martin 	struct user_fpsimd_state fpsimd;
278f3ac48aaSMark Brown 	u16 user_vl, flags;
2798cd969d2SDave Martin 
280b57682b3SMark Brown 	if (user->sve_size < sizeof(*user->sve))
281b57682b3SMark Brown 		return -EINVAL;
2828cd969d2SDave Martin 
283f3ac48aaSMark Brown 	__get_user_error(user_vl, &(user->sve->vl), err);
284f3ac48aaSMark Brown 	__get_user_error(flags, &(user->sve->flags), err);
285f3ac48aaSMark Brown 	if (err)
286f3ac48aaSMark Brown 		return err;
2878cd969d2SDave Martin 
288f3ac48aaSMark Brown 	if (flags & SVE_SIG_FLAG_SM) {
28985ed24daSMark Brown 		if (!system_supports_sme())
29085ed24daSMark Brown 			return -EINVAL;
29185ed24daSMark Brown 
29285ed24daSMark Brown 		vl = task_get_sme_vl(current);
29385ed24daSMark Brown 	} else {
2947dde62f0SMark Brown 		/*
2957dde62f0SMark Brown 		 * A SME only system use SVE for streaming mode so can
2967dde62f0SMark Brown 		 * have a SVE formatted context with a zero VL and no
2977dde62f0SMark Brown 		 * payload data.
2987dde62f0SMark Brown 		 */
2997dde62f0SMark Brown 		if (!system_supports_sve() && !system_supports_sme())
300df07443fSMark Brown 			return -EINVAL;
301df07443fSMark Brown 
30285ed24daSMark Brown 		vl = task_get_sve_vl(current);
30385ed24daSMark Brown 	}
30485ed24daSMark Brown 
305f3ac48aaSMark Brown 	if (user_vl != vl)
3068cd969d2SDave Martin 		return -EINVAL;
3078cd969d2SDave Martin 
308b57682b3SMark Brown 	if (user->sve_size == sizeof(*user->sve)) {
3098cd969d2SDave Martin 		clear_thread_flag(TIF_SVE);
310ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_SM_MASK;
311baa85152SMark Brown 		current->thread.fp_type = FP_STATE_FPSIMD;
3128cd969d2SDave Martin 		goto fpsimd_only;
3138cd969d2SDave Martin 	}
3148cd969d2SDave Martin 
315f3ac48aaSMark Brown 	vq = sve_vq_from_vl(vl);
3168cd969d2SDave Martin 
317b57682b3SMark Brown 	if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq))
3188cd969d2SDave Martin 		return -EINVAL;
3198cd969d2SDave Martin 
3208cd969d2SDave Martin 	/*
3218cd969d2SDave Martin 	 * Careful: we are about __copy_from_user() directly into
3228cd969d2SDave Martin 	 * thread.sve_state with preemption enabled, so protection is
3238cd969d2SDave Martin 	 * needed to prevent a racing context switch from writing stale
3248cd969d2SDave Martin 	 * registers back over the new data.
3258cd969d2SDave Martin 	 */
3268cd969d2SDave Martin 
3278cd969d2SDave Martin 	fpsimd_flush_task_state(current);
3288cd969d2SDave Martin 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
3298cd969d2SDave Martin 
330826a4fddSMark Brown 	sve_alloc(current, true);
3317559b7d7SMark Brown 	if (!current->thread.sve_state) {
3327559b7d7SMark Brown 		clear_thread_flag(TIF_SVE);
3337559b7d7SMark Brown 		return -ENOMEM;
3347559b7d7SMark Brown 	}
3357559b7d7SMark Brown 
3368cd969d2SDave Martin 	err = __copy_from_user(current->thread.sve_state,
3378cd969d2SDave Martin 			       (char __user const *)user->sve +
3388cd969d2SDave Martin 					SVE_SIG_REGS_OFFSET,
3398cd969d2SDave Martin 			       SVE_SIG_REGS_SIZE(vq));
3408cd969d2SDave Martin 	if (err)
3418cd969d2SDave Martin 		return -EFAULT;
3428cd969d2SDave Martin 
343f3ac48aaSMark Brown 	if (flags & SVE_SIG_FLAG_SM)
344ec0067a6SMark Brown 		current->thread.svcr |= SVCR_SM_MASK;
34585ed24daSMark Brown 	else
3468cd969d2SDave Martin 		set_thread_flag(TIF_SVE);
347baa85152SMark Brown 	current->thread.fp_type = FP_STATE_SVE;
3488cd969d2SDave Martin 
3498cd969d2SDave Martin fpsimd_only:
3508cd969d2SDave Martin 	/* copy the FP and status/control registers */
3518cd969d2SDave Martin 	/* restore_sigframe() already checked that user->fpsimd != NULL. */
3528cd969d2SDave Martin 	err = __copy_from_user(fpsimd.vregs, user->fpsimd->vregs,
3538cd969d2SDave Martin 			       sizeof(fpsimd.vregs));
3548cd969d2SDave Martin 	__get_user_error(fpsimd.fpsr, &user->fpsimd->fpsr, err);
3558cd969d2SDave Martin 	__get_user_error(fpsimd.fpcr, &user->fpsimd->fpcr, err);
3568cd969d2SDave Martin 
3578cd969d2SDave Martin 	/* load the hardware registers from the fpsimd_state structure */
3588cd969d2SDave Martin 	if (!err)
3598cd969d2SDave Martin 		fpsimd_update_current_state(&fpsimd);
3608cd969d2SDave Martin 
3618cd969d2SDave Martin 	return err ? -EFAULT : 0;
3628cd969d2SDave Martin }
3638cd969d2SDave Martin 
3648cd969d2SDave Martin #else /* ! CONFIG_ARM64_SVE */
3658cd969d2SDave Martin 
restore_sve_fpsimd_context(struct user_ctxs * user)366df07443fSMark Brown static int restore_sve_fpsimd_context(struct user_ctxs *user)
367df07443fSMark Brown {
368df07443fSMark Brown 	WARN_ON_ONCE(1);
369df07443fSMark Brown 	return -EINVAL;
370df07443fSMark Brown }
371df07443fSMark Brown 
372df07443fSMark Brown /* Turn any non-optimised out attempts to use this into a link error: */
3738cd969d2SDave Martin extern int preserve_sve_context(void __user *ctx);
3748cd969d2SDave Martin 
3758cd969d2SDave Martin #endif /* ! CONFIG_ARM64_SVE */
3768cd969d2SDave Martin 
37739782210SMark Brown #ifdef CONFIG_ARM64_SME
37839782210SMark Brown 
preserve_tpidr2_context(struct tpidr2_context __user * ctx)37939e54499SMark Brown static int preserve_tpidr2_context(struct tpidr2_context __user *ctx)
38039e54499SMark Brown {
38139e54499SMark Brown 	int err = 0;
38239e54499SMark Brown 
38339e54499SMark Brown 	current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);
38439e54499SMark Brown 
38539e54499SMark Brown 	__put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err);
38639e54499SMark Brown 	__put_user_error(sizeof(*ctx), &ctx->head.size, err);
38739e54499SMark Brown 	__put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err);
38839e54499SMark Brown 
38939e54499SMark Brown 	return err;
39039e54499SMark Brown }
39139e54499SMark Brown 
restore_tpidr2_context(struct user_ctxs * user)39239e54499SMark Brown static int restore_tpidr2_context(struct user_ctxs *user)
39339e54499SMark Brown {
39439e54499SMark Brown 	u64 tpidr2_el0;
39539e54499SMark Brown 	int err = 0;
39639e54499SMark Brown 
397b57682b3SMark Brown 	if (user->tpidr2_size != sizeof(*user->tpidr2))
398b57682b3SMark Brown 		return -EINVAL;
399b57682b3SMark Brown 
40039e54499SMark Brown 	__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
40139e54499SMark Brown 	if (!err)
402616cb2f4SMark Brown 		write_sysreg_s(tpidr2_el0, SYS_TPIDR2_EL0);
40339e54499SMark Brown 
40439e54499SMark Brown 	return err;
40539e54499SMark Brown }
40639e54499SMark Brown 
preserve_za_context(struct za_context __user * ctx)40739782210SMark Brown static int preserve_za_context(struct za_context __user *ctx)
40839782210SMark Brown {
40939782210SMark Brown 	int err = 0;
41039782210SMark Brown 	u16 reserved[ARRAY_SIZE(ctx->__reserved)];
41139782210SMark Brown 	unsigned int vl = task_get_sme_vl(current);
41239782210SMark Brown 	unsigned int vq;
41339782210SMark Brown 
41439782210SMark Brown 	if (thread_za_enabled(&current->thread))
41539782210SMark Brown 		vq = sve_vq_from_vl(vl);
41639782210SMark Brown 	else
41739782210SMark Brown 		vq = 0;
41839782210SMark Brown 
41939782210SMark Brown 	memset(reserved, 0, sizeof(reserved));
42039782210SMark Brown 
42139782210SMark Brown 	__put_user_error(ZA_MAGIC, &ctx->head.magic, err);
42239782210SMark Brown 	__put_user_error(round_up(ZA_SIG_CONTEXT_SIZE(vq), 16),
42339782210SMark Brown 			 &ctx->head.size, err);
42439782210SMark Brown 	__put_user_error(vl, &ctx->vl, err);
42539782210SMark Brown 	BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved));
42639782210SMark Brown 	err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved));
42739782210SMark Brown 
42839782210SMark Brown 	if (vq) {
42939782210SMark Brown 		/*
43039782210SMark Brown 		 * This assumes that the ZA state has already been saved to
43139782210SMark Brown 		 * the task struct by calling the function
43239782210SMark Brown 		 * fpsimd_signal_preserve_current_state().
43339782210SMark Brown 		 */
43439782210SMark Brown 		err |= __copy_to_user((char __user *)ctx + ZA_SIG_REGS_OFFSET,
435ce514000SMark Brown 				      current->thread.sme_state,
43639782210SMark Brown 				      ZA_SIG_REGS_SIZE(vq));
43739782210SMark Brown 	}
43839782210SMark Brown 
43939782210SMark Brown 	return err ? -EFAULT : 0;
44039782210SMark Brown }
44139782210SMark Brown 
restore_za_context(struct user_ctxs * user)4421bec877bSCatalin Marinas static int restore_za_context(struct user_ctxs *user)
44339782210SMark Brown {
44424d68345SMark Brown 	int err = 0;
44539782210SMark Brown 	unsigned int vq;
44624d68345SMark Brown 	u16 user_vl;
44739782210SMark Brown 
448b57682b3SMark Brown 	if (user->za_size < sizeof(*user->za))
44939782210SMark Brown 		return -EINVAL;
45039782210SMark Brown 
45124d68345SMark Brown 	__get_user_error(user_vl, &(user->za->vl), err);
45224d68345SMark Brown 	if (err)
45324d68345SMark Brown 		return err;
45439782210SMark Brown 
45524d68345SMark Brown 	if (user_vl != task_get_sme_vl(current))
45639782210SMark Brown 		return -EINVAL;
45739782210SMark Brown 
458b57682b3SMark Brown 	if (user->za_size == sizeof(*user->za)) {
459ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_ZA_MASK;
46039782210SMark Brown 		return 0;
46139782210SMark Brown 	}
46239782210SMark Brown 
46324d68345SMark Brown 	vq = sve_vq_from_vl(user_vl);
46439782210SMark Brown 
465b57682b3SMark Brown 	if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq))
46639782210SMark Brown 		return -EINVAL;
46739782210SMark Brown 
46839782210SMark Brown 	/*
46939782210SMark Brown 	 * Careful: we are about __copy_from_user() directly into
470ce514000SMark Brown 	 * thread.sme_state with preemption enabled, so protection is
47139782210SMark Brown 	 * needed to prevent a racing context switch from writing stale
47239782210SMark Brown 	 * registers back over the new data.
47339782210SMark Brown 	 */
47439782210SMark Brown 
47539782210SMark Brown 	fpsimd_flush_task_state(current);
47639782210SMark Brown 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
47739782210SMark Brown 
4785d0a8d2fSMark Brown 	sme_alloc(current, true);
479ce514000SMark Brown 	if (!current->thread.sme_state) {
480ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_ZA_MASK;
48139782210SMark Brown 		clear_thread_flag(TIF_SME);
48239782210SMark Brown 		return -ENOMEM;
48339782210SMark Brown 	}
48439782210SMark Brown 
485ce514000SMark Brown 	err = __copy_from_user(current->thread.sme_state,
48639782210SMark Brown 			       (char __user const *)user->za +
48739782210SMark Brown 					ZA_SIG_REGS_OFFSET,
48839782210SMark Brown 			       ZA_SIG_REGS_SIZE(vq));
48939782210SMark Brown 	if (err)
49039782210SMark Brown 		return -EFAULT;
49139782210SMark Brown 
49239782210SMark Brown 	set_thread_flag(TIF_SME);
493ec0067a6SMark Brown 	current->thread.svcr |= SVCR_ZA_MASK;
49439782210SMark Brown 
49539782210SMark Brown 	return 0;
49639782210SMark Brown }
497ee072cf7SMark Brown 
preserve_zt_context(struct zt_context __user * ctx)498ee072cf7SMark Brown static int preserve_zt_context(struct zt_context __user *ctx)
499ee072cf7SMark Brown {
500ee072cf7SMark Brown 	int err = 0;
501ee072cf7SMark Brown 	u16 reserved[ARRAY_SIZE(ctx->__reserved)];
502ee072cf7SMark Brown 
503ee072cf7SMark Brown 	if (WARN_ON(!thread_za_enabled(&current->thread)))
504ee072cf7SMark Brown 		return -EINVAL;
505ee072cf7SMark Brown 
506ee072cf7SMark Brown 	memset(reserved, 0, sizeof(reserved));
507ee072cf7SMark Brown 
508ee072cf7SMark Brown 	__put_user_error(ZT_MAGIC, &ctx->head.magic, err);
509ee072cf7SMark Brown 	__put_user_error(round_up(ZT_SIG_CONTEXT_SIZE(1), 16),
510ee072cf7SMark Brown 			 &ctx->head.size, err);
511ee072cf7SMark Brown 	__put_user_error(1, &ctx->nregs, err);
512ee072cf7SMark Brown 	BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved));
513ee072cf7SMark Brown 	err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved));
514ee072cf7SMark Brown 
515ee072cf7SMark Brown 	/*
516ee072cf7SMark Brown 	 * This assumes that the ZT state has already been saved to
517ee072cf7SMark Brown 	 * the task struct by calling the function
518ee072cf7SMark Brown 	 * fpsimd_signal_preserve_current_state().
519ee072cf7SMark Brown 	 */
520ee072cf7SMark Brown 	err |= __copy_to_user((char __user *)ctx + ZT_SIG_REGS_OFFSET,
521ee072cf7SMark Brown 			      thread_zt_state(&current->thread),
522ee072cf7SMark Brown 			      ZT_SIG_REGS_SIZE(1));
523ee072cf7SMark Brown 
524ee072cf7SMark Brown 	return err ? -EFAULT : 0;
525ee072cf7SMark Brown }
526ee072cf7SMark Brown 
restore_zt_context(struct user_ctxs * user)527ee072cf7SMark Brown static int restore_zt_context(struct user_ctxs *user)
528ee072cf7SMark Brown {
529ee072cf7SMark Brown 	int err;
530ad678be4SMark Brown 	u16 nregs;
531ee072cf7SMark Brown 
532ee072cf7SMark Brown 	/* ZA must be restored first for this check to be valid */
533ee072cf7SMark Brown 	if (!thread_za_enabled(&current->thread))
534ee072cf7SMark Brown 		return -EINVAL;
535ee072cf7SMark Brown 
536b57682b3SMark Brown 	if (user->zt_size != ZT_SIG_CONTEXT_SIZE(1))
537b57682b3SMark Brown 		return -EINVAL;
538b57682b3SMark Brown 
539ad678be4SMark Brown 	if (__copy_from_user(&nregs, &(user->zt->nregs), sizeof(nregs)))
540ee072cf7SMark Brown 		return -EFAULT;
541ee072cf7SMark Brown 
542ad678be4SMark Brown 	if (nregs != 1)
543ee072cf7SMark Brown 		return -EINVAL;
544ee072cf7SMark Brown 
545ee072cf7SMark Brown 	/*
546ee072cf7SMark Brown 	 * Careful: we are about __copy_from_user() directly into
547ee072cf7SMark Brown 	 * thread.zt_state with preemption enabled, so protection is
548ee072cf7SMark Brown 	 * needed to prevent a racing context switch from writing stale
549ee072cf7SMark Brown 	 * registers back over the new data.
550ee072cf7SMark Brown 	 */
551ee072cf7SMark Brown 
552ee072cf7SMark Brown 	fpsimd_flush_task_state(current);
553ee072cf7SMark Brown 	/* From now, fpsimd_thread_switch() won't touch ZT in thread state */
554ee072cf7SMark Brown 
555ee072cf7SMark Brown 	err = __copy_from_user(thread_zt_state(&current->thread),
556ee072cf7SMark Brown 			       (char __user const *)user->zt +
557ee072cf7SMark Brown 					ZT_SIG_REGS_OFFSET,
558ee072cf7SMark Brown 			       ZT_SIG_REGS_SIZE(1));
559ee072cf7SMark Brown 	if (err)
560ee072cf7SMark Brown 		return -EFAULT;
561ee072cf7SMark Brown 
562ee072cf7SMark Brown 	return 0;
563ee072cf7SMark Brown }
564ee072cf7SMark Brown 
56539782210SMark Brown #else /* ! CONFIG_ARM64_SME */
56639782210SMark Brown 
56739782210SMark Brown /* Turn any non-optimised out attempts to use these into a link error: */
56839e54499SMark Brown extern int preserve_tpidr2_context(void __user *ctx);
56939e54499SMark Brown extern int restore_tpidr2_context(struct user_ctxs *user);
57039782210SMark Brown extern int preserve_za_context(void __user *ctx);
57139782210SMark Brown extern int restore_za_context(struct user_ctxs *user);
572ee072cf7SMark Brown extern int preserve_zt_context(void __user *ctx);
573ee072cf7SMark Brown extern int restore_zt_context(struct user_ctxs *user);
57439782210SMark Brown 
57539782210SMark Brown #endif /* ! CONFIG_ARM64_SME */
5768cd969d2SDave Martin 
parse_user_sigframe(struct user_ctxs * user,struct rt_sigframe __user * sf)57747ccb028SDave Martin static int parse_user_sigframe(struct user_ctxs *user,
57847ccb028SDave Martin 			       struct rt_sigframe __user *sf)
57947ccb028SDave Martin {
58047ccb028SDave Martin 	struct sigcontext __user *const sc = &sf->uc.uc_mcontext;
581bb4891a6SDave Martin 	struct _aarch64_ctx __user *head;
582bb4891a6SDave Martin 	char __user *base = (char __user *)&sc->__reserved;
58347ccb028SDave Martin 	size_t offset = 0;
584bb4891a6SDave Martin 	size_t limit = sizeof(sc->__reserved);
58533f08261SDave Martin 	bool have_extra_context = false;
58633f08261SDave Martin 	char const __user *const sfp = (char const __user *)sf;
58747ccb028SDave Martin 
58847ccb028SDave Martin 	user->fpsimd = NULL;
5898cd969d2SDave Martin 	user->sve = NULL;
59039e54499SMark Brown 	user->tpidr2 = NULL;
59139782210SMark Brown 	user->za = NULL;
592ee072cf7SMark Brown 	user->zt = NULL;
59347ccb028SDave Martin 
594bb4891a6SDave Martin 	if (!IS_ALIGNED((unsigned long)base, 16))
59547ccb028SDave Martin 		goto invalid;
59647ccb028SDave Martin 
597bb4891a6SDave Martin 	while (1) {
598bb4891a6SDave Martin 		int err = 0;
599bb4891a6SDave Martin 		u32 magic, size;
60033f08261SDave Martin 		char const __user *userp;
60133f08261SDave Martin 		struct extra_context const __user *extra;
60233f08261SDave Martin 		u64 extra_datap;
60333f08261SDave Martin 		u32 extra_size;
60433f08261SDave Martin 		struct _aarch64_ctx const __user *end;
60533f08261SDave Martin 		u32 end_magic, end_size;
606bb4891a6SDave Martin 
607bb4891a6SDave Martin 		if (limit - offset < sizeof(*head))
608bb4891a6SDave Martin 			goto invalid;
609bb4891a6SDave Martin 
610bb4891a6SDave Martin 		if (!IS_ALIGNED(offset, 16))
611bb4891a6SDave Martin 			goto invalid;
612bb4891a6SDave Martin 
613bb4891a6SDave Martin 		head = (struct _aarch64_ctx __user *)(base + offset);
61447ccb028SDave Martin 		__get_user_error(magic, &head->magic, err);
61547ccb028SDave Martin 		__get_user_error(size, &head->size, err);
61647ccb028SDave Martin 		if (err)
61747ccb028SDave Martin 			return err;
61847ccb028SDave Martin 
619bb4891a6SDave Martin 		if (limit - offset < size)
620bb4891a6SDave Martin 			goto invalid;
621bb4891a6SDave Martin 
62247ccb028SDave Martin 		switch (magic) {
62347ccb028SDave Martin 		case 0:
62447ccb028SDave Martin 			if (size)
62547ccb028SDave Martin 				goto invalid;
62647ccb028SDave Martin 
62747ccb028SDave Martin 			goto done;
62847ccb028SDave Martin 
62947ccb028SDave Martin 		case FPSIMD_MAGIC:
6306d502b6bSSuzuki K Poulose 			if (!system_supports_fpsimd())
6316d502b6bSSuzuki K Poulose 				goto invalid;
63247ccb028SDave Martin 			if (user->fpsimd)
63347ccb028SDave Martin 				goto invalid;
63447ccb028SDave Martin 
63547ccb028SDave Martin 			user->fpsimd = (struct fpsimd_context __user *)head;
636b57682b3SMark Brown 			user->fpsimd_size = size;
63747ccb028SDave Martin 			break;
63847ccb028SDave Martin 
63947ccb028SDave Martin 		case ESR_MAGIC:
64047ccb028SDave Martin 			/* ignore */
64147ccb028SDave Martin 			break;
64247ccb028SDave Martin 
6438cd969d2SDave Martin 		case SVE_MAGIC:
64485ed24daSMark Brown 			if (!system_supports_sve() && !system_supports_sme())
6458cd969d2SDave Martin 				goto invalid;
6468cd969d2SDave Martin 
6478cd969d2SDave Martin 			if (user->sve)
6488cd969d2SDave Martin 				goto invalid;
6498cd969d2SDave Martin 
6508cd969d2SDave Martin 			user->sve = (struct sve_context __user *)head;
651b57682b3SMark Brown 			user->sve_size = size;
6528cd969d2SDave Martin 			break;
6538cd969d2SDave Martin 
65439e54499SMark Brown 		case TPIDR2_MAGIC:
655e9d14f3fSDongxu Sun 			if (!system_supports_tpidr2())
65647ccb028SDave Martin 				goto invalid;
65747ccb028SDave Martin 
65839e54499SMark Brown 			if (user->tpidr2)
65939e54499SMark Brown 				goto invalid;
66039e54499SMark Brown 
66139e54499SMark Brown 			user->tpidr2 = (struct tpidr2_context __user *)head;
662b57682b3SMark Brown 			user->tpidr2_size = size;
66347ccb028SDave Martin 			break;
66447ccb028SDave Martin 
66539782210SMark Brown 		case ZA_MAGIC:
66639782210SMark Brown 			if (!system_supports_sme())
66739782210SMark Brown 				goto invalid;
66839782210SMark Brown 
66939782210SMark Brown 			if (user->za)
67039782210SMark Brown 				goto invalid;
67139782210SMark Brown 
67239782210SMark Brown 			user->za = (struct za_context __user *)head;
673b57682b3SMark Brown 			user->za_size = size;
67439782210SMark Brown 			break;
67539782210SMark Brown 
676ee072cf7SMark Brown 		case ZT_MAGIC:
677ee072cf7SMark Brown 			if (!system_supports_sme2())
67847ccb028SDave Martin 				goto invalid;
67947ccb028SDave Martin 
680ee072cf7SMark Brown 			if (user->zt)
681ee072cf7SMark Brown 				goto invalid;
682ee072cf7SMark Brown 
683ee072cf7SMark Brown 			user->zt = (struct zt_context __user *)head;
684b57682b3SMark Brown 			user->zt_size = size;
68547ccb028SDave Martin 			break;
68647ccb028SDave Martin 
68733f08261SDave Martin 		case EXTRA_MAGIC:
68833f08261SDave Martin 			if (have_extra_context)
68933f08261SDave Martin 				goto invalid;
69033f08261SDave Martin 
69133f08261SDave Martin 			if (size < sizeof(*extra))
69233f08261SDave Martin 				goto invalid;
69333f08261SDave Martin 
69433f08261SDave Martin 			userp = (char const __user *)head;
69533f08261SDave Martin 
69633f08261SDave Martin 			extra = (struct extra_context const __user *)userp;
69733f08261SDave Martin 			userp += size;
69833f08261SDave Martin 
69933f08261SDave Martin 			__get_user_error(extra_datap, &extra->datap, err);
70033f08261SDave Martin 			__get_user_error(extra_size, &extra->size, err);
70133f08261SDave Martin 			if (err)
70233f08261SDave Martin 				return err;
70333f08261SDave Martin 
70433f08261SDave Martin 			/* Check for the dummy terminator in __reserved[]: */
70533f08261SDave Martin 
70633f08261SDave Martin 			if (limit - offset - size < TERMINATOR_SIZE)
70733f08261SDave Martin 				goto invalid;
70833f08261SDave Martin 
70933f08261SDave Martin 			end = (struct _aarch64_ctx const __user *)userp;
71033f08261SDave Martin 			userp += TERMINATOR_SIZE;
71133f08261SDave Martin 
71233f08261SDave Martin 			__get_user_error(end_magic, &end->magic, err);
71333f08261SDave Martin 			__get_user_error(end_size, &end->size, err);
71433f08261SDave Martin 			if (err)
71533f08261SDave Martin 				return err;
71633f08261SDave Martin 
71733f08261SDave Martin 			if (end_magic || end_size)
71833f08261SDave Martin 				goto invalid;
71933f08261SDave Martin 
72033f08261SDave Martin 			/* Prevent looping/repeated parsing of extra_context */
72133f08261SDave Martin 			have_extra_context = true;
72233f08261SDave Martin 
72333f08261SDave Martin 			base = (__force void __user *)extra_datap;
72433f08261SDave Martin 			if (!IS_ALIGNED((unsigned long)base, 16))
72533f08261SDave Martin 				goto invalid;
72633f08261SDave Martin 
72733f08261SDave Martin 			if (!IS_ALIGNED(extra_size, 16))
72833f08261SDave Martin 				goto invalid;
72933f08261SDave Martin 
73033f08261SDave Martin 			if (base != userp)
73133f08261SDave Martin 				goto invalid;
73233f08261SDave Martin 
73333f08261SDave Martin 			/* Reject "unreasonably large" frames: */
73433f08261SDave Martin 			if (extra_size > sfp + SIGFRAME_MAXSZ - userp)
73533f08261SDave Martin 				goto invalid;
73633f08261SDave Martin 
73733f08261SDave Martin 			/*
73833f08261SDave Martin 			 * Ignore trailing terminator in __reserved[]
73933f08261SDave Martin 			 * and start parsing extra data:
74033f08261SDave Martin 			 */
74133f08261SDave Martin 			offset = 0;
74233f08261SDave Martin 			limit = extra_size;
743abf73988SDave Martin 
74496d4f267SLinus Torvalds 			if (!access_ok(base, limit))
745abf73988SDave Martin 				goto invalid;
746abf73988SDave Martin 
74733f08261SDave Martin 			continue;
74833f08261SDave Martin 
74947ccb028SDave Martin 		default:
75047ccb028SDave Martin 			goto invalid;
75147ccb028SDave Martin 		}
75247ccb028SDave Martin 
75347ccb028SDave Martin 		if (size < sizeof(*head))
75447ccb028SDave Martin 			goto invalid;
75547ccb028SDave Martin 
756bb4891a6SDave Martin 		if (limit - offset < size)
75747ccb028SDave Martin 			goto invalid;
75847ccb028SDave Martin 
75947ccb028SDave Martin 		offset += size;
76047ccb028SDave Martin 	}
76147ccb028SDave Martin 
76247ccb028SDave Martin done:
76347ccb028SDave Martin 	return 0;
76447ccb028SDave Martin 
76547ccb028SDave Martin invalid:
76647ccb028SDave Martin 	return -EINVAL;
76747ccb028SDave Martin }
76847ccb028SDave Martin 
restore_sigframe(struct pt_regs * regs,struct rt_sigframe __user * sf)7692c020ed8SCatalin Marinas static int restore_sigframe(struct pt_regs *regs,
7702c020ed8SCatalin Marinas 			    struct rt_sigframe __user *sf)
7712c020ed8SCatalin Marinas {
7722c020ed8SCatalin Marinas 	sigset_t set;
7732c020ed8SCatalin Marinas 	int i, err;
77447ccb028SDave Martin 	struct user_ctxs user;
7752c020ed8SCatalin Marinas 
7762c020ed8SCatalin Marinas 	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
7772c020ed8SCatalin Marinas 	if (err == 0)
7782c020ed8SCatalin Marinas 		set_current_blocked(&set);
7792c020ed8SCatalin Marinas 
7802c020ed8SCatalin Marinas 	for (i = 0; i < 31; i++)
7812c020ed8SCatalin Marinas 		__get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
7822c020ed8SCatalin Marinas 				 err);
7832c020ed8SCatalin Marinas 	__get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
7842c020ed8SCatalin Marinas 	__get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
7852c020ed8SCatalin Marinas 	__get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
7862c020ed8SCatalin Marinas 
7872c020ed8SCatalin Marinas 	/*
7882c020ed8SCatalin Marinas 	 * Avoid sys_rt_sigreturn() restarting.
7892c020ed8SCatalin Marinas 	 */
79017c28958SDave Martin 	forget_syscall(regs);
7912c020ed8SCatalin Marinas 
792dbd4d7caSMark Rutland 	err |= !valid_user_regs(&regs->user_regs, current);
79347ccb028SDave Martin 	if (err == 0)
79447ccb028SDave Martin 		err = parse_user_sigframe(&user, sf);
7952c020ed8SCatalin Marinas 
7966d502b6bSSuzuki K Poulose 	if (err == 0 && system_supports_fpsimd()) {
7978cd969d2SDave Martin 		if (!user.fpsimd)
7988cd969d2SDave Martin 			return -EINVAL;
7998cd969d2SDave Martin 
800df07443fSMark Brown 		if (user.sve)
8018cd969d2SDave Martin 			err = restore_sve_fpsimd_context(&user);
802df07443fSMark Brown 		else
8034e4e9304SMark Brown 			err = restore_fpsimd_context(&user);
8048cd969d2SDave Martin 	}
8052c020ed8SCatalin Marinas 
806e9d14f3fSDongxu Sun 	if (err == 0 && system_supports_tpidr2() && user.tpidr2)
80739e54499SMark Brown 		err = restore_tpidr2_context(&user);
80839e54499SMark Brown 
80939782210SMark Brown 	if (err == 0 && system_supports_sme() && user.za)
81039782210SMark Brown 		err = restore_za_context(&user);
81139782210SMark Brown 
812ee072cf7SMark Brown 	if (err == 0 && system_supports_sme2() && user.zt)
813ee072cf7SMark Brown 		err = restore_zt_context(&user);
814ee072cf7SMark Brown 
8152c020ed8SCatalin Marinas 	return err;
8162c020ed8SCatalin Marinas }
8172c020ed8SCatalin Marinas 
SYSCALL_DEFINE0(rt_sigreturn)818bf4ce5ccSMark Rutland SYSCALL_DEFINE0(rt_sigreturn)
8192c020ed8SCatalin Marinas {
8203085e164SMark Rutland 	struct pt_regs *regs = current_pt_regs();
8212c020ed8SCatalin Marinas 	struct rt_sigframe __user *frame;
8222c020ed8SCatalin Marinas 
8232c020ed8SCatalin Marinas 	/* Always make any pending restarted system calls return -EINTR */
824f56141e3SAndy Lutomirski 	current->restart_block.fn = do_no_restart_syscall;
8252c020ed8SCatalin Marinas 
8262c020ed8SCatalin Marinas 	/*
8272c020ed8SCatalin Marinas 	 * Since we stacked the signal on a 128-bit boundary, then 'sp' should
8282c020ed8SCatalin Marinas 	 * be word aligned here.
8292c020ed8SCatalin Marinas 	 */
8302c020ed8SCatalin Marinas 	if (regs->sp & 15)
8312c020ed8SCatalin Marinas 		goto badframe;
8322c020ed8SCatalin Marinas 
8332c020ed8SCatalin Marinas 	frame = (struct rt_sigframe __user *)regs->sp;
8342c020ed8SCatalin Marinas 
83596d4f267SLinus Torvalds 	if (!access_ok(frame, sizeof (*frame)))
8362c020ed8SCatalin Marinas 		goto badframe;
8372c020ed8SCatalin Marinas 
8382c020ed8SCatalin Marinas 	if (restore_sigframe(regs, frame))
8392c020ed8SCatalin Marinas 		goto badframe;
8402c020ed8SCatalin Marinas 
841207bdae4SAl Viro 	if (restore_altstack(&frame->uc.uc_stack))
8422c020ed8SCatalin Marinas 		goto badframe;
8432c020ed8SCatalin Marinas 
8442c020ed8SCatalin Marinas 	return regs->regs[0];
8452c020ed8SCatalin Marinas 
8462c020ed8SCatalin Marinas badframe:
847f71016a8SWill Deacon 	arm64_notify_segfault(regs->sp);
8482c020ed8SCatalin Marinas 	return 0;
8492c020ed8SCatalin Marinas }
8502c020ed8SCatalin Marinas 
85194b07c1fSDave Martin /*
85294b07c1fSDave Martin  * Determine the layout of optional records in the signal frame
85394b07c1fSDave Martin  *
85494b07c1fSDave Martin  * add_all: if true, lays out the biggest possible signal frame for
85594b07c1fSDave Martin  *	this task; otherwise, generates a layout for the current state
85694b07c1fSDave Martin  *	of the task.
85794b07c1fSDave Martin  */
setup_sigframe_layout(struct rt_sigframe_user_layout * user,bool add_all)85894b07c1fSDave Martin static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
85994b07c1fSDave Martin 				 bool add_all)
860bb4891a6SDave Martin {
861bb4322f7SDave Martin 	int err;
862bb4322f7SDave Martin 
8630a32c88dSDavid Engraf 	if (system_supports_fpsimd()) {
864bb4322f7SDave Martin 		err = sigframe_alloc(user, &user->fpsimd_offset,
865bb4322f7SDave Martin 				     sizeof(struct fpsimd_context));
866bb4322f7SDave Martin 		if (err)
867bb4322f7SDave Martin 			return err;
8680a32c88dSDavid Engraf 	}
869bb4891a6SDave Martin 
870bb4891a6SDave Martin 	/* fault information, if valid */
87194b07c1fSDave Martin 	if (add_all || current->thread.fault_code) {
872bb4322f7SDave Martin 		err = sigframe_alloc(user, &user->esr_offset,
873bb4322f7SDave Martin 				     sizeof(struct esr_context));
874bb4322f7SDave Martin 		if (err)
875bb4322f7SDave Martin 			return err;
876bb4891a6SDave Martin 	}
877bb4891a6SDave Martin 
878f26cd737SMark Brown 	if (system_supports_sve() || system_supports_sme()) {
8798cd969d2SDave Martin 		unsigned int vq = 0;
8808cd969d2SDave Martin 
881*60480c6bSMark Brown 		if (add_all || current->thread.fp_type == FP_STATE_SVE ||
88285ed24daSMark Brown 		    thread_sm_enabled(&current->thread)) {
88385ed24daSMark Brown 			int vl = max(sve_max_vl(), sme_max_vl());
88494b07c1fSDave Martin 
88594b07c1fSDave Martin 			if (!add_all)
88685ed24daSMark Brown 				vl = thread_get_cur_vl(&current->thread);
88794b07c1fSDave Martin 
88894b07c1fSDave Martin 			vq = sve_vq_from_vl(vl);
88994b07c1fSDave Martin 		}
8908cd969d2SDave Martin 
8918cd969d2SDave Martin 		err = sigframe_alloc(user, &user->sve_offset,
8928cd969d2SDave Martin 				     SVE_SIG_CONTEXT_SIZE(vq));
8938cd969d2SDave Martin 		if (err)
8948cd969d2SDave Martin 			return err;
8958cd969d2SDave Martin 	}
8968cd969d2SDave Martin 
89719e99e7dSDongxu Sun 	if (system_supports_tpidr2()) {
89819e99e7dSDongxu Sun 		err = sigframe_alloc(user, &user->tpidr2_offset,
89919e99e7dSDongxu Sun 				     sizeof(struct tpidr2_context));
90019e99e7dSDongxu Sun 		if (err)
90119e99e7dSDongxu Sun 			return err;
90219e99e7dSDongxu Sun 	}
90319e99e7dSDongxu Sun 
90439782210SMark Brown 	if (system_supports_sme()) {
90539782210SMark Brown 		unsigned int vl;
90639782210SMark Brown 		unsigned int vq = 0;
90739782210SMark Brown 
90839782210SMark Brown 		if (add_all)
90939782210SMark Brown 			vl = sme_max_vl();
91039782210SMark Brown 		else
91139782210SMark Brown 			vl = task_get_sme_vl(current);
91239782210SMark Brown 
91339782210SMark Brown 		if (thread_za_enabled(&current->thread))
91439782210SMark Brown 			vq = sve_vq_from_vl(vl);
91539782210SMark Brown 
91639782210SMark Brown 		err = sigframe_alloc(user, &user->za_offset,
91739782210SMark Brown 				     ZA_SIG_CONTEXT_SIZE(vq));
91839782210SMark Brown 		if (err)
91939782210SMark Brown 			return err;
92039782210SMark Brown 	}
92139782210SMark Brown 
922ee072cf7SMark Brown 	if (system_supports_sme2()) {
923ee072cf7SMark Brown 		if (add_all || thread_za_enabled(&current->thread)) {
924ee072cf7SMark Brown 			err = sigframe_alloc(user, &user->zt_offset,
925ee072cf7SMark Brown 					     ZT_SIG_CONTEXT_SIZE(1));
926ee072cf7SMark Brown 			if (err)
927ee072cf7SMark Brown 				return err;
928ee072cf7SMark Brown 		}
929ee072cf7SMark Brown 	}
930ee072cf7SMark Brown 
93133f08261SDave Martin 	return sigframe_alloc_end(user);
932bb4891a6SDave Martin }
933bb4891a6SDave Martin 
setup_sigframe(struct rt_sigframe_user_layout * user,struct pt_regs * regs,sigset_t * set)93420987de3SDave Martin static int setup_sigframe(struct rt_sigframe_user_layout *user,
9352c020ed8SCatalin Marinas 			  struct pt_regs *regs, sigset_t *set)
9362c020ed8SCatalin Marinas {
9372c020ed8SCatalin Marinas 	int i, err = 0;
93820987de3SDave Martin 	struct rt_sigframe __user *sf = user->sigframe;
9392c020ed8SCatalin Marinas 
940304ef4e8SWill Deacon 	/* set up the stack frame for unwinding */
94120987de3SDave Martin 	__put_user_error(regs->regs[29], &user->next_frame->fp, err);
94220987de3SDave Martin 	__put_user_error(regs->regs[30], &user->next_frame->lr, err);
943304ef4e8SWill Deacon 
9442c020ed8SCatalin Marinas 	for (i = 0; i < 31; i++)
9452c020ed8SCatalin Marinas 		__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
9462c020ed8SCatalin Marinas 				 err);
9472c020ed8SCatalin Marinas 	__put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
9482c020ed8SCatalin Marinas 	__put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
9492c020ed8SCatalin Marinas 	__put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
9502c020ed8SCatalin Marinas 
9512c020ed8SCatalin Marinas 	__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
9522c020ed8SCatalin Marinas 
9532c020ed8SCatalin Marinas 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
9542c020ed8SCatalin Marinas 
9556d502b6bSSuzuki K Poulose 	if (err == 0 && system_supports_fpsimd()) {
956bb4891a6SDave Martin 		struct fpsimd_context __user *fpsimd_ctx =
957bb4891a6SDave Martin 			apply_user_offset(user, user->fpsimd_offset);
9580e0276d1SCatalin Marinas 		err |= preserve_fpsimd_context(fpsimd_ctx);
9590e0276d1SCatalin Marinas 	}
9602c020ed8SCatalin Marinas 
96115af1942SCatalin Marinas 	/* fault information, if valid */
962bb4891a6SDave Martin 	if (err == 0 && user->esr_offset) {
963bb4891a6SDave Martin 		struct esr_context __user *esr_ctx =
964bb4891a6SDave Martin 			apply_user_offset(user, user->esr_offset);
965bb4891a6SDave Martin 
96615af1942SCatalin Marinas 		__put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
96715af1942SCatalin Marinas 		__put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
96815af1942SCatalin Marinas 		__put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
96915af1942SCatalin Marinas 	}
97015af1942SCatalin Marinas 
97185ed24daSMark Brown 	/* Scalable Vector Extension state (including streaming), if present */
97285ed24daSMark Brown 	if ((system_supports_sve() || system_supports_sme()) &&
97385ed24daSMark Brown 	    err == 0 && user->sve_offset) {
9748cd969d2SDave Martin 		struct sve_context __user *sve_ctx =
9758cd969d2SDave Martin 			apply_user_offset(user, user->sve_offset);
9768cd969d2SDave Martin 		err |= preserve_sve_context(sve_ctx);
9778cd969d2SDave Martin 	}
9788cd969d2SDave Martin 
97939e54499SMark Brown 	/* TPIDR2 if supported */
980e9d14f3fSDongxu Sun 	if (system_supports_tpidr2() && err == 0) {
98139e54499SMark Brown 		struct tpidr2_context __user *tpidr2_ctx =
98239e54499SMark Brown 			apply_user_offset(user, user->tpidr2_offset);
98339e54499SMark Brown 		err |= preserve_tpidr2_context(tpidr2_ctx);
98439e54499SMark Brown 	}
98539e54499SMark Brown 
98639782210SMark Brown 	/* ZA state if present */
98739782210SMark Brown 	if (system_supports_sme() && err == 0 && user->za_offset) {
98839782210SMark Brown 		struct za_context __user *za_ctx =
98939782210SMark Brown 			apply_user_offset(user, user->za_offset);
99039782210SMark Brown 		err |= preserve_za_context(za_ctx);
99139782210SMark Brown 	}
99239782210SMark Brown 
993ee072cf7SMark Brown 	/* ZT state if present */
994ee072cf7SMark Brown 	if (system_supports_sme2() && err == 0 && user->zt_offset) {
995ee072cf7SMark Brown 		struct zt_context __user *zt_ctx =
996ee072cf7SMark Brown 			apply_user_offset(user, user->zt_offset);
997ee072cf7SMark Brown 		err |= preserve_zt_context(zt_ctx);
998ee072cf7SMark Brown 	}
999ee072cf7SMark Brown 
100033f08261SDave Martin 	if (err == 0 && user->extra_offset) {
100133f08261SDave Martin 		char __user *sfp = (char __user *)user->sigframe;
100233f08261SDave Martin 		char __user *userp =
100333f08261SDave Martin 			apply_user_offset(user, user->extra_offset);
100433f08261SDave Martin 
100533f08261SDave Martin 		struct extra_context __user *extra;
100633f08261SDave Martin 		struct _aarch64_ctx __user *end;
100733f08261SDave Martin 		u64 extra_datap;
100833f08261SDave Martin 		u32 extra_size;
100933f08261SDave Martin 
101033f08261SDave Martin 		extra = (struct extra_context __user *)userp;
101133f08261SDave Martin 		userp += EXTRA_CONTEXT_SIZE;
101233f08261SDave Martin 
101333f08261SDave Martin 		end = (struct _aarch64_ctx __user *)userp;
101433f08261SDave Martin 		userp += TERMINATOR_SIZE;
101533f08261SDave Martin 
101633f08261SDave Martin 		/*
101733f08261SDave Martin 		 * extra_datap is just written to the signal frame.
101833f08261SDave Martin 		 * The value gets cast back to a void __user *
101933f08261SDave Martin 		 * during sigreturn.
102033f08261SDave Martin 		 */
102133f08261SDave Martin 		extra_datap = (__force u64)userp;
102233f08261SDave Martin 		extra_size = sfp + round_up(user->size, 16) - userp;
102333f08261SDave Martin 
102433f08261SDave Martin 		__put_user_error(EXTRA_MAGIC, &extra->head.magic, err);
102533f08261SDave Martin 		__put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err);
102633f08261SDave Martin 		__put_user_error(extra_datap, &extra->datap, err);
102733f08261SDave Martin 		__put_user_error(extra_size, &extra->size, err);
102833f08261SDave Martin 
102933f08261SDave Martin 		/* Add the terminator */
103033f08261SDave Martin 		__put_user_error(0, &end->magic, err);
103133f08261SDave Martin 		__put_user_error(0, &end->size, err);
103233f08261SDave Martin 	}
103333f08261SDave Martin 
10342c020ed8SCatalin Marinas 	/* set the "end" magic */
1035bb4891a6SDave Martin 	if (err == 0) {
1036bb4891a6SDave Martin 		struct _aarch64_ctx __user *end =
1037bb4891a6SDave Martin 			apply_user_offset(user, user->end_offset);
1038bb4891a6SDave Martin 
10390e0276d1SCatalin Marinas 		__put_user_error(0, &end->magic, err);
10400e0276d1SCatalin Marinas 		__put_user_error(0, &end->size, err);
1041bb4891a6SDave Martin 	}
10422c020ed8SCatalin Marinas 
10432c020ed8SCatalin Marinas 	return err;
10442c020ed8SCatalin Marinas }
10452c020ed8SCatalin Marinas 
get_sigframe(struct rt_sigframe_user_layout * user,struct ksignal * ksig,struct pt_regs * regs)104620987de3SDave Martin static int get_sigframe(struct rt_sigframe_user_layout *user,
104720987de3SDave Martin 			 struct ksignal *ksig, struct pt_regs *regs)
10482c020ed8SCatalin Marinas {
10492c020ed8SCatalin Marinas 	unsigned long sp, sp_top;
1050bb4891a6SDave Martin 	int err;
1051bb4891a6SDave Martin 
1052bb4891a6SDave Martin 	init_user_layout(user);
105394b07c1fSDave Martin 	err = setup_sigframe_layout(user, false);
1054bb4891a6SDave Martin 	if (err)
1055bb4891a6SDave Martin 		return err;
10562c020ed8SCatalin Marinas 
105738a7be3cSRichard Weinberger 	sp = sp_top = sigsp(regs->sp, ksig);
10582c020ed8SCatalin Marinas 
105920987de3SDave Martin 	sp = round_down(sp - sizeof(struct frame_record), 16);
106020987de3SDave Martin 	user->next_frame = (struct frame_record __user *)sp;
106120987de3SDave Martin 
1062bb4891a6SDave Martin 	sp = round_down(sp, 16) - sigframe_size(user);
106320987de3SDave Martin 	user->sigframe = (struct rt_sigframe __user *)sp;
10642c020ed8SCatalin Marinas 
10652c020ed8SCatalin Marinas 	/*
10662c020ed8SCatalin Marinas 	 * Check that we can actually write to the signal frame.
10672c020ed8SCatalin Marinas 	 */
106896d4f267SLinus Torvalds 	if (!access_ok(user->sigframe, sp_top - sp))
106920987de3SDave Martin 		return -EFAULT;
10702c020ed8SCatalin Marinas 
107120987de3SDave Martin 	return 0;
10722c020ed8SCatalin Marinas }
10732c020ed8SCatalin Marinas 
setup_return(struct pt_regs * regs,struct k_sigaction * ka,struct rt_sigframe_user_layout * user,int usig)1074304ef4e8SWill Deacon static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
107520987de3SDave Martin 			 struct rt_sigframe_user_layout *user, int usig)
10762c020ed8SCatalin Marinas {
10772c020ed8SCatalin Marinas 	__sigrestore_t sigtramp;
10782c020ed8SCatalin Marinas 
10792c020ed8SCatalin Marinas 	regs->regs[0] = usig;
108020987de3SDave Martin 	regs->sp = (unsigned long)user->sigframe;
108120987de3SDave Martin 	regs->regs[29] = (unsigned long)&user->next_frame->fp;
10822c020ed8SCatalin Marinas 	regs->pc = (unsigned long)ka->sa.sa_handler;
10832c020ed8SCatalin Marinas 
10848ef8f360SDave Martin 	/*
10858ef8f360SDave Martin 	 * Signal delivery is a (wacky) indirect function call in
10868ef8f360SDave Martin 	 * userspace, so simulate the same setting of BTYPE as a BLR
10878ef8f360SDave Martin 	 * <register containing the signal handler entry point>.
10888ef8f360SDave Martin 	 * Signal delivery to a location in a PROT_BTI guarded page
10898ef8f360SDave Martin 	 * that is not a function entry point will now trigger a
10908ef8f360SDave Martin 	 * SIGILL in userspace.
10918ef8f360SDave Martin 	 *
10928ef8f360SDave Martin 	 * If the signal handler entry point is not in a PROT_BTI
10938ef8f360SDave Martin 	 * guarded page, this is harmless.
10948ef8f360SDave Martin 	 */
10958ef8f360SDave Martin 	if (system_supports_bti()) {
10968ef8f360SDave Martin 		regs->pstate &= ~PSR_BTYPE_MASK;
10978ef8f360SDave Martin 		regs->pstate |= PSR_BTYPE_C;
10988ef8f360SDave Martin 	}
10998ef8f360SDave Martin 
1100637ec831SVincenzo Frascino 	/* TCO (Tag Check Override) always cleared for signal handlers */
1101637ec831SVincenzo Frascino 	regs->pstate &= ~PSR_TCO_BIT;
1102637ec831SVincenzo Frascino 
110340a8e87bSMark Brown 	/* Signal handlers are invoked with ZA and streaming mode disabled */
110440a8e87bSMark Brown 	if (system_supports_sme()) {
1105ea64baacSMark Brown 		/*
1106ea64baacSMark Brown 		 * If we were in streaming mode the saved register
1107ea64baacSMark Brown 		 * state was SVE but we will exit SM and use the
1108ea64baacSMark Brown 		 * FPSIMD register state - flush the saved FPSIMD
1109ea64baacSMark Brown 		 * register state in case it gets loaded.
1110ea64baacSMark Brown 		 */
1111baa85152SMark Brown 		if (current->thread.svcr & SVCR_SM_MASK) {
1112ea64baacSMark Brown 			memset(&current->thread.uw.fpsimd_state, 0,
1113ea64baacSMark Brown 			       sizeof(current->thread.uw.fpsimd_state));
1114baa85152SMark Brown 			current->thread.fp_type = FP_STATE_FPSIMD;
1115baa85152SMark Brown 		}
1116ea64baacSMark Brown 
1117ec0067a6SMark Brown 		current->thread.svcr &= ~(SVCR_ZA_MASK |
1118ec0067a6SMark Brown 					  SVCR_SM_MASK);
111940a8e87bSMark Brown 		sme_smstop();
112040a8e87bSMark Brown 	}
112140a8e87bSMark Brown 
11222c020ed8SCatalin Marinas 	if (ka->sa.sa_flags & SA_RESTORER)
11232c020ed8SCatalin Marinas 		sigtramp = ka->sa.sa_restorer;
11242c020ed8SCatalin Marinas 	else
11252c020ed8SCatalin Marinas 		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
11262c020ed8SCatalin Marinas 
11272c020ed8SCatalin Marinas 	regs->regs[30] = (unsigned long)sigtramp;
11282c020ed8SCatalin Marinas }
11292c020ed8SCatalin Marinas 
setup_rt_frame(int usig,struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)113000554fa4SRichard Weinberger static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
113100554fa4SRichard Weinberger 			  struct pt_regs *regs)
11322c020ed8SCatalin Marinas {
113320987de3SDave Martin 	struct rt_sigframe_user_layout user;
11342c020ed8SCatalin Marinas 	struct rt_sigframe __user *frame;
11352c020ed8SCatalin Marinas 	int err = 0;
11362c020ed8SCatalin Marinas 
11378cd969d2SDave Martin 	fpsimd_signal_preserve_current_state();
11388cd969d2SDave Martin 
113920987de3SDave Martin 	if (get_sigframe(&user, ksig, regs))
11402c020ed8SCatalin Marinas 		return 1;
11412c020ed8SCatalin Marinas 
114220987de3SDave Martin 	frame = user.sigframe;
114320987de3SDave Martin 
11442c020ed8SCatalin Marinas 	__put_user_error(0, &frame->uc.uc_flags, err);
11452c020ed8SCatalin Marinas 	__put_user_error(NULL, &frame->uc.uc_link, err);
11462c020ed8SCatalin Marinas 
1147207bdae4SAl Viro 	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
114820987de3SDave Martin 	err |= setup_sigframe(&user, regs, set);
1149304ef4e8SWill Deacon 	if (err == 0) {
115020987de3SDave Martin 		setup_return(regs, &ksig->ka, &user, usig);
115100554fa4SRichard Weinberger 		if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
115200554fa4SRichard Weinberger 			err |= copy_siginfo_to_user(&frame->info, &ksig->info);
11532c020ed8SCatalin Marinas 			regs->regs[1] = (unsigned long)&frame->info;
11542c020ed8SCatalin Marinas 			regs->regs[2] = (unsigned long)&frame->uc;
11552c020ed8SCatalin Marinas 		}
1156304ef4e8SWill Deacon 	}
11572c020ed8SCatalin Marinas 
11582c020ed8SCatalin Marinas 	return err;
11592c020ed8SCatalin Marinas }
11602c020ed8SCatalin Marinas 
setup_restart_syscall(struct pt_regs * regs)11612c020ed8SCatalin Marinas static void setup_restart_syscall(struct pt_regs *regs)
11622c020ed8SCatalin Marinas {
11632c020ed8SCatalin Marinas 	if (is_compat_task())
11642c020ed8SCatalin Marinas 		compat_setup_restart_syscall(regs);
11652c020ed8SCatalin Marinas 	else
11662c020ed8SCatalin Marinas 		regs->regs[8] = __NR_restart_syscall;
11672c020ed8SCatalin Marinas }
11682c020ed8SCatalin Marinas 
11692c020ed8SCatalin Marinas /*
11702c020ed8SCatalin Marinas  * OK, we're invoking a handler
11712c020ed8SCatalin Marinas  */
handle_signal(struct ksignal * ksig,struct pt_regs * regs)117200554fa4SRichard Weinberger static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
11732c020ed8SCatalin Marinas {
11742c020ed8SCatalin Marinas 	sigset_t *oldset = sigmask_to_save();
117500554fa4SRichard Weinberger 	int usig = ksig->sig;
11762c020ed8SCatalin Marinas 	int ret;
11772c020ed8SCatalin Marinas 
1178409d5db4SWill Deacon 	rseq_signal_deliver(ksig, regs);
1179409d5db4SWill Deacon 
11802c020ed8SCatalin Marinas 	/*
11812c020ed8SCatalin Marinas 	 * Set up the stack frame
11822c020ed8SCatalin Marinas 	 */
11832c020ed8SCatalin Marinas 	if (is_compat_task()) {
118400554fa4SRichard Weinberger 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
118500554fa4SRichard Weinberger 			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
11862c020ed8SCatalin Marinas 		else
118700554fa4SRichard Weinberger 			ret = compat_setup_frame(usig, ksig, oldset, regs);
11882c020ed8SCatalin Marinas 	} else {
118900554fa4SRichard Weinberger 		ret = setup_rt_frame(usig, ksig, oldset, regs);
11902c020ed8SCatalin Marinas 	}
11912c020ed8SCatalin Marinas 
11922c020ed8SCatalin Marinas 	/*
11932c020ed8SCatalin Marinas 	 * Check that the resulting registers are actually sane.
11942c020ed8SCatalin Marinas 	 */
1195dbd4d7caSMark Rutland 	ret |= !valid_user_regs(&regs->user_regs, current);
11962c020ed8SCatalin Marinas 
1197ac2081cdSWill Deacon 	/* Step into the signal handler if we are stepping */
1198ac2081cdSWill Deacon 	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
11992c020ed8SCatalin Marinas }
12002c020ed8SCatalin Marinas 
12012c020ed8SCatalin Marinas /*
12022c020ed8SCatalin Marinas  * Note that 'init' is a special process: it doesn't get signals it doesn't
12032c020ed8SCatalin Marinas  * want to handle. Thus you cannot kill init even with a SIGKILL even by
12042c020ed8SCatalin Marinas  * mistake.
12052c020ed8SCatalin Marinas  *
12062c020ed8SCatalin Marinas  * Note that we go through the signals twice: once to check the signals that
12072c020ed8SCatalin Marinas  * the kernel can handle, and then we build all the user-level signal handling
12082c020ed8SCatalin Marinas  * stack-frames in one go after that.
12092c020ed8SCatalin Marinas  */
do_signal(struct pt_regs * regs)12102c020ed8SCatalin Marinas static void do_signal(struct pt_regs *regs)
12112c020ed8SCatalin Marinas {
12122c020ed8SCatalin Marinas 	unsigned long continue_addr = 0, restart_addr = 0;
121300554fa4SRichard Weinberger 	int retval = 0;
121400554fa4SRichard Weinberger 	struct ksignal ksig;
12150fe42512SDave Martin 	bool syscall = in_syscall(regs);
12162c020ed8SCatalin Marinas 
12172c020ed8SCatalin Marinas 	/*
12182c020ed8SCatalin Marinas 	 * If we were from a system call, check for system call restarting...
12192c020ed8SCatalin Marinas 	 */
12200fe42512SDave Martin 	if (syscall) {
12212c020ed8SCatalin Marinas 		continue_addr = regs->pc;
12222c020ed8SCatalin Marinas 		restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4);
12232c020ed8SCatalin Marinas 		retval = regs->regs[0];
12242c020ed8SCatalin Marinas 
12252c020ed8SCatalin Marinas 		/*
12262c020ed8SCatalin Marinas 		 * Avoid additional syscall restarting via ret_to_user.
12272c020ed8SCatalin Marinas 		 */
122817c28958SDave Martin 		forget_syscall(regs);
12292c020ed8SCatalin Marinas 
12302c020ed8SCatalin Marinas 		/*
12312c020ed8SCatalin Marinas 		 * Prepare for system call restart. We do this here so that a
12322c020ed8SCatalin Marinas 		 * debugger will see the already changed PC.
12332c020ed8SCatalin Marinas 		 */
12342c020ed8SCatalin Marinas 		switch (retval) {
12352c020ed8SCatalin Marinas 		case -ERESTARTNOHAND:
12362c020ed8SCatalin Marinas 		case -ERESTARTSYS:
12372c020ed8SCatalin Marinas 		case -ERESTARTNOINTR:
12382c020ed8SCatalin Marinas 		case -ERESTART_RESTARTBLOCK:
12392c020ed8SCatalin Marinas 			regs->regs[0] = regs->orig_x0;
12402c020ed8SCatalin Marinas 			regs->pc = restart_addr;
12412c020ed8SCatalin Marinas 			break;
12422c020ed8SCatalin Marinas 		}
12432c020ed8SCatalin Marinas 	}
12442c020ed8SCatalin Marinas 
12452c020ed8SCatalin Marinas 	/*
12462c020ed8SCatalin Marinas 	 * Get the signal to deliver. When running under ptrace, at this point
12472c020ed8SCatalin Marinas 	 * the debugger may change all of our registers.
12482c020ed8SCatalin Marinas 	 */
124900554fa4SRichard Weinberger 	if (get_signal(&ksig)) {
12502c020ed8SCatalin Marinas 		/*
12512c020ed8SCatalin Marinas 		 * Depending on the signal settings, we may need to revert the
12522c020ed8SCatalin Marinas 		 * decision to restart the system call, but skip this if a
12532c020ed8SCatalin Marinas 		 * debugger has chosen to restart at a different PC.
12542c020ed8SCatalin Marinas 		 */
12552c020ed8SCatalin Marinas 		if (regs->pc == restart_addr &&
12562c020ed8SCatalin Marinas 		    (retval == -ERESTARTNOHAND ||
12572c020ed8SCatalin Marinas 		     retval == -ERESTART_RESTARTBLOCK ||
12582c020ed8SCatalin Marinas 		     (retval == -ERESTARTSYS &&
125900554fa4SRichard Weinberger 		      !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
1260e30e8d46SMark Rutland 			syscall_set_return_value(current, regs, -EINTR, 0);
12612c020ed8SCatalin Marinas 			regs->pc = continue_addr;
12622c020ed8SCatalin Marinas 		}
12632c020ed8SCatalin Marinas 
126400554fa4SRichard Weinberger 		handle_signal(&ksig, regs);
12652c020ed8SCatalin Marinas 		return;
12662c020ed8SCatalin Marinas 	}
12672c020ed8SCatalin Marinas 
12682c020ed8SCatalin Marinas 	/*
12692c020ed8SCatalin Marinas 	 * Handle restarting a different system call. As above, if a debugger
12702c020ed8SCatalin Marinas 	 * has chosen to restart at a different PC, ignore the restart.
12712c020ed8SCatalin Marinas 	 */
12720fe42512SDave Martin 	if (syscall && regs->pc == restart_addr) {
12732c020ed8SCatalin Marinas 		if (retval == -ERESTART_RESTARTBLOCK)
12742c020ed8SCatalin Marinas 			setup_restart_syscall(regs);
12752c020ed8SCatalin Marinas 		user_rewind_single_step(current);
12762c020ed8SCatalin Marinas 	}
12772c020ed8SCatalin Marinas 
12782c020ed8SCatalin Marinas 	restore_saved_sigmask();
12792c020ed8SCatalin Marinas }
12802c020ed8SCatalin Marinas 
do_notify_resume(struct pt_regs * regs,unsigned long thread_flags)12814d1c2ee2SMark Rutland void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
12822c020ed8SCatalin Marinas {
1283a2048e34SThomas Garnier 	do {
1284421dd6faSChris Metcalf 		if (thread_flags & _TIF_NEED_RESCHED) {
12858d66772eSJames Morse 			/* Unmask Debug and SError for the next task */
12868d66772eSJames Morse 			local_daif_restore(DAIF_PROCCTX_NOIRQ);
12878d66772eSJames Morse 
1288421dd6faSChris Metcalf 			schedule();
1289421dd6faSChris Metcalf 		} else {
12908d66772eSJames Morse 			local_daif_restore(DAIF_PROCCTX);
1291421dd6faSChris Metcalf 
12929842ceaeSPratyush Anand 			if (thread_flags & _TIF_UPROBE)
12939842ceaeSPratyush Anand 				uprobe_notify_resume(regs);
12949842ceaeSPratyush Anand 
1295637ec831SVincenzo Frascino 			if (thread_flags & _TIF_MTE_ASYNC_FAULT) {
1296637ec831SVincenzo Frascino 				clear_thread_flag(TIF_MTE_ASYNC_FAULT);
1297637ec831SVincenzo Frascino 				send_sig_fault(SIGSEGV, SEGV_MTEAERR,
1298637ec831SVincenzo Frascino 					       (void __user *)NULL, current);
1299637ec831SVincenzo Frascino 			}
1300637ec831SVincenzo Frascino 
1301192caabdSJens Axboe 			if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
13022c020ed8SCatalin Marinas 				do_signal(regs);
13032c020ed8SCatalin Marinas 
1304a68de80fSSean Christopherson 			if (thread_flags & _TIF_NOTIFY_RESUME)
130503248addSEric W. Biederman 				resume_user_mode_work(regs);
1306005f78cdSArd Biesheuvel 
1307005f78cdSArd Biesheuvel 			if (thread_flags & _TIF_FOREIGN_FPSTATE)
1308005f78cdSArd Biesheuvel 				fpsimd_restore_current_state();
1309421dd6faSChris Metcalf 		}
1310005f78cdSArd Biesheuvel 
13118d66772eSJames Morse 		local_daif_mask();
1312342b3808SMark Rutland 		thread_flags = read_thread_flags();
1313421dd6faSChris Metcalf 	} while (thread_flags & _TIF_WORK_MASK);
13142c020ed8SCatalin Marinas }
131594b07c1fSDave Martin 
131694b07c1fSDave Martin unsigned long __ro_after_init signal_minsigstksz;
131794b07c1fSDave Martin 
131894b07c1fSDave Martin /*
131994b07c1fSDave Martin  * Determine the stack space required for guaranteed signal devliery.
132094b07c1fSDave Martin  * This function is used to populate AT_MINSIGSTKSZ at process startup.
132194b07c1fSDave Martin  * cpufeatures setup is assumed to be complete.
132294b07c1fSDave Martin  */
minsigstksz_setup(void)132394b07c1fSDave Martin void __init minsigstksz_setup(void)
132494b07c1fSDave Martin {
132594b07c1fSDave Martin 	struct rt_sigframe_user_layout user;
132694b07c1fSDave Martin 
132794b07c1fSDave Martin 	init_user_layout(&user);
132894b07c1fSDave Martin 
132994b07c1fSDave Martin 	/*
133094b07c1fSDave Martin 	 * If this fails, SIGFRAME_MAXSZ needs to be enlarged.  It won't
133194b07c1fSDave Martin 	 * be big enough, but it's our best guess:
133294b07c1fSDave Martin 	 */
133394b07c1fSDave Martin 	if (WARN_ON(setup_sigframe_layout(&user, true)))
133494b07c1fSDave Martin 		return;
133594b07c1fSDave Martin 
133694b07c1fSDave Martin 	signal_minsigstksz = sigframe_size(&user) +
133794b07c1fSDave Martin 		round_up(sizeof(struct frame_record), 16) +
133894b07c1fSDave Martin 		16; /* max alignment padding */
133994b07c1fSDave Martin }
1340726e337bSMarco Elver 
1341726e337bSMarco Elver /*
1342726e337bSMarco Elver  * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
1343726e337bSMarco Elver  * changes likely come with new fields that should be added below.
1344726e337bSMarco Elver  */
1345726e337bSMarco Elver static_assert(NSIGILL	== 11);
1346726e337bSMarco Elver static_assert(NSIGFPE	== 15);
1347a5f6c2acSRick Edgecombe static_assert(NSIGSEGV	== 10);
1348726e337bSMarco Elver static_assert(NSIGBUS	== 5);
1349726e337bSMarco Elver static_assert(NSIGTRAP	== 6);
1350726e337bSMarco Elver static_assert(NSIGCHLD	== 6);
1351726e337bSMarco Elver static_assert(NSIGSYS	== 2);
135250ae8130SEric W. Biederman static_assert(sizeof(siginfo_t) == 128);
135350ae8130SEric W. Biederman static_assert(__alignof__(siginfo_t) == 8);
1354726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_signo)	== 0x00);
1355726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_errno)	== 0x04);
1356726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_code)	== 0x08);
1357726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pid)	== 0x10);
1358726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_uid)	== 0x14);
1359726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_tid)	== 0x10);
1360726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_overrun)	== 0x14);
1361726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_status)	== 0x18);
1362726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_utime)	== 0x20);
1363726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_stime)	== 0x28);
1364726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_value)	== 0x18);
1365726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_int)	== 0x18);
1366726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_ptr)	== 0x18);
1367726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr)	== 0x10);
1368726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr_lsb)	== 0x18);
1369726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_lower)	== 0x20);
1370726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_upper)	== 0x28);
1371726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pkey)	== 0x20);
1372726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_data)	== 0x18);
1373726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_type)	== 0x20);
137478ed93d7SMarco Elver static_assert(offsetof(siginfo_t, si_perf_flags) == 0x24);
1375726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_band)	== 0x10);
1376726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_fd)	== 0x18);
1377726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_call_addr)	== 0x10);
1378726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_syscall)	== 0x18);
1379726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_arch)	== 0x1c);
1380