aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/helper.c5
-rw-r--r--target-arm/kvm64.c1
-rw-r--r--target-arm/machine.c2
-rw-r--r--target-arm/op_helper.c5
4 files changed, 7 insertions, 6 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 014bb80d85..c491cd80ab 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5268,7 +5268,7 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
* In a V8 implementation, it is permitted for privileged software to
* change the CPSR A/F bits regardless of the SCR.AW/FW bits.
*/
- if (!arm_feature(env, ARM_FEATURE_V8) &&
+ if (write_type != CPSRWriteRaw && !arm_feature(env, ARM_FEATURE_V8) &&
arm_feature(env, ARM_FEATURE_EL3) &&
!arm_feature(env, ARM_FEATURE_EL2) &&
!arm_is_secure(env)) {
@@ -5315,7 +5315,8 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
env->daif &= ~(CPSR_AIF & mask);
env->daif |= val & CPSR_AIF & mask;
- if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
+ if (write_type != CPSRWriteRaw &&
+ ((env->uncached_cpsr ^ val) & mask & CPSR_M)) {
if (bad_mode_switch(env, val & CPSR_M)) {
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
* We choose to ignore the attempt and leave the CPSR M field
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 08c2c81479..e8527bf0cc 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -722,7 +722,6 @@ int kvm_arch_get_registers(CPUState *cs)
if (is_a64(env)) {
pstate_write(env, val);
} else {
- env->uncached_cpsr = val & CPSR_M;
cpsr_write(env, val, 0xffffffff, CPSRWriteRaw);
}
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 0fc7df0ee2..03a73d950e 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -173,8 +173,6 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
return 0;
}
- /* Avoid mode switch when restoring CPSR */
- env->uncached_cpsr = val & CPSR_M;
cpsr_write(env, val, 0xffffffff, CPSRWriteRaw);
return 0;
}
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 543d33aad2..4881e34177 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -779,7 +779,10 @@ void HELPER(exception_return)(CPUARMState *env)
if (!return_to_aa64) {
env->aarch64 = 0;
- env->uncached_cpsr = spsr & CPSR_M;
+ /* We do a raw CPSR write because aarch64_sync_64_to_32()
+ * will sort the register banks out for us, and we've already
+ * caught all the bad-mode cases in el_from_spsr().
+ */
cpsr_write(env, spsr, ~0, CPSRWriteRaw);
if (!arm_singlestep_active(env)) {
env->uncached_cpsr &= ~PSTATE_SS;