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>
This commit is contained in:
Родитель
17d0c4a27b
Коммит
39e5449928
|
@ -144,6 +144,14 @@ struct sve_context {
|
||||||
|
|
||||||
#define SVE_SIG_FLAG_SM 0x1 /* Context describes streaming mode */
|
#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
|
#define ZA_MAGIC 0x54366345
|
||||||
|
|
||||||
struct za_context {
|
struct za_context {
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct rt_sigframe_user_layout {
|
||||||
unsigned long fpsimd_offset;
|
unsigned long fpsimd_offset;
|
||||||
unsigned long esr_offset;
|
unsigned long esr_offset;
|
||||||
unsigned long sve_offset;
|
unsigned long sve_offset;
|
||||||
|
unsigned long tpidr2_offset;
|
||||||
unsigned long za_offset;
|
unsigned long za_offset;
|
||||||
unsigned long extra_offset;
|
unsigned long extra_offset;
|
||||||
unsigned long end_offset;
|
unsigned long end_offset;
|
||||||
|
@ -220,6 +221,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
|
||||||
struct user_ctxs {
|
struct user_ctxs {
|
||||||
struct fpsimd_context __user *fpsimd;
|
struct fpsimd_context __user *fpsimd;
|
||||||
struct sve_context __user *sve;
|
struct sve_context __user *sve;
|
||||||
|
struct tpidr2_context __user *tpidr2;
|
||||||
struct za_context __user *za;
|
struct za_context __user *za;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -361,6 +363,32 @@ extern int preserve_sve_context(void __user *ctx);
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_SME
|
#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);
|
||||||
|
|
||||||
|
__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 */
|
||||||
|
__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
|
||||||
|
if (!err)
|
||||||
|
current->thread.tpidr2_el0 = tpidr2_el0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int preserve_za_context(struct za_context __user *ctx)
|
static int preserve_za_context(struct za_context __user *ctx)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -450,6 +478,8 @@ static int restore_za_context(struct user_ctxs *user)
|
||||||
#else /* ! CONFIG_ARM64_SME */
|
#else /* ! CONFIG_ARM64_SME */
|
||||||
|
|
||||||
/* Turn any non-optimised out attempts to use these into a link error: */
|
/* 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 preserve_za_context(void __user *ctx);
|
||||||
extern int restore_za_context(struct user_ctxs *user);
|
extern int restore_za_context(struct user_ctxs *user);
|
||||||
|
|
||||||
|
@ -468,6 +498,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
||||||
|
|
||||||
user->fpsimd = NULL;
|
user->fpsimd = NULL;
|
||||||
user->sve = NULL;
|
user->sve = NULL;
|
||||||
|
user->tpidr2 = NULL;
|
||||||
user->za = NULL;
|
user->za = NULL;
|
||||||
|
|
||||||
if (!IS_ALIGNED((unsigned long)base, 16))
|
if (!IS_ALIGNED((unsigned long)base, 16))
|
||||||
|
@ -534,6 +565,19 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
||||||
user->sve = (struct sve_context __user *)head;
|
user->sve = (struct sve_context __user *)head;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TPIDR2_MAGIC:
|
||||||
|
if (!system_supports_sme())
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
if (user->tpidr2)
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
if (size != sizeof(*user->tpidr2))
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
user->tpidr2 = (struct tpidr2_context __user *)head;
|
||||||
|
break;
|
||||||
|
|
||||||
case ZA_MAGIC:
|
case ZA_MAGIC:
|
||||||
if (!system_supports_sme())
|
if (!system_supports_sme())
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
@ -666,6 +710,9 @@ static int restore_sigframe(struct pt_regs *regs,
|
||||||
err = restore_fpsimd_context(user.fpsimd);
|
err = restore_fpsimd_context(user.fpsimd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (err == 0 && system_supports_sme() && user.tpidr2)
|
||||||
|
err = restore_tpidr2_context(&user);
|
||||||
|
|
||||||
if (err == 0 && system_supports_sme() && user.za)
|
if (err == 0 && system_supports_sme() && user.za)
|
||||||
err = restore_za_context(&user);
|
err = restore_za_context(&user);
|
||||||
|
|
||||||
|
@ -760,6 +807,11 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
|
||||||
else
|
else
|
||||||
vl = task_get_sme_vl(current);
|
vl = task_get_sme_vl(current);
|
||||||
|
|
||||||
|
err = sigframe_alloc(user, &user->tpidr2_offset,
|
||||||
|
sizeof(struct tpidr2_context));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (thread_za_enabled(¤t->thread))
|
if (thread_za_enabled(¤t->thread))
|
||||||
vq = sve_vq_from_vl(vl);
|
vq = sve_vq_from_vl(vl);
|
||||||
|
|
||||||
|
@ -817,6 +869,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
|
||||||
err |= preserve_sve_context(sve_ctx);
|
err |= preserve_sve_context(sve_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TPIDR2 if supported */
|
||||||
|
if (system_supports_sme() && err == 0) {
|
||||||
|
struct tpidr2_context __user *tpidr2_ctx =
|
||||||
|
apply_user_offset(user, user->tpidr2_offset);
|
||||||
|
err |= preserve_tpidr2_context(tpidr2_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* ZA state if present */
|
/* ZA state if present */
|
||||||
if (system_supports_sme() && err == 0 && user->za_offset) {
|
if (system_supports_sme() && err == 0 && user->za_offset) {
|
||||||
struct za_context __user *za_ctx =
|
struct za_context __user *za_ctx =
|
||||||
|
|
Загрузка…
Ссылка в новой задаче