@@ -61,6 +61,7 @@ struct rt_sigframe_user_layout {
6161 unsigned long za_offset ;
6262 unsigned long zt_offset ;
6363 unsigned long fpmr_offset ;
64+ unsigned long poe_offset ;
6465 unsigned long extra_offset ;
6566 unsigned long end_offset ;
6667};
@@ -185,6 +186,8 @@ struct user_ctxs {
185186 u32 zt_size ;
186187 struct fpmr_context __user * fpmr ;
187188 u32 fpmr_size ;
189+ struct poe_context __user * poe ;
190+ u32 poe_size ;
188191};
189192
190193static int preserve_fpsimd_context (struct fpsimd_context __user * ctx )
@@ -258,6 +261,32 @@ static int restore_fpmr_context(struct user_ctxs *user)
258261 return err ;
259262}
260263
264+ static int preserve_poe_context (struct poe_context __user * ctx )
265+ {
266+ int err = 0 ;
267+
268+ __put_user_error (POE_MAGIC , & ctx -> head .magic , err );
269+ __put_user_error (sizeof (* ctx ), & ctx -> head .size , err );
270+ __put_user_error (read_sysreg_s (SYS_POR_EL0 ), & ctx -> por_el0 , err );
271+
272+ return err ;
273+ }
274+
275+ static int restore_poe_context (struct user_ctxs * user )
276+ {
277+ u64 por_el0 ;
278+ int err = 0 ;
279+
280+ if (user -> poe_size != sizeof (* user -> poe ))
281+ return - EINVAL ;
282+
283+ __get_user_error (por_el0 , & (user -> poe -> por_el0 ), err );
284+ if (!err )
285+ write_sysreg_s (por_el0 , SYS_POR_EL0 );
286+
287+ return err ;
288+ }
289+
261290#ifdef CONFIG_ARM64_SVE
262291
263292static int preserve_sve_context (struct sve_context __user * ctx )
@@ -621,6 +650,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
621650 user -> za = NULL ;
622651 user -> zt = NULL ;
623652 user -> fpmr = NULL ;
653+ user -> poe = NULL ;
624654
625655 if (!IS_ALIGNED ((unsigned long )base , 16 ))
626656 goto invalid ;
@@ -671,6 +701,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
671701 /* ignore */
672702 break ;
673703
704+ case POE_MAGIC :
705+ if (!system_supports_poe ())
706+ goto invalid ;
707+
708+ if (user -> poe )
709+ goto invalid ;
710+
711+ user -> poe = (struct poe_context __user * )head ;
712+ user -> poe_size = size ;
713+ break ;
714+
674715 case SVE_MAGIC :
675716 if (!system_supports_sve () && !system_supports_sme ())
676717 goto invalid ;
@@ -857,6 +898,9 @@ static int restore_sigframe(struct pt_regs *regs,
857898 if (err == 0 && system_supports_sme2 () && user .zt )
858899 err = restore_zt_context (& user );
859900
901+ if (err == 0 && system_supports_poe () && user .poe )
902+ err = restore_poe_context (& user );
903+
860904 return err ;
861905}
862906
@@ -980,6 +1024,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
9801024 return err ;
9811025 }
9821026
1027+ if (system_supports_poe ()) {
1028+ err = sigframe_alloc (user , & user -> poe_offset ,
1029+ sizeof (struct poe_context ));
1030+ if (err )
1031+ return err ;
1032+ }
1033+
9831034 return sigframe_alloc_end (user );
9841035}
9851036
@@ -1042,6 +1093,14 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
10421093 err |= preserve_fpmr_context (fpmr_ctx );
10431094 }
10441095
1096+ if (system_supports_poe () && err == 0 && user -> poe_offset ) {
1097+ struct poe_context __user * poe_ctx =
1098+ apply_user_offset (user , user -> poe_offset );
1099+
1100+ err |= preserve_poe_context (poe_ctx );
1101+ }
1102+
1103+
10451104 /* ZA state if present */
10461105 if (system_supports_sme () && err == 0 && user -> za_offset ) {
10471106 struct za_context __user * za_ctx =
@@ -1178,6 +1237,9 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
11781237 sme_smstop ();
11791238 }
11801239
1240+ if (system_supports_poe ())
1241+ write_sysreg_s (POR_EL0_INIT , SYS_POR_EL0 );
1242+
11811243 if (ka -> sa .sa_flags & SA_RESTORER )
11821244 sigtramp = ka -> sa .sa_restorer ;
11831245 else
0 commit comments