diff options
Diffstat (limited to 'arch/x86/machine/pmu_intel.c')
-rw-r--r-- | arch/x86/machine/pmu_intel.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/x86/machine/pmu_intel.c b/arch/x86/machine/pmu_intel.c index fcebb06..6439282 100644 --- a/arch/x86/machine/pmu_intel.c +++ b/arch/x86/machine/pmu_intel.c @@ -49,7 +49,11 @@ */ #define PMU_INTEL_EVTSEL_USR 0x00010000 #define PMU_INTEL_EVTSEL_OS 0x00020000 +#define PMU_INTEL_EVTSEL_EDGE 0x00040000 +#define PMU_INTEL_EVTSEL_PC 0x00080000 +#define PMU_INTEL_EVTSEL_INT 0x00100000 #define PMU_INTEL_EVTSEL_EN 0x00400000 +#define PMU_INTEL_EVTSEL_INV 0x00800000 #define PMU_INTEL_ID_VERSION_MASK 0x000000ff #define PMU_INTEL_ID_NR_PMCS_MASK 0x0000ff00 @@ -209,6 +213,7 @@ pmu_intel_start(unsigned int pmc_id, unsigned int raw_event_id) evtsel = PMU_INTEL_EVTSEL_EN | PMU_INTEL_EVTSEL_OS | PMU_INTEL_EVTSEL_USR + | PMU_INTEL_EVTSEL_INT | (code->umask << 8) | code->event_select; cpu_set_msr(PMU_INTEL_MSR_EVTSEL0 + pmc_id, 0, evtsel); @@ -226,6 +231,36 @@ pmu_intel_read(unsigned int pmc_id) return cpu_get_msr64(PMU_INTEL_MSR_PMC0 + pmc_id); } +static void +pmu_intel_handle_of_intr_v1(struct trap_frame *frame) +{ + struct pmu_intel *pmu; + unsigned int mask; + uint64_t value; + uint64_t prev; + + (void)frame; + + pmu = pmu_intel_get(); + + for (unsigned int pmc_id = 0; pmc_id != pmu->nr_pmcs; pmc_id++) { + mask = (1U << pmc_id); + if (pmu->pmc_bm & mask) { + /* counter not enabled: can't overflow. */ + continue; + } + + value = pmu_intel_read(pmc_id); + prev = perfmon_cpu_pmc_get_prev(pmc_id); + if (prev > value) { + /* Overflow */ + perfmon_cpu_pmc_inc_of(pmc_id); + /* Prevents us from overflowing twice */ + perfmon_cpu_pmc_set_prev(pmc_id, value); + } + } +} + static uint8_t pmu_intel_get_pmc_width(void) { @@ -282,6 +317,7 @@ pmu_intel_setup(void) pmu_driver.stop = pmu_intel_stop; pmu_driver.read = pmu_intel_read; pmu_driver.get_pmc_width = pmu_intel_get_pmc_width; + pmu_driver.handle_of_intr = pmu_intel_handle_of_intr_v1; return perfmon_pmu_register(&pmu_driver); } |