Loading arch/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ config KPROBES_ON_FTRACE config UPROBES def_bool n depends on ARCH_SUPPORTS_UPROBES select TASKS_TRACE_RCU help Uprobes is the user-space counterpart to kprobes: they enable instrumentation applications (such as 'perf probe') Loading arch/x86/events/amd/core.c +8 −2 Original line number Diff line number Diff line Loading @@ -943,11 +943,12 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u static int amd_pmu_v2_handle_irq(struct pt_regs *regs) { struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); static atomic64_t status_warned = ATOMIC64_INIT(0); u64 reserved, status, mask, new_bits, prev_bits; struct perf_sample_data data; struct hw_perf_event *hwc; struct perf_event *event; int handled = 0, idx; u64 reserved, status, mask; bool pmu_enabled; /* Loading Loading @@ -1012,7 +1013,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) * the corresponding PMCs are expected to be inactive according to the * active_mask */ WARN_ON(status > 0); if (status > 0) { prev_bits = atomic64_fetch_or(status, &status_warned); // A new bit was set for the very first time. new_bits = status & ~prev_bits; WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits); } /* Clear overflow and freeze bits */ amd_pmu_ack_global_status(~status); Loading arch/x86/events/intel/core.c +121 −12 Original line number Diff line number Diff line Loading @@ -4599,6 +4599,28 @@ static inline bool erratum_hsw11(struct perf_event *event) X86_CONFIG(.event=0xc0, .umask=0x01); } static struct event_constraint * arl_h_get_event_constraints(struct cpu_hw_events *cpuc, int idx, struct perf_event *event) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return cmt_get_event_constraints(cpuc, idx, event); return mtl_get_event_constraints(cpuc, idx, event); } static int arl_h_hw_config(struct perf_event *event) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return intel_pmu_hw_config(event); return adl_hw_config(event); } /* * The HSW11 requires a period larger than 100 which is the same as the BDM11. * A minimum period of 128 is enforced as well for the INST_RETIRED.ALL. Loading Loading @@ -4924,18 +4946,27 @@ static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void) /* * This essentially just maps between the 'hybrid_cpu_type' * and 'hybrid_pmu_type' enums: * and 'hybrid_pmu_type' enums except for ARL-H processor * which needs to compare atom uarch native id since ARL-H * contains two different atom uarchs. */ for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) { enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type; u32 native_id; if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_ATOM) { if (x86_pmu.num_hybrid_pmus == 2 && pmu_type == hybrid_small) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big) native_id = get_this_hybrid_cpu_native_id(); if (native_id == skt_native_id && pmu_type == hybrid_small) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_ATOM && pmu_type == hybrid_small) if (native_id == cmt_native_id && pmu_type == hybrid_tiny) return &x86_pmu.hybrid_pmu[i]; } } return NULL; } Loading Loading @@ -5965,6 +5996,37 @@ static struct attribute *lnl_hybrid_events_attrs[] = { NULL }; /* The event string must be in PMU IDX order. */ EVENT_ATTR_STR_HYBRID(topdown-retiring, td_retiring_arl_h, "event=0xc2,umask=0x02;event=0x00,umask=0x80;event=0xc2,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-bad-spec, td_bad_spec_arl_h, "event=0x73,umask=0x0;event=0x00,umask=0x81;event=0x73,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-fe-bound, td_fe_bound_arl_h, "event=0x9c,umask=0x01;event=0x00,umask=0x82;event=0x71,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-be-bound, td_be_bound_arl_h, "event=0xa4,umask=0x02;event=0x00,umask=0x83;event=0x74,umask=0x0", hybrid_big_small_tiny); static struct attribute *arl_h_hybrid_events_attrs[] = { EVENT_PTR(slots_adl), EVENT_PTR(td_retiring_arl_h), EVENT_PTR(td_bad_spec_arl_h), EVENT_PTR(td_fe_bound_arl_h), EVENT_PTR(td_be_bound_arl_h), EVENT_PTR(td_heavy_ops_adl), EVENT_PTR(td_br_mis_adl), EVENT_PTR(td_fetch_lat_adl), EVENT_PTR(td_mem_bound_adl), NULL, }; /* Must be in IDX order */ EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_adl, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3", hybrid_big_small); EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_adl, "event=0xd0,umask=0x6;event=0xcd,umask=0x2", hybrid_big_small); Loading @@ -5983,6 +6045,21 @@ static struct attribute *mtl_hybrid_mem_attrs[] = { NULL }; EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_arl_h, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3;event=0xd0,umask=0x5,ldlat=3", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_arl_h, "event=0xd0,umask=0x6;event=0xcd,umask=0x2;event=0xd0,umask=0x6", hybrid_big_small_tiny); static struct attribute *arl_h_hybrid_mem_attrs[] = { EVENT_PTR(mem_ld_arl_h), EVENT_PTR(mem_st_arl_h), NULL, }; EVENT_ATTR_STR_HYBRID(tx-start, tx_start_adl, "event=0xc9,umask=0x1", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-commit, tx_commit_adl, "event=0xc9,umask=0x2", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-abort, tx_abort_adl, "event=0xc9,umask=0x4", hybrid_big); Loading @@ -6006,8 +6083,8 @@ static struct attribute *adl_hybrid_tsx_attrs[] = { FORMAT_ATTR_HYBRID(in_tx, hybrid_big); FORMAT_ATTR_HYBRID(in_tx_cp, hybrid_big); FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small); FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small); FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small_tiny); FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small_tiny); FORMAT_ATTR_HYBRID(frontend, hybrid_big); #define ADL_HYBRID_RTM_FORMAT_ATTR \ Loading @@ -6030,7 +6107,7 @@ static struct attribute *adl_hybrid_extra_attr[] = { NULL }; FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small); FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small_tiny); static struct attribute *mtl_hybrid_extra_attr_rtm[] = { ADL_HYBRID_RTM_FORMAT_ATTR, Loading Loading @@ -6240,6 +6317,7 @@ static inline int intel_pmu_v6_addr_offset(int index, bool eventsel) static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = { { hybrid_small, "cpu_atom" }, { hybrid_big, "cpu_core" }, { hybrid_tiny, "cpu_lowpower" }, }; static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) Loading Loading @@ -6272,7 +6350,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) 0, x86_pmu_num_counters(&pmu->pmu), 0, 0); pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; if (pmu->pmu_type & hybrid_small) { if (pmu->pmu_type & hybrid_small_tiny) { pmu->intel_cap.perf_metrics = 0; pmu->intel_cap.pebs_output_pt_available = 1; pmu->mid_ack = true; Loading Loading @@ -7111,6 +7189,37 @@ __init int intel_pmu_init(void) name = "lunarlake_hybrid"; break; case INTEL_ARROWLAKE_H: intel_pmu_init_hybrid(hybrid_big_small_tiny); x86_pmu.pebs_latency_data = arl_h_latency_data; x86_pmu.get_event_constraints = arl_h_get_event_constraints; x86_pmu.hw_config = arl_h_hw_config; td_attr = arl_h_hybrid_events_attrs; mem_attr = arl_h_hybrid_mem_attrs; tsx_attr = adl_hybrid_tsx_attrs; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr; /* Initialize big core specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX]; intel_pmu_init_lnc(&pmu->pmu); /* Initialize Atom core specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX]; intel_pmu_init_skt(&pmu->pmu); /* Initialize Lower Power Atom specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX]; intel_pmu_init_grt(&pmu->pmu); pmu->extra_regs = intel_cmt_extra_regs; intel_pmu_pebs_data_source_arl_h(); pr_cont("ArrowLake-H Hybrid events, "); name = "arrowlake_h_hybrid"; break; default: switch (x86_pmu.version) { case 1: Loading arch/x86/events/intel/ds.c +21 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,17 @@ void __init intel_pmu_pebs_data_source_mtl(void) __intel_pmu_pebs_data_source_cmt(data_source); } void __init intel_pmu_pebs_data_source_arl_h(void) { u64 *data_source; intel_pmu_pebs_data_source_lnl(); data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX].pebs_data_source; memcpy(data_source, pebs_data_source, sizeof(pebs_data_source)); __intel_pmu_pebs_data_source_cmt(data_source); } void __init intel_pmu_pebs_data_source_cmt(void) { __intel_pmu_pebs_data_source_cmt(pebs_data_source); Loading Loading @@ -388,6 +399,16 @@ u64 lnl_latency_data(struct perf_event *event, u64 status) return lnc_latency_data(event, status); } u64 arl_h_latency_data(struct perf_event *event, u64 status) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return cmt_latency_data(event, status); return lnl_latency_data(event, status); } static u64 load_latency_data(struct perf_event *event, u64 status) { union intel_x86_pebs_dse dse; Loading arch/x86/events/perf_event.h +26 −8 Original line number Diff line number Diff line Loading @@ -668,24 +668,38 @@ enum { #define PERF_PEBS_DATA_SOURCE_GRT_MAX 0x10 #define PERF_PEBS_DATA_SOURCE_GRT_MASK (PERF_PEBS_DATA_SOURCE_GRT_MAX - 1) /* * CPUID.1AH.EAX[31:0] uniquely identifies the microarchitecture * of the core. Bits 31-24 indicates its core type (Core or Atom) * and Bits [23:0] indicates the native model ID of the core. * Core type and native model ID are defined in below enumerations. */ enum hybrid_cpu_type { HYBRID_INTEL_NONE, HYBRID_INTEL_ATOM = 0x20, HYBRID_INTEL_CORE = 0x40, }; #define X86_HYBRID_PMU_ATOM_IDX 0 #define X86_HYBRID_PMU_CORE_IDX 1 #define X86_HYBRID_PMU_TINY_IDX 2 enum hybrid_pmu_type { not_hybrid, hybrid_small = BIT(0), hybrid_big = BIT(1), hybrid_big_small = hybrid_big | hybrid_small, /* only used for matching */ hybrid_small = BIT(X86_HYBRID_PMU_ATOM_IDX), hybrid_big = BIT(X86_HYBRID_PMU_CORE_IDX), hybrid_tiny = BIT(X86_HYBRID_PMU_TINY_IDX), /* The belows are only used for matching */ hybrid_big_small = hybrid_big | hybrid_small, hybrid_small_tiny = hybrid_small | hybrid_tiny, hybrid_big_small_tiny = hybrid_big | hybrid_small_tiny, }; #define X86_HYBRID_PMU_ATOM_IDX 0 #define X86_HYBRID_PMU_CORE_IDX 1 #define X86_HYBRID_NUM_PMUS 2 enum atom_native_id { cmt_native_id = 0x2, /* Crestmont */ skt_native_id = 0x3, /* Skymont */ }; struct x86_hybrid_pmu { struct pmu pmu; Loading Loading @@ -1578,6 +1592,8 @@ u64 cmt_latency_data(struct perf_event *event, u64 status); u64 lnl_latency_data(struct perf_event *event, u64 status); u64 arl_h_latency_data(struct perf_event *event, u64 status); extern struct event_constraint intel_core2_pebs_event_constraints[]; extern struct event_constraint intel_atom_pebs_event_constraints[]; Loading Loading @@ -1697,6 +1713,8 @@ void intel_pmu_pebs_data_source_grt(void); void intel_pmu_pebs_data_source_mtl(void); void intel_pmu_pebs_data_source_arl_h(void); void intel_pmu_pebs_data_source_cmt(void); void intel_pmu_pebs_data_source_lnl(void); Loading Loading
arch/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ config KPROBES_ON_FTRACE config UPROBES def_bool n depends on ARCH_SUPPORTS_UPROBES select TASKS_TRACE_RCU help Uprobes is the user-space counterpart to kprobes: they enable instrumentation applications (such as 'perf probe') Loading
arch/x86/events/amd/core.c +8 −2 Original line number Diff line number Diff line Loading @@ -943,11 +943,12 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u static int amd_pmu_v2_handle_irq(struct pt_regs *regs) { struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); static atomic64_t status_warned = ATOMIC64_INIT(0); u64 reserved, status, mask, new_bits, prev_bits; struct perf_sample_data data; struct hw_perf_event *hwc; struct perf_event *event; int handled = 0, idx; u64 reserved, status, mask; bool pmu_enabled; /* Loading Loading @@ -1012,7 +1013,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) * the corresponding PMCs are expected to be inactive according to the * active_mask */ WARN_ON(status > 0); if (status > 0) { prev_bits = atomic64_fetch_or(status, &status_warned); // A new bit was set for the very first time. new_bits = status & ~prev_bits; WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits); } /* Clear overflow and freeze bits */ amd_pmu_ack_global_status(~status); Loading
arch/x86/events/intel/core.c +121 −12 Original line number Diff line number Diff line Loading @@ -4599,6 +4599,28 @@ static inline bool erratum_hsw11(struct perf_event *event) X86_CONFIG(.event=0xc0, .umask=0x01); } static struct event_constraint * arl_h_get_event_constraints(struct cpu_hw_events *cpuc, int idx, struct perf_event *event) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return cmt_get_event_constraints(cpuc, idx, event); return mtl_get_event_constraints(cpuc, idx, event); } static int arl_h_hw_config(struct perf_event *event) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return intel_pmu_hw_config(event); return adl_hw_config(event); } /* * The HSW11 requires a period larger than 100 which is the same as the BDM11. * A minimum period of 128 is enforced as well for the INST_RETIRED.ALL. Loading Loading @@ -4924,18 +4946,27 @@ static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void) /* * This essentially just maps between the 'hybrid_cpu_type' * and 'hybrid_pmu_type' enums: * and 'hybrid_pmu_type' enums except for ARL-H processor * which needs to compare atom uarch native id since ARL-H * contains two different atom uarchs. */ for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) { enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type; u32 native_id; if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_ATOM) { if (x86_pmu.num_hybrid_pmus == 2 && pmu_type == hybrid_small) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big) native_id = get_this_hybrid_cpu_native_id(); if (native_id == skt_native_id && pmu_type == hybrid_small) return &x86_pmu.hybrid_pmu[i]; if (cpu_type == HYBRID_INTEL_ATOM && pmu_type == hybrid_small) if (native_id == cmt_native_id && pmu_type == hybrid_tiny) return &x86_pmu.hybrid_pmu[i]; } } return NULL; } Loading Loading @@ -5965,6 +5996,37 @@ static struct attribute *lnl_hybrid_events_attrs[] = { NULL }; /* The event string must be in PMU IDX order. */ EVENT_ATTR_STR_HYBRID(topdown-retiring, td_retiring_arl_h, "event=0xc2,umask=0x02;event=0x00,umask=0x80;event=0xc2,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-bad-spec, td_bad_spec_arl_h, "event=0x73,umask=0x0;event=0x00,umask=0x81;event=0x73,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-fe-bound, td_fe_bound_arl_h, "event=0x9c,umask=0x01;event=0x00,umask=0x82;event=0x71,umask=0x0", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(topdown-be-bound, td_be_bound_arl_h, "event=0xa4,umask=0x02;event=0x00,umask=0x83;event=0x74,umask=0x0", hybrid_big_small_tiny); static struct attribute *arl_h_hybrid_events_attrs[] = { EVENT_PTR(slots_adl), EVENT_PTR(td_retiring_arl_h), EVENT_PTR(td_bad_spec_arl_h), EVENT_PTR(td_fe_bound_arl_h), EVENT_PTR(td_be_bound_arl_h), EVENT_PTR(td_heavy_ops_adl), EVENT_PTR(td_br_mis_adl), EVENT_PTR(td_fetch_lat_adl), EVENT_PTR(td_mem_bound_adl), NULL, }; /* Must be in IDX order */ EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_adl, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3", hybrid_big_small); EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_adl, "event=0xd0,umask=0x6;event=0xcd,umask=0x2", hybrid_big_small); Loading @@ -5983,6 +6045,21 @@ static struct attribute *mtl_hybrid_mem_attrs[] = { NULL }; EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_arl_h, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3;event=0xd0,umask=0x5,ldlat=3", hybrid_big_small_tiny); EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_arl_h, "event=0xd0,umask=0x6;event=0xcd,umask=0x2;event=0xd0,umask=0x6", hybrid_big_small_tiny); static struct attribute *arl_h_hybrid_mem_attrs[] = { EVENT_PTR(mem_ld_arl_h), EVENT_PTR(mem_st_arl_h), NULL, }; EVENT_ATTR_STR_HYBRID(tx-start, tx_start_adl, "event=0xc9,umask=0x1", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-commit, tx_commit_adl, "event=0xc9,umask=0x2", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-abort, tx_abort_adl, "event=0xc9,umask=0x4", hybrid_big); Loading @@ -6006,8 +6083,8 @@ static struct attribute *adl_hybrid_tsx_attrs[] = { FORMAT_ATTR_HYBRID(in_tx, hybrid_big); FORMAT_ATTR_HYBRID(in_tx_cp, hybrid_big); FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small); FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small); FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small_tiny); FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small_tiny); FORMAT_ATTR_HYBRID(frontend, hybrid_big); #define ADL_HYBRID_RTM_FORMAT_ATTR \ Loading @@ -6030,7 +6107,7 @@ static struct attribute *adl_hybrid_extra_attr[] = { NULL }; FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small); FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small_tiny); static struct attribute *mtl_hybrid_extra_attr_rtm[] = { ADL_HYBRID_RTM_FORMAT_ATTR, Loading Loading @@ -6240,6 +6317,7 @@ static inline int intel_pmu_v6_addr_offset(int index, bool eventsel) static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = { { hybrid_small, "cpu_atom" }, { hybrid_big, "cpu_core" }, { hybrid_tiny, "cpu_lowpower" }, }; static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) Loading Loading @@ -6272,7 +6350,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) 0, x86_pmu_num_counters(&pmu->pmu), 0, 0); pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; if (pmu->pmu_type & hybrid_small) { if (pmu->pmu_type & hybrid_small_tiny) { pmu->intel_cap.perf_metrics = 0; pmu->intel_cap.pebs_output_pt_available = 1; pmu->mid_ack = true; Loading Loading @@ -7111,6 +7189,37 @@ __init int intel_pmu_init(void) name = "lunarlake_hybrid"; break; case INTEL_ARROWLAKE_H: intel_pmu_init_hybrid(hybrid_big_small_tiny); x86_pmu.pebs_latency_data = arl_h_latency_data; x86_pmu.get_event_constraints = arl_h_get_event_constraints; x86_pmu.hw_config = arl_h_hw_config; td_attr = arl_h_hybrid_events_attrs; mem_attr = arl_h_hybrid_mem_attrs; tsx_attr = adl_hybrid_tsx_attrs; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr; /* Initialize big core specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX]; intel_pmu_init_lnc(&pmu->pmu); /* Initialize Atom core specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX]; intel_pmu_init_skt(&pmu->pmu); /* Initialize Lower Power Atom specific PerfMon capabilities. */ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX]; intel_pmu_init_grt(&pmu->pmu); pmu->extra_regs = intel_cmt_extra_regs; intel_pmu_pebs_data_source_arl_h(); pr_cont("ArrowLake-H Hybrid events, "); name = "arrowlake_h_hybrid"; break; default: switch (x86_pmu.version) { case 1: Loading
arch/x86/events/intel/ds.c +21 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,17 @@ void __init intel_pmu_pebs_data_source_mtl(void) __intel_pmu_pebs_data_source_cmt(data_source); } void __init intel_pmu_pebs_data_source_arl_h(void) { u64 *data_source; intel_pmu_pebs_data_source_lnl(); data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX].pebs_data_source; memcpy(data_source, pebs_data_source, sizeof(pebs_data_source)); __intel_pmu_pebs_data_source_cmt(data_source); } void __init intel_pmu_pebs_data_source_cmt(void) { __intel_pmu_pebs_data_source_cmt(pebs_data_source); Loading Loading @@ -388,6 +399,16 @@ u64 lnl_latency_data(struct perf_event *event, u64 status) return lnc_latency_data(event, status); } u64 arl_h_latency_data(struct perf_event *event, u64 status) { struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); if (pmu->pmu_type == hybrid_tiny) return cmt_latency_data(event, status); return lnl_latency_data(event, status); } static u64 load_latency_data(struct perf_event *event, u64 status) { union intel_x86_pebs_dse dse; Loading
arch/x86/events/perf_event.h +26 −8 Original line number Diff line number Diff line Loading @@ -668,24 +668,38 @@ enum { #define PERF_PEBS_DATA_SOURCE_GRT_MAX 0x10 #define PERF_PEBS_DATA_SOURCE_GRT_MASK (PERF_PEBS_DATA_SOURCE_GRT_MAX - 1) /* * CPUID.1AH.EAX[31:0] uniquely identifies the microarchitecture * of the core. Bits 31-24 indicates its core type (Core or Atom) * and Bits [23:0] indicates the native model ID of the core. * Core type and native model ID are defined in below enumerations. */ enum hybrid_cpu_type { HYBRID_INTEL_NONE, HYBRID_INTEL_ATOM = 0x20, HYBRID_INTEL_CORE = 0x40, }; #define X86_HYBRID_PMU_ATOM_IDX 0 #define X86_HYBRID_PMU_CORE_IDX 1 #define X86_HYBRID_PMU_TINY_IDX 2 enum hybrid_pmu_type { not_hybrid, hybrid_small = BIT(0), hybrid_big = BIT(1), hybrid_big_small = hybrid_big | hybrid_small, /* only used for matching */ hybrid_small = BIT(X86_HYBRID_PMU_ATOM_IDX), hybrid_big = BIT(X86_HYBRID_PMU_CORE_IDX), hybrid_tiny = BIT(X86_HYBRID_PMU_TINY_IDX), /* The belows are only used for matching */ hybrid_big_small = hybrid_big | hybrid_small, hybrid_small_tiny = hybrid_small | hybrid_tiny, hybrid_big_small_tiny = hybrid_big | hybrid_small_tiny, }; #define X86_HYBRID_PMU_ATOM_IDX 0 #define X86_HYBRID_PMU_CORE_IDX 1 #define X86_HYBRID_NUM_PMUS 2 enum atom_native_id { cmt_native_id = 0x2, /* Crestmont */ skt_native_id = 0x3, /* Skymont */ }; struct x86_hybrid_pmu { struct pmu pmu; Loading Loading @@ -1578,6 +1592,8 @@ u64 cmt_latency_data(struct perf_event *event, u64 status); u64 lnl_latency_data(struct perf_event *event, u64 status); u64 arl_h_latency_data(struct perf_event *event, u64 status); extern struct event_constraint intel_core2_pebs_event_constraints[]; extern struct event_constraint intel_atom_pebs_event_constraints[]; Loading Loading @@ -1697,6 +1713,8 @@ void intel_pmu_pebs_data_source_grt(void); void intel_pmu_pebs_data_source_mtl(void); void intel_pmu_pebs_data_source_arl_h(void); void intel_pmu_pebs_data_source_cmt(void); void intel_pmu_pebs_data_source_lnl(void); Loading