diff options
Diffstat (limited to 'arch/x86/machine/pmu_intel.c')
-rw-r--r-- | arch/x86/machine/pmu_intel.c | 49 |
1 files changed, 12 insertions, 37 deletions
diff --git a/arch/x86/machine/pmu_intel.c b/arch/x86/machine/pmu_intel.c index ccc2294..e5d9ef7 100644 --- a/arch/x86/machine/pmu_intel.c +++ b/arch/x86/machine/pmu_intel.c @@ -21,6 +21,7 @@ #include <stdint.h> #include <kern/init.h> +#include <kern/clock.h> #include <kern/log.h> #include <kern/perfmon.h> #include <machine/cpu.h> @@ -174,7 +175,7 @@ pmu_intel_info(void) pmu = pmu_intel_get(); nr_events = pmu_popcount(pmu->events); - log_info("pmu: driver: intel, architectural v%d\n" + log_info("pmu: driver: intel, architectural v%d " "pmu: nr_pmcs: %u, pmc_width: %u, events: %#x, nr_events: %u\n", pmu->version, pmu->nr_pmcs, pmu->pmc_width, pmu->events, nr_events); @@ -233,19 +234,23 @@ static void pmu_intel_start(unsigned int pmc_id, unsigned int raw_event_id) { const struct pmu_intel_event_code *code; + struct pmu_intel *pmu; uint32_t evtsel; assert(raw_event_id < ARRAY_SIZE(pmu_intel_event_codes)); code = &pmu_intel_event_codes[raw_event_id]; + pmu = pmu_intel_get(); /* TODO Handle PERFMON_EF_KERN/PERFMON_EF_USER */ evtsel = PMU_INTEL_EVTSEL_EN | PMU_INTEL_EVTSEL_OS | PMU_INTEL_EVTSEL_USR - | PMU_INTEL_EVTSEL_INT | (code->umask << 8) | code->event_select; + if (pmu->version >= 2) { + evtsel |= PMU_INTEL_EVTSEL_INT; + } cpu_set_msr(PMU_INTEL_MSR_EVTSEL0 + pmc_id, 0, evtsel); } @@ -267,38 +272,6 @@ pmu_intel_write(unsigned int pmc_id, uint64_t value) cpu_set_msr64(PMU_INTEL_MSR_PMC0 + pmc_id, value); } -/* - * TODO Make the perfmon module handle basic overflow handling by polling - * counters. - */ -static void -pmu_intel_handle_of_intr_v1(void) -{ - struct pmu_intel *pmu; - unsigned int mask; - uint64_t value; - uint64_t prev; - - 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 int pmu_intel_consume_bits(uint64_t *bits) { @@ -330,7 +303,7 @@ pmu_intel_handle_of_intr_v2(void) pmu_intel_ack_status(status); pmu = pmu_intel_get(); - status &= ((1U << pmu->pmc_width) - 1); + status &= ((1ULL << pmu->pmc_width) - 1); for (;;) { pmc_id = pmu_intel_consume_bits(&status); @@ -366,7 +339,6 @@ pmu_intel_setup(void) cpu_cpuid(&eax, &ebx, &ecx, &edx); pmu->version = eax & PMU_INTEL_ID_VERSION_MASK; - /* TODO Check this */ if (pmu->version == 0) { return ENODEV; } @@ -396,7 +368,10 @@ pmu_intel_setup(void) pmu_driver.ops.handle_of_intr = pmu_intel_handle_of_intr_v2; pmu_driver.of_max_ticks = 0; } else { - pmu_driver.of_max_ticks = 1UL << (pmu_driver.pmc_width - 1); + /* Set max_tick to half the number of instruction per seconds. */ + pmu_driver.ops.handle_of_intr = NULL; + pmu_driver.of_max_ticks = + (1ULL << (pmu_driver.pmc_width - 1)) / (cpu_get_freq() / CLOCK_FREQ); } return perfmon_pmu_register(&pmu_driver); |