target/arm: Implement FEAT_E0PD
FEAT_E0PD adds new bits E0PD0 and E0PD1 to TCR_EL1, which allow the OS to forbid EL0 access to half of the address space. Since this is an EL0-specific variation on the existing TCR_ELx.{EPD0,EPD1}, we can implement it entirely in aa64_va_parameters(). This requires moving the existing regime_is_user() to internals.h so that the code in helper.c can get at it. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20221021160131.3531787-1-peter.maydell@linaro.org
This commit is contained in:
parent
344744e148
commit
e4c93e44ab
@ -24,6 +24,7 @@ the following architecture extensions:
|
|||||||
- FEAT_Debugv8p4 (Debug changes for v8.4)
|
- FEAT_Debugv8p4 (Debug changes for v8.4)
|
||||||
- FEAT_DotProd (Advanced SIMD dot product instructions)
|
- FEAT_DotProd (Advanced SIMD dot product instructions)
|
||||||
- FEAT_DoubleFault (Double Fault Extension)
|
- FEAT_DoubleFault (Double Fault Extension)
|
||||||
|
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
|
||||||
- FEAT_ETS (Enhanced Translation Synchronization)
|
- FEAT_ETS (Enhanced Translation Synchronization)
|
||||||
- FEAT_FCMA (Floating-point complex number instructions)
|
- FEAT_FCMA (Floating-point complex number instructions)
|
||||||
- FEAT_FHM (Floating-point half-precision multiplication instructions)
|
- FEAT_FHM (Floating-point half-precision multiplication instructions)
|
||||||
|
@ -4147,6 +4147,11 @@ static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
|
|||||||
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
|
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
|
||||||
|
{
|
||||||
|
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
|
static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
|
||||||
{
|
{
|
||||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
|
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
|
||||||
|
@ -1185,6 +1185,7 @@ static void aarch64_max_initfn(Object *obj)
|
|||||||
t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1); /* FEAT_S2FWB */
|
t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1); /* FEAT_S2FWB */
|
||||||
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
|
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
|
||||||
t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
|
t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
|
||||||
|
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
|
||||||
cpu->isar.id_aa64mmfr2 = t;
|
cpu->isar.id_aa64mmfr2 = t;
|
||||||
|
|
||||||
t = cpu->isar.id_aa64zfr0;
|
t = cpu->isar.id_aa64zfr0;
|
||||||
|
@ -10491,6 +10491,8 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
|
|||||||
ps = extract32(tcr, 16, 3);
|
ps = extract32(tcr, 16, 3);
|
||||||
ds = extract64(tcr, 32, 1);
|
ds = extract64(tcr, 32, 1);
|
||||||
} else {
|
} else {
|
||||||
|
bool e0pd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bit 55 is always between the two regions, and is canonical for
|
* Bit 55 is always between the two regions, and is canonical for
|
||||||
* determining if address tagging is enabled.
|
* determining if address tagging is enabled.
|
||||||
@ -10502,15 +10504,22 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
|
|||||||
epd = extract32(tcr, 7, 1);
|
epd = extract32(tcr, 7, 1);
|
||||||
sh = extract32(tcr, 12, 2);
|
sh = extract32(tcr, 12, 2);
|
||||||
hpd = extract64(tcr, 41, 1);
|
hpd = extract64(tcr, 41, 1);
|
||||||
|
e0pd = extract64(tcr, 55, 1);
|
||||||
} else {
|
} else {
|
||||||
tsz = extract32(tcr, 16, 6);
|
tsz = extract32(tcr, 16, 6);
|
||||||
gran = tg1_to_gran_size(extract32(tcr, 30, 2));
|
gran = tg1_to_gran_size(extract32(tcr, 30, 2));
|
||||||
epd = extract32(tcr, 23, 1);
|
epd = extract32(tcr, 23, 1);
|
||||||
sh = extract32(tcr, 28, 2);
|
sh = extract32(tcr, 28, 2);
|
||||||
hpd = extract64(tcr, 42, 1);
|
hpd = extract64(tcr, 42, 1);
|
||||||
|
e0pd = extract64(tcr, 56, 1);
|
||||||
}
|
}
|
||||||
ps = extract64(tcr, 32, 3);
|
ps = extract64(tcr, 32, 3);
|
||||||
ds = extract64(tcr, 59, 1);
|
ds = extract64(tcr, 59, 1);
|
||||||
|
|
||||||
|
if (e0pd && cpu_isar_feature(aa64_e0pd, cpu) &&
|
||||||
|
regime_is_user(env, mmu_idx)) {
|
||||||
|
epd = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gran = sanitize_gran_size(cpu, gran, stage2);
|
gran = sanitize_gran_size(cpu, gran, stage2);
|
||||||
|
@ -707,6 +707,25 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
|
{
|
||||||
|
switch (mmu_idx) {
|
||||||
|
case ARMMMUIdx_E20_0:
|
||||||
|
case ARMMMUIdx_Stage1_E0:
|
||||||
|
case ARMMMUIdx_MUser:
|
||||||
|
case ARMMMUIdx_MSUser:
|
||||||
|
case ARMMMUIdx_MUserNegPri:
|
||||||
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case ARMMMUIdx_E10_0:
|
||||||
|
case ARMMMUIdx_E10_1:
|
||||||
|
case ARMMMUIdx_E10_1_PAN:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the SCTLR value which controls this address translation regime */
|
/* Return the SCTLR value which controls this address translation regime */
|
||||||
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
|
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
{
|
{
|
||||||
|
@ -104,25 +104,6 @@ static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||||||
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
|
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|
||||||
{
|
|
||||||
switch (mmu_idx) {
|
|
||||||
case ARMMMUIdx_E20_0:
|
|
||||||
case ARMMMUIdx_Stage1_E0:
|
|
||||||
case ARMMMUIdx_MUser:
|
|
||||||
case ARMMMUIdx_MSUser:
|
|
||||||
case ARMMMUIdx_MUserNegPri:
|
|
||||||
case ARMMMUIdx_MSUserNegPri:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
case ARMMMUIdx_E10_0:
|
|
||||||
case ARMMMUIdx_E10_1:
|
|
||||||
case ARMMMUIdx_E10_1_PAN:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the TTBR associated with this translation regime */
|
/* Return the TTBR associated with this translation regime */
|
||||||
static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
|
static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user