@@ -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)
220221struct 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+
364392static 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 );
453483extern int preserve_za_context (void __user * ctx );
454484extern 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