selftests/powerpc/pmu: Add support for perf sampling tests

Add support functions for enabling perf sampling test in a new folder
"sampling_tests" under "selftests/powerpc/pmu". This includes support
functions for allocating and processing the mmap buffer. These functions
are added/defined in "sampling_tests/misc.*" files.

Also updates the corresponding Makefiles in "selftests/powerpc" and
"sampling_tests" folder.

Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
[mpe: Drop unneeded bits from the Makefile]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220127072012.662451-3-kjain@linux.ibm.com
This commit is contained in:
Athira Rajeev 2022-01-27 12:49:54 +05:30 committed by Michael Ellerman
parent f961e20f15
commit c315669e2f
4 changed files with 130 additions and 2 deletions

View file

@ -8,7 +8,7 @@ EXTRA_SOURCES := ../harness.c event.c lib.c ../utils.c
top_srcdir = ../../../../..
include ../../lib.mk
all: $(TEST_GEN_PROGS) ebb
all: $(TEST_GEN_PROGS) ebb sampling_tests
$(TEST_GEN_PROGS): $(EXTRA_SOURCES)
@ -26,25 +26,32 @@ DEFAULT_RUN_TESTS := $(RUN_TESTS)
override define RUN_TESTS
$(DEFAULT_RUN_TESTS)
TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests
TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests
endef
DEFAULT_EMIT_TESTS := $(EMIT_TESTS)
override define EMIT_TESTS
$(DEFAULT_EMIT_TESTS)
TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests
TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests
endef
DEFAULT_INSTALL_RULE := $(INSTALL_RULE)
override define INSTALL_RULE
$(DEFAULT_INSTALL_RULE)
TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install
TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install
endef
clean:
$(RM) $(TEST_GEN_PROGS) $(OUTPUT)/loop.o
TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean
TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean
ebb:
TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all
.PHONY: all run_tests clean ebb
sampling_tests:
TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all
.PHONY: all run_tests clean ebb sampling_tests

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS += -m64
top_srcdir = ../../../../../..
include ../../../lib.mk
$(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c misc.c misc.h

View file

@ -0,0 +1,105 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <ctype.h>
#include "misc.h"
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
/*
* Allocate mmap buffer of "mmap_pages" number of
* pages.
*/
void *event_sample_buf_mmap(int fd, int mmap_pages)
{
size_t page_size = sysconf(_SC_PAGESIZE);
size_t mmap_size;
void *buff;
if (mmap_pages <= 0)
return NULL;
if (fd <= 0)
return NULL;
mmap_size = page_size * (1 + mmap_pages);
buff = mmap(NULL, mmap_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buff == MAP_FAILED) {
perror("mmap() failed.");
return NULL;
}
return buff;
}
/*
* Post process the mmap buffer.
* - If sample_count != NULL then return count of total
* number of samples present in the mmap buffer.
* - If sample_count == NULL then return the address
* of first sample from the mmap buffer
*/
void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
{
size_t page_size = sysconf(_SC_PAGESIZE);
struct perf_event_header *header = sample_buff + page_size;
struct perf_event_mmap_page *metadata_page = sample_buff;
unsigned long data_head, data_tail;
/*
* PERF_RECORD_SAMPLE:
* struct {
* struct perf_event_header hdr;
* u64 data[];
* };
*/
data_head = metadata_page->data_head;
/* sync memory before reading sample */
mb();
data_tail = metadata_page->data_tail;
/* Check for sample_count */
if (sample_count)
*sample_count = 0;
while (1) {
/*
* Reads the mmap data buffer by moving
* the data_tail to know the last read data.
* data_head points to head in data buffer.
* refer "struct perf_event_mmap_page" in
* "include/uapi/linux/perf_event.h".
*/
if (data_head - data_tail < sizeof(header))
return NULL;
data_tail += sizeof(header);
if (header->type == PERF_RECORD_SAMPLE) {
*size = (header->size - sizeof(header));
if (!sample_count)
return sample_buff + page_size + data_tail;
data_tail += *size;
*sample_count += 1;
} else {
*size = (header->size - sizeof(header));
if ((metadata_page->data_tail + *size) > metadata_page->data_head)
data_tail = metadata_page->data_head;
else
data_tail += *size;
}
header = (struct perf_event_header *)((void *)header + header->size);
}
return NULL;
}

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include "../event.h"
void *event_sample_buf_mmap(int fd, int mmap_pages);
void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count);