From 75924457863e9dc90475b5cbd9bcabfff87cfc0d Mon Sep 17 00:00:00 2001 From: Remy Noel Date: Wed, 18 Apr 2018 19:21:42 +0200 Subject: perfmon: Add overflow handling. Only architectural version 1 handled so far. --- arch/x86/machine/pmu_intel.c | 36 ++++++++++++++++++++++++++++++++++++ arch/x86/machine/trap.c | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'arch/x86/machine') 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); } diff --git a/arch/x86/machine/trap.c b/arch/x86/machine/trap.c index 0e98015..101adf8 100644 --- a/arch/x86/machine/trap.c +++ b/arch/x86/machine/trap.c @@ -210,7 +210,7 @@ trap_setup(void) trap_install(TRAP_XCALL, TRAP_HF_INTR, cpu_xcall_intr); trap_install(TRAP_THREAD_SCHEDULE, TRAP_HF_INTR, cpu_thread_schedule_intr); trap_install(TRAP_CPU_HALT, TRAP_HF_INTR, cpu_halt_intr); - trap_install(TRAP_LAPIC_PMC_OF, TRAP_HF_INTR, lapic_pmc_of_intr); + trap_install(TRAP_LAPIC_PMC_OF, TRAP_HF_INTR, trap_default); trap_install(TRAP_LAPIC_TIMER, TRAP_HF_INTR, lapic_timer_intr); trap_install(TRAP_LAPIC_ERROR, TRAP_HF_INTR, lapic_error_intr); trap_install(TRAP_LAPIC_SPURIOUS, TRAP_HF_INTR, lapic_spurious_intr); -- cgit v1.2.3