@@ -2119,6 +2119,16 @@ static struct extra_reg intel_grt_extra_regs[] __read_mostly = {
21192119 EVENT_EXTRA_END
21202120};
21212121
2122+ static struct extra_reg intel_cmt_extra_regs [] __read_mostly = {
2123+ /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
2124+ INTEL_UEVENT_EXTRA_REG (0x01b7 , MSR_OFFCORE_RSP_0 , 0x800ff3ffffffffffull , RSP_0 ),
2125+ INTEL_UEVENT_EXTRA_REG (0x02b7 , MSR_OFFCORE_RSP_1 , 0xff3ffffffffffull , RSP_1 ),
2126+ INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG (0x5d0 ),
2127+ INTEL_UEVENT_EXTRA_REG (0x0127 , MSR_SNOOP_RSP_0 , 0xffffffffffffffffull , SNOOP_0 ),
2128+ INTEL_UEVENT_EXTRA_REG (0x0227 , MSR_SNOOP_RSP_1 , 0xffffffffffffffffull , SNOOP_1 ),
2129+ EVENT_EXTRA_END
2130+ };
2131+
21222132#define KNL_OT_L2_HITE BIT_ULL(19) /* Other Tile L2 Hit */
21232133#define KNL_OT_L2_HITF BIT_ULL(20) /* Other Tile L2 Hit */
21242134#define KNL_MCDRAM_LOCAL BIT_ULL(21)
@@ -3026,10 +3036,8 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
30263036
30273037 perf_sample_data_init (& data , 0 , event -> hw .last_period );
30283038
3029- if (has_branch_stack (event )) {
3030- data .br_stack = & cpuc -> lbr_stack ;
3031- data .sample_flags |= PERF_SAMPLE_BRANCH_STACK ;
3032- }
3039+ if (has_branch_stack (event ))
3040+ perf_sample_save_brstack (& data , event , & cpuc -> lbr_stack );
30333041
30343042 if (perf_event_overflow (event , & data , regs ))
30353043 x86_pmu_stop (event , 0 );
@@ -4182,6 +4190,12 @@ static int hsw_hw_config(struct perf_event *event)
41824190static struct event_constraint counter0_constraint =
41834191 INTEL_ALL_EVENT_CONSTRAINT (0 , 0x1 );
41844192
4193+ static struct event_constraint counter1_constraint =
4194+ INTEL_ALL_EVENT_CONSTRAINT (0 , 0x2 );
4195+
4196+ static struct event_constraint counter0_1_constraint =
4197+ INTEL_ALL_EVENT_CONSTRAINT (0 , 0x3 );
4198+
41854199static struct event_constraint counter2_constraint =
41864200 EVENT_CONSTRAINT (0 , 0x4 , 0 );
41874201
@@ -4191,6 +4205,12 @@ static struct event_constraint fixed0_constraint =
41914205static struct event_constraint fixed0_counter0_constraint =
41924206 INTEL_ALL_EVENT_CONSTRAINT (0 , 0x100000001ULL );
41934207
4208+ static struct event_constraint fixed0_counter0_1_constraint =
4209+ INTEL_ALL_EVENT_CONSTRAINT (0 , 0x100000003ULL );
4210+
4211+ static struct event_constraint counters_1_7_constraint =
4212+ INTEL_ALL_EVENT_CONSTRAINT (0 , 0xfeULL );
4213+
41944214static struct event_constraint *
41954215hsw_get_event_constraints (struct cpu_hw_events * cpuc , int idx ,
41964216 struct perf_event * event )
@@ -4322,6 +4342,78 @@ adl_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
43224342 return & emptyconstraint ;
43234343}
43244344
4345+ static struct event_constraint *
4346+ cmt_get_event_constraints (struct cpu_hw_events * cpuc , int idx ,
4347+ struct perf_event * event )
4348+ {
4349+ struct event_constraint * c ;
4350+
4351+ c = intel_get_event_constraints (cpuc , idx , event );
4352+
4353+ /*
4354+ * The :ppp indicates the Precise Distribution (PDist) facility, which
4355+ * is only supported on the GP counter 0 & 1 and Fixed counter 0.
4356+ * If a :ppp event which is not available on the above eligible counters,
4357+ * error out.
4358+ */
4359+ if (event -> attr .precise_ip == 3 ) {
4360+ /* Force instruction:ppp on PMC0, 1 and Fixed counter 0 */
4361+ if (constraint_match (& fixed0_constraint , event -> hw .config ))
4362+ return & fixed0_counter0_1_constraint ;
4363+
4364+ switch (c -> idxmsk64 & 0x3ull ) {
4365+ case 0x1 :
4366+ return & counter0_constraint ;
4367+ case 0x2 :
4368+ return & counter1_constraint ;
4369+ case 0x3 :
4370+ return & counter0_1_constraint ;
4371+ }
4372+ return & emptyconstraint ;
4373+ }
4374+
4375+ return c ;
4376+ }
4377+
4378+ static struct event_constraint *
4379+ rwc_get_event_constraints (struct cpu_hw_events * cpuc , int idx ,
4380+ struct perf_event * event )
4381+ {
4382+ struct event_constraint * c ;
4383+
4384+ c = spr_get_event_constraints (cpuc , idx , event );
4385+
4386+ /* The Retire Latency is not supported by the fixed counter 0. */
4387+ if (event -> attr .precise_ip &&
4388+ (event -> attr .sample_type & PERF_SAMPLE_WEIGHT_TYPE ) &&
4389+ constraint_match (& fixed0_constraint , event -> hw .config )) {
4390+ /*
4391+ * The Instruction PDIR is only available
4392+ * on the fixed counter 0. Error out for this case.
4393+ */
4394+ if (event -> attr .precise_ip == 3 )
4395+ return & emptyconstraint ;
4396+ return & counters_1_7_constraint ;
4397+ }
4398+
4399+ return c ;
4400+ }
4401+
4402+ static struct event_constraint *
4403+ mtl_get_event_constraints (struct cpu_hw_events * cpuc , int idx ,
4404+ struct perf_event * event )
4405+ {
4406+ struct x86_hybrid_pmu * pmu = hybrid_pmu (event -> pmu );
4407+
4408+ if (pmu -> cpu_type == hybrid_big )
4409+ return rwc_get_event_constraints (cpuc , idx , event );
4410+ if (pmu -> cpu_type == hybrid_small )
4411+ return cmt_get_event_constraints (cpuc , idx , event );
4412+
4413+ WARN_ON (1 );
4414+ return & emptyconstraint ;
4415+ }
4416+
43254417static int adl_hw_config (struct perf_event * event )
43264418{
43274419 struct x86_hybrid_pmu * pmu = hybrid_pmu (event -> pmu );
@@ -4494,6 +4586,25 @@ static void flip_smm_bit(void *data)
44944586 }
44954587}
44964588
4589+ static void intel_pmu_check_num_counters (int * num_counters ,
4590+ int * num_counters_fixed ,
4591+ u64 * intel_ctrl , u64 fixed_mask );
4592+
4593+ static void update_pmu_cap (struct x86_hybrid_pmu * pmu )
4594+ {
4595+ unsigned int sub_bitmaps = cpuid_eax (ARCH_PERFMON_EXT_LEAF );
4596+ unsigned int eax , ebx , ecx , edx ;
4597+
4598+ if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT ) {
4599+ cpuid_count (ARCH_PERFMON_EXT_LEAF , ARCH_PERFMON_NUM_COUNTER_LEAF ,
4600+ & eax , & ebx , & ecx , & edx );
4601+ pmu -> num_counters = fls (eax );
4602+ pmu -> num_counters_fixed = fls (ebx );
4603+ intel_pmu_check_num_counters (& pmu -> num_counters , & pmu -> num_counters_fixed ,
4604+ & pmu -> intel_ctrl , ebx );
4605+ }
4606+ }
4607+
44974608static bool init_hybrid_pmu (int cpu )
44984609{
44994610 struct cpu_hw_events * cpuc = & per_cpu (cpu_hw_events , cpu );
@@ -4519,6 +4630,9 @@ static bool init_hybrid_pmu(int cpu)
45194630 if (!cpumask_empty (& pmu -> supported_cpus ))
45204631 goto end ;
45214632
4633+ if (this_cpu_has (X86_FEATURE_ARCH_PERFMON_EXT ))
4634+ update_pmu_cap (pmu );
4635+
45224636 if (!check_hw_exists (& pmu -> pmu , pmu -> num_counters , pmu -> num_counters_fixed ))
45234637 return false;
45244638
@@ -5463,6 +5577,12 @@ static struct attribute *adl_hybrid_mem_attrs[] = {
54635577 NULL ,
54645578};
54655579
5580+ static struct attribute * mtl_hybrid_mem_attrs [] = {
5581+ EVENT_PTR (mem_ld_adl ),
5582+ EVENT_PTR (mem_st_adl ),
5583+ NULL
5584+ };
5585+
54665586EVENT_ATTR_STR_HYBRID (tx - start , tx_start_adl , "event=0xc9,umask=0x1" , hybrid_big );
54675587EVENT_ATTR_STR_HYBRID (tx - commit , tx_commit_adl , "event=0xc9,umask=0x2" , hybrid_big );
54685588EVENT_ATTR_STR_HYBRID (tx - abort , tx_abort_adl , "event=0xc9,umask=0x4" , hybrid_big );
@@ -5490,20 +5610,40 @@ FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small);
54905610FORMAT_ATTR_HYBRID (ldlat , hybrid_big_small );
54915611FORMAT_ATTR_HYBRID (frontend , hybrid_big );
54925612
5613+ #define ADL_HYBRID_RTM_FORMAT_ATTR \
5614+ FORMAT_HYBRID_PTR(in_tx), \
5615+ FORMAT_HYBRID_PTR(in_tx_cp)
5616+
5617+ #define ADL_HYBRID_FORMAT_ATTR \
5618+ FORMAT_HYBRID_PTR(offcore_rsp), \
5619+ FORMAT_HYBRID_PTR(ldlat), \
5620+ FORMAT_HYBRID_PTR(frontend)
5621+
54935622static struct attribute * adl_hybrid_extra_attr_rtm [] = {
5494- FORMAT_HYBRID_PTR (in_tx ),
5495- FORMAT_HYBRID_PTR (in_tx_cp ),
5496- FORMAT_HYBRID_PTR (offcore_rsp ),
5497- FORMAT_HYBRID_PTR (ldlat ),
5498- FORMAT_HYBRID_PTR (frontend ),
5499- NULL ,
5623+ ADL_HYBRID_RTM_FORMAT_ATTR ,
5624+ ADL_HYBRID_FORMAT_ATTR ,
5625+ NULL
55005626};
55015627
55025628static struct attribute * adl_hybrid_extra_attr [] = {
5503- FORMAT_HYBRID_PTR (offcore_rsp ),
5504- FORMAT_HYBRID_PTR (ldlat ),
5505- FORMAT_HYBRID_PTR (frontend ),
5506- NULL ,
5629+ ADL_HYBRID_FORMAT_ATTR ,
5630+ NULL
5631+ };
5632+
5633+ PMU_FORMAT_ATTR_SHOW (snoop_rsp , "config1:0-63" );
5634+ FORMAT_ATTR_HYBRID (snoop_rsp , hybrid_small );
5635+
5636+ static struct attribute * mtl_hybrid_extra_attr_rtm [] = {
5637+ ADL_HYBRID_RTM_FORMAT_ATTR ,
5638+ ADL_HYBRID_FORMAT_ATTR ,
5639+ FORMAT_HYBRID_PTR (snoop_rsp ),
5640+ NULL
5641+ };
5642+
5643+ static struct attribute * mtl_hybrid_extra_attr [] = {
5644+ ADL_HYBRID_FORMAT_ATTR ,
5645+ FORMAT_HYBRID_PTR (snoop_rsp ),
5646+ NULL
55075647};
55085648
55095649static bool is_attr_for_this_pmu (struct kobject * kobj , struct attribute * attr )
@@ -5725,6 +5865,12 @@ static void intel_pmu_check_hybrid_pmus(u64 fixed_mask)
57255865 }
57265866}
57275867
5868+ static __always_inline bool is_mtl (u8 x86_model )
5869+ {
5870+ return (x86_model == INTEL_FAM6_METEORLAKE ) ||
5871+ (x86_model == INTEL_FAM6_METEORLAKE_L );
5872+ }
5873+
57285874__init int intel_pmu_init (void )
57295875{
57305876 struct attribute * * extra_skl_attr = & empty_attrs ;
@@ -6382,6 +6528,8 @@ __init int intel_pmu_init(void)
63826528 case INTEL_FAM6_RAPTORLAKE :
63836529 case INTEL_FAM6_RAPTORLAKE_P :
63846530 case INTEL_FAM6_RAPTORLAKE_S :
6531+ case INTEL_FAM6_METEORLAKE :
6532+ case INTEL_FAM6_METEORLAKE_L :
63856533 /*
63866534 * Alder Lake has 2 types of CPU, core and atom.
63876535 *
@@ -6401,9 +6549,7 @@ __init int intel_pmu_init(void)
64016549 x86_pmu .flags |= PMU_FL_HAS_RSP_1 ;
64026550 x86_pmu .flags |= PMU_FL_NO_HT_SHARING ;
64036551 x86_pmu .flags |= PMU_FL_INSTR_LATENCY ;
6404- x86_pmu .flags |= PMU_FL_MEM_LOADS_AUX ;
64056552 x86_pmu .lbr_pt_coexist = true;
6406- intel_pmu_pebs_data_source_adl ();
64076553 x86_pmu .pebs_latency_data = adl_latency_data_small ;
64086554 x86_pmu .num_topdown_events = 8 ;
64096555 static_call_update (intel_pmu_update_topdown_event ,
@@ -6490,8 +6636,22 @@ __init int intel_pmu_init(void)
64906636 pmu -> event_constraints = intel_slm_event_constraints ;
64916637 pmu -> pebs_constraints = intel_grt_pebs_event_constraints ;
64926638 pmu -> extra_regs = intel_grt_extra_regs ;
6493- pr_cont ("Alderlake Hybrid events, " );
6494- name = "alderlake_hybrid" ;
6639+ if (is_mtl (boot_cpu_data .x86_model )) {
6640+ x86_pmu .pebs_latency_data = mtl_latency_data_small ;
6641+ extra_attr = boot_cpu_has (X86_FEATURE_RTM ) ?
6642+ mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr ;
6643+ mem_attr = mtl_hybrid_mem_attrs ;
6644+ intel_pmu_pebs_data_source_mtl ();
6645+ x86_pmu .get_event_constraints = mtl_get_event_constraints ;
6646+ pmu -> extra_regs = intel_cmt_extra_regs ;
6647+ pr_cont ("Meteorlake Hybrid events, " );
6648+ name = "meteorlake_hybrid" ;
6649+ } else {
6650+ x86_pmu .flags |= PMU_FL_MEM_LOADS_AUX ;
6651+ intel_pmu_pebs_data_source_adl ();
6652+ pr_cont ("Alderlake Hybrid events, " );
6653+ name = "alderlake_hybrid" ;
6654+ }
64956655 break ;
64966656
64976657 default :
@@ -6606,6 +6766,9 @@ __init int intel_pmu_init(void)
66066766 if (is_hybrid ())
66076767 intel_pmu_check_hybrid_pmus ((u64 )fixed_mask );
66086768
6769+ if (x86_pmu .intel_cap .pebs_timing_info )
6770+ x86_pmu .flags |= PMU_FL_RETIRE_LATENCY ;
6771+
66096772 intel_aux_output_init ();
66106773
66116774 return 0 ;
0 commit comments