target/arm: Split out rebuild_hflags_a64

Create a function to compute the values of the TBFLAG_A64 bits
that will be cached.  For now, the env->hflags variable is not
used, and the results are fed back to cpu_get_tb_cpu_state.

Note that not all BTI related flags are cached, so we have to
test the BTI feature twice -- once for those bits moved out to
rebuild_hflags_a64 and once for those bits that remain in
cpu_get_tb_cpu_state.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20191023150057.25731-3-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2019-10-23 11:00:35 -04:00 committed by Peter Maydell
parent fdd1b228c2
commit d4d7503ac6

View File

@ -11070,27 +11070,17 @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
return flags; return flags;
} }
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
target_ulong *cs_base, uint32_t *pflags) ARMMMUIdx mmu_idx)
{ {
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
int current_el = arm_current_el(env);
int fp_el = fp_exception_el(env, current_el);
uint32_t flags = 0;
if (is_a64(env)) {
ARMCPU *cpu = env_archcpu(env);
uint64_t sctlr;
*pc = env->pc;
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
/* Get control bits for tagged addresses. */
{
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1); ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
uint32_t flags = 0;
uint64_t sctlr;
int tbii, tbid; int tbii, tbid;
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
/* FIXME: ARMv8.1-VHE S2 translation regime. */ /* FIXME: ARMv8.1-VHE S2 translation regime. */
if (regime_el(env, stage1) < 2) { if (regime_el(env, stage1) < 2) {
ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1); ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
@ -11103,27 +11093,27 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii); flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid); flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
}
if (cpu_isar_feature(aa64_sve, cpu)) { if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
int sve_el = sve_exception_el(env, current_el); int sve_el = sve_exception_el(env, el);
uint32_t zcr_len; uint32_t zcr_len;
/* If SVE is disabled, but FP is enabled, /*
* If SVE is disabled, but FP is enabled,
* then the effective len is 0. * then the effective len is 0.
*/ */
if (sve_el != 0 && fp_el == 0) { if (sve_el != 0 && fp_el == 0) {
zcr_len = 0; zcr_len = 0;
} else { } else {
zcr_len = sve_zcr_len_for_el(env, current_el); zcr_len = sve_zcr_len_for_el(env, el);
} }
flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el); flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len); flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
} }
sctlr = arm_sctlr(env, current_el); sctlr = arm_sctlr(env, el);
if (cpu_isar_feature(aa64_pauth, cpu)) { if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
/* /*
* In order to save space in flags, we record only whether * In order to save space in flags, we record only whether
* pauth is "inactive", meaning all insns are implemented as * pauth is "inactive", meaning all insns are implemented as
@ -11135,11 +11125,28 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
} }
} }
if (cpu_isar_feature(aa64_bti, cpu)) { if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
/* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1); flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
} }
}
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
}
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
int current_el = arm_current_el(env);
int fp_el = fp_exception_el(env, current_el);
uint32_t flags = 0;
if (is_a64(env)) {
*pc = env->pc;
flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
} }
} else { } else {
@ -11159,9 +11166,9 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
flags = FIELD_DP32(flags, TBFLAG_A32, flags = FIELD_DP32(flags, TBFLAG_A32,
XSCALE_CPAR, env->cp15.c15_cpar); XSCALE_CPAR, env->cp15.c15_cpar);
} }
}
flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags); flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
}
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
* states defined in the ARM ARM for software singlestep: * states defined in the ARM ARM for software singlestep: