Update hwpmc on armv7 to handle overflow better
When testing hwpmc on arm64 we found the counter could overflow while reading the event count. Handle this case in the armv7 code by also checking if the overflow bit is set and incrementing the overflow cound as needed. Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D27969
This commit is contained in:
parent
8ddea0b127
commit
90a6e9ef63
@ -109,9 +109,13 @@ armv7_counter_disable(unsigned int pmc)
|
||||
* 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 @@ armv7_read_pmc(int cpu, int ri, pmc_value_t *v)
|
||||
{
|
||||
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 @@ armv7_read_pmc(int cpu, int ri, pmc_value_t *v)
|
||||
|
||||
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)))
|
||||
@ -205,6 +226,7 @@ armv7_write_pmc(int cpu, int ri, pmc_value_t v)
|
||||
|
||||
PMCDBG3(MDP, WRI, 1, "armv7-write cpu=%d ri=%d v=%jx", cpu, ri, v);
|
||||
|
||||
pm->pm_overflowcnt = v >> 32;
|
||||
if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES)
|
||||
cp15_pmccntr_set(v);
|
||||
else
|
||||
@ -247,8 +269,6 @@ armv7_start_pmc(int cpu, int ri)
|
||||
pm = phw->phw_pmc;
|
||||
config = pm->pm_md.pm_armv7.pm_armv7_evsel;
|
||||
|
||||
pm->pm_overflowcnt = 0;
|
||||
|
||||
/*
|
||||
* Configure the event selection.
|
||||
*/
|
||||
@ -329,9 +349,9 @@ armv7_intr(struct trapframe *tf)
|
||||
|
||||
/* 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user