mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:56:38 +00:00
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>
This commit is contained in:
committed by
Peter Maydell
parent
5dd04faf9f
commit
82e6411eac
@@ -73,6 +73,13 @@ struct target_esr_context {
|
||||
uint64_t esr;
|
||||
};
|
||||
|
||||
#define TARGET_FPMR_MAGIC 0x46504d52
|
||||
|
||||
struct target_fpmr_context {
|
||||
struct target_aarch64_ctx head;
|
||||
uint64_t fpmr;
|
||||
};
|
||||
|
||||
#define TARGET_EXTRA_MAGIC 0x45585401
|
||||
|
||||
struct target_extra_context {
|
||||
@@ -362,6 +369,14 @@ static bool target_setup_gcs_record(struct target_gcs_context *ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void target_setup_fpmr_record(struct target_fpmr_context *ctx,
|
||||
CPUARMState *env)
|
||||
{
|
||||
__put_user(TARGET_FPMR_MAGIC, &ctx->head.magic);
|
||||
__put_user(sizeof(*ctx), &ctx->head.size);
|
||||
__put_user(env->vfp.fpmr, &ctx->fpmr);
|
||||
}
|
||||
|
||||
static void target_restore_general_frame(CPUARMState *env,
|
||||
struct target_rt_sigframe *sf)
|
||||
{
|
||||
@@ -518,6 +533,12 @@ static void target_restore_tpidr2_record(CPUARMState *env,
|
||||
__get_user(env->cp15.tpidr2_el0, &tpidr2->tpidr2);
|
||||
}
|
||||
|
||||
static void target_restore_fpmr_record(CPUARMState *env,
|
||||
struct target_fpmr_context *fpmr)
|
||||
{
|
||||
__get_user(env->vfp.fpmr, &fpmr->fpmr);
|
||||
}
|
||||
|
||||
static bool target_restore_zt_record(CPUARMState *env,
|
||||
struct target_zt_context *zt, int size,
|
||||
int svcr)
|
||||
@@ -610,6 +631,7 @@ static int target_restore_sigframe(CPUARMState *env,
|
||||
struct target_tpidr2_context *tpidr2 = NULL;
|
||||
struct target_zt_context *zt = NULL;
|
||||
struct target_gcs_context *gcs = NULL;
|
||||
struct target_fpmr_context *fpmr = NULL;
|
||||
uint64_t extra_datap = 0;
|
||||
bool used_extra = false;
|
||||
bool rebuild_hflags = false;
|
||||
@@ -691,6 +713,15 @@ static int target_restore_sigframe(CPUARMState *env,
|
||||
gcs = (struct target_gcs_context *)ctx;
|
||||
break;
|
||||
|
||||
case TARGET_FPMR_MAGIC:
|
||||
if (fpmr
|
||||
|| size != sizeof(struct target_fpmr_context)
|
||||
|| !cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
|
||||
goto err;
|
||||
}
|
||||
fpmr = (struct target_fpmr_context *)ctx;
|
||||
break;
|
||||
|
||||
case TARGET_EXTRA_MAGIC:
|
||||
if (extra || size != sizeof(struct target_extra_context)) {
|
||||
goto err;
|
||||
@@ -735,6 +766,9 @@ static int target_restore_sigframe(CPUARMState *env,
|
||||
if (tpidr2) {
|
||||
target_restore_tpidr2_record(env, tpidr2);
|
||||
}
|
||||
if (fpmr) {
|
||||
target_restore_fpmr_record(env, fpmr);
|
||||
}
|
||||
/*
|
||||
* NB that we must restore ZT after ZA so the check that there's
|
||||
* 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,
|
||||
uc.tuc_mcontext.__reserved),
|
||||
};
|
||||
int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0, tpidr2_ofs = 0;
|
||||
int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0;
|
||||
int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0, fpmr_ofs = 0;
|
||||
int sve_size = 0, za_size = 0, tpidr2_size = 0, zt_size = 0;
|
||||
struct target_rt_sigframe *frame;
|
||||
struct target_rt_frame_record *fr;
|
||||
@@ -841,6 +875,11 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
|
||||
&layout);
|
||||
}
|
||||
|
||||
if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
|
||||
fpmr_ofs = alloc_sigframe_space(sizeof(struct target_fpmr_context),
|
||||
&layout);
|
||||
}
|
||||
|
||||
/* SVE state needs saving only if it exists. */
|
||||
if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
|
||||
cpu_isar_feature(aa64_sme, env_archcpu(env))) {
|
||||
@@ -917,6 +956,9 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
|
||||
!target_setup_gcs_record((void *)frame + gcs_ofs, env, return_addr)) {
|
||||
goto give_sigsegv;
|
||||
}
|
||||
if (fpmr_ofs) {
|
||||
target_setup_fpmr_record((void *)frame + fpmr_ofs, env);
|
||||
}
|
||||
target_setup_end_record((void *)frame + layout.std_end_ofs);
|
||||
if (layout.extra_ofs) {
|
||||
target_setup_extra_record((void *)frame + layout.extra_ofs,
|
||||
|
||||
Reference in New Issue
Block a user