aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-09-13 10:54:30 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-09-21 16:28:27 +0100
commit85e7d1e9ff11e5df827cc7b81034b85efae7d315 (patch)
tree5c14dd8f712571c7dec5c39e071e76e7d2159a02 /target
parent84848481c3d2c1e1b7fb375894fa20dab56b4bde (diff)
target/arm: Enforce that FPDSCR.LTPSIZE is 4 on inbound migration
Architecturally, for an M-profile CPU with the LOB feature the LTPSIZE field in FPDSCR is always constant 4. QEMU's implementation enforces this everywhere, except that we don't check that it is true in incoming migration data. We're going to add come in gen_update_fp_context() which relies on the "always 4" property. Since this is TCG-only, we don't actually need to be robust to bogus incoming migration data, and the effect of it being wrong would be wrong code generation rather than a QEMU crash; but if it did ever happen somehow it would be very difficult to track down the cause. Add a check so that we fail the inbound migration if the FPDSCR.LTPSIZE value is incorrect. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210913095440.13462-3-peter.maydell@linaro.org
Diffstat (limited to 'target')
-rw-r--r--target/arm/machine.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 81e30de824..c74d8c3f4b 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -781,6 +781,19 @@ static int cpu_post_load(void *opaque, int version_id)
hw_breakpoint_update_all(cpu);
hw_watchpoint_update_all(cpu);
+ /*
+ * TCG gen_update_fp_context() relies on the invariant that
+ * FPDSCR.LTPSIZE is constant 4 for M-profile with the LOB extension;
+ * forbid bogus incoming data with some other value.
+ */
+ if (arm_feature(env, ARM_FEATURE_M) && cpu_isar_feature(aa32_lob, cpu)) {
+ if (extract32(env->v7m.fpdscr[M_REG_NS],
+ FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4 ||
+ extract32(env->v7m.fpdscr[M_REG_S],
+ FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4) {
+ return -1;
+ }
+ }
if (!kvm_enabled()) {
pmu_op_finish(&cpu->env);
}