svn commit: r319911 - in head/sys: dev/hwpmc sys
Zbigniew Bodek
zbb at FreeBSD.org
Tue Jun 13 18:51:25 UTC 2017
Author: zbb
Date: Tue Jun 13 18:51:23 2017
New Revision: 319911
URL: https://svnweb.freebsd.org/changeset/base/319911
Log:
Fix HWPMC interrupt handling in Counting Mode
Additionally:
- Fix support for Cycle Counter (evsel == 0xFF)
- Stop and mask interrupts from all counters on init and finish
Submitted by: Michal Mazur <mkm at semihalf.com>
Obtained from: Semihalf
Sponsored by: Stormshield, Netgate
Differential revision: https://reviews.freebsd.org/D10910
Modified:
head/sys/dev/hwpmc/hwpmc_armv7.c
head/sys/sys/pmc.h
Modified: head/sys/dev/hwpmc/hwpmc_armv7.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_armv7.c Tue Jun 13 18:50:08 2017 (r319910)
+++ head/sys/dev/hwpmc/hwpmc_armv7.c Tue Jun 13 18:51:23 2017 (r319911)
@@ -46,6 +46,8 @@ struct armv7_event_code_map {
uint8_t pe_code;
};
+#define PMC_EV_CPU_CYCLES 0xFF
+
/*
* Per-processor information.
*/
@@ -171,10 +173,11 @@ armv7_read_pmc(int cpu, int ri, pmc_value_t *v)
pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc;
- if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF)
- tmp = cp15_pmccntr_get();
+ if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES)
+ tmp = (uint32_t)cp15_pmccntr_get();
else
tmp = armv7_pmcn_read(ri);
+ tmp += 0x100000000llu * pm->pm_overflowcnt;
PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp);
if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
@@ -202,7 +205,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);
- if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF)
+ if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES)
cp15_pmccntr_set(v);
else
armv7_pmcn_write(ri, v);
@@ -244,11 +247,16 @@ 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.
*/
- cp15_pmselr_set(ri);
- cp15_pmxevtyper_set(config);
+ if (config != PMC_EV_CPU_CYCLES) {
+ cp15_pmselr_set(ri);
+ cp15_pmxevtyper_set(config);
+ } else
+ ri = 31;
/*
* Enable the PMC.
@@ -264,9 +272,13 @@ armv7_stop_pmc(int cpu, int ri)
{
struct pmc_hw *phw;
struct pmc *pm;
+ uint32_t config;
phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri];
pm = phw->phw_pmc;
+ config = pm->pm_md.pm_armv7.pm_armv7_evsel;
+ if (config == PMC_EV_CPU_CYCLES)
+ ri = 31;
/*
* Disable the PMCs.
@@ -313,11 +325,9 @@ armv7_intr(int cpu, struct trapframe *tf)
pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc;
if (pm == NULL)
continue;
- if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
- continue;
/* Check if counter has overflowed */
- if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF)
+ if (pm->pm_md.pm_armv7.pm_armv7_evsel == PMC_EV_CPU_CYCLES)
reg = (1 << 31);
else
reg = (1 << ri);
@@ -330,6 +340,11 @@ armv7_intr(int cpu, struct trapframe *tf)
cp15_pmovsr_set(reg);
retval = 1; /* Found an interrupting PMC. */
+
+ if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
+ pm->pm_overflowcnt += 1;
+ continue;
+ }
if (pm->pm_state != PMC_STATE_RUNNING)
continue;
@@ -430,6 +445,11 @@ armv7_pcpu_init(struct pmc_mdep *md, int cpu)
pc->pc_hwpmcs[i + first_ri] = phw;
}
+ pmnc = 0xffffffff;
+ cp15_pmcnten_clr(pmnc);
+ cp15_pminten_clr(pmnc);
+ cp15_pmovsr_set(pmnc);
+
/* Enable unit */
pmnc = cp15_pmcr_get();
pmnc |= ARMV7_PMNC_ENABLE;
@@ -446,6 +466,11 @@ armv7_pcpu_fini(struct pmc_mdep *md, int cpu)
pmnc = cp15_pmcr_get();
pmnc &= ~ARMV7_PMNC_ENABLE;
cp15_pmcr_set(pmnc);
+
+ pmnc = 0xffffffff;
+ cp15_pmcnten_clr(pmnc);
+ cp15_pminten_clr(pmnc);
+ cp15_pmovsr_set(pmnc);
return 0;
}
Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h Tue Jun 13 18:50:08 2017 (r319910)
+++ head/sys/sys/pmc.h Tue Jun 13 18:51:23 2017 (r319911)
@@ -741,6 +741,7 @@ struct pmc {
struct pmc_owner *pm_owner; /* owner thread state */
int pm_runcount; /* #cpus currently on */
enum pmc_state pm_state; /* current PMC state */
+ uint32_t pm_overflowcnt; /* count overflow interrupts */
/*
* The PMC ID field encodes the row-index for the PMC, its
More information about the svn-src-all
mailing list