target/arm: Implement FEAT_SCTLR2 and enable with -cpu max
Add FEAT_SCTLR2, which introduces the SCTLR2_EL1, SCTLR2_EL2, and SCTLR2_EL3 registers. These registers are extensions of the SCTLR_ELx ones. Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20250727074202.83141-4-richard.henderson@linaro.org Message-ID: <20250711140828.1714666-4-gustavo.romero@linaro.org> [rth: Remove FEAT_MEC code; handle SCR and HCRX enable bits.] Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
84249d026b
commit
8a60ffe9a8
7 changed files with 119 additions and 8 deletions
|
|
@ -121,6 +121,7 @@ the following architecture extensions:
|
|||
- FEAT_RPRES (Increased precision of FRECPE and FRSQRTE)
|
||||
- FEAT_S2FWB (Stage 2 forced Write-Back)
|
||||
- FEAT_SB (Speculation Barrier)
|
||||
- FEAT_SCTLR2 (Extension to SCTLR_ELx)
|
||||
- FEAT_SEL2 (Secure EL2)
|
||||
- FEAT_SHA1 (SHA1 instructions)
|
||||
- FEAT_SHA256 (SHA256 instructions)
|
||||
|
|
|
|||
|
|
@ -904,6 +904,11 @@ static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
|
|||
return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) >= 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sctlr2(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64_IDREG(id, ID_AA64MMFR3, SCTLRX) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 &&
|
||||
|
|
|
|||
|
|
@ -644,6 +644,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
|
|||
if (cpu_isar_feature(aa64_fgt, cpu)) {
|
||||
env->cp15.scr_el3 |= SCR_FGTEN;
|
||||
}
|
||||
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
|
||||
env->cp15.scr_el3 |= SCR_SCTLR2EN;
|
||||
}
|
||||
}
|
||||
|
||||
if (target_el == 2) {
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@ typedef struct CPUArchState {
|
|||
};
|
||||
uint64_t sctlr_el[4];
|
||||
};
|
||||
uint64_t sctlr2_el[4]; /* Extension to System control register. */
|
||||
uint64_t vsctlr; /* Virtualization System control register. */
|
||||
uint64_t cpacr_el1; /* Architectural feature access control register */
|
||||
uint64_t cptr_el[4]; /* ARMv8 feature trap registers */
|
||||
|
|
@ -1420,6 +1421,19 @@ void pmu_init(ARMCPU *cpu);
|
|||
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
|
||||
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
|
||||
|
||||
#define SCTLR2_EMEC (1ULL << 1) /* FEAT_MEC */
|
||||
#define SCTLR2_NMEA (1ULL << 2) /* FEAT_DoubleFault2 */
|
||||
#define SCTLR2_ENADERR (1ULL << 3) /* FEAT_ADERR */
|
||||
#define SCTLR2_ENANERR (1ULL << 4) /* FEAT_ANERR */
|
||||
#define SCTLR2_EASE (1ULL << 5) /* FEAT_DoubleFault2 */
|
||||
#define SCTLR2_ENIDCP128 (1ULL << 6) /* FEAT_SYSREG128 */
|
||||
#define SCTLR2_ENPACM (1ULL << 7) /* FEAT_PAuth_LR */
|
||||
#define SCTLR2_ENPACM0 (1ULL << 8) /* FEAT_PAuth_LR */
|
||||
#define SCTLR2_CPTA (1ULL << 9) /* FEAT_CPA2 */
|
||||
#define SCTLR2_CPTA0 (1ULL << 10) /* FEAT_CPA2 */
|
||||
#define SCTLR2_CPTM (1ULL << 11) /* FEAT_CPA2 */
|
||||
#define SCTLR2_CPTM0 (1ULL << 12) /* FEAT_CAP2 */
|
||||
|
||||
#define CPSR_M (0x1fU)
|
||||
#define CPSR_T (1U << 5)
|
||||
#define CPSR_F (1U << 6)
|
||||
|
|
@ -1712,6 +1726,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
|||
#define SCR_HXEN (1ULL << 38)
|
||||
#define SCR_TRNDR (1ULL << 40)
|
||||
#define SCR_ENTP2 (1ULL << 41)
|
||||
#define SCR_SCTLR2EN (1ULL << 44)
|
||||
#define SCR_GPF (1ULL << 48)
|
||||
#define SCR_NSE (1ULL << 62)
|
||||
|
||||
|
|
|
|||
|
|
@ -741,6 +741,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
if (cpu_isar_feature(aa64_ecv, cpu)) {
|
||||
valid_mask |= SCR_ECVEN;
|
||||
}
|
||||
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
|
||||
valid_mask |= SCR_SCTLR2EN;
|
||||
}
|
||||
} else {
|
||||
valid_mask &= ~(SCR_RW | SCR_ST);
|
||||
if (cpu_isar_feature(aa32_ras, cpu)) {
|
||||
|
|
@ -3907,23 +3910,21 @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t valid_mask = 0;
|
||||
|
||||
/* FEAT_MOPS adds MSCEn and MCE2 */
|
||||
if (cpu_isar_feature(aa64_mops, cpu)) {
|
||||
valid_mask |= HCRX_MSCEN | HCRX_MCE2;
|
||||
}
|
||||
|
||||
/* FEAT_NMI adds TALLINT, VINMI and VFNMI */
|
||||
if (cpu_isar_feature(aa64_nmi, cpu)) {
|
||||
valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
|
||||
}
|
||||
/* FEAT_CMOW adds CMOW */
|
||||
if (cpu_isar_feature(aa64_cmow, cpu)) {
|
||||
valid_mask |= HCRX_CMOW;
|
||||
}
|
||||
/* FEAT_XS adds FGTnXS, FnXS */
|
||||
if (cpu_isar_feature(aa64_xs, cpu)) {
|
||||
valid_mask |= HCRX_FGTNXS | HCRX_FNXS;
|
||||
}
|
||||
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
|
||||
valid_mask |= HCRX_SCTLR2EN;
|
||||
}
|
||||
|
||||
/* Clear RES0 bits. */
|
||||
env->cp15.hcrx_el2 = value & valid_mask;
|
||||
|
|
@ -3981,11 +3982,16 @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env)
|
|||
* This may need to be revisited for future bits.
|
||||
*/
|
||||
if (!arm_is_el2_enabled(env)) {
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t hcrx = 0;
|
||||
if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
|
||||
/* MSCEn behaves as 1 if EL2 is not enabled */
|
||||
|
||||
/* Bits which whose effective value is 1 if el2 not enabled. */
|
||||
if (cpu_isar_feature(aa64_mops, cpu)) {
|
||||
hcrx |= HCRX_MSCEN;
|
||||
}
|
||||
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
|
||||
hcrx |= HCRX_SCTLR2EN;
|
||||
}
|
||||
return hcrx;
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_HXEN)) {
|
||||
|
|
@ -4513,6 +4519,8 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
|
|||
static const struct E2HAlias aliases[] = {
|
||||
{ K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0),
|
||||
"SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
|
||||
{ K(3, 0, 1, 0, 3), K(3, 4, 1, 0, 3), K(3, 5, 1, 0, 3),
|
||||
"SCTLR2_EL1", "SCTLR2_EL2", "SCTLR2_EL12", isar_feature_aa64_sctlr2 },
|
||||
{ K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2),
|
||||
"CPACR", "CPTR_EL2", "CPACR_EL12" },
|
||||
{ K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0),
|
||||
|
|
@ -5994,6 +6002,77 @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
|
|||
.resetvalue = 0 },
|
||||
};
|
||||
|
||||
static CPAccessResult sctlr2_el2_access(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
if (arm_current_el(env) < 3
|
||||
&& arm_feature(env, ARM_FEATURE_EL3)
|
||||
&& !(env->cp15.scr_el3 & SCR_SCTLR2EN)) {
|
||||
return CP_ACCESS_TRAP_EL3;
|
||||
}
|
||||
return CP_ACCESS_OK;
|
||||
}
|
||||
|
||||
static CPAccessResult sctlr2_el1_access(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
CPAccessResult ret = access_tvm_trvm(env, ri, isread);
|
||||
if (ret != CP_ACCESS_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (arm_current_el(env) < 2 && !(arm_hcrx_el2_eff(env) & HCRX_SCTLR2EN)) {
|
||||
return CP_ACCESS_TRAP_EL2;
|
||||
}
|
||||
return sctlr2_el2_access(env, ri, isread);
|
||||
}
|
||||
|
||||
static void sctlr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
uint64_t valid_mask = 0;
|
||||
|
||||
value &= valid_mask;
|
||||
raw_write(env, ri, value);
|
||||
}
|
||||
|
||||
static void sctlr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
uint64_t valid_mask = 0;
|
||||
|
||||
value &= valid_mask;
|
||||
raw_write(env, ri, value);
|
||||
}
|
||||
|
||||
static void sctlr2_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
uint64_t valid_mask = 0;
|
||||
|
||||
value &= valid_mask;
|
||||
raw_write(env, ri, value);
|
||||
}
|
||||
|
||||
static const ARMCPRegInfo sctlr2_reginfo[] = {
|
||||
{ .name = "SCTLR2_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .opc2 = 3, .crn = 1, .crm = 0,
|
||||
.access = PL1_RW, .accessfn = sctlr2_el1_access,
|
||||
.writefn = sctlr2_el1_write, .fgt = FGT_SCTLR_EL1,
|
||||
.nv2_redirect_offset = 0x278 | NV2_REDIR_NV1,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[1]) },
|
||||
{ .name = "SCTLR2_EL2", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 1, .crm = 0,
|
||||
.access = PL2_RW, .accessfn = sctlr2_el2_access,
|
||||
.writefn = sctlr2_el2_write,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[2]) },
|
||||
{ .name = "SCTLR2_EL3", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 6, .opc2 = 3, .crn = 1, .crm = 0,
|
||||
.access = PL3_RW, .writefn = sctlr2_el3_write,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[3]) },
|
||||
};
|
||||
|
||||
void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
{
|
||||
/* Register all the coprocessor registers based on feature bits */
|
||||
|
|
@ -7223,6 +7302,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
|||
define_arm_cp_regs(cpu, nmi_reginfo);
|
||||
}
|
||||
|
||||
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
|
||||
define_arm_cp_regs(cpu, sctlr2_reginfo);
|
||||
}
|
||||
|
||||
if (cpu_isar_feature(any_predinv, cpu)) {
|
||||
define_arm_cp_regs(cpu, predinv_reginfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ FIELD(VSTCR, SA, 30, 1)
|
|||
#define HCRX_CMOW (1ULL << 9)
|
||||
#define HCRX_MCE2 (1ULL << 10)
|
||||
#define HCRX_MSCEN (1ULL << 11)
|
||||
#define HCRX_SCTLR2EN (1ULL << 15)
|
||||
|
||||
#define HPFAR_NS (1ULL << 63)
|
||||
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,10 @@ void aarch64_max_tcg_initfn(Object *obj)
|
|||
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
|
||||
SET_IDREG(isar, ID_AA64MMFR2, t);
|
||||
|
||||
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
|
||||
t = GET_IDREG(isar, ID_AA64MMFR3);
|
||||
t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
|
||||
SET_IDREG(isar, ID_AA64MMFR3, t);
|
||||
|
||||
t = GET_IDREG(isar, ID_AA64ZFR0);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 2); /* FEAT_SVE2p1 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue