Skip to content

Commit 18049c8

Browse files
yabincIngo Molnar
authored andcommitted
perf/aux: Allocate non-contiguous AUX pages by default
perf always allocates contiguous AUX pages based on aux_watermark. However, this contiguous allocation doesn't benefit all PMUs. For instance, ARM SPE and TRBE operate with virtual pages, and Coresight ETR allocates a separate buffer. For these PMUs, allocating contiguous AUX pages unnecessarily exacerbates memory fragmentation. This fragmentation can prevent their use on long-running devices. This patch modifies the perf driver to be memory-friendly by default, by allocating non-contiguous AUX pages. For PMUs requiring contiguous pages (Intel BTS and some Intel PT), the existing PERF_PMU_CAP_AUX_NO_SG capability can be used. For PMUs that don't require but can benefit from contiguous pages (some Intel PT), a new capability, PERF_PMU_CAP_AUX_PREFER_LARGE, is added to maintain their existing behavior. Signed-off-by: Yabin Cui <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: James Clark <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 881097c commit 18049c8

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

arch/x86/events/intel/pt.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,8 @@ static __init int pt_init(void)
18631863

18641864
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
18651865
pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG;
1866+
else
1867+
pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_PREFER_LARGE;
18661868

18671869
pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE |
18681870
PERF_PMU_CAP_ITRACE |

include/linux/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ struct perf_event_pmu_context;
303303
#define PERF_PMU_CAP_AUX_OUTPUT 0x0080
304304
#define PERF_PMU_CAP_EXTENDED_HW_TYPE 0x0100
305305
#define PERF_PMU_CAP_AUX_PAUSE 0x0200
306+
#define PERF_PMU_CAP_AUX_PREFER_LARGE 0x0400
306307

307308
/**
308309
* pmu::scope

kernel/events/ring_buffer.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,15 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
679679
{
680680
bool overwrite = !(flags & RING_BUFFER_WRITABLE);
681681
int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu);
682-
int ret = -ENOMEM, max_order;
682+
bool use_contiguous_pages = event->pmu->capabilities & (
683+
PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_PREFER_LARGE);
684+
/*
685+
* Initialize max_order to 0 for page allocation. This allocates single
686+
* pages to minimize memory fragmentation. This is overridden if the
687+
* PMU needs or prefers contiguous pages (use_contiguous_pages = true).
688+
*/
689+
int max_order = 0;
690+
int ret = -ENOMEM;
683691

684692
if (!has_aux(event))
685693
return -EOPNOTSUPP;
@@ -689,25 +697,28 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
689697

690698
if (!overwrite) {
691699
/*
692-
* Watermark defaults to half the buffer, and so does the
693-
* max_order, to aid PMU drivers in double buffering.
700+
* Watermark defaults to half the buffer, to aid PMU drivers
701+
* in double buffering.
694702
*/
695703
if (!watermark)
696704
watermark = min_t(unsigned long,
697705
U32_MAX,
698706
(unsigned long)nr_pages << (PAGE_SHIFT - 1));
699707

700708
/*
701-
* Use aux_watermark as the basis for chunking to
702-
* help PMU drivers honor the watermark.
709+
* If using contiguous pages, use aux_watermark as the basis
710+
* for chunking to help PMU drivers honor the watermark.
703711
*/
704-
max_order = get_order(watermark);
712+
if (use_contiguous_pages)
713+
max_order = get_order(watermark);
705714
} else {
706715
/*
707-
* We need to start with the max_order that fits in nr_pages,
708-
* not the other way around, hence ilog2() and not get_order.
716+
* If using contiguous pages, we need to start with the
717+
* max_order that fits in nr_pages, not the other way around,
718+
* hence ilog2() and not get_order.
709719
*/
710-
max_order = ilog2(nr_pages);
720+
if (use_contiguous_pages)
721+
max_order = ilog2(nr_pages);
711722
watermark = 0;
712723
}
713724

0 commit comments

Comments
 (0)