summaryrefslogtreecommitdiff
path: root/arch/x86/machine/pmu_intel.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/machine/pmu_intel.c')
-rw-r--r--arch/x86/machine/pmu_intel.c36
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);
}