aboutsummaryrefslogtreecommitdiff
path: root/target/arm/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a4f7b61b4e..3a93844a3b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5974,6 +5974,52 @@ static const ARMCPRegInfo rndr_reginfo[] = {
.access = PL0_R, .readfn = rndr_readfn },
REGINFO_SENTINEL
};
+
+#ifndef CONFIG_USER_ONLY
+static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ /* CTR_EL0 System register -> DminLine, bits [19:16] */
+ uint64_t dline_size = 4 << ((cpu->ctr >> 16) & 0xF);
+ uint64_t vaddr_in = (uint64_t) value;
+ uint64_t vaddr = vaddr_in & ~(dline_size - 1);
+ void *haddr;
+ int mem_idx = cpu_mmu_index(env, false);
+
+ /* This won't be crossing page boundaries */
+ haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
+ if (haddr) {
+
+ ram_addr_t offset;
+ MemoryRegion *mr;
+
+ /* RCU lock is already being held */
+ mr = memory_region_from_host(haddr, &offset);
+
+ if (mr) {
+ memory_region_do_writeback(mr, offset, dline_size);
+ }
+ }
+}
+
+static const ARMCPRegInfo dcpop_reg[] = {
+ { .name = "DC_CVAP", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
+ .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
+ REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo dcpodp_reg[] = {
+ { .name = "DC_CVADP", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
+ .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
+ REGINFO_SENTINEL
+};
+#endif /*CONFIG_USER_ONLY*/
+
#endif
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -7046,6 +7092,16 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (cpu_isar_feature(aa64_rndr, cpu)) {
define_arm_cp_regs(cpu, rndr_reginfo);
}
+#ifndef CONFIG_USER_ONLY
+ /* Data Cache clean instructions up to PoP */
+ if (cpu_isar_feature(aa64_dcpop, cpu)) {
+ define_one_arm_cp_reg(cpu, dcpop_reg);
+
+ if (cpu_isar_feature(aa64_dcpodp, cpu)) {
+ define_one_arm_cp_reg(cpu, dcpodp_reg);
+ }
+ }
+#endif /*CONFIG_USER_ONLY*/
#endif
/*