aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorBeata Michalska <beata.michalska@linaro.org>2019-11-21 00:08:43 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-12-16 10:46:35 +0000
commit0d57b49992200a926c4436eead97ecfc8cc710be (patch)
tree0e2ae1b8f481d7d1347ddf18d29bf716f7ded7f5 /target
parentbd108a44bc29cb648dd930564996b0128e66ac01 (diff)
downloadqemu-0d57b49992200a926c4436eead97ecfc8cc710be.zip
qemu-0d57b49992200a926c4436eead97ecfc8cc710be.tar.gz
qemu-0d57b49992200a926c4436eead97ecfc8cc710be.tar.bz2
target/arm: Add support for DC CVAP & DC CVADP ins
ARMv8.2 introduced support for Data Cache Clean instructions to PoP (point-of-persistence) - DC CVAP and PoDP (point-of-deep-persistence) - DV CVADP. Both specify conceptual points in a memory system where all writes that are to reach them are considered persistent. The support provided considers both to be actually the same so there is no distinction between the two. If none is available (there is no backing store for given memory) both will result in Data Cache Clean up to the point of coherency. Otherwise sync for the specified range shall be performed. Signed-off-by: Beata Michalska <beata.michalska@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191121000843.24844-5-beata.michalska@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu.h10
-rw-r--r--target/arm/cpu64.c1
-rw-r--r--target/arm/helper.c56
3 files changed, 67 insertions, 0 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index cebb351..4106e4a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3618,6 +3618,16 @@ static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
}
+static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
+}
+
+static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
+}
+
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a39d6fc..61fd0ad 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -646,6 +646,7 @@ static void aarch64_max_initfn(Object *obj)
cpu->isar.id_aa64isar0 = t;
t = cpu->isar.id_aa64isar1;
+ t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a4f7b61..3a93844 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
/*