Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Athira Rajeev and committed by
Michael Ellerman
c315669e f961e20f

+130 -2
+9 -2
tools/testing/selftests/powerpc/pmu/Makefile
··· 8 8 top_srcdir = ../../../../.. 9 9 include ../../lib.mk 10 10 11 - all: $(TEST_GEN_PROGS) ebb 11 + all: $(TEST_GEN_PROGS) ebb sampling_tests 12 12 13 13 $(TEST_GEN_PROGS): $(EXTRA_SOURCES) 14 14 ··· 26 26 override define RUN_TESTS 27 27 $(DEFAULT_RUN_TESTS) 28 28 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests 29 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests 29 30 endef 30 31 31 32 DEFAULT_EMIT_TESTS := $(EMIT_TESTS) 32 33 override define EMIT_TESTS 33 34 $(DEFAULT_EMIT_TESTS) 34 35 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests 36 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests 35 37 endef 36 38 37 39 DEFAULT_INSTALL_RULE := $(INSTALL_RULE) 38 40 override define INSTALL_RULE 39 41 $(DEFAULT_INSTALL_RULE) 40 42 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install 43 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install 41 44 endef 42 45 43 46 clean: 44 47 $(RM) $(TEST_GEN_PROGS) $(OUTPUT)/loop.o 45 48 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean 49 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean 46 50 47 51 ebb: 48 52 TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all 49 53 50 - .PHONY: all run_tests clean ebb 54 + sampling_tests: 55 + TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all 56 + 57 + .PHONY: all run_tests clean ebb sampling_tests
+7
tools/testing/selftests/powerpc/pmu/sampling_tests/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + CFLAGS += -m64 3 + 4 + top_srcdir = ../../../../../.. 5 + include ../../../lib.mk 6 + 7 + $(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c misc.c misc.h
+105
tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <unistd.h> 7 + #include <sys/syscall.h> 8 + #include <string.h> 9 + #include <stdio.h> 10 + #include <sys/ioctl.h> 11 + #include <sys/mman.h> 12 + #include <stdlib.h> 13 + #include <ctype.h> 14 + 15 + #include "misc.h" 16 + 17 + #define PAGE_SIZE sysconf(_SC_PAGESIZE) 18 + 19 + /* 20 + * Allocate mmap buffer of "mmap_pages" number of 21 + * pages. 22 + */ 23 + void *event_sample_buf_mmap(int fd, int mmap_pages) 24 + { 25 + size_t page_size = sysconf(_SC_PAGESIZE); 26 + size_t mmap_size; 27 + void *buff; 28 + 29 + if (mmap_pages <= 0) 30 + return NULL; 31 + 32 + if (fd <= 0) 33 + return NULL; 34 + 35 + mmap_size = page_size * (1 + mmap_pages); 36 + buff = mmap(NULL, mmap_size, 37 + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 38 + 39 + if (buff == MAP_FAILED) { 40 + perror("mmap() failed."); 41 + return NULL; 42 + } 43 + return buff; 44 + } 45 + 46 + /* 47 + * Post process the mmap buffer. 48 + * - If sample_count != NULL then return count of total 49 + * number of samples present in the mmap buffer. 50 + * - If sample_count == NULL then return the address 51 + * of first sample from the mmap buffer 52 + */ 53 + void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count) 54 + { 55 + size_t page_size = sysconf(_SC_PAGESIZE); 56 + struct perf_event_header *header = sample_buff + page_size; 57 + struct perf_event_mmap_page *metadata_page = sample_buff; 58 + unsigned long data_head, data_tail; 59 + 60 + /* 61 + * PERF_RECORD_SAMPLE: 62 + * struct { 63 + * struct perf_event_header hdr; 64 + * u64 data[]; 65 + * }; 66 + */ 67 + 68 + data_head = metadata_page->data_head; 69 + /* sync memory before reading sample */ 70 + mb(); 71 + data_tail = metadata_page->data_tail; 72 + 73 + /* Check for sample_count */ 74 + if (sample_count) 75 + *sample_count = 0; 76 + 77 + while (1) { 78 + /* 79 + * Reads the mmap data buffer by moving 80 + * the data_tail to know the last read data. 81 + * data_head points to head in data buffer. 82 + * refer "struct perf_event_mmap_page" in 83 + * "include/uapi/linux/perf_event.h". 84 + */ 85 + if (data_head - data_tail < sizeof(header)) 86 + return NULL; 87 + 88 + data_tail += sizeof(header); 89 + if (header->type == PERF_RECORD_SAMPLE) { 90 + *size = (header->size - sizeof(header)); 91 + if (!sample_count) 92 + return sample_buff + page_size + data_tail; 93 + data_tail += *size; 94 + *sample_count += 1; 95 + } else { 96 + *size = (header->size - sizeof(header)); 97 + if ((metadata_page->data_tail + *size) > metadata_page->data_head) 98 + data_tail = metadata_page->data_head; 99 + else 100 + data_tail += *size; 101 + } 102 + header = (struct perf_event_header *)((void *)header + header->size); 103 + } 104 + return NULL; 105 + }
+9
tools/testing/selftests/powerpc/pmu/sampling_tests/misc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include "../event.h" 7 + 8 + void *event_sample_buf_mmap(int fd, int mmap_pages); 9 + void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count);