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%.

Backports commit b830a5ee82e66f54697dcc6450fe9239b7412d13 from qemu
This commit is contained in:
Richard Henderson 2020-03-21 18:04:37 -04:00 committed by Lioncash
parent 2cce7e0dd0
commit 0131e804fb
2 changed files with 37 additions and 34 deletions

View file

@ -10089,12 +10089,34 @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
} }
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va, static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
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; uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
bool tbi, tbid, epd, hpd, using16k, using64k; bool epd, hpd, using16k, using64k;
int select, tsz; int select, tsz, tbi;
if (!regime_has_2_ranges(mmu_idx)) { if (!regime_has_2_ranges(mmu_idx)) {
select = 0; select = 0;
@ -10103,11 +10125,9 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
using16k = extract32(tcr, 15, 1); using16k = extract32(tcr, 15, 1);
if (mmu_idx == ARMMMUIdx_Stage2) { if (mmu_idx == ARMMMUIdx_Stage2) {
/* VTCR_EL2 */ /* VTCR_EL2 */
tbi = tbid = hpd = false; hpd = false;
} else { } else {
tbi = extract32(tcr, 20, 1);
hpd = extract32(tcr, 24, 1); hpd = extract32(tcr, 24, 1);
tbid = extract32(tcr, 29, 1);
} }
epd = false; epd = false;
} else { } else {
@ -10121,28 +10141,30 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
epd = extract32(tcr, 7, 1); epd = extract32(tcr, 7, 1);
using64k = extract32(tcr, 14, 1); using64k = extract32(tcr, 14, 1);
using16k = extract32(tcr, 15, 1); using16k = extract32(tcr, 15, 1);
tbi = extract64(tcr, 37, 1);
hpd = extract64(tcr, 41, 1); hpd = extract64(tcr, 41, 1);
tbid = extract64(tcr, 51, 1);
} else { } else {
int tg = extract32(tcr, 30, 2); int tg = extract32(tcr, 30, 2);
using16k = tg == 1; using16k = tg == 1;
using64k = tg == 3; using64k = tg == 3;
tsz = extract32(tcr, 16, 6); tsz = extract32(tcr, 16, 6);
epd = extract32(tcr, 23, 1); epd = extract32(tcr, 23, 1);
tbi = extract64(tcr, 38, 1);
hpd = extract64(tcr, 42, 1); hpd = extract64(tcr, 42, 1);
tbid = extract64(tcr, 52, 1);
} }
} }
tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */ tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */ 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) { return (ARMVAParameters) {
.tsz = tsz, .tsz = tsz,
.select = select, .select = select,
.tbi = tbi, .tbi = tbi,
.tbid = tbid,
.epd = epd, .epd = epd,
.hpd = hpd, .hpd = hpd,
.using16k = using16k, .using16k = using16k,
@ -10150,16 +10172,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 #ifndef CONFIG_USER_ONLY
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va, static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx) ARMMMUIdx mmu_idx)
@ -11940,18 +11952,12 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
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); uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
int tbii, tbid; int tbii, tbid;
/* Get control bits for tagged addresses. */ /* Get control bits for tagged addresses. */
if (regime_has_2_ranges(mmu_idx)) { tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1); tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
tbid = (p1.tbi << 1) | p0.tbi;
tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
} else {
tbid = p0.tbi;
tbii = tbid & !p0.tbid;
}
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);

View file

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