xref: /openbmc/linux/arch/arm64/kernel/signal.c (revision 39e54499)
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;
59*39e54499SMark Brown 	unsigned long tpidr2_offset;
6039782210SMark Brown 	unsigned long za_offset;
6133f08261SDave Martin 	unsigned long extra_offset;
62bb4891a6SDave Martin 	unsigned long end_offset;
6320987de3SDave Martin };
6420987de3SDave Martin 
6533f08261SDave Martin #define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
6633f08261SDave Martin #define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
6733f08261SDave Martin #define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
6833f08261SDave Martin 
69bb4891a6SDave Martin static void init_user_layout(struct rt_sigframe_user_layout *user)
70bb4891a6SDave Martin {
7133f08261SDave Martin 	const size_t reserved_size =
7233f08261SDave Martin 		sizeof(user->sigframe->uc.uc_mcontext.__reserved);
7333f08261SDave Martin 
74bb4891a6SDave Martin 	memset(user, 0, sizeof(*user));
75bb4891a6SDave Martin 	user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved);
76bb4891a6SDave Martin 
7733f08261SDave Martin 	user->limit = user->size + reserved_size;
7833f08261SDave Martin 
7933f08261SDave Martin 	user->limit -= TERMINATOR_SIZE;
8033f08261SDave Martin 	user->limit -= EXTRA_CONTEXT_SIZE;
8133f08261SDave Martin 	/* Reserve space for extension and terminator ^ */
82bb4891a6SDave Martin }
83bb4891a6SDave Martin 
84bb4891a6SDave Martin static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
85bb4891a6SDave Martin {
86bb4891a6SDave Martin 	return round_up(max(user->size, sizeof(struct rt_sigframe)), 16);
87bb4891a6SDave Martin }
88bb4891a6SDave Martin 
89bb4322f7SDave Martin /*
9033f08261SDave Martin  * Sanity limit on the approximate maximum size of signal frame we'll
9133f08261SDave Martin  * try to generate.  Stack alignment padding and the frame record are
9233f08261SDave Martin  * not taken into account.  This limit is not a guarantee and is
9333f08261SDave Martin  * NOT ABI.
9433f08261SDave Martin  */
957ddcaf78SMark Brown #define SIGFRAME_MAXSZ SZ_256K
9633f08261SDave Martin 
9733f08261SDave Martin static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
9833f08261SDave Martin 			    unsigned long *offset, size_t size, bool extend)
9933f08261SDave Martin {
10033f08261SDave Martin 	size_t padded_size = round_up(size, 16);
10133f08261SDave Martin 
10233f08261SDave Martin 	if (padded_size > user->limit - user->size &&
10333f08261SDave Martin 	    !user->extra_offset &&
10433f08261SDave Martin 	    extend) {
10533f08261SDave Martin 		int ret;
10633f08261SDave Martin 
10733f08261SDave Martin 		user->limit += EXTRA_CONTEXT_SIZE;
10833f08261SDave Martin 		ret = __sigframe_alloc(user, &user->extra_offset,
10933f08261SDave Martin 				       sizeof(struct extra_context), false);
11033f08261SDave Martin 		if (ret) {
11133f08261SDave Martin 			user->limit -= EXTRA_CONTEXT_SIZE;
11233f08261SDave Martin 			return ret;
11333f08261SDave Martin 		}
11433f08261SDave Martin 
11533f08261SDave Martin 		/* Reserve space for the __reserved[] terminator */
11633f08261SDave Martin 		user->size += TERMINATOR_SIZE;
11733f08261SDave Martin 
11833f08261SDave Martin 		/*
11933f08261SDave Martin 		 * Allow expansion up to SIGFRAME_MAXSZ, ensuring space for
12033f08261SDave Martin 		 * the terminator:
12133f08261SDave Martin 		 */
12233f08261SDave Martin 		user->limit = SIGFRAME_MAXSZ - TERMINATOR_SIZE;
12333f08261SDave Martin 	}
12433f08261SDave Martin 
12533f08261SDave Martin 	/* Still not enough space?  Bad luck! */
12633f08261SDave Martin 	if (padded_size > user->limit - user->size)
12733f08261SDave Martin 		return -ENOMEM;
12833f08261SDave Martin 
12933f08261SDave Martin 	*offset = user->size;
13033f08261SDave Martin 	user->size += padded_size;
13133f08261SDave Martin 
13233f08261SDave Martin 	return 0;
13333f08261SDave Martin }
13433f08261SDave Martin 
13533f08261SDave Martin /*
136bb4322f7SDave Martin  * Allocate space for an optional record of <size> bytes in the user
137bb4322f7SDave Martin  * signal frame.  The offset from the signal frame base address to the
138bb4322f7SDave Martin  * allocated block is assigned to *offset.
139bb4322f7SDave Martin  */
140bb4322f7SDave Martin static int sigframe_alloc(struct rt_sigframe_user_layout *user,
141bb4322f7SDave Martin 			  unsigned long *offset, size_t size)
142bb4322f7SDave Martin {
14333f08261SDave Martin 	return __sigframe_alloc(user, offset, size, true);
14433f08261SDave Martin }
145bb4322f7SDave Martin 
14633f08261SDave Martin /* Allocate the null terminator record and prevent further allocations */
14733f08261SDave Martin static int sigframe_alloc_end(struct rt_sigframe_user_layout *user)
14833f08261SDave Martin {
14933f08261SDave Martin 	int ret;
150bb4322f7SDave Martin 
15133f08261SDave Martin 	/* Un-reserve the space reserved for the terminator: */
15233f08261SDave Martin 	user->limit += TERMINATOR_SIZE;
15333f08261SDave Martin 
15433f08261SDave Martin 	ret = sigframe_alloc(user, &user->end_offset,
15533f08261SDave Martin 			     sizeof(struct _aarch64_ctx));
15633f08261SDave Martin 	if (ret)
15733f08261SDave Martin 		return ret;
15833f08261SDave Martin 
15933f08261SDave Martin 	/* Prevent further allocation: */
16033f08261SDave Martin 	user->limit = user->size;
161bb4322f7SDave Martin 	return 0;
162bb4322f7SDave Martin }
163bb4322f7SDave Martin 
164bb4891a6SDave Martin static void __user *apply_user_offset(
165bb4891a6SDave Martin 	struct rt_sigframe_user_layout const *user, unsigned long offset)
166bb4891a6SDave Martin {
167bb4891a6SDave Martin 	char __user *base = (char __user *)user->sigframe;
168bb4891a6SDave Martin 
169bb4891a6SDave Martin 	return base + offset;
170bb4891a6SDave Martin }
171bb4891a6SDave Martin 
1722c020ed8SCatalin Marinas static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
1732c020ed8SCatalin Marinas {
17465896545SDave Martin 	struct user_fpsimd_state const *fpsimd =
17565896545SDave Martin 		&current->thread.uw.fpsimd_state;
1762c020ed8SCatalin Marinas 	int err;
1772c020ed8SCatalin Marinas 
1782c020ed8SCatalin Marinas 	/* copy the FP and status/control registers */
1792c020ed8SCatalin Marinas 	err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs));
1802c020ed8SCatalin Marinas 	__put_user_error(fpsimd->fpsr, &ctx->fpsr, err);
1812c020ed8SCatalin Marinas 	__put_user_error(fpsimd->fpcr, &ctx->fpcr, err);
1822c020ed8SCatalin Marinas 
1832c020ed8SCatalin Marinas 	/* copy the magic/size information */
1842c020ed8SCatalin Marinas 	__put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err);
1852c020ed8SCatalin Marinas 	__put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err);
1862c020ed8SCatalin Marinas 
1872c020ed8SCatalin Marinas 	return err ? -EFAULT : 0;
1882c020ed8SCatalin Marinas }
1892c020ed8SCatalin Marinas 
1902c020ed8SCatalin Marinas static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
1912c020ed8SCatalin Marinas {
1920abdeff5SDave Martin 	struct user_fpsimd_state fpsimd;
1932c020ed8SCatalin Marinas 	__u32 magic, size;
1942c020ed8SCatalin Marinas 	int err = 0;
1952c020ed8SCatalin Marinas 
1962c020ed8SCatalin Marinas 	/* check the magic/size information */
1972c020ed8SCatalin Marinas 	__get_user_error(magic, &ctx->head.magic, err);
1982c020ed8SCatalin Marinas 	__get_user_error(size, &ctx->head.size, err);
1992c020ed8SCatalin Marinas 	if (err)
2002c020ed8SCatalin Marinas 		return -EFAULT;
2012c020ed8SCatalin Marinas 	if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context))
2022c020ed8SCatalin Marinas 		return -EINVAL;
2032c020ed8SCatalin Marinas 
2042c020ed8SCatalin Marinas 	/* copy the FP and status/control registers */
2052c020ed8SCatalin Marinas 	err = __copy_from_user(fpsimd.vregs, ctx->vregs,
2062c020ed8SCatalin Marinas 			       sizeof(fpsimd.vregs));
2072c020ed8SCatalin Marinas 	__get_user_error(fpsimd.fpsr, &ctx->fpsr, err);
2082c020ed8SCatalin Marinas 	__get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
2092c020ed8SCatalin Marinas 
2108cd969d2SDave Martin 	clear_thread_flag(TIF_SVE);
211baa85152SMark Brown 	current->thread.fp_type = FP_STATE_FPSIMD;
2128cd969d2SDave Martin 
2132c020ed8SCatalin Marinas 	/* load the hardware registers from the fpsimd_state structure */
214c51f9269SArd Biesheuvel 	if (!err)
215c51f9269SArd Biesheuvel 		fpsimd_update_current_state(&fpsimd);
2162c020ed8SCatalin Marinas 
2172c020ed8SCatalin Marinas 	return err ? -EFAULT : 0;
2182c020ed8SCatalin Marinas }
2192c020ed8SCatalin Marinas 
2208cd969d2SDave Martin 
22147ccb028SDave Martin struct user_ctxs {
22247ccb028SDave Martin 	struct fpsimd_context __user *fpsimd;
2238cd969d2SDave Martin 	struct sve_context __user *sve;
224*39e54499SMark Brown 	struct tpidr2_context __user *tpidr2;
22539782210SMark Brown 	struct za_context __user *za;
22647ccb028SDave Martin };
22747ccb028SDave Martin 
2288cd969d2SDave Martin #ifdef CONFIG_ARM64_SVE
2298cd969d2SDave Martin 
2308cd969d2SDave Martin static int preserve_sve_context(struct sve_context __user *ctx)
2318cd969d2SDave Martin {
2328cd969d2SDave Martin 	int err = 0;
2338cd969d2SDave Martin 	u16 reserved[ARRAY_SIZE(ctx->__reserved)];
23485ed24daSMark Brown 	u16 flags = 0;
2350423eedcSMark Brown 	unsigned int vl = task_get_sve_vl(current);
2368cd969d2SDave Martin 	unsigned int vq = 0;
2378cd969d2SDave Martin 
23885ed24daSMark Brown 	if (thread_sm_enabled(&current->thread)) {
23985ed24daSMark Brown 		vl = task_get_sme_vl(current);
2408cd969d2SDave Martin 		vq = sve_vq_from_vl(vl);
24185ed24daSMark Brown 		flags |= SVE_SIG_FLAG_SM;
24285ed24daSMark Brown 	} else if (test_thread_flag(TIF_SVE)) {
24385ed24daSMark Brown 		vq = sve_vq_from_vl(vl);
24485ed24daSMark Brown 	}
2458cd969d2SDave Martin 
2468cd969d2SDave Martin 	memset(reserved, 0, sizeof(reserved));
2478cd969d2SDave Martin 
2488cd969d2SDave Martin 	__put_user_error(SVE_MAGIC, &ctx->head.magic, err);
2498cd969d2SDave Martin 	__put_user_error(round_up(SVE_SIG_CONTEXT_SIZE(vq), 16),
2508cd969d2SDave Martin 			 &ctx->head.size, err);
2518cd969d2SDave Martin 	__put_user_error(vl, &ctx->vl, err);
25285ed24daSMark Brown 	__put_user_error(flags, &ctx->flags, err);
2538cd969d2SDave Martin 	BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved));
2548cd969d2SDave Martin 	err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved));
2558cd969d2SDave Martin 
2568cd969d2SDave Martin 	if (vq) {
2578cd969d2SDave Martin 		/*
2588cd969d2SDave Martin 		 * This assumes that the SVE state has already been saved to
25968a4c52eSJulien Grall 		 * the task struct by calling the function
26068a4c52eSJulien Grall 		 * fpsimd_signal_preserve_current_state().
2618cd969d2SDave Martin 		 */
2628cd969d2SDave Martin 		err |= __copy_to_user((char __user *)ctx + SVE_SIG_REGS_OFFSET,
2638cd969d2SDave Martin 				      current->thread.sve_state,
2648cd969d2SDave Martin 				      SVE_SIG_REGS_SIZE(vq));
2658cd969d2SDave Martin 	}
2668cd969d2SDave Martin 
2678cd969d2SDave Martin 	return err ? -EFAULT : 0;
2688cd969d2SDave Martin }
2698cd969d2SDave Martin 
2708cd969d2SDave Martin static int restore_sve_fpsimd_context(struct user_ctxs *user)
2718cd969d2SDave Martin {
2728cd969d2SDave Martin 	int err;
27385ed24daSMark Brown 	unsigned int vl, vq;
2740abdeff5SDave Martin 	struct user_fpsimd_state fpsimd;
2758cd969d2SDave Martin 	struct sve_context sve;
2768cd969d2SDave Martin 
2778cd969d2SDave Martin 	if (__copy_from_user(&sve, user->sve, sizeof(sve)))
2788cd969d2SDave Martin 		return -EFAULT;
2798cd969d2SDave Martin 
28085ed24daSMark Brown 	if (sve.flags & SVE_SIG_FLAG_SM) {
28185ed24daSMark Brown 		if (!system_supports_sme())
28285ed24daSMark Brown 			return -EINVAL;
28385ed24daSMark Brown 
28485ed24daSMark Brown 		vl = task_get_sme_vl(current);
28585ed24daSMark Brown 	} else {
286df07443fSMark Brown 		if (!system_supports_sve())
287df07443fSMark Brown 			return -EINVAL;
288df07443fSMark Brown 
28985ed24daSMark Brown 		vl = task_get_sve_vl(current);
29085ed24daSMark Brown 	}
29185ed24daSMark Brown 
29285ed24daSMark Brown 	if (sve.vl != vl)
2938cd969d2SDave Martin 		return -EINVAL;
2948cd969d2SDave Martin 
2958cd969d2SDave Martin 	if (sve.head.size <= sizeof(*user->sve)) {
2968cd969d2SDave Martin 		clear_thread_flag(TIF_SVE);
297ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_SM_MASK;
298baa85152SMark Brown 		current->thread.fp_type = FP_STATE_FPSIMD;
2998cd969d2SDave Martin 		goto fpsimd_only;
3008cd969d2SDave Martin 	}
3018cd969d2SDave Martin 
3028cd969d2SDave Martin 	vq = sve_vq_from_vl(sve.vl);
3038cd969d2SDave Martin 
3048cd969d2SDave Martin 	if (sve.head.size < SVE_SIG_CONTEXT_SIZE(vq))
3058cd969d2SDave Martin 		return -EINVAL;
3068cd969d2SDave Martin 
3078cd969d2SDave Martin 	/*
3088cd969d2SDave Martin 	 * Careful: we are about __copy_from_user() directly into
3098cd969d2SDave Martin 	 * thread.sve_state with preemption enabled, so protection is
3108cd969d2SDave Martin 	 * needed to prevent a racing context switch from writing stale
3118cd969d2SDave Martin 	 * registers back over the new data.
3128cd969d2SDave Martin 	 */
3138cd969d2SDave Martin 
3148cd969d2SDave Martin 	fpsimd_flush_task_state(current);
3158cd969d2SDave Martin 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
3168cd969d2SDave Martin 
317826a4fddSMark Brown 	sve_alloc(current, true);
3187559b7d7SMark Brown 	if (!current->thread.sve_state) {
3197559b7d7SMark Brown 		clear_thread_flag(TIF_SVE);
3207559b7d7SMark Brown 		return -ENOMEM;
3217559b7d7SMark Brown 	}
3227559b7d7SMark Brown 
3238cd969d2SDave Martin 	err = __copy_from_user(current->thread.sve_state,
3248cd969d2SDave Martin 			       (char __user const *)user->sve +
3258cd969d2SDave Martin 					SVE_SIG_REGS_OFFSET,
3268cd969d2SDave Martin 			       SVE_SIG_REGS_SIZE(vq));
3278cd969d2SDave Martin 	if (err)
3288cd969d2SDave Martin 		return -EFAULT;
3298cd969d2SDave Martin 
33085ed24daSMark Brown 	if (sve.flags & SVE_SIG_FLAG_SM)
331ec0067a6SMark Brown 		current->thread.svcr |= SVCR_SM_MASK;
33285ed24daSMark Brown 	else
3338cd969d2SDave Martin 		set_thread_flag(TIF_SVE);
334baa85152SMark Brown 	current->thread.fp_type = FP_STATE_SVE;
3358cd969d2SDave Martin 
3368cd969d2SDave Martin fpsimd_only:
3378cd969d2SDave Martin 	/* copy the FP and status/control registers */
3388cd969d2SDave Martin 	/* restore_sigframe() already checked that user->fpsimd != NULL. */
3398cd969d2SDave Martin 	err = __copy_from_user(fpsimd.vregs, user->fpsimd->vregs,
3408cd969d2SDave Martin 			       sizeof(fpsimd.vregs));
3418cd969d2SDave Martin 	__get_user_error(fpsimd.fpsr, &user->fpsimd->fpsr, err);
3428cd969d2SDave Martin 	__get_user_error(fpsimd.fpcr, &user->fpsimd->fpcr, err);
3438cd969d2SDave Martin 
3448cd969d2SDave Martin 	/* load the hardware registers from the fpsimd_state structure */
3458cd969d2SDave Martin 	if (!err)
3468cd969d2SDave Martin 		fpsimd_update_current_state(&fpsimd);
3478cd969d2SDave Martin 
3488cd969d2SDave Martin 	return err ? -EFAULT : 0;
3498cd969d2SDave Martin }
3508cd969d2SDave Martin 
3518cd969d2SDave Martin #else /* ! CONFIG_ARM64_SVE */
3528cd969d2SDave Martin 
353df07443fSMark Brown static int restore_sve_fpsimd_context(struct user_ctxs *user)
354df07443fSMark Brown {
355df07443fSMark Brown 	WARN_ON_ONCE(1);
356df07443fSMark Brown 	return -EINVAL;
357df07443fSMark Brown }
358df07443fSMark Brown 
359df07443fSMark Brown /* Turn any non-optimised out attempts to use this into a link error: */
3608cd969d2SDave Martin extern int preserve_sve_context(void __user *ctx);
3618cd969d2SDave Martin 
3628cd969d2SDave Martin #endif /* ! CONFIG_ARM64_SVE */
3638cd969d2SDave Martin 
36439782210SMark Brown #ifdef CONFIG_ARM64_SME
36539782210SMark Brown 
366*39e54499SMark Brown static int preserve_tpidr2_context(struct tpidr2_context __user *ctx)
367*39e54499SMark Brown {
368*39e54499SMark Brown 	int err = 0;
369*39e54499SMark Brown 
370*39e54499SMark Brown 	current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);
371*39e54499SMark Brown 
372*39e54499SMark Brown 	__put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err);
373*39e54499SMark Brown 	__put_user_error(sizeof(*ctx), &ctx->head.size, err);
374*39e54499SMark Brown 	__put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err);
375*39e54499SMark Brown 
376*39e54499SMark Brown 	return err;
377*39e54499SMark Brown }
378*39e54499SMark Brown 
379*39e54499SMark Brown static int restore_tpidr2_context(struct user_ctxs *user)
380*39e54499SMark Brown {
381*39e54499SMark Brown 	u64 tpidr2_el0;
382*39e54499SMark Brown 	int err = 0;
383*39e54499SMark Brown 
384*39e54499SMark Brown 	/* Magic and size were validated deciding to call this function */
385*39e54499SMark Brown 	__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
386*39e54499SMark Brown 	if (!err)
387*39e54499SMark Brown 		current->thread.tpidr2_el0 = tpidr2_el0;
388*39e54499SMark Brown 
389*39e54499SMark Brown 	return err;
390*39e54499SMark Brown }
391*39e54499SMark Brown 
39239782210SMark Brown static int preserve_za_context(struct za_context __user *ctx)
39339782210SMark Brown {
39439782210SMark Brown 	int err = 0;
39539782210SMark Brown 	u16 reserved[ARRAY_SIZE(ctx->__reserved)];
39639782210SMark Brown 	unsigned int vl = task_get_sme_vl(current);
39739782210SMark Brown 	unsigned int vq;
39839782210SMark Brown 
39939782210SMark Brown 	if (thread_za_enabled(&current->thread))
40039782210SMark Brown 		vq = sve_vq_from_vl(vl);
40139782210SMark Brown 	else
40239782210SMark Brown 		vq = 0;
40339782210SMark Brown 
40439782210SMark Brown 	memset(reserved, 0, sizeof(reserved));
40539782210SMark Brown 
40639782210SMark Brown 	__put_user_error(ZA_MAGIC, &ctx->head.magic, err);
40739782210SMark Brown 	__put_user_error(round_up(ZA_SIG_CONTEXT_SIZE(vq), 16),
40839782210SMark Brown 			 &ctx->head.size, err);
40939782210SMark Brown 	__put_user_error(vl, &ctx->vl, err);
41039782210SMark Brown 	BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved));
41139782210SMark Brown 	err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved));
41239782210SMark Brown 
41339782210SMark Brown 	if (vq) {
41439782210SMark Brown 		/*
41539782210SMark Brown 		 * This assumes that the ZA state has already been saved to
41639782210SMark Brown 		 * the task struct by calling the function
41739782210SMark Brown 		 * fpsimd_signal_preserve_current_state().
41839782210SMark Brown 		 */
41939782210SMark Brown 		err |= __copy_to_user((char __user *)ctx + ZA_SIG_REGS_OFFSET,
42039782210SMark Brown 				      current->thread.za_state,
42139782210SMark Brown 				      ZA_SIG_REGS_SIZE(vq));
42239782210SMark Brown 	}
42339782210SMark Brown 
42439782210SMark Brown 	return err ? -EFAULT : 0;
42539782210SMark Brown }
42639782210SMark Brown 
4271bec877bSCatalin Marinas static int restore_za_context(struct user_ctxs *user)
42839782210SMark Brown {
42939782210SMark Brown 	int err;
43039782210SMark Brown 	unsigned int vq;
43139782210SMark Brown 	struct za_context za;
43239782210SMark Brown 
43339782210SMark Brown 	if (__copy_from_user(&za, user->za, sizeof(za)))
43439782210SMark Brown 		return -EFAULT;
43539782210SMark Brown 
43639782210SMark Brown 	if (za.vl != task_get_sme_vl(current))
43739782210SMark Brown 		return -EINVAL;
43839782210SMark Brown 
43939782210SMark Brown 	if (za.head.size <= sizeof(*user->za)) {
440ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_ZA_MASK;
44139782210SMark Brown 		return 0;
44239782210SMark Brown 	}
44339782210SMark Brown 
44439782210SMark Brown 	vq = sve_vq_from_vl(za.vl);
44539782210SMark Brown 
44639782210SMark Brown 	if (za.head.size < ZA_SIG_CONTEXT_SIZE(vq))
44739782210SMark Brown 		return -EINVAL;
44839782210SMark Brown 
44939782210SMark Brown 	/*
45039782210SMark Brown 	 * Careful: we are about __copy_from_user() directly into
45139782210SMark Brown 	 * thread.za_state with preemption enabled, so protection is
45239782210SMark Brown 	 * needed to prevent a racing context switch from writing stale
45339782210SMark Brown 	 * registers back over the new data.
45439782210SMark Brown 	 */
45539782210SMark Brown 
45639782210SMark Brown 	fpsimd_flush_task_state(current);
45739782210SMark Brown 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
45839782210SMark Brown 
45939782210SMark Brown 	sme_alloc(current);
46039782210SMark Brown 	if (!current->thread.za_state) {
461ec0067a6SMark Brown 		current->thread.svcr &= ~SVCR_ZA_MASK;
46239782210SMark Brown 		clear_thread_flag(TIF_SME);
46339782210SMark Brown 		return -ENOMEM;
46439782210SMark Brown 	}
46539782210SMark Brown 
46639782210SMark Brown 	err = __copy_from_user(current->thread.za_state,
46739782210SMark Brown 			       (char __user const *)user->za +
46839782210SMark Brown 					ZA_SIG_REGS_OFFSET,
46939782210SMark Brown 			       ZA_SIG_REGS_SIZE(vq));
47039782210SMark Brown 	if (err)
47139782210SMark Brown 		return -EFAULT;
47239782210SMark Brown 
47339782210SMark Brown 	set_thread_flag(TIF_SME);
474ec0067a6SMark Brown 	current->thread.svcr |= SVCR_ZA_MASK;
47539782210SMark Brown 
47639782210SMark Brown 	return 0;
47739782210SMark Brown }
47839782210SMark Brown #else /* ! CONFIG_ARM64_SME */
47939782210SMark Brown 
48039782210SMark Brown /* Turn any non-optimised out attempts to use these into a link error: */
481*39e54499SMark Brown extern int preserve_tpidr2_context(void __user *ctx);
482*39e54499SMark Brown extern int restore_tpidr2_context(struct user_ctxs *user);
48339782210SMark Brown extern int preserve_za_context(void __user *ctx);
48439782210SMark Brown extern int restore_za_context(struct user_ctxs *user);
48539782210SMark Brown 
48639782210SMark Brown #endif /* ! CONFIG_ARM64_SME */
4878cd969d2SDave Martin 
48847ccb028SDave Martin static int parse_user_sigframe(struct user_ctxs *user,
48947ccb028SDave Martin 			       struct rt_sigframe __user *sf)
49047ccb028SDave Martin {
49147ccb028SDave Martin 	struct sigcontext __user *const sc = &sf->uc.uc_mcontext;
492bb4891a6SDave Martin 	struct _aarch64_ctx __user *head;
493bb4891a6SDave Martin 	char __user *base = (char __user *)&sc->__reserved;
49447ccb028SDave Martin 	size_t offset = 0;
495bb4891a6SDave Martin 	size_t limit = sizeof(sc->__reserved);
49633f08261SDave Martin 	bool have_extra_context = false;
49733f08261SDave Martin 	char const __user *const sfp = (char const __user *)sf;
49847ccb028SDave Martin 
49947ccb028SDave Martin 	user->fpsimd = NULL;
5008cd969d2SDave Martin 	user->sve = NULL;
501*39e54499SMark Brown 	user->tpidr2 = NULL;
50239782210SMark Brown 	user->za = NULL;
50347ccb028SDave Martin 
504bb4891a6SDave Martin 	if (!IS_ALIGNED((unsigned long)base, 16))
50547ccb028SDave Martin 		goto invalid;
50647ccb028SDave Martin 
507bb4891a6SDave Martin 	while (1) {
508bb4891a6SDave Martin 		int err = 0;
509bb4891a6SDave Martin 		u32 magic, size;
51033f08261SDave Martin 		char const __user *userp;
51133f08261SDave Martin 		struct extra_context const __user *extra;
51233f08261SDave Martin 		u64 extra_datap;
51333f08261SDave Martin 		u32 extra_size;
51433f08261SDave Martin 		struct _aarch64_ctx const __user *end;
51533f08261SDave Martin 		u32 end_magic, end_size;
516bb4891a6SDave Martin 
517bb4891a6SDave Martin 		if (limit - offset < sizeof(*head))
518bb4891a6SDave Martin 			goto invalid;
519bb4891a6SDave Martin 
520bb4891a6SDave Martin 		if (!IS_ALIGNED(offset, 16))
521bb4891a6SDave Martin 			goto invalid;
522bb4891a6SDave Martin 
523bb4891a6SDave Martin 		head = (struct _aarch64_ctx __user *)(base + offset);
52447ccb028SDave Martin 		__get_user_error(magic, &head->magic, err);
52547ccb028SDave Martin 		__get_user_error(size, &head->size, err);
52647ccb028SDave Martin 		if (err)
52747ccb028SDave Martin 			return err;
52847ccb028SDave Martin 
529bb4891a6SDave Martin 		if (limit - offset < size)
530bb4891a6SDave Martin 			goto invalid;
531bb4891a6SDave Martin 
53247ccb028SDave Martin 		switch (magic) {
53347ccb028SDave Martin 		case 0:
53447ccb028SDave Martin 			if (size)
53547ccb028SDave Martin 				goto invalid;
53647ccb028SDave Martin 
53747ccb028SDave Martin 			goto done;
53847ccb028SDave Martin 
53947ccb028SDave Martin 		case FPSIMD_MAGIC:
5406d502b6bSSuzuki K Poulose 			if (!system_supports_fpsimd())
5416d502b6bSSuzuki K Poulose 				goto invalid;
54247ccb028SDave Martin 			if (user->fpsimd)
54347ccb028SDave Martin 				goto invalid;
54447ccb028SDave Martin 
545bb4891a6SDave Martin 			if (size < sizeof(*user->fpsimd))
54647ccb028SDave Martin 				goto invalid;
54747ccb028SDave Martin 
54847ccb028SDave Martin 			user->fpsimd = (struct fpsimd_context __user *)head;
54947ccb028SDave Martin 			break;
55047ccb028SDave Martin 
55147ccb028SDave Martin 		case ESR_MAGIC:
55247ccb028SDave Martin 			/* ignore */
55347ccb028SDave Martin 			break;
55447ccb028SDave Martin 
5558cd969d2SDave Martin 		case SVE_MAGIC:
55685ed24daSMark Brown 			if (!system_supports_sve() && !system_supports_sme())
5578cd969d2SDave Martin 				goto invalid;
5588cd969d2SDave Martin 
5598cd969d2SDave Martin 			if (user->sve)
5608cd969d2SDave Martin 				goto invalid;
5618cd969d2SDave Martin 
5628cd969d2SDave Martin 			if (size < sizeof(*user->sve))
5638cd969d2SDave Martin 				goto invalid;
5648cd969d2SDave Martin 
5658cd969d2SDave Martin 			user->sve = (struct sve_context __user *)head;
5668cd969d2SDave Martin 			break;
5678cd969d2SDave Martin 
568*39e54499SMark Brown 		case TPIDR2_MAGIC:
569*39e54499SMark Brown 			if (!system_supports_sme())
570*39e54499SMark Brown 				goto invalid;
571*39e54499SMark Brown 
572*39e54499SMark Brown 			if (user->tpidr2)
573*39e54499SMark Brown 				goto invalid;
574*39e54499SMark Brown 
575*39e54499SMark Brown 			if (size != sizeof(*user->tpidr2))
576*39e54499SMark Brown 				goto invalid;
577*39e54499SMark Brown 
578*39e54499SMark Brown 			user->tpidr2 = (struct tpidr2_context __user *)head;
579*39e54499SMark Brown 			break;
580*39e54499SMark Brown 
58139782210SMark Brown 		case ZA_MAGIC:
58239782210SMark Brown 			if (!system_supports_sme())
58339782210SMark Brown 				goto invalid;
58439782210SMark Brown 
58539782210SMark Brown 			if (user->za)
58639782210SMark Brown 				goto invalid;
58739782210SMark Brown 
58839782210SMark Brown 			if (size < sizeof(*user->za))
58939782210SMark Brown 				goto invalid;
59039782210SMark Brown 
59139782210SMark Brown 			user->za = (struct za_context __user *)head;
59239782210SMark Brown 			break;
59339782210SMark Brown 
59433f08261SDave Martin 		case EXTRA_MAGIC:
59533f08261SDave Martin 			if (have_extra_context)
59633f08261SDave Martin 				goto invalid;
59733f08261SDave Martin 
59833f08261SDave Martin 			if (size < sizeof(*extra))
59933f08261SDave Martin 				goto invalid;
60033f08261SDave Martin 
60133f08261SDave Martin 			userp = (char const __user *)head;
60233f08261SDave Martin 
60333f08261SDave Martin 			extra = (struct extra_context const __user *)userp;
60433f08261SDave Martin 			userp += size;
60533f08261SDave Martin 
60633f08261SDave Martin 			__get_user_error(extra_datap, &extra->datap, err);
60733f08261SDave Martin 			__get_user_error(extra_size, &extra->size, err);
60833f08261SDave Martin 			if (err)
60933f08261SDave Martin 				return err;
61033f08261SDave Martin 
61133f08261SDave Martin 			/* Check for the dummy terminator in __reserved[]: */
61233f08261SDave Martin 
61333f08261SDave Martin 			if (limit - offset - size < TERMINATOR_SIZE)
61433f08261SDave Martin 				goto invalid;
61533f08261SDave Martin 
61633f08261SDave Martin 			end = (struct _aarch64_ctx const __user *)userp;
61733f08261SDave Martin 			userp += TERMINATOR_SIZE;
61833f08261SDave Martin 
61933f08261SDave Martin 			__get_user_error(end_magic, &end->magic, err);
62033f08261SDave Martin 			__get_user_error(end_size, &end->size, err);
62133f08261SDave Martin 			if (err)
62233f08261SDave Martin 				return err;
62333f08261SDave Martin 
62433f08261SDave Martin 			if (end_magic || end_size)
62533f08261SDave Martin 				goto invalid;
62633f08261SDave Martin 
62733f08261SDave Martin 			/* Prevent looping/repeated parsing of extra_context */
62833f08261SDave Martin 			have_extra_context = true;
62933f08261SDave Martin 
63033f08261SDave Martin 			base = (__force void __user *)extra_datap;
63133f08261SDave Martin 			if (!IS_ALIGNED((unsigned long)base, 16))
63233f08261SDave Martin 				goto invalid;
63333f08261SDave Martin 
63433f08261SDave Martin 			if (!IS_ALIGNED(extra_size, 16))
63533f08261SDave Martin 				goto invalid;
63633f08261SDave Martin 
63733f08261SDave Martin 			if (base != userp)
63833f08261SDave Martin 				goto invalid;
63933f08261SDave Martin 
64033f08261SDave Martin 			/* Reject "unreasonably large" frames: */
64133f08261SDave Martin 			if (extra_size > sfp + SIGFRAME_MAXSZ - userp)
64233f08261SDave Martin 				goto invalid;
64333f08261SDave Martin 
64433f08261SDave Martin 			/*
64533f08261SDave Martin 			 * Ignore trailing terminator in __reserved[]
64633f08261SDave Martin 			 * and start parsing extra data:
64733f08261SDave Martin 			 */
64833f08261SDave Martin 			offset = 0;
64933f08261SDave Martin 			limit = extra_size;
650abf73988SDave Martin 
65196d4f267SLinus Torvalds 			if (!access_ok(base, limit))
652abf73988SDave Martin 				goto invalid;
653abf73988SDave Martin 
65433f08261SDave Martin 			continue;
65533f08261SDave Martin 
65647ccb028SDave Martin 		default:
65747ccb028SDave Martin 			goto invalid;
65847ccb028SDave Martin 		}
65947ccb028SDave Martin 
66047ccb028SDave Martin 		if (size < sizeof(*head))
66147ccb028SDave Martin 			goto invalid;
66247ccb028SDave Martin 
663bb4891a6SDave Martin 		if (limit - offset < size)
66447ccb028SDave Martin 			goto invalid;
66547ccb028SDave Martin 
66647ccb028SDave Martin 		offset += size;
66747ccb028SDave Martin 	}
66847ccb028SDave Martin 
66947ccb028SDave Martin done:
67047ccb028SDave Martin 	return 0;
67147ccb028SDave Martin 
67247ccb028SDave Martin invalid:
67347ccb028SDave Martin 	return -EINVAL;
67447ccb028SDave Martin }
67547ccb028SDave Martin 
6762c020ed8SCatalin Marinas static int restore_sigframe(struct pt_regs *regs,
6772c020ed8SCatalin Marinas 			    struct rt_sigframe __user *sf)
6782c020ed8SCatalin Marinas {
6792c020ed8SCatalin Marinas 	sigset_t set;
6802c020ed8SCatalin Marinas 	int i, err;
68147ccb028SDave Martin 	struct user_ctxs user;
6822c020ed8SCatalin Marinas 
6832c020ed8SCatalin Marinas 	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
6842c020ed8SCatalin Marinas 	if (err == 0)
6852c020ed8SCatalin Marinas 		set_current_blocked(&set);
6862c020ed8SCatalin Marinas 
6872c020ed8SCatalin Marinas 	for (i = 0; i < 31; i++)
6882c020ed8SCatalin Marinas 		__get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
6892c020ed8SCatalin Marinas 				 err);
6902c020ed8SCatalin Marinas 	__get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
6912c020ed8SCatalin Marinas 	__get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
6922c020ed8SCatalin Marinas 	__get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
6932c020ed8SCatalin Marinas 
6942c020ed8SCatalin Marinas 	/*
6952c020ed8SCatalin Marinas 	 * Avoid sys_rt_sigreturn() restarting.
6962c020ed8SCatalin Marinas 	 */
69717c28958SDave Martin 	forget_syscall(regs);
6982c020ed8SCatalin Marinas 
699dbd4d7caSMark Rutland 	err |= !valid_user_regs(&regs->user_regs, current);
70047ccb028SDave Martin 	if (err == 0)
70147ccb028SDave Martin 		err = parse_user_sigframe(&user, sf);
7022c020ed8SCatalin Marinas 
7036d502b6bSSuzuki K Poulose 	if (err == 0 && system_supports_fpsimd()) {
7048cd969d2SDave Martin 		if (!user.fpsimd)
7058cd969d2SDave Martin 			return -EINVAL;
7068cd969d2SDave Martin 
707df07443fSMark Brown 		if (user.sve)
7088cd969d2SDave Martin 			err = restore_sve_fpsimd_context(&user);
709df07443fSMark Brown 		else
71047ccb028SDave Martin 			err = restore_fpsimd_context(user.fpsimd);
7118cd969d2SDave Martin 	}
7122c020ed8SCatalin Marinas 
713*39e54499SMark Brown 	if (err == 0 && system_supports_sme() && user.tpidr2)
714*39e54499SMark Brown 		err = restore_tpidr2_context(&user);
715*39e54499SMark Brown 
71639782210SMark Brown 	if (err == 0 && system_supports_sme() && user.za)
71739782210SMark Brown 		err = restore_za_context(&user);
71839782210SMark Brown 
7192c020ed8SCatalin Marinas 	return err;
7202c020ed8SCatalin Marinas }
7212c020ed8SCatalin Marinas 
722bf4ce5ccSMark Rutland SYSCALL_DEFINE0(rt_sigreturn)
7232c020ed8SCatalin Marinas {
7243085e164SMark Rutland 	struct pt_regs *regs = current_pt_regs();
7252c020ed8SCatalin Marinas 	struct rt_sigframe __user *frame;
7262c020ed8SCatalin Marinas 
7272c020ed8SCatalin Marinas 	/* Always make any pending restarted system calls return -EINTR */
728f56141e3SAndy Lutomirski 	current->restart_block.fn = do_no_restart_syscall;
7292c020ed8SCatalin Marinas 
7302c020ed8SCatalin Marinas 	/*
7312c020ed8SCatalin Marinas 	 * Since we stacked the signal on a 128-bit boundary, then 'sp' should
7322c020ed8SCatalin Marinas 	 * be word aligned here.
7332c020ed8SCatalin Marinas 	 */
7342c020ed8SCatalin Marinas 	if (regs->sp & 15)
7352c020ed8SCatalin Marinas 		goto badframe;
7362c020ed8SCatalin Marinas 
7372c020ed8SCatalin Marinas 	frame = (struct rt_sigframe __user *)regs->sp;
7382c020ed8SCatalin Marinas 
73996d4f267SLinus Torvalds 	if (!access_ok(frame, sizeof (*frame)))
7402c020ed8SCatalin Marinas 		goto badframe;
7412c020ed8SCatalin Marinas 
7422c020ed8SCatalin Marinas 	if (restore_sigframe(regs, frame))
7432c020ed8SCatalin Marinas 		goto badframe;
7442c020ed8SCatalin Marinas 
745207bdae4SAl Viro 	if (restore_altstack(&frame->uc.uc_stack))
7462c020ed8SCatalin Marinas 		goto badframe;
7472c020ed8SCatalin Marinas 
7482c020ed8SCatalin Marinas 	return regs->regs[0];
7492c020ed8SCatalin Marinas 
7502c020ed8SCatalin Marinas badframe:
751f71016a8SWill Deacon 	arm64_notify_segfault(regs->sp);
7522c020ed8SCatalin Marinas 	return 0;
7532c020ed8SCatalin Marinas }
7542c020ed8SCatalin Marinas 
75594b07c1fSDave Martin /*
75694b07c1fSDave Martin  * Determine the layout of optional records in the signal frame
75794b07c1fSDave Martin  *
75894b07c1fSDave Martin  * add_all: if true, lays out the biggest possible signal frame for
75994b07c1fSDave Martin  *	this task; otherwise, generates a layout for the current state
76094b07c1fSDave Martin  *	of the task.
76194b07c1fSDave Martin  */
76294b07c1fSDave Martin static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
76394b07c1fSDave Martin 				 bool add_all)
764bb4891a6SDave Martin {
765bb4322f7SDave Martin 	int err;
766bb4322f7SDave Martin 
7670a32c88dSDavid Engraf 	if (system_supports_fpsimd()) {
768bb4322f7SDave Martin 		err = sigframe_alloc(user, &user->fpsimd_offset,
769bb4322f7SDave Martin 				     sizeof(struct fpsimd_context));
770bb4322f7SDave Martin 		if (err)
771bb4322f7SDave Martin 			return err;
7720a32c88dSDavid Engraf 	}
773bb4891a6SDave Martin 
774bb4891a6SDave Martin 	/* fault information, if valid */
77594b07c1fSDave Martin 	if (add_all || current->thread.fault_code) {
776bb4322f7SDave Martin 		err = sigframe_alloc(user, &user->esr_offset,
777bb4322f7SDave Martin 				     sizeof(struct esr_context));
778bb4322f7SDave Martin 		if (err)
779bb4322f7SDave Martin 			return err;
780bb4891a6SDave Martin 	}
781bb4891a6SDave Martin 
7828cd969d2SDave Martin 	if (system_supports_sve()) {
7838cd969d2SDave Martin 		unsigned int vq = 0;
7848cd969d2SDave Martin 
78585ed24daSMark Brown 		if (add_all || test_thread_flag(TIF_SVE) ||
78685ed24daSMark Brown 		    thread_sm_enabled(&current->thread)) {
78785ed24daSMark Brown 			int vl = max(sve_max_vl(), sme_max_vl());
78894b07c1fSDave Martin 
78994b07c1fSDave Martin 			if (!add_all)
79085ed24daSMark Brown 				vl = thread_get_cur_vl(&current->thread);
79194b07c1fSDave Martin 
79294b07c1fSDave Martin 			vq = sve_vq_from_vl(vl);
79394b07c1fSDave Martin 		}
7948cd969d2SDave Martin 
7958cd969d2SDave Martin 		err = sigframe_alloc(user, &user->sve_offset,
7968cd969d2SDave Martin 				     SVE_SIG_CONTEXT_SIZE(vq));
7978cd969d2SDave Martin 		if (err)
7988cd969d2SDave Martin 			return err;
7998cd969d2SDave Martin 	}
8008cd969d2SDave Martin 
80139782210SMark Brown 	if (system_supports_sme()) {
80239782210SMark Brown 		unsigned int vl;
80339782210SMark Brown 		unsigned int vq = 0;
80439782210SMark Brown 
80539782210SMark Brown 		if (add_all)
80639782210SMark Brown 			vl = sme_max_vl();
80739782210SMark Brown 		else
80839782210SMark Brown 			vl = task_get_sme_vl(current);
80939782210SMark Brown 
810*39e54499SMark Brown 		err = sigframe_alloc(user, &user->tpidr2_offset,
811*39e54499SMark Brown 				     sizeof(struct tpidr2_context));
812*39e54499SMark Brown 		if (err)
813*39e54499SMark Brown 			return err;
814*39e54499SMark Brown 
81539782210SMark Brown 		if (thread_za_enabled(&current->thread))
81639782210SMark Brown 			vq = sve_vq_from_vl(vl);
81739782210SMark Brown 
81839782210SMark Brown 		err = sigframe_alloc(user, &user->za_offset,
81939782210SMark Brown 				     ZA_SIG_CONTEXT_SIZE(vq));
82039782210SMark Brown 		if (err)
82139782210SMark Brown 			return err;
82239782210SMark Brown 	}
82339782210SMark Brown 
82433f08261SDave Martin 	return sigframe_alloc_end(user);
825bb4891a6SDave Martin }
826bb4891a6SDave Martin 
82720987de3SDave Martin static int setup_sigframe(struct rt_sigframe_user_layout *user,
8282c020ed8SCatalin Marinas 			  struct pt_regs *regs, sigset_t *set)
8292c020ed8SCatalin Marinas {
8302c020ed8SCatalin Marinas 	int i, err = 0;
83120987de3SDave Martin 	struct rt_sigframe __user *sf = user->sigframe;
8322c020ed8SCatalin Marinas 
833304ef4e8SWill Deacon 	/* set up the stack frame for unwinding */
83420987de3SDave Martin 	__put_user_error(regs->regs[29], &user->next_frame->fp, err);
83520987de3SDave Martin 	__put_user_error(regs->regs[30], &user->next_frame->lr, err);
836304ef4e8SWill Deacon 
8372c020ed8SCatalin Marinas 	for (i = 0; i < 31; i++)
8382c020ed8SCatalin Marinas 		__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
8392c020ed8SCatalin Marinas 				 err);
8402c020ed8SCatalin Marinas 	__put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
8412c020ed8SCatalin Marinas 	__put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
8422c020ed8SCatalin Marinas 	__put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
8432c020ed8SCatalin Marinas 
8442c020ed8SCatalin Marinas 	__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
8452c020ed8SCatalin Marinas 
8462c020ed8SCatalin Marinas 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
8472c020ed8SCatalin Marinas 
8486d502b6bSSuzuki K Poulose 	if (err == 0 && system_supports_fpsimd()) {
849bb4891a6SDave Martin 		struct fpsimd_context __user *fpsimd_ctx =
850bb4891a6SDave Martin 			apply_user_offset(user, user->fpsimd_offset);
8510e0276d1SCatalin Marinas 		err |= preserve_fpsimd_context(fpsimd_ctx);
8520e0276d1SCatalin Marinas 	}
8532c020ed8SCatalin Marinas 
85415af1942SCatalin Marinas 	/* fault information, if valid */
855bb4891a6SDave Martin 	if (err == 0 && user->esr_offset) {
856bb4891a6SDave Martin 		struct esr_context __user *esr_ctx =
857bb4891a6SDave Martin 			apply_user_offset(user, user->esr_offset);
858bb4891a6SDave Martin 
85915af1942SCatalin Marinas 		__put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
86015af1942SCatalin Marinas 		__put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
86115af1942SCatalin Marinas 		__put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
86215af1942SCatalin Marinas 	}
86315af1942SCatalin Marinas 
86485ed24daSMark Brown 	/* Scalable Vector Extension state (including streaming), if present */
86585ed24daSMark Brown 	if ((system_supports_sve() || system_supports_sme()) &&
86685ed24daSMark Brown 	    err == 0 && user->sve_offset) {
8678cd969d2SDave Martin 		struct sve_context __user *sve_ctx =
8688cd969d2SDave Martin 			apply_user_offset(user, user->sve_offset);
8698cd969d2SDave Martin 		err |= preserve_sve_context(sve_ctx);
8708cd969d2SDave Martin 	}
8718cd969d2SDave Martin 
872*39e54499SMark Brown 	/* TPIDR2 if supported */
873*39e54499SMark Brown 	if (system_supports_sme() && err == 0) {
874*39e54499SMark Brown 		struct tpidr2_context __user *tpidr2_ctx =
875*39e54499SMark Brown 			apply_user_offset(user, user->tpidr2_offset);
876*39e54499SMark Brown 		err |= preserve_tpidr2_context(tpidr2_ctx);
877*39e54499SMark Brown 	}
878*39e54499SMark Brown 
87939782210SMark Brown 	/* ZA state if present */
88039782210SMark Brown 	if (system_supports_sme() && err == 0 && user->za_offset) {
88139782210SMark Brown 		struct za_context __user *za_ctx =
88239782210SMark Brown 			apply_user_offset(user, user->za_offset);
88339782210SMark Brown 		err |= preserve_za_context(za_ctx);
88439782210SMark Brown 	}
88539782210SMark Brown 
88633f08261SDave Martin 	if (err == 0 && user->extra_offset) {
88733f08261SDave Martin 		char __user *sfp = (char __user *)user->sigframe;
88833f08261SDave Martin 		char __user *userp =
88933f08261SDave Martin 			apply_user_offset(user, user->extra_offset);
89033f08261SDave Martin 
89133f08261SDave Martin 		struct extra_context __user *extra;
89233f08261SDave Martin 		struct _aarch64_ctx __user *end;
89333f08261SDave Martin 		u64 extra_datap;
89433f08261SDave Martin 		u32 extra_size;
89533f08261SDave Martin 
89633f08261SDave Martin 		extra = (struct extra_context __user *)userp;
89733f08261SDave Martin 		userp += EXTRA_CONTEXT_SIZE;
89833f08261SDave Martin 
89933f08261SDave Martin 		end = (struct _aarch64_ctx __user *)userp;
90033f08261SDave Martin 		userp += TERMINATOR_SIZE;
90133f08261SDave Martin 
90233f08261SDave Martin 		/*
90333f08261SDave Martin 		 * extra_datap is just written to the signal frame.
90433f08261SDave Martin 		 * The value gets cast back to a void __user *
90533f08261SDave Martin 		 * during sigreturn.
90633f08261SDave Martin 		 */
90733f08261SDave Martin 		extra_datap = (__force u64)userp;
90833f08261SDave Martin 		extra_size = sfp + round_up(user->size, 16) - userp;
90933f08261SDave Martin 
91033f08261SDave Martin 		__put_user_error(EXTRA_MAGIC, &extra->head.magic, err);
91133f08261SDave Martin 		__put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err);
91233f08261SDave Martin 		__put_user_error(extra_datap, &extra->datap, err);
91333f08261SDave Martin 		__put_user_error(extra_size, &extra->size, err);
91433f08261SDave Martin 
91533f08261SDave Martin 		/* Add the terminator */
91633f08261SDave Martin 		__put_user_error(0, &end->magic, err);
91733f08261SDave Martin 		__put_user_error(0, &end->size, err);
91833f08261SDave Martin 	}
91933f08261SDave Martin 
9202c020ed8SCatalin Marinas 	/* set the "end" magic */
921bb4891a6SDave Martin 	if (err == 0) {
922bb4891a6SDave Martin 		struct _aarch64_ctx __user *end =
923bb4891a6SDave Martin 			apply_user_offset(user, user->end_offset);
924bb4891a6SDave Martin 
9250e0276d1SCatalin Marinas 		__put_user_error(0, &end->magic, err);
9260e0276d1SCatalin Marinas 		__put_user_error(0, &end->size, err);
927bb4891a6SDave Martin 	}
9282c020ed8SCatalin Marinas 
9292c020ed8SCatalin Marinas 	return err;
9302c020ed8SCatalin Marinas }
9312c020ed8SCatalin Marinas 
93220987de3SDave Martin static int get_sigframe(struct rt_sigframe_user_layout *user,
93320987de3SDave Martin 			 struct ksignal *ksig, struct pt_regs *regs)
9342c020ed8SCatalin Marinas {
9352c020ed8SCatalin Marinas 	unsigned long sp, sp_top;
936bb4891a6SDave Martin 	int err;
937bb4891a6SDave Martin 
938bb4891a6SDave Martin 	init_user_layout(user);
93994b07c1fSDave Martin 	err = setup_sigframe_layout(user, false);
940bb4891a6SDave Martin 	if (err)
941bb4891a6SDave Martin 		return err;
9422c020ed8SCatalin Marinas 
94338a7be3cSRichard Weinberger 	sp = sp_top = sigsp(regs->sp, ksig);
9442c020ed8SCatalin Marinas 
94520987de3SDave Martin 	sp = round_down(sp - sizeof(struct frame_record), 16);
94620987de3SDave Martin 	user->next_frame = (struct frame_record __user *)sp;
94720987de3SDave Martin 
948bb4891a6SDave Martin 	sp = round_down(sp, 16) - sigframe_size(user);
94920987de3SDave Martin 	user->sigframe = (struct rt_sigframe __user *)sp;
9502c020ed8SCatalin Marinas 
9512c020ed8SCatalin Marinas 	/*
9522c020ed8SCatalin Marinas 	 * Check that we can actually write to the signal frame.
9532c020ed8SCatalin Marinas 	 */
95496d4f267SLinus Torvalds 	if (!access_ok(user->sigframe, sp_top - sp))
95520987de3SDave Martin 		return -EFAULT;
9562c020ed8SCatalin Marinas 
95720987de3SDave Martin 	return 0;
9582c020ed8SCatalin Marinas }
9592c020ed8SCatalin Marinas 
960304ef4e8SWill Deacon static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
96120987de3SDave Martin 			 struct rt_sigframe_user_layout *user, int usig)
9622c020ed8SCatalin Marinas {
9632c020ed8SCatalin Marinas 	__sigrestore_t sigtramp;
9642c020ed8SCatalin Marinas 
9652c020ed8SCatalin Marinas 	regs->regs[0] = usig;
96620987de3SDave Martin 	regs->sp = (unsigned long)user->sigframe;
96720987de3SDave Martin 	regs->regs[29] = (unsigned long)&user->next_frame->fp;
9682c020ed8SCatalin Marinas 	regs->pc = (unsigned long)ka->sa.sa_handler;
9692c020ed8SCatalin Marinas 
9708ef8f360SDave Martin 	/*
9718ef8f360SDave Martin 	 * Signal delivery is a (wacky) indirect function call in
9728ef8f360SDave Martin 	 * userspace, so simulate the same setting of BTYPE as a BLR
9738ef8f360SDave Martin 	 * <register containing the signal handler entry point>.
9748ef8f360SDave Martin 	 * Signal delivery to a location in a PROT_BTI guarded page
9758ef8f360SDave Martin 	 * that is not a function entry point will now trigger a
9768ef8f360SDave Martin 	 * SIGILL in userspace.
9778ef8f360SDave Martin 	 *
9788ef8f360SDave Martin 	 * If the signal handler entry point is not in a PROT_BTI
9798ef8f360SDave Martin 	 * guarded page, this is harmless.
9808ef8f360SDave Martin 	 */
9818ef8f360SDave Martin 	if (system_supports_bti()) {
9828ef8f360SDave Martin 		regs->pstate &= ~PSR_BTYPE_MASK;
9838ef8f360SDave Martin 		regs->pstate |= PSR_BTYPE_C;
9848ef8f360SDave Martin 	}
9858ef8f360SDave Martin 
986637ec831SVincenzo Frascino 	/* TCO (Tag Check Override) always cleared for signal handlers */
987637ec831SVincenzo Frascino 	regs->pstate &= ~PSR_TCO_BIT;
988637ec831SVincenzo Frascino 
98940a8e87bSMark Brown 	/* Signal handlers are invoked with ZA and streaming mode disabled */
99040a8e87bSMark Brown 	if (system_supports_sme()) {
991ea64baacSMark Brown 		/*
992ea64baacSMark Brown 		 * If we were in streaming mode the saved register
993ea64baacSMark Brown 		 * state was SVE but we will exit SM and use the
994ea64baacSMark Brown 		 * FPSIMD register state - flush the saved FPSIMD
995ea64baacSMark Brown 		 * register state in case it gets loaded.
996ea64baacSMark Brown 		 */
997baa85152SMark Brown 		if (current->thread.svcr & SVCR_SM_MASK) {
998ea64baacSMark Brown 			memset(&current->thread.uw.fpsimd_state, 0,
999ea64baacSMark Brown 			       sizeof(current->thread.uw.fpsimd_state));
1000baa85152SMark Brown 			current->thread.fp_type = FP_STATE_FPSIMD;
1001baa85152SMark Brown 		}
1002ea64baacSMark Brown 
1003ec0067a6SMark Brown 		current->thread.svcr &= ~(SVCR_ZA_MASK |
1004ec0067a6SMark Brown 					  SVCR_SM_MASK);
100540a8e87bSMark Brown 		sme_smstop();
100640a8e87bSMark Brown 	}
100740a8e87bSMark Brown 
10082c020ed8SCatalin Marinas 	if (ka->sa.sa_flags & SA_RESTORER)
10092c020ed8SCatalin Marinas 		sigtramp = ka->sa.sa_restorer;
10102c020ed8SCatalin Marinas 	else
10112c020ed8SCatalin Marinas 		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
10122c020ed8SCatalin Marinas 
10132c020ed8SCatalin Marinas 	regs->regs[30] = (unsigned long)sigtramp;
10142c020ed8SCatalin Marinas }
10152c020ed8SCatalin Marinas 
101600554fa4SRichard Weinberger static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
101700554fa4SRichard Weinberger 			  struct pt_regs *regs)
10182c020ed8SCatalin Marinas {
101920987de3SDave Martin 	struct rt_sigframe_user_layout user;
10202c020ed8SCatalin Marinas 	struct rt_sigframe __user *frame;
10212c020ed8SCatalin Marinas 	int err = 0;
10222c020ed8SCatalin Marinas 
10238cd969d2SDave Martin 	fpsimd_signal_preserve_current_state();
10248cd969d2SDave Martin 
102520987de3SDave Martin 	if (get_sigframe(&user, ksig, regs))
10262c020ed8SCatalin Marinas 		return 1;
10272c020ed8SCatalin Marinas 
102820987de3SDave Martin 	frame = user.sigframe;
102920987de3SDave Martin 
10302c020ed8SCatalin Marinas 	__put_user_error(0, &frame->uc.uc_flags, err);
10312c020ed8SCatalin Marinas 	__put_user_error(NULL, &frame->uc.uc_link, err);
10322c020ed8SCatalin Marinas 
1033207bdae4SAl Viro 	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
103420987de3SDave Martin 	err |= setup_sigframe(&user, regs, set);
1035304ef4e8SWill Deacon 	if (err == 0) {
103620987de3SDave Martin 		setup_return(regs, &ksig->ka, &user, usig);
103700554fa4SRichard Weinberger 		if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
103800554fa4SRichard Weinberger 			err |= copy_siginfo_to_user(&frame->info, &ksig->info);
10392c020ed8SCatalin Marinas 			regs->regs[1] = (unsigned long)&frame->info;
10402c020ed8SCatalin Marinas 			regs->regs[2] = (unsigned long)&frame->uc;
10412c020ed8SCatalin Marinas 		}
1042304ef4e8SWill Deacon 	}
10432c020ed8SCatalin Marinas 
10442c020ed8SCatalin Marinas 	return err;
10452c020ed8SCatalin Marinas }
10462c020ed8SCatalin Marinas 
10472c020ed8SCatalin Marinas static void setup_restart_syscall(struct pt_regs *regs)
10482c020ed8SCatalin Marinas {
10492c020ed8SCatalin Marinas 	if (is_compat_task())
10502c020ed8SCatalin Marinas 		compat_setup_restart_syscall(regs);
10512c020ed8SCatalin Marinas 	else
10522c020ed8SCatalin Marinas 		regs->regs[8] = __NR_restart_syscall;
10532c020ed8SCatalin Marinas }
10542c020ed8SCatalin Marinas 
10552c020ed8SCatalin Marinas /*
10562c020ed8SCatalin Marinas  * OK, we're invoking a handler
10572c020ed8SCatalin Marinas  */
105800554fa4SRichard Weinberger static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
10592c020ed8SCatalin Marinas {
10602c020ed8SCatalin Marinas 	sigset_t *oldset = sigmask_to_save();
106100554fa4SRichard Weinberger 	int usig = ksig->sig;
10622c020ed8SCatalin Marinas 	int ret;
10632c020ed8SCatalin Marinas 
1064409d5db4SWill Deacon 	rseq_signal_deliver(ksig, regs);
1065409d5db4SWill Deacon 
10662c020ed8SCatalin Marinas 	/*
10672c020ed8SCatalin Marinas 	 * Set up the stack frame
10682c020ed8SCatalin Marinas 	 */
10692c020ed8SCatalin Marinas 	if (is_compat_task()) {
107000554fa4SRichard Weinberger 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
107100554fa4SRichard Weinberger 			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
10722c020ed8SCatalin Marinas 		else
107300554fa4SRichard Weinberger 			ret = compat_setup_frame(usig, ksig, oldset, regs);
10742c020ed8SCatalin Marinas 	} else {
107500554fa4SRichard Weinberger 		ret = setup_rt_frame(usig, ksig, oldset, regs);
10762c020ed8SCatalin Marinas 	}
10772c020ed8SCatalin Marinas 
10782c020ed8SCatalin Marinas 	/*
10792c020ed8SCatalin Marinas 	 * Check that the resulting registers are actually sane.
10802c020ed8SCatalin Marinas 	 */
1081dbd4d7caSMark Rutland 	ret |= !valid_user_regs(&regs->user_regs, current);
10822c020ed8SCatalin Marinas 
1083ac2081cdSWill Deacon 	/* Step into the signal handler if we are stepping */
1084ac2081cdSWill Deacon 	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
10852c020ed8SCatalin Marinas }
10862c020ed8SCatalin Marinas 
10872c020ed8SCatalin Marinas /*
10882c020ed8SCatalin Marinas  * Note that 'init' is a special process: it doesn't get signals it doesn't
10892c020ed8SCatalin Marinas  * want to handle. Thus you cannot kill init even with a SIGKILL even by
10902c020ed8SCatalin Marinas  * mistake.
10912c020ed8SCatalin Marinas  *
10922c020ed8SCatalin Marinas  * Note that we go through the signals twice: once to check the signals that
10932c020ed8SCatalin Marinas  * the kernel can handle, and then we build all the user-level signal handling
10942c020ed8SCatalin Marinas  * stack-frames in one go after that.
10952c020ed8SCatalin Marinas  */
10962c020ed8SCatalin Marinas static void do_signal(struct pt_regs *regs)
10972c020ed8SCatalin Marinas {
10982c020ed8SCatalin Marinas 	unsigned long continue_addr = 0, restart_addr = 0;
109900554fa4SRichard Weinberger 	int retval = 0;
110000554fa4SRichard Weinberger 	struct ksignal ksig;
11010fe42512SDave Martin 	bool syscall = in_syscall(regs);
11022c020ed8SCatalin Marinas 
11032c020ed8SCatalin Marinas 	/*
11042c020ed8SCatalin Marinas 	 * If we were from a system call, check for system call restarting...
11052c020ed8SCatalin Marinas 	 */
11060fe42512SDave Martin 	if (syscall) {
11072c020ed8SCatalin Marinas 		continue_addr = regs->pc;
11082c020ed8SCatalin Marinas 		restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4);
11092c020ed8SCatalin Marinas 		retval = regs->regs[0];
11102c020ed8SCatalin Marinas 
11112c020ed8SCatalin Marinas 		/*
11122c020ed8SCatalin Marinas 		 * Avoid additional syscall restarting via ret_to_user.
11132c020ed8SCatalin Marinas 		 */
111417c28958SDave Martin 		forget_syscall(regs);
11152c020ed8SCatalin Marinas 
11162c020ed8SCatalin Marinas 		/*
11172c020ed8SCatalin Marinas 		 * Prepare for system call restart. We do this here so that a
11182c020ed8SCatalin Marinas 		 * debugger will see the already changed PC.
11192c020ed8SCatalin Marinas 		 */
11202c020ed8SCatalin Marinas 		switch (retval) {
11212c020ed8SCatalin Marinas 		case -ERESTARTNOHAND:
11222c020ed8SCatalin Marinas 		case -ERESTARTSYS:
11232c020ed8SCatalin Marinas 		case -ERESTARTNOINTR:
11242c020ed8SCatalin Marinas 		case -ERESTART_RESTARTBLOCK:
11252c020ed8SCatalin Marinas 			regs->regs[0] = regs->orig_x0;
11262c020ed8SCatalin Marinas 			regs->pc = restart_addr;
11272c020ed8SCatalin Marinas 			break;
11282c020ed8SCatalin Marinas 		}
11292c020ed8SCatalin Marinas 	}
11302c020ed8SCatalin Marinas 
11312c020ed8SCatalin Marinas 	/*
11322c020ed8SCatalin Marinas 	 * Get the signal to deliver. When running under ptrace, at this point
11332c020ed8SCatalin Marinas 	 * the debugger may change all of our registers.
11342c020ed8SCatalin Marinas 	 */
113500554fa4SRichard Weinberger 	if (get_signal(&ksig)) {
11362c020ed8SCatalin Marinas 		/*
11372c020ed8SCatalin Marinas 		 * Depending on the signal settings, we may need to revert the
11382c020ed8SCatalin Marinas 		 * decision to restart the system call, but skip this if a
11392c020ed8SCatalin Marinas 		 * debugger has chosen to restart at a different PC.
11402c020ed8SCatalin Marinas 		 */
11412c020ed8SCatalin Marinas 		if (regs->pc == restart_addr &&
11422c020ed8SCatalin Marinas 		    (retval == -ERESTARTNOHAND ||
11432c020ed8SCatalin Marinas 		     retval == -ERESTART_RESTARTBLOCK ||
11442c020ed8SCatalin Marinas 		     (retval == -ERESTARTSYS &&
114500554fa4SRichard Weinberger 		      !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
1146e30e8d46SMark Rutland 			syscall_set_return_value(current, regs, -EINTR, 0);
11472c020ed8SCatalin Marinas 			regs->pc = continue_addr;
11482c020ed8SCatalin Marinas 		}
11492c020ed8SCatalin Marinas 
115000554fa4SRichard Weinberger 		handle_signal(&ksig, regs);
11512c020ed8SCatalin Marinas 		return;
11522c020ed8SCatalin Marinas 	}
11532c020ed8SCatalin Marinas 
11542c020ed8SCatalin Marinas 	/*
11552c020ed8SCatalin Marinas 	 * Handle restarting a different system call. As above, if a debugger
11562c020ed8SCatalin Marinas 	 * has chosen to restart at a different PC, ignore the restart.
11572c020ed8SCatalin Marinas 	 */
11580fe42512SDave Martin 	if (syscall && regs->pc == restart_addr) {
11592c020ed8SCatalin Marinas 		if (retval == -ERESTART_RESTARTBLOCK)
11602c020ed8SCatalin Marinas 			setup_restart_syscall(regs);
11612c020ed8SCatalin Marinas 		user_rewind_single_step(current);
11622c020ed8SCatalin Marinas 	}
11632c020ed8SCatalin Marinas 
11642c020ed8SCatalin Marinas 	restore_saved_sigmask();
11652c020ed8SCatalin Marinas }
11662c020ed8SCatalin Marinas 
11674d1c2ee2SMark Rutland void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
11682c020ed8SCatalin Marinas {
1169a2048e34SThomas Garnier 	do {
1170421dd6faSChris Metcalf 		if (thread_flags & _TIF_NEED_RESCHED) {
11718d66772eSJames Morse 			/* Unmask Debug and SError for the next task */
11728d66772eSJames Morse 			local_daif_restore(DAIF_PROCCTX_NOIRQ);
11738d66772eSJames Morse 
1174421dd6faSChris Metcalf 			schedule();
1175421dd6faSChris Metcalf 		} else {
11768d66772eSJames Morse 			local_daif_restore(DAIF_PROCCTX);
1177421dd6faSChris Metcalf 
11789842ceaeSPratyush Anand 			if (thread_flags & _TIF_UPROBE)
11799842ceaeSPratyush Anand 				uprobe_notify_resume(regs);
11809842ceaeSPratyush Anand 
1181637ec831SVincenzo Frascino 			if (thread_flags & _TIF_MTE_ASYNC_FAULT) {
1182637ec831SVincenzo Frascino 				clear_thread_flag(TIF_MTE_ASYNC_FAULT);
1183637ec831SVincenzo Frascino 				send_sig_fault(SIGSEGV, SEGV_MTEAERR,
1184637ec831SVincenzo Frascino 					       (void __user *)NULL, current);
1185637ec831SVincenzo Frascino 			}
1186637ec831SVincenzo Frascino 
1187192caabdSJens Axboe 			if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
11882c020ed8SCatalin Marinas 				do_signal(regs);
11892c020ed8SCatalin Marinas 
1190a68de80fSSean Christopherson 			if (thread_flags & _TIF_NOTIFY_RESUME)
119103248addSEric W. Biederman 				resume_user_mode_work(regs);
1192005f78cdSArd Biesheuvel 
1193005f78cdSArd Biesheuvel 			if (thread_flags & _TIF_FOREIGN_FPSTATE)
1194005f78cdSArd Biesheuvel 				fpsimd_restore_current_state();
1195421dd6faSChris Metcalf 		}
1196005f78cdSArd Biesheuvel 
11978d66772eSJames Morse 		local_daif_mask();
1198342b3808SMark Rutland 		thread_flags = read_thread_flags();
1199421dd6faSChris Metcalf 	} while (thread_flags & _TIF_WORK_MASK);
12002c020ed8SCatalin Marinas }
120194b07c1fSDave Martin 
120294b07c1fSDave Martin unsigned long __ro_after_init signal_minsigstksz;
120394b07c1fSDave Martin 
120494b07c1fSDave Martin /*
120594b07c1fSDave Martin  * Determine the stack space required for guaranteed signal devliery.
120694b07c1fSDave Martin  * This function is used to populate AT_MINSIGSTKSZ at process startup.
120794b07c1fSDave Martin  * cpufeatures setup is assumed to be complete.
120894b07c1fSDave Martin  */
120994b07c1fSDave Martin void __init minsigstksz_setup(void)
121094b07c1fSDave Martin {
121194b07c1fSDave Martin 	struct rt_sigframe_user_layout user;
121294b07c1fSDave Martin 
121394b07c1fSDave Martin 	init_user_layout(&user);
121494b07c1fSDave Martin 
121594b07c1fSDave Martin 	/*
121694b07c1fSDave Martin 	 * If this fails, SIGFRAME_MAXSZ needs to be enlarged.  It won't
121794b07c1fSDave Martin 	 * be big enough, but it's our best guess:
121894b07c1fSDave Martin 	 */
121994b07c1fSDave Martin 	if (WARN_ON(setup_sigframe_layout(&user, true)))
122094b07c1fSDave Martin 		return;
122194b07c1fSDave Martin 
122294b07c1fSDave Martin 	signal_minsigstksz = sigframe_size(&user) +
122394b07c1fSDave Martin 		round_up(sizeof(struct frame_record), 16) +
122494b07c1fSDave Martin 		16; /* max alignment padding */
122594b07c1fSDave Martin }
1226726e337bSMarco Elver 
1227726e337bSMarco Elver /*
1228726e337bSMarco Elver  * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
1229726e337bSMarco Elver  * changes likely come with new fields that should be added below.
1230726e337bSMarco Elver  */
1231726e337bSMarco Elver static_assert(NSIGILL	== 11);
1232726e337bSMarco Elver static_assert(NSIGFPE	== 15);
1233726e337bSMarco Elver static_assert(NSIGSEGV	== 9);
1234726e337bSMarco Elver static_assert(NSIGBUS	== 5);
1235726e337bSMarco Elver static_assert(NSIGTRAP	== 6);
1236726e337bSMarco Elver static_assert(NSIGCHLD	== 6);
1237726e337bSMarco Elver static_assert(NSIGSYS	== 2);
123850ae8130SEric W. Biederman static_assert(sizeof(siginfo_t) == 128);
123950ae8130SEric W. Biederman static_assert(__alignof__(siginfo_t) == 8);
1240726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_signo)	== 0x00);
1241726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_errno)	== 0x04);
1242726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_code)	== 0x08);
1243726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pid)	== 0x10);
1244726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_uid)	== 0x14);
1245726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_tid)	== 0x10);
1246726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_overrun)	== 0x14);
1247726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_status)	== 0x18);
1248726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_utime)	== 0x20);
1249726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_stime)	== 0x28);
1250726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_value)	== 0x18);
1251726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_int)	== 0x18);
1252726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_ptr)	== 0x18);
1253726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr)	== 0x10);
1254726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr_lsb)	== 0x18);
1255726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_lower)	== 0x20);
1256726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_upper)	== 0x28);
1257726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pkey)	== 0x20);
1258726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_data)	== 0x18);
1259726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_type)	== 0x20);
126078ed93d7SMarco Elver static_assert(offsetof(siginfo_t, si_perf_flags) == 0x24);
1261726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_band)	== 0x10);
1262726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_fd)	== 0x18);
1263726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_call_addr)	== 0x10);
1264726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_syscall)	== 0x18);
1265726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_arch)	== 0x1c);
1266