Commit b1dc3c4820428ac6216537416b2fcd140fdc52e5
Committed by
Ingo Molnar
1 parent
a1eac7ac90
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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 | } |