@@ -60,6 +60,7 @@ struct rt_sigframe_user_layout {
60
60
unsigned long tpidr2_offset ;
61
61
unsigned long za_offset ;
62
62
unsigned long zt_offset ;
63
+ unsigned long fpmr_offset ;
63
64
unsigned long extra_offset ;
64
65
unsigned long end_offset ;
65
66
};
@@ -182,6 +183,8 @@ struct user_ctxs {
182
183
u32 za_size ;
183
184
struct zt_context __user * zt ;
184
185
u32 zt_size ;
186
+ struct fpmr_context __user * fpmr ;
187
+ u32 fpmr_size ;
185
188
};
186
189
187
190
static int preserve_fpsimd_context (struct fpsimd_context __user * ctx )
@@ -227,6 +230,33 @@ static int restore_fpsimd_context(struct user_ctxs *user)
227
230
return err ? - EFAULT : 0 ;
228
231
}
229
232
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
+ }
230
260
231
261
#ifdef CONFIG_ARM64_SVE
232
262
@@ -590,6 +620,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
590
620
user -> tpidr2 = NULL ;
591
621
user -> za = NULL ;
592
622
user -> zt = NULL ;
623
+ user -> fpmr = NULL ;
593
624
594
625
if (!IS_ALIGNED ((unsigned long )base , 16 ))
595
626
goto invalid ;
@@ -684,6 +715,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
684
715
user -> zt_size = size ;
685
716
break ;
686
717
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
+
687
729
case EXTRA_MAGIC :
688
730
if (have_extra_context )
689
731
goto invalid ;
@@ -806,6 +848,9 @@ static int restore_sigframe(struct pt_regs *regs,
806
848
if (err == 0 && system_supports_tpidr2 () && user .tpidr2 )
807
849
err = restore_tpidr2_context (& user );
808
850
851
+ if (err == 0 && system_supports_fpmr () && user .fpmr )
852
+ err = restore_fpmr_context (& user );
853
+
809
854
if (err == 0 && system_supports_sme () && user .za )
810
855
err = restore_za_context (& user );
811
856
@@ -928,6 +973,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
928
973
}
929
974
}
930
975
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
+
931
983
return sigframe_alloc_end (user );
932
984
}
933
985
@@ -983,6 +1035,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
983
1035
err |= preserve_tpidr2_context (tpidr2_ctx );
984
1036
}
985
1037
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
+
986
1045
/* ZA state if present */
987
1046
if (system_supports_sme () && err == 0 && user -> za_offset ) {
988
1047
struct za_context __user * za_ctx =
0 commit comments