-
Notifications
You must be signed in to change notification settings - Fork 122
[Deepin-Kernel-SIG] [linux 6.6-y] [Upstream] [Intel] Intel: Backport SRF LBR branch counter support to kernel v6.6 #828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2527,9 +2527,14 @@ static void intel_pmu_assign_event(struct perf_event *event, int idx) | |||||
| perf_report_aux_output_id(event, idx); | ||||||
| } | ||||||
|
|
||||||
| static __always_inline bool intel_pmu_needs_branch_stack(struct perf_event *event) | ||||||
| { | ||||||
| return event->hw.flags & PERF_X86_EVENT_NEEDS_BRANCH_STACK; | ||||||
| } | ||||||
|
|
||||||
| static void intel_pmu_del_event(struct perf_event *event) | ||||||
| { | ||||||
| if (needs_branch_stack(event)) | ||||||
| if (intel_pmu_needs_branch_stack(event)) | ||||||
| intel_pmu_lbr_del(event); | ||||||
| if (event->attr.precise_ip) | ||||||
| intel_pmu_pebs_del(event); | ||||||
|
|
@@ -2792,6 +2797,7 @@ static void intel_pmu_enable_fixed(struct perf_event *event) | |||||
|
|
||||||
| static void intel_pmu_enable_event(struct perf_event *event) | ||||||
| { | ||||||
| u64 enable_mask = ARCH_PERFMON_EVENTSEL_ENABLE; | ||||||
| struct hw_perf_event *hwc = &event->hw; | ||||||
| int idx = hwc->idx; | ||||||
|
|
||||||
|
|
@@ -2800,8 +2806,10 @@ static void intel_pmu_enable_event(struct perf_event *event) | |||||
|
|
||||||
| switch (idx) { | ||||||
| case 0 ... INTEL_PMC_IDX_FIXED - 1: | ||||||
| if (branch_sample_counters(event)) | ||||||
| enable_mask |= ARCH_PERFMON_EVENTSEL_BR_CNTR; | ||||||
| intel_set_masks(event, idx); | ||||||
| __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE); | ||||||
| __x86_pmu_enable_event(hwc, enable_mask); | ||||||
| break; | ||||||
| case INTEL_PMC_IDX_FIXED ... INTEL_PMC_IDX_FIXED_BTS - 1: | ||||||
| case INTEL_PMC_IDX_METRIC_BASE ... INTEL_PMC_IDX_METRIC_END: | ||||||
|
|
@@ -2825,7 +2833,7 @@ static void intel_pmu_add_event(struct perf_event *event) | |||||
| { | ||||||
| if (event->attr.precise_ip) | ||||||
| intel_pmu_pebs_add(event); | ||||||
| if (needs_branch_stack(event)) | ||||||
| if (intel_pmu_needs_branch_stack(event)) | ||||||
| intel_pmu_lbr_add(event); | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -3052,7 +3060,7 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status) | |||||
| perf_sample_data_init(&data, 0, event->hw.last_period); | ||||||
|
|
||||||
| if (has_branch_stack(event)) | ||||||
| perf_sample_save_brstack(&data, event, &cpuc->lbr_stack); | ||||||
| intel_pmu_lbr_save_brstack(&data, cpuc, event); | ||||||
|
|
||||||
| if (perf_event_overflow(event, &data, regs)) | ||||||
| x86_pmu_stop(event, 0); | ||||||
|
|
@@ -3617,6 +3625,13 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx, | |||||
| if (cpuc->excl_cntrs) | ||||||
| return intel_get_excl_constraints(cpuc, event, idx, c2); | ||||||
|
|
||||||
| /* Not all counters support the branch counter feature. */ | ||||||
| if (branch_sample_counters(event)) { | ||||||
| c2 = dyn_constraint(cpuc, c2, idx); | ||||||
| c2->idxmsk64 &= x86_pmu.lbr_counters; | ||||||
| c2->weight = hweight64(c2->idxmsk64); | ||||||
| } | ||||||
|
|
||||||
| return c2; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -3987,7 +4002,62 @@ static int intel_pmu_hw_config(struct perf_event *event) | |||||
| x86_pmu.pebs_aliases(event); | ||||||
| } | ||||||
|
|
||||||
| if (needs_branch_stack(event)) { | ||||||
| if (needs_branch_stack(event) && is_sampling_event(event)) | ||||||
|
||||||
| if (needs_branch_stack(event) && is_sampling_event(event)) | |
| if (intel_pmu_needs_branch_stack(event) && is_sampling_event(event)) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -676,6 +676,25 @@ void intel_pmu_lbr_del(struct perf_event *event) | |||||
| WARN_ON_ONCE(cpuc->lbr_users < 0); | ||||||
| WARN_ON_ONCE(cpuc->lbr_pebs_users < 0); | ||||||
| perf_sched_cb_dec(event->pmu); | ||||||
|
|
||||||
| /* | ||||||
| * The logged occurrences information is only valid for the | ||||||
| * current LBR group. If another LBR group is scheduled in | ||||||
| * later, the information from the stale LBRs will be wrongly | ||||||
| * interpreted. Reset the LBRs here. | ||||||
| * | ||||||
| * Only clear once for a branch counter group with the leader | ||||||
| * event. Because | ||||||
| * - Cannot simply reset the LBRs with the !cpuc->lbr_users. | ||||||
| * Because it's possible that the last LBR user is not in a | ||||||
| * branch counter group, e.g., a branch_counters group + | ||||||
| * several normal LBR events. | ||||||
| * - The LBR reset can be done with any one of the events in a | ||||||
| * branch counter group, since they are always scheduled together. | ||||||
| * It's easy to force the leader event an LBR event. | ||||||
| */ | ||||||
| if (is_branch_counters_group(event) && event == event->group_leader) | ||||||
| intel_pmu_lbr_reset(); | ||||||
| } | ||||||
|
|
||||||
| static inline bool vlbr_exclude_host(void) | ||||||
|
|
@@ -866,6 +885,8 @@ static __always_inline u16 get_lbr_cycles(u64 info) | |||||
| return cycles; | ||||||
| } | ||||||
|
|
||||||
| static_assert((64 - PERF_BRANCH_ENTRY_INFO_BITS_MAX) > LBR_INFO_BR_CNTR_NUM * LBR_INFO_BR_CNTR_BITS); | ||||||
|
|
||||||
| static void intel_pmu_store_lbr(struct cpu_hw_events *cpuc, | ||||||
| struct lbr_entry *entries) | ||||||
| { | ||||||
|
|
@@ -898,11 +919,67 @@ static void intel_pmu_store_lbr(struct cpu_hw_events *cpuc, | |||||
| e->abort = !!(info & LBR_INFO_ABORT); | ||||||
| e->cycles = get_lbr_cycles(info); | ||||||
| e->type = get_lbr_br_type(info); | ||||||
|
|
||||||
| /* | ||||||
| * Leverage the reserved field of cpuc->lbr_entries[i] to | ||||||
| * temporarily store the branch counters information. | ||||||
| * The later code will decide what content can be disclosed | ||||||
| * to the perf tool. Pleae see intel_pmu_lbr_counters_reorder(). | ||||||
|
||||||
| * to the perf tool. Pleae see intel_pmu_lbr_counters_reorder(). | |
| * to the perf tool. Please see intel_pmu_lbr_counters_reorder(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Use explicit boolean conversion in intel_pmu_needs_branch_stack
Use
!!(event->hw.flags & PERF_X86_EVENT_NEEDS_BRANCH_STACK)to ensure the function returns a true boolean value.