Skip to content

Commit 471af00

Browse files
kimphillamdPeter Zijlstra
authored andcommitted
perf/x86/amd: Constrain Large Increment per Cycle events
AMD Family 17h processors and above gain support for Large Increment per Cycle events. Unfortunately there is no CPUID or equivalent bit that indicates whether the feature exists or not, so we continue to determine eligibility based on a CPU family number comparison. For Large Increment per Cycle events, we add a f17h-and-compatibles get_event_constraints_f17h() that returns an even counter bitmask: Large Increment per Cycle events can only be placed on PMCs 0, 2, and 4 out of the currently available 0-5. The only currently public event that requires this feature to report valid counts is PMCx003 "Retired SSE/AVX Operations". Note that the CPU family logic in amd_core_pmu_init() is changed so as to be able to selectively add initialization for features available in ranges of backward-compatible CPU families. This Large Increment per Cycle feature is expected to be retained in future families. A side-effect of assigning a new get_constraints function for f17h disables calling the old (prior to f15h) amd_get_event_constraints implementation left enabled by commit e40ed15 ("perf/x86: Add perf support for AMD family-17h processors"), which is no longer necessary since those North Bridge event codes are obsoleted. Also fix a spelling mistake whilst in the area (calulating -> calculating). Fixes: e40ed15 ("perf/x86: Add perf support for AMD family-17h processors") Signed-off-by: Kim Phillips <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 1e0f177 commit 471af00

File tree

2 files changed

+63
-30
lines changed

2 files changed

+63
-30
lines changed

arch/x86/events/amd/core.c

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,25 @@ static inline int amd_pmu_addr_offset(int index, bool eventsel)
301301
return offset;
302302
}
303303

304+
/*
305+
* AMD64 events are detected based on their event codes.
306+
*/
307+
static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
308+
{
309+
return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
310+
}
311+
312+
static inline bool amd_is_pair_event_code(struct hw_perf_event *hwc)
313+
{
314+
if (!(x86_pmu.flags & PMU_FL_PAIR))
315+
return false;
316+
317+
switch (amd_get_event_code(hwc)) {
318+
case 0x003: return true; /* Retired SSE/AVX FLOPs */
319+
default: return false;
320+
}
321+
}
322+
304323
static int amd_core_hw_config(struct perf_event *event)
305324
{
306325
if (event->attr.exclude_host && event->attr.exclude_guest)
@@ -319,14 +338,6 @@ static int amd_core_hw_config(struct perf_event *event)
319338
return 0;
320339
}
321340

322-
/*
323-
* AMD64 events are detected based on their event codes.
324-
*/
325-
static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
326-
{
327-
return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
328-
}
329-
330341
static inline int amd_is_nb_event(struct hw_perf_event *hwc)
331342
{
332343
return (hwc->config & 0xe0) == 0xe0;
@@ -855,6 +866,20 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx,
855866
}
856867
}
857868

869+
static struct event_constraint pair_constraint;
870+
871+
static struct event_constraint *
872+
amd_get_event_constraints_f17h(struct cpu_hw_events *cpuc, int idx,
873+
struct perf_event *event)
874+
{
875+
struct hw_perf_event *hwc = &event->hw;
876+
877+
if (amd_is_pair_event_code(hwc))
878+
return &pair_constraint;
879+
880+
return &unconstrained;
881+
}
882+
858883
static ssize_t amd_event_sysfs_show(char *page, u64 config)
859884
{
860885
u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
@@ -898,33 +923,15 @@ static __initconst const struct x86_pmu amd_pmu = {
898923

899924
static int __init amd_core_pmu_init(void)
900925
{
926+
u64 even_ctr_mask = 0ULL;
927+
int i;
928+
901929
if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
902930
return 0;
903931

904-
/* Avoid calulating the value each time in the NMI handler */
932+
/* Avoid calculating the value each time in the NMI handler */
905933
perf_nmi_window = msecs_to_jiffies(100);
906934

907-
switch (boot_cpu_data.x86) {
908-
case 0x15:
909-
pr_cont("Fam15h ");
910-
x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
911-
break;
912-
case 0x17:
913-
pr_cont("Fam17h ");
914-
/*
915-
* In family 17h, there are no event constraints in the PMC hardware.
916-
* We fallback to using default amd_get_event_constraints.
917-
*/
918-
break;
919-
case 0x18:
920-
pr_cont("Fam18h ");
921-
/* Using default amd_get_event_constraints. */
922-
break;
923-
default:
924-
pr_err("core perfctr but no constraints; unknown hardware!\n");
925-
return -ENODEV;
926-
}
927-
928935
/*
929936
* If core performance counter extensions exists, we must use
930937
* MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
@@ -939,6 +946,30 @@ static int __init amd_core_pmu_init(void)
939946
*/
940947
x86_pmu.amd_nb_constraints = 0;
941948

949+
if (boot_cpu_data.x86 == 0x15) {
950+
pr_cont("Fam15h ");
951+
x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
952+
}
953+
if (boot_cpu_data.x86 >= 0x17) {
954+
pr_cont("Fam17h+ ");
955+
/*
956+
* Family 17h and compatibles have constraints for Large
957+
* Increment per Cycle events: they may only be assigned an
958+
* even numbered counter that has a consecutive adjacent odd
959+
* numbered counter following it.
960+
*/
961+
for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
962+
even_ctr_mask |= 1 << i;
963+
964+
pair_constraint = (struct event_constraint)
965+
__EVENT_CONSTRAINT(0, even_ctr_mask, 0,
966+
x86_pmu.num_counters / 2, 0,
967+
PERF_X86_EVENT_PAIR);
968+
969+
x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
970+
x86_pmu.flags |= PMU_FL_PAIR;
971+
}
972+
942973
pr_cont("core perfctr, ");
943974
return 0;
944975
}

arch/x86/events/perf_event.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static inline bool constraint_match(struct event_constraint *c, u64 ecode)
7777
#define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */
7878
#define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */
7979
#define PERF_X86_EVENT_PEBS_VIA_PT 0x0800 /* use PT buffer for PEBS */
80+
#define PERF_X86_EVENT_PAIR 0x1000 /* Large Increment per Cycle */
8081

8182
struct amd_nb {
8283
int nb_id; /* NorthBridge id */
@@ -743,6 +744,7 @@ do { \
743744
#define PMU_FL_EXCL_ENABLED 0x8 /* exclusive counter active */
744745
#define PMU_FL_PEBS_ALL 0x10 /* all events are valid PEBS events */
745746
#define PMU_FL_TFA 0x20 /* deal with TSX force abort */
747+
#define PMU_FL_PAIR 0x40 /* merge counters for large incr. events */
746748

747749
#define EVENT_VAR(_id) event_attr_##_id
748750
#define EVENT_PTR(_id) &event_attr_##_id.attr.attr

0 commit comments

Comments
 (0)