summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYury Norov <ynorov@caviumnetworks.com>2017-06-26 19:11:58 +0300
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2018-04-03 10:52:44 +0200
commit6bed079e579a4258c65230bf4b53a3c9a509eee9 (patch)
tree249e645f21fd6f8ba358b1efadde72a1bbde477f
parentad6b3f6a0e309c717321bf15255a692dfe1a5cab (diff)
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 <ynorov@caviumnetworks.com>
-rw-r--r--arch/arm64/include/asm/signal_common.h69
-rw-r--r--arch/arm64/kernel/signal.c110
2 files changed, 111 insertions, 68 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SIGNAL_COMMON_H
+#define __ASM_SIGNAL_COMMON_H
+
+#include <linux/uaccess.h>
+#include <asm/fpsimd.h>
+
+#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 e17b8054992a..587c0a532fa7 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -41,6 +41,7 @@
#include <asm/ptrace.h>
#include <asm/signal32.h>
#include <asm/vdso.h>
+#include <asm/signal_common.h>
/*
* 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 fpsimd_state *fpsimd = &current->thread.fpsimd_state;
int err;
@@ -193,7 +179,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 fpsimd_state fpsimd;
__u32 magic, size;
@@ -222,15 +208,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)];
@@ -262,7 +242,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;
@@ -325,15 +305,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)
{
@@ -491,9 +465,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)
{
@@ -607,6 +578,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)
@@ -652,39 +656,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) {