ARMPACKey apdb;
ARMPACKey apga;
} keys;
+
+ uint64_t scxtnum_el[4];
#endif
#if defined(CONFIG_USER_ONLY)
#define SCTLR_WXN (1U << 19)
#define SCTLR_ST (1U << 20) /* up to ??, RAZ in v6 */
#define SCTLR_UWXN (1U << 20) /* v7 onward, AArch32 only */
+#define SCTLR_TSCXT (1U << 20) /* FEAT_CSV2_1p2, AArch64 only */
#define SCTLR_FI (1U << 21) /* up to v7, v8 RES0 */
#define SCTLR_IESB (1U << 21) /* v8.2-IESB, AArch64 only */
#define SCTLR_U (1U << 22) /* up to v6, RAO in v7 */
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
}
+static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
+{
+ int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2);
+ if (key >= 2) {
+ return true; /* FEAT_CSV2_2 */
+ }
+ if (key == 1) {
+ key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC);
+ return key >= 2; /* FEAT_CSV2_1p2 */
+ }
+ return false;
+}
+
static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
- t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 1); /* FEAT_CSV2 */
+ t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
cpu->isar.id_aa64pfr0 = t;
t = cpu->isar.id_aa64pfr1;
* we do for EL2 with the virtualization=on property.
*/
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
+ t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
cpu->isar.id_aa64pfr1 = t;
t = cpu->isar.id_aa64mmfr0;
if (cpu_isar_feature(aa64_mte, cpu)) {
valid_mask |= SCR_ATA;
}
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
+ valid_mask |= SCR_ENSCXT;
+ }
} else {
valid_mask &= ~(SCR_RW | SCR_ST);
if (cpu_isar_feature(aa32_ras, cpu)) {
if (cpu_isar_feature(aa64_mte, cpu)) {
valid_mask |= HCR_ATA | HCR_DCT | HCR_TID5;
}
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
+ valid_mask |= HCR_ENSCXT;
+ }
}
/* Clear RES0 bits. */
{ K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0),
"TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte },
+ { K(3, 0, 13, 0, 7), K(3, 4, 13, 0, 7), K(3, 5, 13, 0, 7),
+ "SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12",
+ isar_feature_aa64_scxtnum },
+
/* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
/* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
};
},
};
-#endif
+static CPAccessResult access_scxtnum(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ uint64_t hcr = arm_hcr_el2_eff(env);
+ int el = arm_current_el(env);
+
+ if (el == 0 && !((hcr & HCR_E2H) && (hcr & HCR_TGE))) {
+ if (env->cp15.sctlr_el[1] & SCTLR_TSCXT) {
+ if (hcr & HCR_TGE) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return CP_ACCESS_TRAP;
+ }
+ } else if (el < 2 && (env->cp15.sctlr_el[2] & SCTLR_TSCXT)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ if (el < 2 && arm_is_el2_enabled(env) && !(hcr & HCR_ENSCXT)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ if (el < 3
+ && arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_ENSCXT)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo scxtnum_reginfo[] = {
+ { .name = "SCXTNUM_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 7,
+ .access = PL0_RW, .accessfn = access_scxtnum,
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[0]) },
+ { .name = "SCXTNUM_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 7,
+ .access = PL1_RW, .accessfn = access_scxtnum,
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[1]) },
+ { .name = "SCXTNUM_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 7,
+ .access = PL2_RW, .accessfn = access_scxtnum,
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[2]) },
+ { .name = "SCXTNUM_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 7,
+ .access = PL3_RW,
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[3]) },
+};
+#endif /* TARGET_AARCH64 */
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
define_arm_cp_regs(cpu, mte_tco_ro_reginfo);
define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
}
+
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
+ define_arm_cp_regs(cpu, scxtnum_reginfo);
+ }
#endif
if (cpu_isar_feature(any_predinv, cpu)) {