On Nov 30 09:13, Richard Henderson wrote: > On 11/20/18 1:26 PM, Aaron Lindsay wrote: > > Setup a QEMUTimer to get a callback when we expect counters to next > > overflow and trigger an interrupt at that time. > > > > Signed-off-by: Aaron Lindsay <alind...@codeaurora.org> > > Signed-off-by: Aaron Lindsay <alind...@os.amperecomputing.com> > > --- > > target/arm/cpu.c | 12 +++++ > > target/arm/cpu.h | 7 +++ > > target/arm/helper.c | 126 +++++++++++++++++++++++++++++++++++++++++--- > > 3 files changed, 139 insertions(+), 6 deletions(-) > > > > diff --git a/target/arm/cpu.c b/target/arm/cpu.c > > index 208a08e867..7311a48e3c 100644 > > --- a/target/arm/cpu.c > > +++ b/target/arm/cpu.c > > @@ -827,6 +827,13 @@ static void arm_cpu_finalizefn(Object *obj) > > QLIST_REMOVE(hook, node); > > g_free(hook); > > } > > +#ifndef CONFIG_USER_ONLY > > + if (arm_feature(&cpu->env, ARM_FEATURE_PMU) && cpu->pmu_timer) { > > No need for two tests here. Just check cpu->pmu_timer. > (If it's set for any reason it should be freed, surely.) > > > @@ -1305,7 +1338,18 @@ void pmccntr_op_start(CPUARMState *env) > > eff_cycles /= 64; > > } > > > > - env->cp15.c15_ccnt = eff_cycles - env->cp15.c15_ccnt_delta; > > + uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta; > > + > > + unsigned int overflow_bit = (env->cp15.c9_pmcr & PMCRLC) ? 63 : 31; > > + uint64_t overflow_mask = (uint64_t)1 << overflow_bit; > > + if (!(new_pmccntr & overflow_mask) && > > + (env->cp15.c15_ccnt & overflow_mask)) { > > Fyi, this expression is > > env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask > > > + env->cp15.c9_pmovsr |= (1 << 31); > > + new_pmccntr &= ~overflow_mask; > > Why this line? You just checked that overflow_mask was unset in new_pmccntr > above.
This ensures that when overflow_bit == 31 (because PMCR.LC is not set) the high 32 bits remain 0 even after an overflow has occurred. As you point out, it's silly when overflow_bit == 64, but I didn't think it was worth the extra conditional to avoid it. > > @@ -1318,13 +1362,28 @@ void pmccntr_op_start(CPUARMState *env) > > void pmccntr_op_finish(CPUARMState *env) > > { > > if (pmu_counter_enabled(env, 31)) { > > - uint64_t prev_cycles = env->cp15.c15_ccnt_delta; > > +#ifndef CONFIG_USER_ONLY > > + uint64_t delta; > > + if (env->cp15.c9_pmcr & PMCRLC) { > > + delta = UINT64_MAX - env->cp15.c15_ccnt + 1; > > + } else { > > + delta = UINT32_MAX - (uint32_t)env->cp15.c15_ccnt + 1; > > + } > > FWIW, this is the same as > > delta = -env->cp15.c15_ccnt; > if (!(env->cp15.c9_pmcr & PMCRLC)) { > delta = (uint32_t)delta; > } Thanks for your review. I'll take a look at your suggested logic simplifications for v9, do you think that this patch looks OK at the big-picture level? -Aaron