if (cpu_isar_feature(aa64_ecv, cpu)) {
valid_mask |= SCR_ECVEN;
}
+ if (cpu_isar_feature(aa64_tcr2, cpu)) {
+ valid_mask |= SCR_TCR2EN;
+ }
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
valid_mask |= SCR_SCTLR2EN;
}
if (cpu_isar_feature(aa64_xs, cpu)) {
valid_mask |= HCRX_FGTNXS | HCRX_FNXS;
}
+ if (cpu_isar_feature(aa64_tcr2, cpu)) {
+ valid_mask |= HCRX_TCR2EN;
+ }
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
valid_mask |= HCRX_SCTLR2EN;
}
if (cpu_isar_feature(aa64_mops, cpu)) {
hcrx |= HCRX_MSCEN;
}
+ if (cpu_isar_feature(aa64_tcr2, cpu)) {
+ hcrx |= HCRX_TCR2EN;
+ }
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
hcrx |= HCRX_SCTLR2EN;
}
"TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
{ K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2),
"TCR_EL1", "TCR_EL2", "TCR_EL12" },
+ { K(3, 0, 2, 0, 3), K(3, 4, 2, 0, 3), K(3, 5, 2, 0, 3),
+ "TCR2_EL1", "TCR2_EL2", "TCR2_EL12", isar_feature_aa64_tcr2 },
{ K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0),
"SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
{ K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1),
.fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[3]) },
};
+static CPAccessResult tcr2_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_TCR2EN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult tcr2_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_TCR2EN)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return tcr2_el2_access(env, ri, isread);
+}
+
+static void tcr2_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 tcr2_el2_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 tcr2_reginfo[] = {
+ { .name = "TCR2_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 3, .crn = 2, .crm = 0,
+ .access = PL1_RW, .accessfn = tcr2_el1_access,
+ .writefn = tcr2_el1_write, .fgt = FGT_TCR_EL1,
+ .nv2_redirect_offset = 0x270 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.tcr2_el[1]) },
+ { .name = "TCR2_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 2, .crm = 0,
+ .access = PL2_RW, .accessfn = tcr2_el2_access,
+ .writefn = tcr2_el2_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.tcr2_el[2]) },
+};
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
define_arm_cp_regs(cpu, sctlr2_reginfo);
}
+ if (cpu_isar_feature(aa64_tcr2, cpu)) {
+ define_arm_cp_regs(cpu, tcr2_reginfo);
+ }
+
if (cpu_isar_feature(any_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);
}
#define TTBCR_SH1 (1U << 28)
#define TTBCR_EAE (1U << 31)
+#define TCR2_PNCH (1ULL << 0)
+#define TCR2_PIE (1ULL << 1)
+#define TCR2_E0POE (1ULL << 2)
+#define TCR2_POE (1ULL << 3)
+#define TCR2_AIE (1ULL << 4)
+#define TCR2_D128 (1ULL << 5)
+#define TCR2_PTTWI (1ULL << 10)
+#define TCR2_HAFT (1ULL << 11)
+#define TCR2_AMEC0 (1ULL << 12)
+#define TCR2_AMEC1 (1ULL << 13)
+#define TCR2_DISCH0 (1ULL << 14)
+#define TCR2_DISCH1 (1ULL << 15)
+#define TCR2_A2 (1ULL << 16)
+#define TCR2_FNG0 (1ULL << 17)
+#define TCR2_FNG1 (1ULL << 18)
+#define TCR2_FNGNA0 (1ULL << 20)
+#define TCR2_FNGNA1 (1ULL << 21)
+
FIELD(VTCR, T0SZ, 0, 6)
FIELD(VTCR, SL0, 6, 2)
FIELD(VTCR, IRGN0, 8, 2)
#define HCRX_CMOW (1ULL << 9)
#define HCRX_MCE2 (1ULL << 10)
#define HCRX_MSCEN (1ULL << 11)
+#define HCRX_TCR2EN (1ULL << 14)
#define HCRX_SCTLR2EN (1ULL << 15)
#define HPFAR_NS (1ULL << 63)