target/arm: Split out aa64_va_parameter_tbi, aa64_va_parameter_tbid

For the purpose of rebuild_hflags_a64, we do not need to compute
all of the va parameters, only tbi.  Moreover, we can compute them
in a form that is more useful to storing in hflags.

This eliminates the need for aa64_va_parameter_both, so fold that
in to aa64_va_parameter.  The remaining calls to aa64_va_parameter
are in get_phys_addr_lpae and in pauth_helper.c.

This reduces the total cpu consumption of aa64_va_parameter in a
kernel boot plus a kvm guest kernel boot from 3% to 0.5%.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200216194343.21331-5-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2020-02-16 11:43:43 -08:00 committed by Peter Maydell
parent 03f27724df
commit b830a5ee82
2 changed files with 37 additions and 34 deletions

View File

@ -10234,12 +10234,34 @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
}
#endif /* !CONFIG_USER_ONLY */
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx)
static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
{
if (regime_has_2_ranges(mmu_idx)) {
return extract64(tcr, 37, 2);
} else if (mmu_idx == ARMMMUIdx_Stage2) {
return 0; /* VTCR_EL2 */
} else {
return extract32(tcr, 20, 1);
}
}
static int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
{
if (regime_has_2_ranges(mmu_idx)) {
return extract64(tcr, 51, 2);
} else if (mmu_idx == ARMMMUIdx_Stage2) {
return 0; /* VTCR_EL2 */
} else {
return extract32(tcr, 29, 1);
}
}
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data)
{
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
bool tbi, tbid, epd, hpd, using16k, using64k;
int select, tsz;
bool epd, hpd, using16k, using64k;
int select, tsz, tbi;
if (!regime_has_2_ranges(mmu_idx)) {
select = 0;
@ -10248,11 +10270,9 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
using16k = extract32(tcr, 15, 1);
if (mmu_idx == ARMMMUIdx_Stage2) {
/* VTCR_EL2 */
tbi = tbid = hpd = false;
hpd = false;
} else {
tbi = extract32(tcr, 20, 1);
hpd = extract32(tcr, 24, 1);
tbid = extract32(tcr, 29, 1);
}
epd = false;
} else {
@ -10266,28 +10286,30 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
epd = extract32(tcr, 7, 1);
using64k = extract32(tcr, 14, 1);
using16k = extract32(tcr, 15, 1);
tbi = extract64(tcr, 37, 1);
hpd = extract64(tcr, 41, 1);
tbid = extract64(tcr, 51, 1);
} else {
int tg = extract32(tcr, 30, 2);
using16k = tg == 1;
using64k = tg == 3;
tsz = extract32(tcr, 16, 6);
epd = extract32(tcr, 23, 1);
tbi = extract64(tcr, 38, 1);
hpd = extract64(tcr, 42, 1);
tbid = extract64(tcr, 52, 1);
}
}
tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
/* Present TBI as a composite with TBID. */
tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
if (!data) {
tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
}
tbi = (tbi >> select) & 1;
return (ARMVAParameters) {
.tsz = tsz,
.select = select,
.tbi = tbi,
.tbid = tbid,
.epd = epd,
.hpd = hpd,
.using16k = using16k,
@ -10295,16 +10317,6 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
};
}
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data)
{
ARMVAParameters ret = aa64_va_parameters_both(env, va, mmu_idx);
/* Present TBI as a composite with TBID. */
ret.tbi &= (data || !ret.tbid);
return ret;
}
#ifndef CONFIG_USER_ONLY
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx)
@ -12134,21 +12146,15 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
{
uint32_t flags = rebuild_hflags_aprofile(env);
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
uint64_t sctlr;
int tbii, tbid;
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
/* Get control bits for tagged addresses. */
if (regime_has_2_ranges(mmu_idx)) {
ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
tbid = (p1.tbi << 1) | p0.tbi;
tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
} else {
tbid = p0.tbi;
tbii = tbid & !p0.tbid;
}
tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);

View File

@ -1127,15 +1127,12 @@ typedef struct ARMVAParameters {
unsigned tsz : 8;
unsigned select : 1;
bool tbi : 1;
bool tbid : 1;
bool epd : 1;
bool hpd : 1;
bool using16k : 1;
bool using64k : 1;
} ARMVAParameters;
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx);
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data);