Skip to content

Commit 39e5449

Browse files
brooniectmarinas
authored andcommitted
arm64/signal: Include TPIDR2 in the signal context
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@kernel.org> Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> Link: https://lore.kernel.org/r/20221208-arm64-tpidr2-sig-v3-2-c77c6c8775f4@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 17d0c4a commit 39e5449

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

arch/arm64/include/uapi/asm/sigcontext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ struct sve_context {
144144

145145
#define SVE_SIG_FLAG_SM 0x1 /* Context describes streaming mode */
146146

147+
/* TPIDR2_EL0 context */
148+
#define TPIDR2_MAGIC 0x54504902
149+
150+
struct tpidr2_context {
151+
struct _aarch64_ctx head;
152+
__u64 tpidr2;
153+
};
154+
147155
#define ZA_MAGIC 0x54366345
148156

149157
struct za_context {

arch/arm64/kernel/signal.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct rt_sigframe_user_layout {
5656
unsigned long fpsimd_offset;
5757
unsigned long esr_offset;
5858
unsigned long sve_offset;
59+
unsigned long tpidr2_offset;
5960
unsigned long za_offset;
6061
unsigned long extra_offset;
6162
unsigned long end_offset;
@@ -220,6 +221,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
220221
struct user_ctxs {
221222
struct fpsimd_context __user *fpsimd;
222223
struct sve_context __user *sve;
224+
struct tpidr2_context __user *tpidr2;
223225
struct za_context __user *za;
224226
};
225227

@@ -361,6 +363,32 @@ extern int preserve_sve_context(void __user *ctx);
361363

362364
#ifdef CONFIG_ARM64_SME
363365

366+
static int preserve_tpidr2_context(struct tpidr2_context __user *ctx)
367+
{
368+
int err = 0;
369+
370+
current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);
371+
372+
__put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err);
373+
__put_user_error(sizeof(*ctx), &ctx->head.size, err);
374+
__put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err);
375+
376+
return err;
377+
}
378+
379+
static int restore_tpidr2_context(struct user_ctxs *user)
380+
{
381+
u64 tpidr2_el0;
382+
int err = 0;
383+
384+
/* Magic and size were validated deciding to call this function */
385+
__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
386+
if (!err)
387+
current->thread.tpidr2_el0 = tpidr2_el0;
388+
389+
return err;
390+
}
391+
364392
static int preserve_za_context(struct za_context __user *ctx)
365393
{
366394
int err = 0;
@@ -450,6 +478,8 @@ static int restore_za_context(struct user_ctxs *user)
450478
#else /* ! CONFIG_ARM64_SME */
451479

452480
/* Turn any non-optimised out attempts to use these into a link error: */
481+
extern int preserve_tpidr2_context(void __user *ctx);
482+
extern int restore_tpidr2_context(struct user_ctxs *user);
453483
extern int preserve_za_context(void __user *ctx);
454484
extern int restore_za_context(struct user_ctxs *user);
455485

@@ -468,6 +498,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
468498

469499
user->fpsimd = NULL;
470500
user->sve = NULL;
501+
user->tpidr2 = NULL;
471502
user->za = NULL;
472503

473504
if (!IS_ALIGNED((unsigned long)base, 16))
@@ -534,6 +565,19 @@ static int parse_user_sigframe(struct user_ctxs *user,
534565
user->sve = (struct sve_context __user *)head;
535566
break;
536567

568+
case TPIDR2_MAGIC:
569+
if (!system_supports_sme())
570+
goto invalid;
571+
572+
if (user->tpidr2)
573+
goto invalid;
574+
575+
if (size != sizeof(*user->tpidr2))
576+
goto invalid;
577+
578+
user->tpidr2 = (struct tpidr2_context __user *)head;
579+
break;
580+
537581
case ZA_MAGIC:
538582
if (!system_supports_sme())
539583
goto invalid;
@@ -666,6 +710,9 @@ static int restore_sigframe(struct pt_regs *regs,
666710
err = restore_fpsimd_context(user.fpsimd);
667711
}
668712

713+
if (err == 0 && system_supports_sme() && user.tpidr2)
714+
err = restore_tpidr2_context(&user);
715+
669716
if (err == 0 && system_supports_sme() && user.za)
670717
err = restore_za_context(&user);
671718

@@ -760,6 +807,11 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
760807
else
761808
vl = task_get_sme_vl(current);
762809

810+
err = sigframe_alloc(user, &user->tpidr2_offset,
811+
sizeof(struct tpidr2_context));
812+
if (err)
813+
return err;
814+
763815
if (thread_za_enabled(&current->thread))
764816
vq = sve_vq_from_vl(vl);
765817

@@ -817,6 +869,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
817869
err |= preserve_sve_context(sve_ctx);
818870
}
819871

872+
/* TPIDR2 if supported */
873+
if (system_supports_sme() && err == 0) {
874+
struct tpidr2_context __user *tpidr2_ctx =
875+
apply_user_offset(user, user->tpidr2_offset);
876+
err |= preserve_tpidr2_context(tpidr2_ctx);
877+
}
878+
820879
/* ZA state if present */
821880
if (system_supports_sme() && err == 0 && user->za_offset) {
822881
struct za_context __user *za_ctx =

0 commit comments

Comments
 (0)