Index: sys/dev/hwpmc/hwpmc_armv7.c =================================================================== --- sys/dev/hwpmc/hwpmc_armv7.c +++ sys/dev/hwpmc/hwpmc_armv7.c @@ -109,9 +109,13 @@ * Performance Count Register N */ static uint32_t -armv7_pmcn_read(unsigned int pmc) +armv7_pmcn_read(unsigned int pmc, uint32_t evsel) { + if (evsel == PMC_EV_CPU_CYCLES) { + return ((uint32_t)cp15_pmccntr_get()); + } + KASSERT(pmc < armv7_npmcs, ("%s: illegal PMC number %d", __func__, pmc)); cp15_pmselr_set(pmc); @@ -165,6 +169,8 @@ { pmc_value_t tmp; struct pmc *pm; + register_t s; + u_int reg; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); @@ -173,11 +179,26 @@ pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; + s = intr_disable(); + tmp = armv7_pmcn_read(ri, pm->pm_md.pm_armv7.pm_armv7_evsel); + + /* Check if counter has overflowed */ if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES) - tmp = (uint32_t)cp15_pmccntr_get(); + reg = (1u << 31); else - tmp = armv7_pmcn_read(ri); + reg = (1u << ri); + + if ((cp15_pmovsr_get() & reg) != 0) { + /* Clear Overflow Flag */ + cp15_pmovsr_set(reg); + if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + pm->pm_overflowcnt += 1; + + /* Reread counter in case we raced. */ + tmp = armv7_pmcn_read(ri, pm->pm_md.pm_armv7.pm_armv7_evsel); + } tmp += 0x100000000llu * pm->pm_overflowcnt; + intr_restore(s); PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) @@ -329,9 +350,9 @@ /* Check if counter has overflowed */ if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES) - reg = (1 << 31); + reg = (1u << 31); else - reg = (1 << ri); + reg = (1u << ri); if ((cp15_pmovsr_get() & reg) == 0) { continue;