hvf: arm: Properly disable PMU

Setting pmu property used to have no effect for hvf so fix it.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Akihiko Odaki 2024-07-20 18:30:53 +09:00 committed by Peter Maydell
parent e9e640148c
commit e6fd3192ed

View File

@ -1204,45 +1204,50 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val)
ARMCPU *arm_cpu = ARM_CPU(cpu);
CPUARMState *env = &arm_cpu->env;
if (arm_feature(env, ARM_FEATURE_PMU)) {
switch (reg) {
case SYSREG_PMCR_EL0:
*val = env->cp15.c9_pmcr;
return 0;
case SYSREG_PMCCNTR_EL0:
pmu_op_start(env);
*val = env->cp15.c15_ccnt;
pmu_op_finish(env);
return 0;
case SYSREG_PMCNTENCLR_EL0:
*val = env->cp15.c9_pmcnten;
return 0;
case SYSREG_PMOVSCLR_EL0:
*val = env->cp15.c9_pmovsr;
return 0;
case SYSREG_PMSELR_EL0:
*val = env->cp15.c9_pmselr;
return 0;
case SYSREG_PMINTENCLR_EL1:
*val = env->cp15.c9_pminten;
return 0;
case SYSREG_PMCCFILTR_EL0:
*val = env->cp15.pmccfiltr_el0;
return 0;
case SYSREG_PMCNTENSET_EL0:
*val = env->cp15.c9_pmcnten;
return 0;
case SYSREG_PMUSERENR_EL0:
*val = env->cp15.c9_pmuserenr;
return 0;
case SYSREG_PMCEID0_EL0:
case SYSREG_PMCEID1_EL0:
/* We can't really count anything yet, declare all events invalid */
*val = 0;
return 0;
}
}
switch (reg) {
case SYSREG_CNTPCT_EL0:
*val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
gt_cntfrq_period_ns(arm_cpu);
return 0;
case SYSREG_PMCR_EL0:
*val = env->cp15.c9_pmcr;
return 0;
case SYSREG_PMCCNTR_EL0:
pmu_op_start(env);
*val = env->cp15.c15_ccnt;
pmu_op_finish(env);
return 0;
case SYSREG_PMCNTENCLR_EL0:
*val = env->cp15.c9_pmcnten;
return 0;
case SYSREG_PMOVSCLR_EL0:
*val = env->cp15.c9_pmovsr;
return 0;
case SYSREG_PMSELR_EL0:
*val = env->cp15.c9_pmselr;
return 0;
case SYSREG_PMINTENCLR_EL1:
*val = env->cp15.c9_pminten;
return 0;
case SYSREG_PMCCFILTR_EL0:
*val = env->cp15.pmccfiltr_el0;
return 0;
case SYSREG_PMCNTENSET_EL0:
*val = env->cp15.c9_pmcnten;
return 0;
case SYSREG_PMUSERENR_EL0:
*val = env->cp15.c9_pmuserenr;
return 0;
case SYSREG_PMCEID0_EL0:
case SYSREG_PMCEID1_EL0:
/* We can't really count anything yet, declare all events invalid */
*val = 0;
return 0;
case SYSREG_OSLSR_EL1:
*val = env->cp15.oslsr_el1;
return 0;
@ -1486,64 +1491,69 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
SYSREG_OP2(reg),
val);
switch (reg) {
case SYSREG_PMCCNTR_EL0:
pmu_op_start(env);
env->cp15.c15_ccnt = val;
pmu_op_finish(env);
return 0;
case SYSREG_PMCR_EL0:
pmu_op_start(env);
if (arm_feature(env, ARM_FEATURE_PMU)) {
switch (reg) {
case SYSREG_PMCCNTR_EL0:
pmu_op_start(env);
env->cp15.c15_ccnt = val;
pmu_op_finish(env);
return 0;
case SYSREG_PMCR_EL0:
pmu_op_start(env);
if (val & PMCRC) {
/* The counter has been reset */
env->cp15.c15_ccnt = 0;
}
if (val & PMCRP) {
unsigned int i;
for (i = 0; i < pmu_num_counters(env); i++) {
env->cp15.c14_pmevcntr[i] = 0;
if (val & PMCRC) {
/* The counter has been reset */
env->cp15.c15_ccnt = 0;
}
if (val & PMCRP) {
unsigned int i;
for (i = 0; i < pmu_num_counters(env); i++) {
env->cp15.c14_pmevcntr[i] = 0;
}
}
env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
env->cp15.c9_pmcr |= (val & PMCR_WRITABLE_MASK);
pmu_op_finish(env);
return 0;
case SYSREG_PMUSERENR_EL0:
env->cp15.c9_pmuserenr = val & 0xf;
return 0;
case SYSREG_PMCNTENSET_EL0:
env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env));
return 0;
case SYSREG_PMCNTENCLR_EL0:
env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env));
return 0;
case SYSREG_PMINTENCLR_EL1:
pmu_op_start(env);
env->cp15.c9_pminten |= val;
pmu_op_finish(env);
return 0;
case SYSREG_PMOVSCLR_EL0:
pmu_op_start(env);
env->cp15.c9_pmovsr &= ~val;
pmu_op_finish(env);
return 0;
case SYSREG_PMSWINC_EL0:
pmu_op_start(env);
pmswinc_write(env, val);
pmu_op_finish(env);
return 0;
case SYSREG_PMSELR_EL0:
env->cp15.c9_pmselr = val & 0x1f;
return 0;
case SYSREG_PMCCFILTR_EL0:
pmu_op_start(env);
env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0;
pmu_op_finish(env);
return 0;
}
}
env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
env->cp15.c9_pmcr |= (val & PMCR_WRITABLE_MASK);
pmu_op_finish(env);
return 0;
case SYSREG_PMUSERENR_EL0:
env->cp15.c9_pmuserenr = val & 0xf;
return 0;
case SYSREG_PMCNTENSET_EL0:
env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env));
return 0;
case SYSREG_PMCNTENCLR_EL0:
env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env));
return 0;
case SYSREG_PMINTENCLR_EL1:
pmu_op_start(env);
env->cp15.c9_pminten |= val;
pmu_op_finish(env);
return 0;
case SYSREG_PMOVSCLR_EL0:
pmu_op_start(env);
env->cp15.c9_pmovsr &= ~val;
pmu_op_finish(env);
return 0;
case SYSREG_PMSWINC_EL0:
pmu_op_start(env);
pmswinc_write(env, val);
pmu_op_finish(env);
return 0;
case SYSREG_PMSELR_EL0:
env->cp15.c9_pmselr = val & 0x1f;
return 0;
case SYSREG_PMCCFILTR_EL0:
pmu_op_start(env);
env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0;
pmu_op_finish(env);
return 0;
switch (reg) {
case SYSREG_OSLAR_EL1:
env->cp15.oslsr_el1 = val & 1;
return 0;