Skip to content

Commit 8c46def

Browse files
brooniectmarinas
authored andcommitted
arm64/signal: Add FPMR signal handling
Expose FPMR in the signal context on systems where it is supported. The kernel validates the exact size of the FPSIMD registers so we can't readily add it to fpsimd_context without disruption. Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 203f2b9 commit 8c46def

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ struct tpidr2_context {
152152
__u64 tpidr2;
153153
};
154154

155+
/* FPMR context */
156+
#define FPMR_MAGIC 0x46504d52
157+
158+
struct fpmr_context {
159+
struct _aarch64_ctx head;
160+
__u64 fpmr;
161+
};
162+
155163
#define ZA_MAGIC 0x54366345
156164

157165
struct za_context {

arch/arm64/kernel/signal.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct rt_sigframe_user_layout {
6060
unsigned long tpidr2_offset;
6161
unsigned long za_offset;
6262
unsigned long zt_offset;
63+
unsigned long fpmr_offset;
6364
unsigned long extra_offset;
6465
unsigned long end_offset;
6566
};
@@ -182,6 +183,8 @@ struct user_ctxs {
182183
u32 za_size;
183184
struct zt_context __user *zt;
184185
u32 zt_size;
186+
struct fpmr_context __user *fpmr;
187+
u32 fpmr_size;
185188
};
186189

187190
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -227,6 +230,33 @@ static int restore_fpsimd_context(struct user_ctxs *user)
227230
return err ? -EFAULT : 0;
228231
}
229232

233+
static int preserve_fpmr_context(struct fpmr_context __user *ctx)
234+
{
235+
int err = 0;
236+
237+
current->thread.uw.fpmr = read_sysreg_s(SYS_FPMR);
238+
239+
__put_user_error(FPMR_MAGIC, &ctx->head.magic, err);
240+
__put_user_error(sizeof(*ctx), &ctx->head.size, err);
241+
__put_user_error(current->thread.uw.fpmr, &ctx->fpmr, err);
242+
243+
return err;
244+
}
245+
246+
static int restore_fpmr_context(struct user_ctxs *user)
247+
{
248+
u64 fpmr;
249+
int err = 0;
250+
251+
if (user->fpmr_size != sizeof(*user->fpmr))
252+
return -EINVAL;
253+
254+
__get_user_error(fpmr, &user->fpmr->fpmr, err);
255+
if (!err)
256+
write_sysreg_s(fpmr, SYS_FPMR);
257+
258+
return err;
259+
}
230260

231261
#ifdef CONFIG_ARM64_SVE
232262

@@ -590,6 +620,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
590620
user->tpidr2 = NULL;
591621
user->za = NULL;
592622
user->zt = NULL;
623+
user->fpmr = NULL;
593624

594625
if (!IS_ALIGNED((unsigned long)base, 16))
595626
goto invalid;
@@ -684,6 +715,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
684715
user->zt_size = size;
685716
break;
686717

718+
case FPMR_MAGIC:
719+
if (!system_supports_fpmr())
720+
goto invalid;
721+
722+
if (user->fpmr)
723+
goto invalid;
724+
725+
user->fpmr = (struct fpmr_context __user *)head;
726+
user->fpmr_size = size;
727+
break;
728+
687729
case EXTRA_MAGIC:
688730
if (have_extra_context)
689731
goto invalid;
@@ -806,6 +848,9 @@ static int restore_sigframe(struct pt_regs *regs,
806848
if (err == 0 && system_supports_tpidr2() && user.tpidr2)
807849
err = restore_tpidr2_context(&user);
808850

851+
if (err == 0 && system_supports_fpmr() && user.fpmr)
852+
err = restore_fpmr_context(&user);
853+
809854
if (err == 0 && system_supports_sme() && user.za)
810855
err = restore_za_context(&user);
811856

@@ -928,6 +973,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
928973
}
929974
}
930975

976+
if (system_supports_fpmr()) {
977+
err = sigframe_alloc(user, &user->fpmr_offset,
978+
sizeof(struct fpmr_context));
979+
if (err)
980+
return err;
981+
}
982+
931983
return sigframe_alloc_end(user);
932984
}
933985

@@ -983,6 +1035,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
9831035
err |= preserve_tpidr2_context(tpidr2_ctx);
9841036
}
9851037

1038+
/* FPMR if supported */
1039+
if (system_supports_fpmr() && err == 0) {
1040+
struct fpmr_context __user *fpmr_ctx =
1041+
apply_user_offset(user, user->fpmr_offset);
1042+
err |= preserve_fpmr_context(fpmr_ctx);
1043+
}
1044+
9861045
/* ZA state if present */
9871046
if (system_supports_sme() && err == 0 && user->za_offset) {
9881047
struct za_context __user *za_ctx =

0 commit comments

Comments
 (0)