[PATCH v2 2/4] arm64/signal: Include TPIDR2 in the signal context
Will Deacon
will at kernel.org
Mon Nov 14 08:10:06 PST 2022
On Mon, Oct 31, 2022 at 08:17:34PM +0000, Mark Brown wrote:
> Add a new signal frame record for TPIDR2 using the same format as we
> already use for ESR with different magic, a header with the value from the
> register appended as the only data. If SME is supported then this record is
> always included.
>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> Reviewed-by: Szabolcs Nagy <szabolcs.nagy at arm.com>
> ---
> arch/arm64/include/uapi/asm/sigcontext.h | 8 ++++
> arch/arm64/kernel/signal.c | 59 ++++++++++++++++++++++++
> 2 files changed, 67 insertions(+)
>
> diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
> index 4aaf31e3bf16..46ce097ca8c0 100644
> --- a/arch/arm64/include/uapi/asm/sigcontext.h
> +++ b/arch/arm64/include/uapi/asm/sigcontext.h
> @@ -140,6 +140,14 @@ struct sve_context {
>
> #define SVE_SIG_FLAG_SM 0x1 /* Context describes streaming mode */
>
> +/* TPIDR2_EL0 context */
> +#define TPIDR2_MAGIC 0x54504902
> +
> +struct tpidr2_context {
> + struct _aarch64_ctx head;
> + __u64 tpidr2;
> +};
> +
> #define ZA_MAGIC 0x54366345
>
> struct za_context {
> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> index 9ad911f1647c..ac4fb42a9613 100644
> --- a/arch/arm64/kernel/signal.c
> +++ b/arch/arm64/kernel/signal.c
> @@ -56,6 +56,7 @@ struct rt_sigframe_user_layout {
> unsigned long fpsimd_offset;
> unsigned long esr_offset;
> unsigned long sve_offset;
> + unsigned long tpidr2_offset;
> unsigned long za_offset;
> unsigned long extra_offset;
> unsigned long end_offset;
> @@ -219,6 +220,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
> struct user_ctxs {
> struct fpsimd_context __user *fpsimd;
> struct sve_context __user *sve;
> + struct tpidr2_context __user *tpidr2;
> struct za_context __user *za;
> };
>
> @@ -358,6 +360,32 @@ extern int preserve_sve_context(void __user *ctx);
>
> #ifdef CONFIG_ARM64_SME
>
> +static int preserve_tpidr2_context(struct tpidr2_context __user *ctx)
> +{
> + int err = 0;
> +
> + current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);
This is half of tls_preserve_current_state() and may be worth factoring out
so that ptrace and signal delivery can use the same sets of helpers.
> +
> + __put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err);
> + __put_user_error(sizeof(*ctx), &ctx->head.size, err);
> + __put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err);
> +
> + return err;
> +}
> +
> +static int restore_tpidr2_context(struct user_ctxs *user)
> +{
> + u64 tpidr2_el0;
> + int err = 0;
> +
> + /* Magic and size were validated deciding to call this function */
typo: before deciding
> + __get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
> + if (!err)
> + current->thread.tpidr2_el0 = tpidr2_el0;
What guarantees this makes its way into the hardware register before we
return to userspace, context switch or deliver another signal?
> +
> + return err;
> +}
> +
> static int preserve_za_context(struct za_context __user *ctx)
> {
> int err = 0;
> @@ -447,6 +475,8 @@ static int restore_za_context(struct user_ctxs *user)
> #else /* ! CONFIG_ARM64_SME */
>
> /* Turn any non-optimised out attempts to use these into a link error: */
> +extern int preserve_tpidr2_context(void __user *ctx);
> +extern int restore_tpidr2_context(struct user_ctxs *user);
> extern int preserve_za_context(void __user *ctx);
> extern int restore_za_context(struct user_ctxs *user);
>
> @@ -465,6 +495,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
>
> user->fpsimd = NULL;
> user->sve = NULL;
> + user->tpidr2 = NULL;
> user->za = NULL;
>
> if (!IS_ALIGNED((unsigned long)base, 16))
> @@ -531,6 +562,19 @@ static int parse_user_sigframe(struct user_ctxs *user,
> user->sve = (struct sve_context __user *)head;
> break;
>
> + case TPIDR2_MAGIC:
> + if (!system_supports_sme())
We seem to be inconsistent between using system_supports_sme() and
system_supports_tpidr2() for tpidr2 checks (see tls_get() and tls_set() for
a glaring example). Please can you tidy this up as a preliminary patch?
> + goto invalid;
> +
> + if (user->tpidr2)
> + goto invalid;
> +
> + if (size != sizeof(*user->tpidr2))
Why are you requiring an exact match here? Won't that hinder any future
extension of the structure?
Will
More information about the linux-arm-kernel
mailing list