Skip to content

Commit 5d75aed

Browse files
Athira Rajeevmaddy-kerneldev
authored andcommitted
powerpc/perf/vpa-dtl: Add support to setup and free aux buffer for capturing DTL data
vpa dtl pmu has one hrtimer added per vpa-dtl pmu thread. When the hrtimer expires, in the timer handler, code is added to save the DTL data to perf event record. DTL (Dispatch Trace Log) contains information about dispatch/preempt, enqueue time etc. We directly copy the DTL buffer data as part of auxiliary buffer and it will be postprocessed later. To enable the support for aux buffer, add the PMU callbacks for setup_aux and free_aux. In setup_aux, set up pmu-private data structures for an AUX area. rb_alloc_aux uses "alloc_pages_node" and returns pointer to each page address. Map these pages to contiguous space using vmap and use that as base address. The aux private data structure ie, "struct vpa_pmu_buf" mainly saves: 1. buf->base: aux buffer base address 2. buf->head: offset from base address where data will be written to. 3. buf->size: Size of allocated memory free_aux will free pmu-private AUX data structures. Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com> Tested-by: Tejas Manhas <tejas05@linux.ibm.com> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20250915102947.26681-5-atrajeev@linux.ibm.com
1 parent 6f2c656 commit 5d75aed

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

arch/powerpc/perf/vpa-dtl.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <asm/dtl.h>
1212
#include <linux/perf_event.h>
1313
#include <asm/plpar_wrappers.h>
14+
#include <linux/vmalloc.h>
1415

1516
#define EVENT(_name, _code) enum{_name = _code}
1617

@@ -74,6 +75,19 @@ struct vpa_dtl {
7475
u64 last_idx;
7576
};
7677

78+
struct vpa_pmu_ctx {
79+
struct perf_output_handle handle;
80+
};
81+
82+
struct vpa_pmu_buf {
83+
int nr_pages;
84+
bool snapshot;
85+
u64 *base;
86+
u64 size;
87+
u64 head;
88+
};
89+
90+
static DEFINE_PER_CPU(struct vpa_pmu_ctx, vpa_pmu_ctx);
7791
static DEFINE_PER_CPU(struct vpa_dtl, vpa_dtl_cpu);
7892

7993
/* variable to capture reference count for the active dtl threads */
@@ -302,6 +316,67 @@ static void vpa_dtl_event_read(struct perf_event *event)
302316
{
303317
}
304318

319+
/*
320+
* Set up pmu-private data structures for an AUX area
321+
* **pages contains the aux buffer allocated for this event
322+
* for the corresponding cpu. rb_alloc_aux uses "alloc_pages_node"
323+
* and returns pointer to each page address. Map these pages to
324+
* contiguous space using vmap and use that as base address.
325+
*
326+
* The aux private data structure ie, "struct vpa_pmu_buf" mainly
327+
* saves
328+
* - buf->base: aux buffer base address
329+
* - buf->head: offset from base address where data will be written to.
330+
* - buf->size: Size of allocated memory
331+
*/
332+
static void *vpa_dtl_setup_aux(struct perf_event *event, void **pages,
333+
int nr_pages, bool snapshot)
334+
{
335+
int i, cpu = event->cpu;
336+
struct vpa_pmu_buf *buf __free(kfree) = NULL;
337+
struct page **pglist __free(kfree) = NULL;
338+
339+
/* We need at least one page for this to work. */
340+
if (!nr_pages)
341+
return NULL;
342+
343+
if (cpu == -1)
344+
cpu = raw_smp_processor_id();
345+
346+
buf = kzalloc_node(sizeof(*buf), GFP_KERNEL, cpu_to_node(cpu));
347+
if (!buf)
348+
return NULL;
349+
350+
pglist = kcalloc(nr_pages, sizeof(*pglist), GFP_KERNEL);
351+
if (!pglist)
352+
return NULL;
353+
354+
for (i = 0; i < nr_pages; ++i)
355+
pglist[i] = virt_to_page(pages[i]);
356+
357+
buf->base = vmap(pglist, nr_pages, VM_MAP, PAGE_KERNEL);
358+
if (!buf->base)
359+
return NULL;
360+
361+
buf->nr_pages = nr_pages;
362+
buf->snapshot = false;
363+
364+
buf->size = nr_pages << PAGE_SHIFT;
365+
buf->head = 0;
366+
return no_free_ptr(buf);
367+
}
368+
369+
/*
370+
* free pmu-private AUX data structures
371+
*/
372+
static void vpa_dtl_free_aux(void *aux)
373+
{
374+
struct vpa_pmu_buf *buf = aux;
375+
376+
vunmap(buf->base);
377+
kfree(buf);
378+
}
379+
305380
static struct pmu vpa_dtl_pmu = {
306381
.task_ctx_nr = perf_invalid_context,
307382

@@ -311,6 +386,8 @@ static struct pmu vpa_dtl_pmu = {
311386
.add = vpa_dtl_event_add,
312387
.del = vpa_dtl_event_del,
313388
.read = vpa_dtl_event_read,
389+
.setup_aux = vpa_dtl_setup_aux,
390+
.free_aux = vpa_dtl_free_aux,
314391
.capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_EXCLUSIVE,
315392
};
316393

0 commit comments

Comments
 (0)