diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -431,9 +431,18 @@ tmp = rdmsr(pd->pm_perfctr); /* RDMSR serializes */ PMCDBG2(MDP,REA,2,"amd-read (pre-munge) id=%d -> %jd", ri, tmp); if (PMC_IS_SAMPLING_MODE(mode)) { - /* Sign extend 48 bit value to 64 bits. */ - tmp = (pmc_value_t) (((int64_t) tmp << 16) >> 16); - tmp = AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + /* + * Clamp value to 0 if the counter just overflowed, + * otherwise the returned reload count would wrap to a + * huge value. + */ + if ((tmp & (1ULL << 47)) == 0) + tmp = 0; + else { + /* Sign extend 48 bit value to 64 bits. */ + tmp = (pmc_value_t) ((int64_t)(tmp << 16) >> 16); + tmp = AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + } } *v = tmp; diff --git a/sys/dev/hwpmc/hwpmc_arm64.c b/sys/dev/hwpmc/hwpmc_arm64.c --- a/sys/dev/hwpmc/hwpmc_arm64.c +++ b/sys/dev/hwpmc/hwpmc_arm64.c @@ -218,8 +218,7 @@ if ((READ_SPECIALREG(pmovsclr_el0) & reg) != 0) { /* Clear Overflow Flag */ WRITE_SPECIALREG(pmovsclr_el0, reg); - if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - pm->pm_pcpu_state[cpu].pps_overflowcnt++; + pm->pm_pcpu_state[cpu].pps_overflowcnt++; /* Reread counter in case we raced. */ tmp = arm64_pmcn_read(ri); @@ -228,10 +227,18 @@ intr_restore(s); PMCDBG2(MDP, REA, 2, "arm64-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = ARMV8_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + /* + * Clamp value to 0 if the counter just overflowed, + * otherwise the returned reload count would wrap to a + * huge value. + */ + if ((tmp & (1ull << 63)) == 0) + tmp = 0; + else + tmp = ARMV8_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + } + *v = tmp; return (0); } @@ -379,10 +386,10 @@ retval = 1; /* Found an interrupting PMC. */ - if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - pm->pm_pcpu_state[cpu].pps_overflowcnt += 1; + pm->pm_pcpu_state[cpu].pps_overflowcnt += 1; + + if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) continue; - } if (pm->pm_state != PMC_STATE_RUNNING) continue; diff --git a/sys/dev/hwpmc/hwpmc_armv7.c b/sys/dev/hwpmc/hwpmc_armv7.c --- a/sys/dev/hwpmc/hwpmc_armv7.c +++ b/sys/dev/hwpmc/hwpmc_armv7.c @@ -189,8 +189,7 @@ if ((cp15_pmovsr_get() & reg) != 0) { /* Clear Overflow Flag */ cp15_pmovsr_set(reg); - if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - pm->pm_pcpu_state[cpu].pps_overflowcnt++; + pm->pm_pcpu_state[cpu].pps_overflowcnt++; /* Reread counter in case we raced. */ tmp = armv7_pmcn_read(ri, pm->pm_md.pm_armv7.pm_armv7_evsel); @@ -199,10 +198,18 @@ intr_restore(s); PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + /* + * Clamp value to 0 if the counter just overflowed, + * otherwise the returned reload count would wrap to a + * huge value. + */ + if ((tmp & (1ull << 63)) == 0) + tmp = 0; + else + tmp = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + } + *v = tmp; return 0; } @@ -360,10 +367,11 @@ retval = 1; /* Found an interrupting PMC. */ - if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - pm->pm_pcpu_state[cpu].pps_overflowcnt += 1; + pm->pm_pcpu_state[cpu].pps_overflowcnt += 1; + + if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) continue; - } + if (pm->pm_state != PMC_STATE_RUNNING) continue; diff --git a/sys/dev/hwpmc/hwpmc_uncore.c b/sys/dev/hwpmc/hwpmc_uncore.c --- a/sys/dev/hwpmc/hwpmc_uncore.c +++ b/sys/dev/hwpmc/hwpmc_uncore.c @@ -175,6 +175,10 @@ static pmc_value_t ucf_perfctr_value_to_reload_count(pmc_value_t v) { + + /* If the PMC has overflowed, return a reload count of zero. */ + if ((v & (1ULL << (uncore_ucf_width - 1))) == 0) + return (0); v &= (1ULL << uncore_ucf_width) - 1; return (1ULL << uncore_ucf_width) - v; }