@samitouri / QOSamiQemu / commits / aa4d11f0f2

target/arm: Introduce FPMR

Introduce the special register FPMR and its fields. Migrate it when present. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed May 22, 2026 at 15:02 UTC aa4d11f0f2f32b3b6495eba9943891cc56923bf5
6 files changed +52 -1
target/arm/cpregs.h
+5
@@ -149,6 +149,11 @@ enum {
149 * should not trap to EL2 when HCR_EL2.NV is set.
150 */
151 ARM_CP_NV_NO_TRAP = 1 << 22,
152 + /*
153 + * Flag: Access check for this sysreg is constrained by the
154 + * ARM pseudocode function CheckFPMREnabled().
155 + */
156 + ARM_CP_FPMR = 1 << 23,
157 };
158
159 /*
target/arm/cpu-features.h
+5
@@ -1192,6 +1192,11 @@ static inline bool isar_feature_aa64_gcie(const ARMISARegisters *id)
1192 return FIELD_EX64_IDREG(id, ID_AA64PFR2, GCIE) != 0;
1193 }
1194
1195 +static inline bool isar_feature_aa64_fpmr(const ARMISARegisters *id)
1196 +{
1197 + return FIELD_EX64_IDREG(id, ID_AA64PFR2, FPMR) != 0;
1198 +}
1199 +
1200 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
1201 {
1202 return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1;
target/arm/cpu.h
+1
@@ -713,6 +713,7 @@ typedef struct CPUArchState {
713 */
714 uint64_t fpsr;
715 uint64_t fpcr;
716 + uint64_t fpmr;
717
718 uint32_t xregs[16];
719
target/arm/helper.c
+11 -1
@@ -6229,6 +6229,14 @@ static const ARMCPRegInfo aie_reginfo[] = {
6229 .type = ARM_CP_CONST, .resetvalue = 0 },
6230 };
6231
6232 +static const ARMCPRegInfo fpmr_reginfo[] = {
6233 + { .name = "FPMR", .state = ARM_CP_STATE_AA64,
6234 + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 4, .opc2 = 2,
6235 + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_FPMR,
6236 + .fieldoffset = offsetof(CPUARMState, vfp.fpmr),
6237 + }
6238 +};
6239 +
6240 void register_cp_regs_for_features(ARMCPU *cpu)
6241 {
6242 /* Register all the coprocessor registers based on feature bits */
@@ -7502,10 +7510,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
7510 define_arm_cp_regs(cpu, mec_mte_reginfo);
7511 }
7512 }
7505 -
7513 if (cpu_isar_feature(aa64_aie, cpu)) {
7514 define_arm_cp_regs(cpu, aie_reginfo);
7515 }
7516 + if (cpu_isar_feature(aa64_fpmr, cpu)) {
7517 + define_arm_cp_regs(cpu, fpmr_reginfo);
7518 + }
7519
7520 if (cpu_isar_feature(any_predinv, cpu)) {
7521 define_arm_cp_regs(cpu, predinv_reginfo);
target/arm/internals.h
+10
@@ -293,6 +293,16 @@ FIELD(CNTHCTL, EVNTIS, 17, 1)
293 FIELD(CNTHCTL, CNTVMASK, 18, 1)
294 FIELD(CNTHCTL, CNTPMASK, 19, 1)
295
296 +FIELD(FPMR, F8S1, 0, 3)
297 +FIELD(FPMR, F8S2, 3, 3)
298 +FIELD(FPMR, F8D, 6, 3)
299 +FIELD(FPMR, OSM, 14, 1)
300 +FIELD(FPMR, OSC, 15, 1)
301 +FIELD(FPMR, LSCALE, 16, 7)
302 +FIELD(FPMR, NSCALE, 24, 8)
303 +FIELD(FPMR, NSCALE_F16, 24, 5)
304 +FIELD(FPMR, LSCALE2, 32, 6)
305 +
306 /* We use a few fake FSR values for internal purposes in M profile.
307 * M profile cores don't have A/R format FSRs, but currently our
308 * get_phys_addr() code assumes A/R profile and reports failures via
target/arm/machine.c
+20
@@ -960,6 +960,25 @@ static const VMStateDescription vmstate_syndrome64 = {
960 },
961 };
962
963 +static bool fpmr_needed(void *opaque)
964 +{
965 + ARMCPU *cpu = opaque;
966 +
967 + return arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
968 + && cpu_isar_feature(aa64_fpmr, cpu);
969 +}
970 +
971 +static const VMStateDescription vmstate_fpmr = {
972 + .name = "cpu/fpmr",
973 + .version_id = 1,
974 + .minimum_version_id = 1,
975 + .needed = fpmr_needed,
976 + .fields = (const VMStateField[]) {
977 + VMSTATE_UINT64(env.vfp.fpmr, ARMCPU),
978 + VMSTATE_END_OF_LIST()
979 + },
980 +};
981 +
982 static int cpu_pre_save(void *opaque)
983 {
984 ARMCPU *cpu = opaque;
@@ -1323,6 +1342,7 @@ const VMStateDescription vmstate_arm_cpu = {
1342 &vmstate_syndrome64,
1343 &vmstate_pstate64,
1344 &vmstate_event,
1345 + &vmstate_fpmr,
1346 NULL
1347 }
1348 };