@samitouri / QOSamiQemu / commits / 82e6411eac

linux-user/aarch64: Implement FPMR signal frames

Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-17-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed May 22, 2026 at 15:02 UTC 82e6411eacee9381cd51c9084c7ba08b7407b39b
1 file changed +43 -1
linux-user/aarch64/signal.c
+43 -1
@@ -73,6 +73,13 @@ struct target_esr_context {
73 uint64_t esr;
74 };
75
76 +#define TARGET_FPMR_MAGIC 0x46504d52
77 +
78 +struct target_fpmr_context {
79 + struct target_aarch64_ctx head;
80 + uint64_t fpmr;
81 +};
82 +
83 #define TARGET_EXTRA_MAGIC 0x45585401
84
85 struct target_extra_context {
@@ -362,6 +369,14 @@ static bool target_setup_gcs_record(struct target_gcs_context *ctx,
369 return true;
370 }
371
372 +static void target_setup_fpmr_record(struct target_fpmr_context *ctx,
373 + CPUARMState *env)
374 +{
375 + __put_user(TARGET_FPMR_MAGIC, &ctx->head.magic);
376 + __put_user(sizeof(*ctx), &ctx->head.size);
377 + __put_user(env->vfp.fpmr, &ctx->fpmr);
378 +}
379 +
380 static void target_restore_general_frame(CPUARMState *env,
381 struct target_rt_sigframe *sf)
382 {
@@ -518,6 +533,12 @@ static void target_restore_tpidr2_record(CPUARMState *env,
533 __get_user(env->cp15.tpidr2_el0, &tpidr2->tpidr2);
534 }
535
536 +static void target_restore_fpmr_record(CPUARMState *env,
537 + struct target_fpmr_context *fpmr)
538 +{
539 + __get_user(env->vfp.fpmr, &fpmr->fpmr);
540 +}
541 +
542 static bool target_restore_zt_record(CPUARMState *env,
543 struct target_zt_context *zt, int size,
544 int svcr)
@@ -610,6 +631,7 @@ static int target_restore_sigframe(CPUARMState *env,
631 struct target_tpidr2_context *tpidr2 = NULL;
632 struct target_zt_context *zt = NULL;
633 struct target_gcs_context *gcs = NULL;
634 + struct target_fpmr_context *fpmr = NULL;
635 uint64_t extra_datap = 0;
636 bool used_extra = false;
637 bool rebuild_hflags = false;
@@ -691,6 +713,15 @@ static int target_restore_sigframe(CPUARMState *env,
713 gcs = (struct target_gcs_context *)ctx;
714 break;
715
716 + case TARGET_FPMR_MAGIC:
717 + if (fpmr
718 + || size != sizeof(struct target_fpmr_context)
719 + || !cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
720 + goto err;
721 + }
722 + fpmr = (struct target_fpmr_context *)ctx;
723 + break;
724 +
725 case TARGET_EXTRA_MAGIC:
726 if (extra || size != sizeof(struct target_extra_context)) {
727 goto err;
@@ -735,6 +766,9 @@ static int target_restore_sigframe(CPUARMState *env,
766 if (tpidr2) {
767 target_restore_tpidr2_record(env, tpidr2);
768 }
769 + if (fpmr) {
770 + target_restore_fpmr_record(env, fpmr);
771 + }
772 /*
773 * NB that we must restore ZT after ZA so the check that there's
774 * no ZT record if SVCR.ZA is 0 gets the right value of SVCR.
@@ -817,7 +851,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
851 uc.tuc_mcontext.__reserved),
852 };
853 int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0, tpidr2_ofs = 0;
820 - int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0;
854 + int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0, fpmr_ofs = 0;
855 int sve_size = 0, za_size = 0, tpidr2_size = 0, zt_size = 0;
856 struct target_rt_sigframe *frame;
857 struct target_rt_frame_record *fr;
@@ -841,6 +875,11 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
875 &layout);
876 }
877
878 + if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
879 + fpmr_ofs = alloc_sigframe_space(sizeof(struct target_fpmr_context),
880 + &layout);
881 + }
882 +
883 /* SVE state needs saving only if it exists. */
884 if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
885 cpu_isar_feature(aa64_sme, env_archcpu(env))) {
@@ -917,6 +956,9 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
956 !target_setup_gcs_record((void *)frame + gcs_ofs, env, return_addr)) {
957 goto give_sigsegv;
958 }
959 + if (fpmr_ofs) {
960 + target_setup_fpmr_record((void *)frame + fpmr_ofs, env);
961 + }
962 target_setup_end_record((void *)frame + layout.std_end_ofs);
963 if (layout.extra_ofs) {
964 target_setup_extra_record((void *)frame + layout.extra_ofs,