@@ -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
187190static 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