target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are defined, which are "self-synchronized" views of the physical and virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers (meaning that no barriers are needed around accesses to them to ensure that reads of them do not occur speculatively and out-of-order with other instructions). For QEMU, all our system registers are self-synchronized, so we can simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0 to the new register encodings. This means we now implement all the functionality required for ID_AA64MMFR0_EL1.ECV == 0b0001. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
This commit is contained in:
parent
dcdad2624b
commit
485eb324e3
@ -3389,6 +3389,34 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
|
||||
* are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
|
||||
* so our implementations here are identical to the normal registers.
|
||||
*/
|
||||
static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
|
||||
{ .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
|
||||
.access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
|
||||
.accessfn = gt_vct_access,
|
||||
.readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
|
||||
},
|
||||
{ .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
|
||||
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
|
||||
.accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
|
||||
},
|
||||
{ .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
|
||||
.access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
|
||||
.accessfn = gt_pct_access,
|
||||
.readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
|
||||
},
|
||||
{ .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
|
||||
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
|
||||
.accessfn = gt_pct_access, .readfn = gt_cnt_read,
|
||||
},
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
@ -3422,6 +3450,18 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
|
||||
* is exposed to userspace by Linux.
|
||||
*/
|
||||
static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
|
||||
{ .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
|
||||
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
|
||||
.readfn = gt_virt_cnt_read,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
||||
@ -9258,6 +9298,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
|
||||
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
|
||||
}
|
||||
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
|
||||
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_VAPA)) {
|
||||
ARMCPRegInfo vapa_cp_reginfo[] = {
|
||||
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
|
||||
|
Loading…
Reference in New Issue
Block a user