From 37991c1e24c54a9b8dbd686e1ac251d3af25cae2 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Mon, 26 Jun 2017 19:11:58 +0300 Subject: arm64: signal: share lp64 signal structures and routines to ilp32 After that, it will be possible to reuse it in ilp32. Signed-off-by: Yury Norov --- arch/arm64/include/asm/signal_common.h | 69 +++++++++++++++++++++ arch/arm64/kernel/signal.c | 110 +++++++++++++-------------------- 2 files changed, 111 insertions(+), 68 deletions(-) create mode 100644 arch/arm64/include/asm/signal_common.h diff --git a/arch/arm64/include/asm/signal_common.h b/arch/arm64/include/asm/signal_common.h new file mode 100644 index 000000000000..1018811b9ea0 --- /dev/null +++ b/arch/arm64/include/asm/signal_common.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 1995-2009 Russell King + * Copyright (C) 2012 ARM Ltd. + * Copyright (C) 2017 Cavium Networks. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ASM_SIGNAL_COMMON_H +#define __ASM_SIGNAL_COMMON_H + +#include +#include + +#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16) +#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16) + +/* + * Sanity limit on the approximate maximum size of signal frame we'll + * try to generate. Stack alignment padding and the frame record are + * not taken into account. This limit is not a guarantee and is + * NOT ABI. + */ +#define SIGFRAME_MAXSZ SZ_64K + +#define parse_user_sigcontext(user, sf) \ + __parse_user_sigcontext(user, &(sf)->uc.uc_mcontext, sf) + +struct user_ctxs { + struct fpsimd_context __user *fpsimd; + struct sve_context __user *sve; +}; + +struct frame_record { + u64 fp; + u64 lr; +}; +struct rt_sigframe_user_layout; + +int setup_extra_context(char __user *sfp, unsigned long users, char __user *userp); +int __parse_user_sigcontext(struct user_ctxs *user, + struct sigcontext __user const *sc, + void __user const *sigframe_base); + +int preserve_fpsimd_context(struct fpsimd_context __user *ctx); +int restore_fpsimd_context(struct fpsimd_context __user *ctx); + +#ifdef CONFIG_ARM64_SVE +int preserve_sve_context(struct sve_context __user *ctx); +int restore_sve_fpsimd_context(struct user_ctxs *user); +#else /* ! CONFIG_ARM64_SVE */ + +/* Turn any non-optimised out attempts to use these into a link error: */ +extern int preserve_sve_context(void __user *ctx); +extern int restore_sve_fpsimd_context(struct user_ctxs *user); + +#endif /* ! CONFIG_ARM64_SVE */ + +#endif /* __ASM_SIGNAL_COMMON_H */ diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 0a829f6f1832..bd2347abf62c 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * Do a signal return; undo the signal stack. These are aligned to 128-bit. @@ -50,11 +51,6 @@ struct rt_sigframe { struct ucontext uc; }; -struct frame_record { - u64 fp; - u64 lr; -}; - struct rt_sigframe_user_layout { struct rt_sigframe __user *sigframe; struct frame_record __user *next_frame; @@ -70,8 +66,6 @@ struct rt_sigframe_user_layout { }; #define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16) -#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16) -#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16) static void init_user_layout(struct rt_sigframe_user_layout *user) { @@ -93,14 +87,6 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user) return round_up(max(user->size, sizeof(struct rt_sigframe)), 16); } -/* - * Sanity limit on the approximate maximum size of signal frame we'll - * try to generate. Stack alignment padding and the frame record are - * not taken into account. This limit is not a guarantee and is - * NOT ABI. - */ -#define SIGFRAME_MAXSZ SZ_64K - static int __sigframe_alloc(struct rt_sigframe_user_layout *user, unsigned long *offset, size_t size, bool extend) { @@ -176,7 +162,7 @@ static void __user *apply_user_offset( return base + offset; } -static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) +int preserve_fpsimd_context(struct fpsimd_context __user *ctx) { struct user_fpsimd_state const *fpsimd = ¤t->thread.fpsimd_state.user_fpsimd; @@ -194,7 +180,7 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) return err ? -EFAULT : 0; } -static int restore_fpsimd_context(struct fpsimd_context __user *ctx) +int restore_fpsimd_context(struct fpsimd_context __user *ctx) { struct user_fpsimd_state fpsimd; __u32 magic, size; @@ -223,15 +209,9 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx) return err ? -EFAULT : 0; } - -struct user_ctxs { - struct fpsimd_context __user *fpsimd; - struct sve_context __user *sve; -}; - #ifdef CONFIG_ARM64_SVE -static int preserve_sve_context(struct sve_context __user *ctx) +int preserve_sve_context(struct sve_context __user *ctx) { int err = 0; u16 reserved[ARRAY_SIZE(ctx->__reserved)]; @@ -263,7 +243,7 @@ static int preserve_sve_context(struct sve_context __user *ctx) return err ? -EFAULT : 0; } -static int restore_sve_fpsimd_context(struct user_ctxs *user) +int restore_sve_fpsimd_context(struct user_ctxs *user) { int err; unsigned int vq; @@ -326,15 +306,9 @@ fpsimd_only: return err ? -EFAULT : 0; } -#else /* ! CONFIG_ARM64_SVE */ - -/* Turn any non-optimised out attempts to use these into a link error: */ -extern int preserve_sve_context(void __user *ctx); -extern int restore_sve_fpsimd_context(struct user_ctxs *user); - #endif /* ! CONFIG_ARM64_SVE */ -static int __parse_user_sigcontext(struct user_ctxs *user, +int __parse_user_sigcontext(struct user_ctxs *user, struct sigcontext __user const *sc, void __user const *sigframe_base) { @@ -492,9 +466,6 @@ invalid: return -EINVAL; } -#define parse_user_sigcontext(user, sf) \ - __parse_user_sigcontext(user, &(sf)->uc.uc_mcontext, sf) - static int restore_sigframe(struct pt_regs *regs, struct rt_sigframe __user *sf) { @@ -608,6 +579,39 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) return sigframe_alloc_end(user); } +int setup_extra_context(char __user *sfp, unsigned long users, char __user *userp) +{ + int err =0; + struct extra_context __user *extra; + struct _aarch64_ctx __user *end; + u64 extra_datap; + u32 extra_size; + + extra = (struct extra_context __user *)userp; + userp += EXTRA_CONTEXT_SIZE; + + end = (struct _aarch64_ctx __user *)userp; + userp += TERMINATOR_SIZE; + + /* + * extra_datap is just written to the signal frame. + * The value gets cast back to a void __user * + * during sigreturn. + */ + extra_datap = (__force u64)userp; + extra_size = sfp + round_up(users, 16) - userp; + + __put_user_error(EXTRA_MAGIC, &extra->head.magic, err); + __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err); + __put_user_error(extra_datap, &extra->datap, err); + __put_user_error(extra_size, &extra->size, err); + + /* Add the terminator */ + __put_user_error(0, &end->magic, err); + __put_user_error(0, &end->size, err); + + return err; +} static int setup_sigframe(struct rt_sigframe_user_layout *user, struct pt_regs *regs, sigset_t *set) @@ -653,39 +657,9 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, err |= preserve_sve_context(sve_ctx); } - if (err == 0 && user->extra_offset) { - char __user *sfp = (char __user *)user->sigframe; - char __user *userp = - apply_user_offset(user, user->extra_offset); - - struct extra_context __user *extra; - struct _aarch64_ctx __user *end; - u64 extra_datap; - u32 extra_size; - - extra = (struct extra_context __user *)userp; - userp += EXTRA_CONTEXT_SIZE; - - end = (struct _aarch64_ctx __user *)userp; - userp += TERMINATOR_SIZE; - - /* - * extra_datap is just written to the signal frame. - * The value gets cast back to a void __user * - * during sigreturn. - */ - extra_datap = (__force u64)userp; - extra_size = sfp + round_up(user->size, 16) - userp; - - __put_user_error(EXTRA_MAGIC, &extra->head.magic, err); - __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err); - __put_user_error(extra_datap, &extra->datap, err); - __put_user_error(extra_size, &extra->size, err); - - /* Add the terminator */ - __put_user_error(0, &end->magic, err); - __put_user_error(0, &end->size, err); - } + if (err == 0 && user->extra_offset) + setup_extra_context((char *) user->sigframe, user->size, + (char *) apply_user_offset(user, user->extra_offset)); /* set the "end" magic */ if (err == 0) { -- cgit v1.2.3