Skip to content

Commit

Permalink
target/arm: Fix cpu_get_tb_cpu_state() for non-SVE CPUs
Browse files Browse the repository at this point in the history
Not only are the sve-related tb_flags fields unused when SVE is
disabled, but not all of the cpu registers are initialized properly
for computing same.  This can corrupt other fields by ORing in -1,
which might result in QEMU crashing.

This bug was not present in 3.0, but this patch is cc'd to
stable because adf92ea where the bug was
introduced was marked for stable.

Fixes: adf92ea
Cc: qemu-stable@nongnu.org (3.0.1)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
rth7680 authored and pm215 committed Sep 25, 2018
1 parent 506e4a0 commit e79b445
Showing 1 changed file with 24 additions and 21 deletions.
45 changes: 24 additions & 21 deletions target/arm/helper.c
Expand Up @@ -12587,36 +12587,39 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
uint32_t flags;

if (is_a64(env)) {
int sve_el = sve_exception_el(env);
uint32_t zcr_len;

*pc = env->pc;
flags = ARM_TBFLAG_AARCH64_STATE_MASK;
/* Get control bits for tagged addresses */
flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
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)) {
int sve_el = sve_exception_el(env);
uint32_t zcr_len;

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]);
/* 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]);
}
}
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
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)
Expand Down

0 comments on commit e79b445

Please sign in to comment.