[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] target/arm: Don't calculate zcr_len for TB flags in
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PATCH] target/arm: Don't calculate zcr_len for TB flags in non-SVE CPUs |
Date: |
Fri, 24 Aug 2018 15:13:33 +0100 |
Skip calculation of the zcr_len part of TB flags if the CPU
doesn't have SVE. This fixes a bug where for a non-SVE CPU
we might end up with a bogus zcr_len value of -1, which then
trashes other TB flags when it is ORed into the flags word,
resulting in a QEMU crash later due to a bogus mmu_idx field.
Signed-off-by: Peter Maydell <address@hidden>
---
Not entirely sure why this doesn't cause us problems more often.
I saw it with an AArch32 setup with an A57 with EL2 but not EL3.
target/arm/helper.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 088f452716e..89767f55a1e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12597,26 +12597,28 @@ void cpu_get_tb_cpu_state(CPUARMState *env,
target_ulong *pc,
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
- /* If SVE is disabled, but FP is enabled,
- then the effective len is 0. */
- if (sve_el != 0 && fp_el == 0) {
- zcr_len = 0;
- } else {
- int current_el = arm_current_el(env);
- ARMCPU *cpu = arm_env_get_cpu(env);
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
+ /* If SVE is disabled, but FP is enabled,
+ then the effective len is 0. */
+ if (sve_el != 0 && fp_el == 0) {
+ zcr_len = 0;
+ } else {
+ int current_el = arm_current_el(env);
+ ARMCPU *cpu = arm_env_get_cpu(env);
- zcr_len = cpu->sve_max_vq - 1;
- if (current_el <= 1) {
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
- }
- if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
- }
- if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
+ zcr_len = cpu->sve_max_vq - 1;
+ if (current_el <= 1) {
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
+ }
+ if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
+ }
+ if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
+ }
}
+ flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
}
- flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
} else {
*pc = env->regs[15];
flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
--
2.18.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] target/arm: Don't calculate zcr_len for TB flags in non-SVE CPUs,
Peter Maydell <=