Commit b1dc3c4820428ac6216537416b2fcd140fdc52e5

Authored by Robert Richter
Committed by Ingo Molnar
1 parent a1eac7ac90

perf/x86/amd: Unify AMD's generic and family 15h pmus

There is no need for keeping separate pmu structs. We can enable
amd_{get,put}_event_constraints() functions also for family 15h event.

The advantage is that there is only a single pmu struct for all AMD
cpus. This patch introduces functions to setup the pmu to enabe core
performance counters or counter constraints.

Also, cpuid checks are used instead of family checks where
possible. Thus, it enables the code independently of cpu families if
the feature flag is set.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1340217996-2254-4-git-send-email-robert.richter@amd.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Showing 3 changed files with 49 additions and 61 deletions Side-by-side Diff

arch/x86/include/asm/perf_event.h
... ... @@ -47,8 +47,7 @@
47 47 (X86_RAW_EVENT_MASK | \
48 48 AMD64_EVENTSEL_EVENT)
49 49 #define AMD64_NUM_COUNTERS 4
50   -#define AMD64_NUM_COUNTERS_F15H 6
51   -#define AMD64_NUM_COUNTERS_MAX AMD64_NUM_COUNTERS_F15H
  50 +#define AMD64_NUM_COUNTERS_CORE 6
52 51  
53 52 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
54 53 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
arch/x86/kernel/cpu/perf_event_amd.c
... ... @@ -366,7 +366,7 @@
366 366  
367 367 cpuc->perf_ctr_virt_mask = AMD_PERFMON_EVENTSEL_HOSTONLY;
368 368  
369   - if (boot_cpu_data.x86_max_cores < 2 || boot_cpu_data.x86 == 0x15)
  369 + if (boot_cpu_data.x86_max_cores < 2)
370 370 return;
371 371  
372 372 nb_id = amd_get_nb_id(cpu);
... ... @@ -422,35 +422,6 @@
422 422 NULL,
423 423 };
424 424  
425   -static __initconst const struct x86_pmu amd_pmu = {
426   - .name = "AMD",
427   - .handle_irq = x86_pmu_handle_irq,
428   - .disable_all = x86_pmu_disable_all,
429   - .enable_all = x86_pmu_enable_all,
430   - .enable = x86_pmu_enable_event,
431   - .disable = x86_pmu_disable_event,
432   - .hw_config = amd_pmu_hw_config,
433   - .schedule_events = x86_schedule_events,
434   - .eventsel = MSR_K7_EVNTSEL0,
435   - .perfctr = MSR_K7_PERFCTR0,
436   - .event_map = amd_pmu_event_map,
437   - .max_events = ARRAY_SIZE(amd_perfmon_event_map),
438   - .num_counters = AMD64_NUM_COUNTERS,
439   - .cntval_bits = 48,
440   - .cntval_mask = (1ULL << 48) - 1,
441   - .apic = 1,
442   - /* use highest bit to detect overflow */
443   - .max_period = (1ULL << 47) - 1,
444   - .get_event_constraints = amd_get_event_constraints,
445   - .put_event_constraints = amd_put_event_constraints,
446   -
447   - .format_attrs = amd_format_attr,
448   -
449   - .cpu_prepare = amd_pmu_cpu_prepare,
450   - .cpu_starting = amd_pmu_cpu_starting,
451   - .cpu_dead = amd_pmu_cpu_dead,
452   -};
453   -
454 425 /* AMD Family 15h */
455 426  
456 427 #define AMD_EVENT_TYPE_MASK 0x000000F0ULL
... ... @@ -597,8 +568,8 @@
597 568 }
598 569 }
599 570  
600   -static __initconst const struct x86_pmu amd_pmu_f15h = {
601   - .name = "AMD Family 15h",
  571 +static __initconst const struct x86_pmu amd_pmu = {
  572 + .name = "AMD",
602 573 .handle_irq = x86_pmu_handle_irq,
603 574 .disable_all = x86_pmu_disable_all,
604 575 .enable_all = x86_pmu_enable_all,
605 576  
606 577  
607 578  
608 579  
609 580  
610 581  
611 582  
... ... @@ -606,50 +577,68 @@
606 577 .disable = x86_pmu_disable_event,
607 578 .hw_config = amd_pmu_hw_config,
608 579 .schedule_events = x86_schedule_events,
609   - .eventsel = MSR_F15H_PERF_CTL,
610   - .perfctr = MSR_F15H_PERF_CTR,
  580 + .eventsel = MSR_K7_EVNTSEL0,
  581 + .perfctr = MSR_K7_PERFCTR0,
611 582 .event_map = amd_pmu_event_map,
612 583 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
613   - .num_counters = AMD64_NUM_COUNTERS_F15H,
  584 + .num_counters = AMD64_NUM_COUNTERS,
614 585 .cntval_bits = 48,
615 586 .cntval_mask = (1ULL << 48) - 1,
616 587 .apic = 1,
617 588 /* use highest bit to detect overflow */
618 589 .max_period = (1ULL << 47) - 1,
619   - .get_event_constraints = amd_get_event_constraints_f15h,
620   - /* nortbridge counters not yet implemented: */
621   -#if 0
  590 + .get_event_constraints = amd_get_event_constraints,
622 591 .put_event_constraints = amd_put_event_constraints,
623 592  
  593 + .format_attrs = amd_format_attr,
  594 +
624 595 .cpu_prepare = amd_pmu_cpu_prepare,
625   - .cpu_dead = amd_pmu_cpu_dead,
626   -#endif
627 596 .cpu_starting = amd_pmu_cpu_starting,
628   - .format_attrs = amd_format_attr,
  597 + .cpu_dead = amd_pmu_cpu_dead,
629 598 };
630 599  
  600 +static int setup_event_constraints(void)
  601 +{
  602 + if (boot_cpu_data.x86 >= 0x15)
  603 + x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
  604 + return 0;
  605 +}
  606 +
  607 +static int setup_perfctr_core(void)
  608 +{
  609 + if (!cpu_has_perfctr_core) {
  610 + WARN(x86_pmu.get_event_constraints == amd_get_event_constraints_f15h,
  611 + KERN_ERR "Odd, counter constraints enabled but no core perfctrs detected!");
  612 + return -ENODEV;
  613 + }
  614 +
  615 + WARN(x86_pmu.get_event_constraints == amd_get_event_constraints,
  616 + KERN_ERR "hw perf events core counters need constraints handler!");
  617 +
  618 + /*
  619 + * If core performance counter extensions exists, we must use
  620 + * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
  621 + * x86_pmu_addr_offset().
  622 + */
  623 + x86_pmu.eventsel = MSR_F15H_PERF_CTL;
  624 + x86_pmu.perfctr = MSR_F15H_PERF_CTR;
  625 + x86_pmu.num_counters = AMD64_NUM_COUNTERS_CORE;
  626 +
  627 + printk(KERN_INFO "perf: AMD core performance counters detected\n");
  628 +
  629 + return 0;
  630 +}
  631 +
631 632 __init int amd_pmu_init(void)
632 633 {
633 634 /* Performance-monitoring supported from K7 and later: */
634 635 if (boot_cpu_data.x86 < 6)
635 636 return -ENODEV;
636 637  
637   - /*
638   - * If core performance counter extensions exists, it must be
639   - * family 15h, otherwise fail. See x86_pmu_addr_offset().
640   - */
641   - switch (boot_cpu_data.x86) {
642   - case 0x15:
643   - if (!cpu_has_perfctr_core)
644   - return -ENODEV;
645   - x86_pmu = amd_pmu_f15h;
646   - break;
647   - default:
648   - if (cpu_has_perfctr_core)
649   - return -ENODEV;
650   - x86_pmu = amd_pmu;
651   - break;
652   - }
  638 + x86_pmu = amd_pmu;
  639 +
  640 + setup_event_constraints();
  641 + setup_perfctr_core();
653 642  
654 643 /* Events are common for all AMDs */
655 644 memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
arch/x86/oprofile/op_model_amd.c
... ... @@ -312,7 +312,7 @@
312 312 goto fail;
313 313 }
314 314 /* both registers must be reserved */
315   - if (num_counters == AMD64_NUM_COUNTERS_F15H) {
  315 + if (num_counters == AMD64_NUM_COUNTERS_CORE) {
316 316 msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
317 317 msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
318 318 } else {
... ... @@ -514,7 +514,7 @@
514 514 ops->create_files = setup_ibs_files;
515 515  
516 516 if (boot_cpu_data.x86 == 0x15) {
517   - num_counters = AMD64_NUM_COUNTERS_F15H;
  517 + num_counters = AMD64_NUM_COUNTERS_CORE;
518 518 } else {
519 519 num_counters = AMD64_NUM_COUNTERS;
520 520 }