Skip to content

Commit 64b609d

Browse files
committed
Merge tag 'perf-urgent-2020-11-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Thomas Gleixner: "A set of fixes for perf: - A set of commits which reduce the stack usage of various perf event handling functions which allocated large data structs on stack causing stack overflows in the worst case - Use the proper mechanism for detecting soft interrupts in the recursion protection - Make the resursion protection simpler and more robust - Simplify the scheduling of event groups to make the code more robust and prepare for fixing the issues vs. scheduling of exclusive event groups - Prevent event multiplexing and rotation for exclusive event groups - Correct the perf event attribute exclusive semantics to take pinned events, e.g. the PMU watchdog, into account - Make the anythread filtering conditional for Intel's generic PMU counters as it is not longer guaranteed to be supported on newer CPUs. Check the corresponding CPUID leaf to make sure - Fixup a duplicate initialization in an array which was probably caused by the usual 'copy & paste - forgot to edit' mishap" * tag 'perf-urgent-2020-11-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel/uncore: Fix Add BW copypasta perf/x86/intel: Make anythread filter support conditional perf: Tweak perf_event_attr::exclusive semantics perf: Fix event multiplexing for exclusive groups perf: Simplify group_sched_in() perf: Simplify group_sched_out() perf/x86: Make dummy_iregs static perf/arch: Remove perf_sample_data::regs_user_copy perf: Optimize get_recursion_context() perf: Fix get_recursion_context() perf/x86: Reduce stack usage for x86_pmu::drain_pebs() perf: Reduce stack usage of perf_output_begin()
2 parents d0a37fd + 1a8cfa2 commit 64b609d

File tree

20 files changed

+116
-111
lines changed

20 files changed

+116
-111
lines changed

arch/arm/kernel/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
3232
}
3333

3434
void perf_get_regs_user(struct perf_regs *regs_user,
35-
struct pt_regs *regs,
36-
struct pt_regs *regs_user_copy)
35+
struct pt_regs *regs)
3736
{
3837
regs_user->regs = task_pt_regs(current);
3938
regs_user->abi = perf_reg_abi(current);

arch/arm64/kernel/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ u64 perf_reg_abi(struct task_struct *task)
7373
}
7474

7575
void perf_get_regs_user(struct perf_regs *regs_user,
76-
struct pt_regs *regs,
77-
struct pt_regs *regs_user_copy)
76+
struct pt_regs *regs)
7877
{
7978
regs_user->regs = task_pt_regs(current);
8079
regs_user->abi = perf_reg_abi(current);

arch/csky/kernel/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
3232
}
3333

3434
void perf_get_regs_user(struct perf_regs *regs_user,
35-
struct pt_regs *regs,
36-
struct pt_regs *regs_user_copy)
35+
struct pt_regs *regs)
3736
{
3837
regs_user->regs = task_pt_regs(current);
3938
regs_user->abi = perf_reg_abi(current);

arch/powerpc/perf/imc-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ static void dump_trace_imc_data(struct perf_event *event)
13361336
/* If this is a valid record, create the sample */
13371337
struct perf_output_handle handle;
13381338

1339-
if (perf_output_begin(&handle, event, header.size))
1339+
if (perf_output_begin(&handle, &data, event, header.size))
13401340
return;
13411341

13421342
perf_output_sample(&handle, &header, &data, event);

arch/powerpc/perf/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ u64 perf_reg_abi(struct task_struct *task)
144144
}
145145

146146
void perf_get_regs_user(struct perf_regs *regs_user,
147-
struct pt_regs *regs,
148-
struct pt_regs *regs_user_copy)
147+
struct pt_regs *regs)
149148
{
150149
regs_user->regs = task_pt_regs(current);
151150
regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :

arch/riscv/kernel/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ u64 perf_reg_abi(struct task_struct *task)
3636
}
3737

3838
void perf_get_regs_user(struct perf_regs *regs_user,
39-
struct pt_regs *regs,
40-
struct pt_regs *regs_user_copy)
39+
struct pt_regs *regs)
4140
{
4241
regs_user->regs = task_pt_regs(current);
4342
regs_user->abi = perf_reg_abi(current);

arch/s390/kernel/perf_cpum_sf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ static void cpumsf_output_event_pid(struct perf_event *event,
672672
rcu_read_lock();
673673

674674
perf_prepare_sample(&header, data, event, regs);
675-
if (perf_output_begin(&handle, event, header.size))
675+
if (perf_output_begin(&handle, data, event, header.size))
676676
goto out;
677677

678678
/* Update the process ID (see also kernel/events/core.c) */

arch/s390/kernel/perf_regs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ u64 perf_reg_abi(struct task_struct *task)
5353
}
5454

5555
void perf_get_regs_user(struct perf_regs *regs_user,
56-
struct pt_regs *regs,
57-
struct pt_regs *regs_user_copy)
56+
struct pt_regs *regs)
5857
{
5958
/*
6059
* Use the regs from the first interruption and let

arch/x86/events/intel/core.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2630,7 +2630,7 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
26302630
u64 pebs_enabled = cpuc->pebs_enabled;
26312631

26322632
handled++;
2633-
x86_pmu.drain_pebs(regs);
2633+
x86_pmu.drain_pebs(regs, &data);
26342634
status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
26352635

26362636
/*
@@ -4987,6 +4987,12 @@ __init int intel_pmu_init(void)
49874987

49884988
x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
49894989

4990+
if (version >= 5) {
4991+
x86_pmu.intel_cap.anythread_deprecated = edx.split.anythread_deprecated;
4992+
if (x86_pmu.intel_cap.anythread_deprecated)
4993+
pr_cont(" AnyThread deprecated, ");
4994+
}
4995+
49904996
/*
49914997
* Install the hw-cache-events table:
49924998
*/
@@ -5512,6 +5518,10 @@ __init int intel_pmu_init(void)
55125518
x86_pmu.intel_ctrl |=
55135519
((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
55145520

5521+
/* AnyThread may be deprecated on arch perfmon v5 or later */
5522+
if (x86_pmu.intel_cap.anythread_deprecated)
5523+
x86_pmu.format_attrs = intel_arch_formats_attr;
5524+
55155525
if (x86_pmu.event_constraints) {
55165526
/*
55175527
* event on fixed counter2 (REF_CYCLES) only works on this

arch/x86/events/intel/ds.c

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,8 @@ int intel_pmu_drain_bts_buffer(void)
642642
rcu_read_lock();
643643
perf_prepare_sample(&header, &data, event, &regs);
644644

645-
if (perf_output_begin(&handle, event, header.size *
646-
(top - base - skip)))
645+
if (perf_output_begin(&handle, &data, event,
646+
header.size * (top - base - skip)))
647647
goto unlock;
648648

649649
for (at = base; at < top; at++) {
@@ -670,7 +670,9 @@ int intel_pmu_drain_bts_buffer(void)
670670

671671
static inline void intel_pmu_drain_pebs_buffer(void)
672672
{
673-
x86_pmu.drain_pebs(NULL);
673+
struct perf_sample_data data;
674+
675+
x86_pmu.drain_pebs(NULL, &data);
674676
}
675677

676678
/*
@@ -1719,23 +1721,24 @@ intel_pmu_save_and_restart_reload(struct perf_event *event, int count)
17191721
return 0;
17201722
}
17211723

1722-
static void __intel_pmu_pebs_event(struct perf_event *event,
1723-
struct pt_regs *iregs,
1724-
void *base, void *top,
1725-
int bit, int count,
1726-
void (*setup_sample)(struct perf_event *,
1727-
struct pt_regs *,
1728-
void *,
1729-
struct perf_sample_data *,
1730-
struct pt_regs *))
1724+
static __always_inline void
1725+
__intel_pmu_pebs_event(struct perf_event *event,
1726+
struct pt_regs *iregs,
1727+
struct perf_sample_data *data,
1728+
void *base, void *top,
1729+
int bit, int count,
1730+
void (*setup_sample)(struct perf_event *,
1731+
struct pt_regs *,
1732+
void *,
1733+
struct perf_sample_data *,
1734+
struct pt_regs *))
17311735
{
17321736
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
17331737
struct hw_perf_event *hwc = &event->hw;
1734-
struct perf_sample_data data;
17351738
struct x86_perf_regs perf_regs;
17361739
struct pt_regs *regs = &perf_regs.regs;
17371740
void *at = get_next_pebs_record_by_bit(base, top, bit);
1738-
struct pt_regs dummy_iregs;
1741+
static struct pt_regs dummy_iregs;
17391742

17401743
if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
17411744
/*
@@ -1752,33 +1755,33 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
17521755
iregs = &dummy_iregs;
17531756

17541757
while (count > 1) {
1755-
setup_sample(event, iregs, at, &data, regs);
1756-
perf_event_output(event, &data, regs);
1758+
setup_sample(event, iregs, at, data, regs);
1759+
perf_event_output(event, data, regs);
17571760
at += cpuc->pebs_record_size;
17581761
at = get_next_pebs_record_by_bit(at, top, bit);
17591762
count--;
17601763
}
17611764

1762-
setup_sample(event, iregs, at, &data, regs);
1765+
setup_sample(event, iregs, at, data, regs);
17631766
if (iregs == &dummy_iregs) {
17641767
/*
17651768
* The PEBS records may be drained in the non-overflow context,
17661769
* e.g., large PEBS + context switch. Perf should treat the
17671770
* last record the same as other PEBS records, and doesn't
17681771
* invoke the generic overflow handler.
17691772
*/
1770-
perf_event_output(event, &data, regs);
1773+
perf_event_output(event, data, regs);
17711774
} else {
17721775
/*
17731776
* All but the last records are processed.
17741777
* The last one is left to be able to call the overflow handler.
17751778
*/
1776-
if (perf_event_overflow(event, &data, regs))
1779+
if (perf_event_overflow(event, data, regs))
17771780
x86_pmu_stop(event, 0);
17781781
}
17791782
}
17801783

1781-
static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
1784+
static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_data *data)
17821785
{
17831786
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
17841787
struct debug_store *ds = cpuc->ds;
@@ -1812,7 +1815,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
18121815
return;
18131816
}
18141817

1815-
__intel_pmu_pebs_event(event, iregs, at, top, 0, n,
1818+
__intel_pmu_pebs_event(event, iregs, data, at, top, 0, n,
18161819
setup_pebs_fixed_sample_data);
18171820
}
18181821

@@ -1835,7 +1838,7 @@ static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int
18351838
}
18361839
}
18371840

1838-
static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
1841+
static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_data *data)
18391842
{
18401843
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
18411844
struct debug_store *ds = cpuc->ds;
@@ -1942,14 +1945,14 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
19421945
}
19431946

19441947
if (counts[bit]) {
1945-
__intel_pmu_pebs_event(event, iregs, base,
1948+
__intel_pmu_pebs_event(event, iregs, data, base,
19461949
top, bit, counts[bit],
19471950
setup_pebs_fixed_sample_data);
19481951
}
19491952
}
19501953
}
19511954

1952-
static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
1955+
static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data)
19531956
{
19541957
short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
19551958
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1997,7 +2000,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
19972000
if (WARN_ON_ONCE(!event->attr.precise_ip))
19982001
continue;
19992002

2000-
__intel_pmu_pebs_event(event, iregs, base,
2003+
__intel_pmu_pebs_event(event, iregs, data, base,
20012004
top, bit, counts[bit],
20022005
setup_pebs_adaptive_sample_data);
20032006
}

0 commit comments

Comments
 (0)