aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2014-02-11 10:20:13 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-02-21 15:49:08 -0500
commitced2efb099f4f24ea7030c22b064e5ddd65cd764 (patch)
tree680bb6373119387ed530edda00aa62c26a6fc157 /arch/x86
parentb9e1ab6d4c0582cad97699285a6b3cf992251b00 (diff)
perf/x86/uncore: add hrtimer to SNB uncore IMC PMU
This patch is needed because that PMU uses 32-bit free running counters with no interrupt capabilities. On SNB/IVB/HSW, we used 20GB/s theoretical peak to calculate the hrtimer timeout necessary to avoid missing an overflow. That delay is set to 5s to be on the cautious side. The SNB IMC uses free running counters, which are handled via pseudo fixed counters. The SNB IMC PMU implementation supports an arbitrary number of events, because the counters are read-only. Therefore it is not possible to track active counters. Instead we put active events on a linked list which is then used by the hrtimer handler to update the SW counts. Cc: mingo@elte.hu Cc: acme@redhat.com Cc: ak@linux.intel.com Cc: zheng.z.yan@intel.com Cc: peterz@infradead.org Signed-off-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1392132015-14521-8-git-send-email-eranian@google.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c12
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.h2
2 files changed, 14 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 66ce5e50cb44..7760aeeefeac 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -1728,6 +1728,7 @@ static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
1728 addr &= ~(PAGE_SIZE - 1); 1728 addr &= ~(PAGE_SIZE - 1);
1729 1729
1730 box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE); 1730 box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
1731 box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
1731} 1732}
1732 1733
1733static void snb_uncore_imc_enable_box(struct intel_uncore_box *box) 1734static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
@@ -3160,6 +3161,7 @@ again:
3160static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer) 3161static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
3161{ 3162{
3162 struct intel_uncore_box *box; 3163 struct intel_uncore_box *box;
3164 struct perf_event *event;
3163 unsigned long flags; 3165 unsigned long flags;
3164 int bit; 3166 int bit;
3165 3167
@@ -3172,6 +3174,14 @@ static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
3172 */ 3174 */
3173 local_irq_save(flags); 3175 local_irq_save(flags);
3174 3176
3177 /*
3178 * handle boxes with an active event list as opposed to active
3179 * counters
3180 */
3181 list_for_each_entry(event, &box->active_list, active_entry) {
3182 uncore_perf_event_update(box, event);
3183 }
3184
3175 for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX) 3185 for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
3176 uncore_perf_event_update(box, box->events[bit]); 3186 uncore_perf_event_update(box, box->events[bit]);
3177 3187
@@ -3221,6 +3231,8 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
3221 /* set default hrtimer timeout */ 3231 /* set default hrtimer timeout */
3222 box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL; 3232 box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
3223 3233
3234 INIT_LIST_HEAD(&box->active_list);
3235
3224 return box; 3236 return box;
3225} 3237}
3226 3238
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index fbf45a0ebf92..90236f0c94a9 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -6,6 +6,7 @@
6 6
7#define UNCORE_PMU_NAME_LEN 32 7#define UNCORE_PMU_NAME_LEN 32
8#define UNCORE_PMU_HRTIMER_INTERVAL (60LL * NSEC_PER_SEC) 8#define UNCORE_PMU_HRTIMER_INTERVAL (60LL * NSEC_PER_SEC)
9#define UNCORE_SNB_IMC_HRTIMER_INTERVAL (5ULL * NSEC_PER_SEC)
9 10
10#define UNCORE_FIXED_EVENT 0xff 11#define UNCORE_FIXED_EVENT 0xff
11#define UNCORE_PMC_IDX_MAX_GENERIC 8 12#define UNCORE_PMC_IDX_MAX_GENERIC 8
@@ -492,6 +493,7 @@ struct intel_uncore_box {
492 u64 hrtimer_duration; /* hrtimer timeout for this box */ 493 u64 hrtimer_duration; /* hrtimer timeout for this box */
493 struct hrtimer hrtimer; 494 struct hrtimer hrtimer;
494 struct list_head list; 495 struct list_head list;
496 struct list_head active_list;
495 void *io_addr; 497 void *io_addr;
496 struct intel_uncore_extra_reg shared_regs[0]; 498 struct intel_uncore_extra_reg shared_regs[0];
497}; 499};