aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-08-17 21:18:43 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-08-26 17:02:01 +0100
commite784807cd26314071290a036b5a70322eda31db1 (patch)
tree150d09cc50afd5f1239ea70033cfb00a9394d399 /linux-user
parent8e228c9e4bcfea634e7ee404f4d13136d2072c71 (diff)
target/arm: Do hflags rebuild in cpsr_write()
Currently we rely on all the callsites of cpsr_write() to rebuild the cached hflags if they change one of the CPSR bits which we use as a TB flag and cache in hflags. This is a bit awkward when we want to change the set of CPSR bits that we cache, because it means we need to re-audit all the cpsr_write() callsites to see which flags they are writing and whether they now need to rebuild the hflags. Switch instead to making cpsr_write() call arm_rebuild_hflags() itself if one of the bits being changed is a cached bit. We don't do the rebuild for the CPSRWriteRaw write type, because that kind of write is generally doing something special anyway. For the CPSRWriteRaw callsites in the KVM code and inbound migration we definitely don't want to recalculate the hflags; the callsites in boot.c and arm-powerctl.c have to do a rebuild-hflags call themselves anyway because of other CPU state changes they make. This allows us to drop explicit arm_rebuild_hflags() calls in a couple of places where the only reason we needed to call it was the CPSR write. This fixes a bug where we were incorrectly failing to rebuild hflags in the code path for a gdbstub write to CPSR, which meant that you could make QEMU assert by breaking into a running guest, altering the CPSR to change the value of, for example, CPSR.E, and then continuing. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210817201843.3829-1-peter.maydell@linaro.org
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/arm/signal.c2
1 files changed, 0 insertions, 2 deletions
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index 32b68ee302..1dfcfd2d57 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -289,7 +289,6 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr);
- arm_rebuild_hflags(env);
return 0;
}
@@ -547,7 +546,6 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
__get_user(env->regs[15], &sc->arm_pc);
__get_user(cpsr, &sc->arm_cpsr);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
- arm_rebuild_hflags(env);
err |= !valid_user_regs(env);