Skip to content

Commit

Permalink
target/arm: Add support for DC CVAP & DC CVADP ins
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Beata Michalska authored and pm215 committed Dec 16, 2019
1 parent bd108a4 commit 0d57b49
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
2 changes: 2 additions & 0 deletions linux-user/elfload.c
Expand Up @@ -656,6 +656,7 @@ static uint32_t get_elf_hwcap(void)
GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);

return hwcaps;
}
Expand All @@ -665,6 +666,7 @@ static uint32_t get_elf_hwcap2(void)
ARMCPU *cpu = ARM_CPU(thread_cpu);
uint32_t hwcaps = 0;

GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);

Expand Down
10 changes: 10 additions & 0 deletions target/arm/cpu.h
Expand Up @@ -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. */
Expand Down
1 change: 1 addition & 0 deletions target/arm/cpu64.c
Expand Up @@ -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 */
Expand Down
56 changes: 56 additions & 0 deletions target/arm/helper.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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

/*
Expand Down

0 comments on commit 0d57b49

Please sign in to comment.