#define SCTLR_TE (1U << 30) /* AArch32 only */
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
#define CPTR_TCPAC (1U << 31)
#define CPTR_TTA (1U << 20)
#define CPSR_IL (1U << 20)
#define CPSR_DIT (1U << 21)
#define CPSR_PAN (1U << 22)
+#define CPSR_SSBS (1U << 23)
#define CPSR_J (1U << 24)
#define CPSR_IT_0_1 (3U << 25)
#define CPSR_Q (1U << 27)
#define PSTATE_A (1U << 8)
#define PSTATE_D (1U << 9)
#define PSTATE_BTYPE (3U << 10)
+#define PSTATE_SSBS (1U << 12)
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
#define PSTATE_PAN (1U << 22)
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
}
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
+}
+
/*
* 64-bit feature tests via id registers.
*/
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
}
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
+}
+
/*
* Feature tests for "does this exist in either 32-bit or 64-bit?"
*/
.readfn = aa64_dit_read, .writefn = aa64_dit_write
};
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_SSBS;
+}
+
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
+}
+
+static const ARMCPRegInfo ssbs_reginfo = {
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
+};
+
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
const ARMCPRegInfo *ri,
bool isread)
if (cpu_isar_feature(aa64_dit, cpu)) {
define_one_arm_cp_reg(cpu, &dit_reginfo);
}
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
+ }
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
define_arm_cp_regs(cpu, vhe_reginfo);
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
env->daif |= mask;
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
+ env->uncached_cpsr |= CPSR_SSBS;
+ } else {
+ env->uncached_cpsr &= ~CPSR_SSBS;
+ }
+ }
+
if (new_mode == ARM_CPU_MODE_HYP) {
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
env->elr_el[2] = env->regs[15];
new_mode |= PSTATE_TCO;
}
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
+ new_mode |= PSTATE_SSBS;
+ } else {
+ new_mode &= ~PSTATE_SSBS;
+ }
+ }
+
pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = 1;
aarch64_restore_sp(env, new_el);
if (isar_feature_aa32_dit(id)) {
valid |= CPSR_DIT;
}
+ if (isar_feature_aa32_ssbs(id)) {
+ valid |= CPSR_SSBS;
+ }
return valid;
}
if (isar_feature_aa64_dit(id)) {
valid |= PSTATE_DIT;
}
+ if (isar_feature_aa64_ssbs(id)) {
+ valid |= PSTATE_SSBS;
+ }
if (isar_feature_aa64_mte(id)) {
valid |= PSTATE_TCO;
}
tcg_temp_free_i32(t1);
break;
+ case 0x19: /* SSBS */
+ if (!dc_isar_feature(aa64_ssbs, s)) {
+ goto do_unallocated;
+ }
+ if (crm & 1) {
+ set_pstate_bits(PSTATE_SSBS);
+ } else {
+ clear_pstate_bits(PSTATE_SSBS);
+ }
+ /* Don't need to rebuild hflags since SSBS is a nop */
+ break;
+
case 0x1a: /* DIT */
if (!dc_isar_feature(aa64_dit, s)) {
goto do_unallocated;