perf tools: Introduce an abstraction for AUX Area and Instruction Tracing
Adrian Hunter
reviewerv7 cover perf tools: Introduce an abstraction for AUX Area and Instruction Tracing
Hi
Here is V7 of some more preparatory patches for Intel PT that introduce an abstraction for using the AUX area and Instruction tracing.
The master branch of the tree:
git://git.infradead.org/users/ahunter/linux-perf.git
contains these patches and working Intel PT and Intel BTS. Intel BTS can be used on most recent Intel CPUs. Intel PT is available on Broadwell.
Examples:
Trace 'ls' with Intel BTS userspace only
perf record --per-thread -e intel_bts//u ls perf report
perf script
Trace 'ls' with Intel BTS kernel and userspace
~/libexec/perf-core/perf-with-kcore record bts-ls --per-thread -e intel_bts// -- ls ~/libexec/perf-core/perf-with-kcore report bts-ls ~/libexec/perf-core/perf-with-kcore script bts-ls
Trace 'ls' with Intel PT userspace only
perf record -e intel_pt//u ls
perf report
perf script
Trace 'ls' with Intel PT kernel and userspace
~/libexec/perf-core/perf-with-kcore record pt-ls -e intel_pt// -- ls ~/libexec/perf-core/perf-with-kcore report pt-ls ~/libexec/perf-core/perf-with-kcore script pt-ls
Changes in V7:
Changes requested by Jiri:
perf evlist: Add initial support for mmapping an AUX area buffer
WARN_ONCE if mm->base is not NULL when mmapping
perf tools: Add support for AUX area recording
Use perf_can_sample_identifier() consistently Drop unused function perf_event__synthesize_auxtrace()
perf record: Add basic AUX area tracing support
Check length before calling record__write a second time
perf record: Extend -m option for AUX area tracing mmap pages
Update change log with -m option change syntax
Changes in V6:
Renamed itrace to auxtrace to better reflect the use of the AUX area. In some cases itrace was retained where it seemed to relate exclusively to Instruction Tracing.
Print warnings for separate auxtrace error types
Re-based on Arnaldo's perf/core branch:
107eb964d8c04417e8bce9e9ec2ed61d9261aec6
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Changes in V5:
perf tools: Add a user event for Instruction Tracing errors
Print error count from stats->nr_events
perf session: Add hooks to allow transparent decoding of Instruction Tracing data
Don't count Instruction Tracing errors (using stats->nr_events instead)
perf itrace: Add helpers for Instruction Tracing errors
Don't count Instruction Tracing errors (using stats->nr_events instead)
perf itrace: Add option to synthesize events for transactions
New patch
perf script: Add field option 'flags' to print sample flags
New patch
Re-based on tip perf/core branch:
94ac003b665fc04f13a7ab3b2be896b9b9503451
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Changes in V4:
perf tools: Add build option NO_ITRACE to exclude Instruction Tracing
New patch
Re-based on Arnaldo's perf/core branch:
3dd417d4010c8e141b0f32121cdc8d82aa4a9c6a perf tools: Remove some unused functions from color.c
Changes in V3:
perf tools: Add support for Instruction Trace recording
Added evsel as a parameter to itrace_record__init
perf record: Add basic Instruction Tracing support
Moved the call to itrace_record__init after parse options so that evsel could be passed and the selected events used to determine what kind of Instruction Tracing to use e.g. Intel PT vs BTS
Re-based on Arnaldo's perf/core branch:
41e950c033b7df997d4b38653efe6554be9b96a7
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Changes in V2:
Dropped patches already applied.
Re-based on Arnaldo's perf/core branch:
a84808083688d82d7f1e5786ccf5df0ff7d448cb perf tools: Only override the default :tid comm entry
The abstraction has two separate aspects:
1. recording AUX area data
2. processing AUX area data
Recording consists of mmapping a separate buffer and copying the data into the perf.data file. The buffer is an AUX area buffer although the details of the AUX area are not implemented because the kernel support is pending. The data is written preceded by a new user event PERF_RECORD_AUXTRACE. The data is too big to fit in the event but follows immediately afterward. Session processing has to skip to get to the next event header in a similar fashion to the existing PERF_RECORD_HEADER_TRACING_DATA event. The main recording patches are:
perf evlist: Add initial support for mmapping an AUX area buffer perf tools: Add user events for AUX area tracing
perf tools: Add support for AUX area recording
perf record: Add basic AUX area tracing support
Processing consists of providing hooks in session processing to enable a decoder to see all the events and deliver synthesized events transparently into the event stream. The main processing patch is:
perf session: Add hooks to allow transparent decoding of AUX area tracing data
Adrian Hunter (25):
perf header: Add AUX area tracing feature
perf evlist: Add initial support for mmapping an AUX area buffer perf tools: Add user events for AUX area tracing
perf tools: Add support for AUX area recording
perf record: Add basic AUX area tracing support
perf record: Extend -m option for AUX area tracing mmap pages perf tools: Add a user event for AUX area tracing errors
perf session: Add hooks to allow transparent decoding of AUX area tracing data perf session: Add instruction tracing options
perf auxtrace: Add helpers for AUX area tracing errors
perf auxtrace: Add helpers for queuing AUX area tracing data perf auxtrace: Add a heap for sorting AUX area tracing queues perf auxtrace: Add processing for AUX area tracing events
perf auxtrace: Add a hashtable for caching
perf tools: Add member to struct dso for an instruction cache perf script: Add Instruction Tracing support
perf script: Always allow fields 'addr' and 'cpu' for auxtrace perf report: Add Instruction Tracing support
perf inject: Re-pipe AUX area tracing events
perf inject: Add Instruction Tracing support
perf tools: Add AUX area tracing index
perf tools: Hit all build ids when AUX area tracing
perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing perf auxtrace: Add option to synthesize events for transactions perf script: Add field option 'flags' to print sample flags
tools/perf/Documentation/perf-inject.txt | 27 + tools/perf/Documentation/perf-record.txt | 2 + tools/perf/Documentation/perf-report.txt | 29 + tools/perf/Documentation/perf-script.txt | 38 +- tools/perf/Makefile.perf | 2 + tools/perf/builtin-buildid-list.c | 9 + tools/perf/builtin-inject.c | 172 +++- tools/perf/builtin-record.c | 168 +++- tools/perf/builtin-report.c | 11 + tools/perf/builtin-script.c | 74 +- tools/perf/config/Makefile | 5 + tools/perf/perf.h | 2 + tools/perf/tests/make | 2 + tools/perf/util/Build | 1 + tools/perf/util/auxtrace.c | 1278 ++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 571 +++++++++++++ tools/perf/util/dso.c | 2 + tools/perf/util/dso.h | 3 + tools/perf/util/event.c | 3 + tools/perf/util/event.h | 46 ++ tools/perf/util/evlist.c | 71 +- tools/perf/util/evlist.h | 6 + tools/perf/util/header.c | 37 + tools/perf/util/header.h | 1 + tools/perf/util/record.c | 11 +- tools/perf/util/session.c | 169 +++- tools/perf/util/session.h | 6 + tools/perf/util/tool.h | 10 +- 28 files changed, 2702 insertions(+), 54 deletions(-) create mode 100644 tools/perf/util/auxtrace.c create mode 100644 tools/perf/util/auxtrace.h
Regards
Adrian
Adrian Hunter
reviewerPATCH v7 1/25 perf header: Add AUX area tracing feature
Add a feature to indicate that a perf.data file
contains AUX area data.
--- tools/perf/util/header.c | 14 ++++++++++++++ tools/perf/util/header.h | 1 + 2 files changed, 15 insertions(+)
tools/perf/util/header.c +14 -0
@@ -869,6 +869,13 @@ static int write_branch_stack(int fd __maybe_unused,return 0 ; } +static int write_auxtrace (int fd__maybe_unused , +struct perf_header *h__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +return 0 ; +} +static void print_hostname (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {
@@ -1163,6 +1170,12 @@ static void print_branch_stack(struct perf_header *ph __maybe_unused,fprintf (fp,"# contains samples with branch stack\n" ); } +static void print_auxtrace (struct perf_header *ph__maybe_unused , +int fd__maybe_unused ,FILE *fp) +{ +fprintf (fp,"# contains AUX area data (e.g. instruction trace)\n" ); +} +static void print_pmu_mappings (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {
@@ -1873,6 +1886,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPA (HEADER_BRANCH_STACK , branch_stack),FEAT_OPP (HEADER_PMU_MAPPINGS , pmu_mappings),FEAT_OPP (HEADER_GROUP_DESC , group_desc), + FEAT_OPA(HEADER_AUXTRACE, auxtrace), }; struct header_print_data {
tools/perf/util/header.h +1 -0
@@ -30,6 +30,7 @@ enum {HEADER_BRANCH_STACK ,HEADER_PMU_MAPPINGS ,HEADER_GROUP_DESC , +HEADER_AUXTRACE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
1.9.1
Re: [PATCH V7 01/25] perf header: Add AUX area tracing feature
Quoted 4 lines · Adrian Hunter
Add a feature to indicate that a perf.data file
contains AUX area data.Signed-off-by Adrian Hunter <[email protected]>
Quoted 59 lines
--- tools/perf/util/header.c | 14 ++++++++++++++ tools/perf/util/header.h | 1 + 2 files changed, 15 insertions(+)tools/perf/util/header.c +14
-0@@ -869,6 +869,13 @@ static int write_branch_stack(int fd __maybe_unused,return 0 ; } +static int write_auxtrace (int fd__maybe_unused , +struct perf_header *h__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +return 0 ; +} +static void print_hostname (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {@@ -1163,6 +1170,12 @@ static void print_branch_stack(struct perf_header *ph __maybe_unused,fprintf (fp,"# contains samples with branch stack\n" ); } +static void print_auxtrace (struct perf_header *ph__maybe_unused , +int fd__maybe_unused ,FILE *fp) +{ +fprintf (fp,"# contains AUX area data (e.g. instruction trace)\n" ); +} +static void print_pmu_mappings (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {@@ -1873,6 +1886,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPA (HEADER_BRANCH_STACK , branch_stack),FEAT_OPP (HEADER_PMU_MAPPINGS , pmu_mappings),FEAT_OPP (HEADER_GROUP_DESC , group_desc), + FEAT_OPA(HEADER_AUXTRACE, auxtrace), }; struct header_print_data {tools/perf/util/header.h +1
-0@@ -30,6 +30,7 @@ enum {HEADER_BRANCH_STACK ,HEADER_PMU_MAPPINGS ,HEADER_GROUP_DESC , +HEADER_AUXTRACE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 2/25 perf evlist: Add initial support for mmapping an AUX area buffer
In reply to Adrian HunterThis patch anticipates the addition to the kernel
of an "aux" buffer that can be mmapped separately
from the perf-events buffer.
The expectation is that this buffer can be configured to contain hardware-produced trace information. The first implementation will support Intel BTS and Intel PT.
One auxtrace buffer is mmapped per perf-events buffer. If the requested auxtrace buffer size is zero, which it will be until further support is added, then no auxtrace mmapping is attempted.
--- tools/perf/util/Build | 1 + tools/perf/util/auxtrace.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 97 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.c | 61 +++++++++++++++++++++++-- tools/perf/util/evlist.h | 5 +++ 5 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 tools/perf/util/auxtrace.c create mode 100644 tools/perf/util/auxtrace.h
tools/perf/util/Build +1 -0
@@ -74,6 +74,7 @@ libperf-y += data.o libperf-$(CONFIG_X86) += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o +libperf-y += auxtrace.o libperf-$(CONFIG_LIBELF) += symbol-elf.o libperf-$(CONFIG_LIBELF) += probe-event.o
tools/perf/util/auxtrace.c new file +108 -0
108 lines not on this page · raw message
tools/perf/util/auxtrace.h new file +97 -0
97 lines not on this page · raw message
tools/perf/util/evlist.c +58 -3
125 lines not on this page · raw message
tools/perf/util/evlist.h +5 -0
@@ -8,6 +8,7 @@#include "event.h" #include "evsel.h" #include "util.h" +#include "auxtrace.h" #include <unistd.h> struct pollfd ;
@@ -28,6 +29,7 @@ struct perf_mmap {int mask;int refcnt;unsigned int prev; +struct auxtrace_mmap auxtrace_mmap; char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); };
@@ -126,6 +128,9 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,const char *str, int unset); +int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages, +bool overwrite,unsigned int auxtrace_pages, +bool auxtrace_overwrite);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages,bool overwrite);void perf_evlist__munmap (struct perf_evlist *evlist);
Signature · 1 line
1.9.1
Re: [PATCH V7 02/25] perf evlist: Add initial support for mmapping an AUX area buffer
Quoted 9 lines · Adrian Hunter
This patch anticipates the addition to the kernel
of an "aux" buffer that can be mmapped separately
from the perf-events buffer.The expectation is that this buffer can be configured to contain hardware-produced trace information. The first implementation will support Intel BTS and Intel PT.
Quoted 6 lines
One auxtrace buffer is mmapped per perf-events buffer. If the requested auxtrace buffer size is zero, which it will be until further support is added, then no auxtrace mmapping is attempted.
Signed-off-by Adrian Hunter <[email protected]>
Quoted 410 lines
--- tools/perf/util/Build | 1 + tools/perf/util/auxtrace.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 97 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.c | 61 +++++++++++++++++++++++-- tools/perf/util/evlist.h | 5 +++ 5 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 tools/perf/util/auxtrace.c create mode 100644 tools/perf/util/auxtrace.htools/perf/util/Build +1
-0@@ -74,6 +74,7 @@ libperf-y += data.o libperf-$(CONFIG_X86) += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o +libperf-y += auxtrace.o libperf-$(CONFIG_LIBELF) += symbol-elf.o libperf-$(CONFIG_LIBELF) += probe-event.otools/perf/util/auxtrace.c new file +108
-0@@ -0,0 +1,108 @@ +/* +* auxtrace.c: AUX area trace support +* Copyright (c) 2013-2015, Intel Corporation. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +*/ + +#include <sys/types.h> +#include <sys/mman.h> +#include <stdbool.h> + +#include <linux/kernel.h> +#include <linux/perf_event.h> +#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/log2.h> + +#include "../perf.h" +#include "util.h" +#include "evlist.h" +#include "cpumap.h" +#include "thread_map.h" +#include "asm/bug.h" +#include "auxtrace.h" + +int auxtrace_mmap__mmap (struct auxtrace_mmap *mm, +struct auxtrace_mmap_params *mp, +void *userpg,int fd) +{ +#if BITS_PER_LONG !=64 && !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT ) +pr_err ("Cannot use AUX area tracing mmaps\n" ); +return -1 ; +#endif + +WARN_ONCE (mm->base,"Uninitialized auxtrace_mmap\n" ); + + mm->userpg = userpg; + mm->mask = mp->mask; + mm->len = mp->len; + mm->prev =0 ; + mm->idx = mp->idx; + mm->tid = mp->tid; + mm->cpu = mp->cpu; + +if (!mp->len) { + mm->base =NULL ; +return 0 ; + } + + mm->base =mmap (NULL , mp->len, mp->prot,MAP_SHARED , fd, mp->offset); +if (mm->base ==MAP_FAILED ) { +pr_debug2 ("failed to mmap AUX area\n" ); + mm->base =NULL ; +return -1 ; + } + +return 0 ; +} + +void auxtrace_mmap__munmap (struct auxtrace_mmap *mm) +{ +if (mm->base) { +munmap (mm->base, mm->len); + mm->base =NULL ; + } +} + +void auxtrace_mmap_params__init (struct auxtrace_mmap_params *mp, +off_t auxtrace_offset, +unsigned int auxtrace_pages, +bool auxtrace_overwrite) +{ +if (auxtrace_pages) { + mp->offset = auxtrace_offset; + mp->len = auxtrace_pages * (size_t )page_size; + mp->mask =is_power_of_2 (mp->len) ? mp->len -1 :0 ; + mp->prot =PROT_READ | (auxtrace_overwrite ?0 :PROT_WRITE ); +pr_debug2 ("AUX area mmap length %zu\n" , mp->len); + }else { + mp->len =0 ; + } +} + +void auxtrace_mmap_params__set_idx (struct auxtrace_mmap_params *mp, +struct perf_evlist *evlist,int idx, +bool per_cpu) +{ + mp->idx = idx; + +if (per_cpu) { + mp->cpu = evlist->cpus->map[idx]; +if (evlist->threads) + mp->tid = evlist->threads->map[0 ]; +else + mp->tid =-1 ; + }else { + mp->cpu =-1 ; + mp->tid = evlist->threads->map[idx]; + } +}tools/perf/util/auxtrace.h new file +97
-0@@ -0,0 +1,97 @@ +/* +* auxtrace.h: AUX area trace support +* Copyright (c) 2013-2015, Intel Corporation. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +*/ + +#ifndef __PERF_AUXTRACE_H +#define __PERF_AUXTRACE_H + +#include <sys/types.h> +#include <stdbool.h> + +#include <linux/perf_event.h> +#include <linux/types.h> + +#include "../perf.h" + +struct perf_evlist ; + +/** +* struct auxtrace_mmap - records an mmap of the auxtrace buffer. +* @base: address of mapped area +* @userpg: pointer to buffer's perf_event_mmap_page +* @mask: %0 if @len is not a power of two, otherwise (@len - %1) +* @len: size of mapped area +* @prev: previous aux_head +* @idx: index of this mmap +* @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu +* mmap) otherwise %0 +* @cpu: cpu number for a per-cpu mmap otherwise %-1 +*/ +struct auxtrace_mmap { +void *base; +void *userpg; +size_t mask; +size_t len; +u64 prev; +int idx; +pid_t tid; +int cpu; +}; + +/** +* struct auxtrace_mmap_params - parameters to set up struct auxtrace_mmap. +* @mask: %0 if @len is not a power of two, otherwise (@len - %1) +* @offset: file offset of mapped area +* @len: size of mapped area +* @prot: mmap memory protection +* @idx: index of this mmap +* @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu +* mmap) otherwise %0 +* @cpu: cpu number for a per-cpu mmap otherwise %-1 +*/ +struct auxtrace_mmap_params { +size_t mask; +off_t offset; +size_t len; +int prot; +int idx; +pid_t tid; +int cpu; +}; + +static inline u64 auxtrace_mmap__read_head (struct auxtrace_mmap *mm__maybe_unused ) +{ +/* Not yet implemented */ +return 0 ; +} + +static inline void auxtrace_mmap__write_tail (struct auxtrace_mmap *mm__maybe_unused , +u64 tail__maybe_unused ) +{ +/* Not yet implemented */ +} + +int auxtrace_mmap__mmap (struct auxtrace_mmap *mm, +struct auxtrace_mmap_params *mp, +void *userpg,int fd); +void auxtrace_mmap__munmap (struct auxtrace_mmap *mm); +void auxtrace_mmap_params__init (struct auxtrace_mmap_params *mp, +off_t auxtrace_offset, +unsigned int auxtrace_pages, +bool auxtrace_overwrite); +void auxtrace_mmap_params__set_idx (struct auxtrace_mmap_params *mp, +struct perf_evlist *evlist,int idx, +bool per_cpu); + +#endif tools/perf/util/evlist.c +58
-3@@ -725,6 +725,34 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)perf_evlist__mmap_put (evlist, idx); } +int __weak auxtrace_mmap__mmap (struct auxtrace_mmap *mm__maybe_unused , +struct auxtrace_mmap_params *mp__maybe_unused , +void *userpg__maybe_unused , +int fd__maybe_unused ) +{ +return 0 ; +} + +void __weak auxtrace_mmap__munmap (struct auxtrace_mmap *mm__maybe_unused ) +{ +} + +void __weak auxtrace_mmap_params__init ( +struct auxtrace_mmap_params *mp__maybe_unused , +off_t auxtrace_offset__maybe_unused , +unsigned int auxtrace_pages__maybe_unused , +bool auxtrace_overwrite__maybe_unused ) +{ +} + +void __weak auxtrace_mmap_params__set_idx ( +struct auxtrace_mmap_params *mp__maybe_unused , +struct perf_evlist *evlist__maybe_unused , +int idx__maybe_unused , +bool per_cpu__maybe_unused ) +{ +} +static void __perf_evlist__munmap (struct perf_evlist *evlist,int idx) {if (evlist->mmap[idx].base !=NULL ) {@@ -732,6 +760,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) evlist->mmap[idx].base =NULL ; evlist->mmap[idx].refcnt =0 ; } +auxtrace_mmap__munmap (&evlist->mmap[idx].auxtrace_mmap); }void perf_evlist__munmap (struct perf_evlist *evlist)@@ -759,6 +788,7 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)struct mmap_params {int prot;int mask; +struct auxtrace_mmap_params auxtrace_mp; }; static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,@@ -789,6 +819,10 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,return -1 ; } +if (auxtrace_mmap__mmap (&evlist->mmap[idx].auxtrace_mmap, + &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) +return -1 ; +return 0 ; }@@ -853,6 +887,9 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,for (cpu =0 ; cpu < nr_cpus; cpu++) {int output =-1 ; +auxtrace_mmap_params__set_idx (&mp->auxtrace_mp, evlist, cpu, + true); +for (thread =0 ; thread < nr_threads; thread++) {if (perf_evlist__mmap_per_evsel (evlist, cpu, mp, cpu, thread, &output))@@ -878,6 +915,9 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,for (thread =0 ; thread < nr_threads; thread++) {int output =-1 ; +auxtrace_mmap_params__set_idx (&mp->auxtrace_mp, evlist, thread, + false); +if (perf_evlist__mmap_per_evsel (evlist, thread, mp,0 , thread, &output)) goto out_unmap;@@ -981,19 +1021,25 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, }/** -* perf_evlist__mmap - Create mmaps to receive events. +* perf_evlist__mmap_ex - Create mmaps to receive events. * @evlist: list of events * @pages: map length in pages * @overwrite: overwrite older events? +* @auxtrace_pages - auxtrace map length in pages +* @auxtrace_overwrite - overwrite older auxtrace data? * * If @overwrite is %false the user needs to signal event consumption using * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this * automatically. * +* Similarly, if @auxtrace_overwrite is %false the user needs to signal data +* consumption using auxtrace_mmap__write_tail(). +* * Return: %0 on success, negative error code otherwise. */ -int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages, -bool overwrite) +int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages, +bool overwrite,unsigned int auxtrace_pages, +bool auxtrace_overwrite) {struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;@@ -1013,6 +1059,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,pr_debug ("mmap size %zuB\n" , evlist->mmap_len); mp.mask = evlist->mmap_len - page_size -1 ; +auxtrace_mmap_params__init (&mp.auxtrace_mp, evlist->mmap_len, + auxtrace_pages, auxtrace_overwrite); +evlist__for_each (evlist, evsel) { if ((evsel->attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL &&@@ -1026,6 +1075,12 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,return perf_evlist__mmap_per_cpu (evlist, &mp); } +int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages, +bool overwrite) +{ +return perf_evlist__mmap_ex (evlist, pages, overwrite,0 , false); +} +int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid,tools/perf/util/evlist.h +5
-0@@ -8,6 +8,7 @@#include "event.h" #include "evsel.h" #include "util.h" +#include "auxtrace.h" #include <unistd.h> struct pollfd ;@@ -28,6 +29,7 @@ struct perf_mmap {int mask;int refcnt;unsigned int prev; +struct auxtrace_mmap auxtrace_mmap; char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); };@@ -126,6 +128,9 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,const char *str, int unset); +int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages, +bool overwrite,unsigned int auxtrace_pages, +bool auxtrace_overwrite);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages,bool overwrite);void perf_evlist__munmap (struct perf_evlist *evlist);Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 3/25 perf tools: Add user events for AUX area tracing
In reply to Adrian HunterAdd two user events for AUX area tracing.
PERF_RECORD_AUXTRACE_INFO contains metadata, consisting primarily the type of the AUX area tracing data plus some amount of architecture-specific information. There should be only one PERF_RECORD_AUXTRACE_INFO event.
PERF_RECORD_AUXTRACE identifies AUX area tracing data copied from the mmapped AUX area tracing region. The actual data is not part of the event but immediately follows it.
--- tools/perf/util/event.c | 2 ++ tools/perf/util/event.h | 22 +++++++++++++++ tools/perf/util/session.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 9 ++++++- 4 files changed, 101 insertions(+), 1 deletion(-)
tools/perf/util/event.c +2 -0
@@ -29,6 +29,8 @@ static const char *perf_event__names[] = { [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", [PERF_RECORD_ID_INDEX] = "ID_INDEX", + [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", + [PERF_RECORD_AUXTRACE] = "AUXTRACE", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +22 -0
@@ -215,6 +215,8 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_HEADER_BUILD_ID =67 ,PERF_RECORD_FINISHED_ROUND =68 ,PERF_RECORD_ID_INDEX =69 , +PERF_RECORD_AUXTRACE_INFO =70 , +PERF_RECORD_AUXTRACE =71 , PERF_RECORD_HEADER_MAX };
@@ -281,6 +283,24 @@ struct id_index_event {struct id_index_entry entries[0 ]; }; +struct auxtrace_info_event { +struct perf_event_header header; +u32 type; +u32 reserved__;/* For alignment */ +u64 priv[]; +}; + +struct auxtrace_event { +struct perf_event_header header; +u64 size; +u64 offset; +u64 reference; +u32 idx; +u32 tid; +u32 cpu; +u32 reserved__;/* For alignment */ +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -296,6 +316,8 @@ union perf_event {struct tracing_data_event tracing_data;struct build_id_event build_id;struct id_index_event id_index; +struct auxtrace_info_event auxtrace_info; +struct auxtrace_event auxtrace; };void perf_event__print_totals (void );
tools/perf/util/session.c +69 -0
99 lines not on this page · raw message
tools/perf/util/tool.h +8 -1
@@ -3,6 +3,8 @@#include <stdbool.h> +#include <linux/types.h> +struct perf_session ;union perf_event ;struct perf_evlist ;
@@ -29,6 +31,9 @@ typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,typedef int (*event_oe )(struct perf_tool *tool,union perf_event *event,struct ordered_events *oe); +typedef s64 (*event_op3 )(struct perf_tool *tool,union perf_event *event, +struct perf_session *session); +struct perf_tool {event_sample sample, read;
@@ -44,7 +49,9 @@ struct perf_tool {event_op2 tracing_data;event_oe finished_round;event_op2 build_id, - id_index; + id_index, + auxtrace_info; +event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps; };
Signature · 1 line
1.9.1
Re: [PATCH V7 03/25] perf tools: Add user events for AUX area tracing
Quoted 9 lines · Adrian Hunter
Add two user events for AUX area tracing.
PERF_RECORD_AUXTRACE_INFOcontains metadata, consisting primarily the type of the AUX area tracing data plus some amount of architecture-specific information. There should be only onePERF_RECORD_AUXTRACE_INFOevent.
Quoted 7 lines
PERF_RECORD_AUXTRACEidentifies AUX area tracing data copied from the mmapped AUX area tracing region. The actual data is not part of the event but immediately follows it.Signed-off-by Adrian Hunter <[email protected]>
Quoted 212 lines
--- tools/perf/util/event.c | 2 ++ tools/perf/util/event.h | 22 +++++++++++++++ tools/perf/util/session.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 9 ++++++- 4 files changed, 101 insertions(+), 1 deletion(-)tools/perf/util/event.c +2
-0@@ -29,6 +29,8 @@ static const char *perf_event__names[] = { [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", [PERF_RECORD_ID_INDEX] = "ID_INDEX", + [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", + [PERF_RECORD_AUXTRACE] = "AUXTRACE", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +22
-0@@ -215,6 +215,8 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_HEADER_BUILD_ID =67 ,PERF_RECORD_FINISHED_ROUND =68 ,PERF_RECORD_ID_INDEX =69 , +PERF_RECORD_AUXTRACE_INFO =70 , +PERF_RECORD_AUXTRACE =71 , PERF_RECORD_HEADER_MAX };@@ -281,6 +283,24 @@ struct id_index_event {struct id_index_entry entries[0 ]; }; +struct auxtrace_info_event { +struct perf_event_header header; +u32 type; +u32 reserved__;/* For alignment */ +u64 priv[]; +}; + +struct auxtrace_event { +struct perf_event_header header; +u64 size; +u64 offset; +u64 reference; +u32 idx; +u32 tid; +u32 cpu; +u32 reserved__;/* For alignment */ +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;@@ -296,6 +316,8 @@ union perf_event {struct tracing_data_event tracing_data;struct build_id_event build_id;struct id_index_event id_index; +struct auxtrace_info_event auxtrace_info; +struct auxtrace_event auxtrace; };void perf_event__print_totals (void );tools/perf/util/session.c +69
-0@@ -254,6 +254,40 @@ static int process_id_index_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_event_auxtrace_info_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} + +static int skipn (int fd,off_t n) +{ +char buf[4096 ]; +ssize_t ret; + +while (n >0 ) { + ret =read (fd, buf,MIN (n,sizeof (buf))); +if (ret <=0 ) +return ret; + n -= ret; + } + +return 0 ; +} + +static s64 process_event_auxtrace_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session +__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +if (perf_data_file__is_pipe (session->file)) +skipn (perf_data_file__fd (session->file), event->auxtrace.size); +return event->auxtrace.size; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )@@ -290,6 +324,10 @@ void perf_tool__fill_defaults(struct perf_tool *tool) }if (tool->id_index ==NULL ) tool->id_index = process_id_index_stub; +if (tool->auxtrace_info ==NULL ) + tool->auxtrace_info = process_event_auxtrace_info_stub; +if (tool->auxtrace ==NULL ) + tool->auxtrace = process_event_auxtrace_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -470,6 +508,29 @@ static void perf_event__tracing_data_swap(union perf_event *event, event->tracing_data.size =bswap_32 (event->tracing_data.size); } +static void perf_event__auxtrace_info_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ +size_t size; + + event->auxtrace_info.type =bswap_32 (event->auxtrace_info.type); + + size = event->header.size; + size -= (void *)&event->auxtrace_info.priv - (void *)event; +mem_bswap_64 (event->auxtrace_info.priv, size); +} + +static void perf_event__auxtrace_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->auxtrace.size =bswap_64 (event->auxtrace.size); + event->auxtrace.offset =bswap_64 (event->auxtrace.offset); + event->auxtrace.reference =bswap_64 (event->auxtrace.reference); + event->auxtrace.idx =bswap_32 (event->auxtrace.idx); + event->auxtrace.tid =bswap_32 (event->auxtrace.tid); + event->auxtrace.cpu =bswap_32 (event->auxtrace.cpu); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);@@ -489,6 +550,8 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_BUILD_ID] = NULL, [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, + [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, + [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -972,6 +1035,12 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->finished_round (tool, event, oe);case PERF_RECORD_ID_INDEX :return tool->id_index (tool, event, session); +case PERF_RECORD_AUXTRACE_INFO : +return tool->auxtrace_info (tool, event, session); +case PERF_RECORD_AUXTRACE : +/* setup for reading amidst mmap */ +lseek (fd, file_offset + event->header.size,SEEK_SET ); +return tool->auxtrace (tool, event, session);default :return -EINVAL ; }tools/perf/util/tool.h +8
-1@@ -3,6 +3,8 @@#include <stdbool.h> +#include <linux/types.h> +struct perf_session ;union perf_event ;struct perf_evlist ;@@ -29,6 +31,9 @@ typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,typedef int (*event_oe )(struct perf_tool *tool,union perf_event *event,struct ordered_events *oe); +typedef s64 (*event_op3 )(struct perf_tool *tool,union perf_event *event, +struct perf_session *session); +struct perf_tool {event_sample sample, read;@@ -44,7 +49,9 @@ struct perf_tool {event_op2 tracing_data;event_oe finished_round;event_op2 build_id, - id_index; + id_index, + auxtrace_info; +event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps; };Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 4/25 perf tools: Add support for AUX area recording
In reply to Adrian HunterAdd support for reading from the AUX area tracing mmap and synthesizing AUX area tracing events.
This patch introduces an abstraction for recording AUX area data. Recording is initialized
by auxtrace_record__init() which is a weak function to be implemented by the architecture to provide recording callbacks. Recording is mainly handled by auxtrace_mmap__read() and perf_event__synthesize_auxtrace() but there are callbacks for miscellaneous needs including validating and processing user options, populating private data in auxtrace_info_event, and freeing the structure when finished.
--- tools/perf/perf.h | 2 + tools/perf/util/auxtrace.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 56 ++++++++++++++- tools/perf/util/record.c | 11 ++- 4 files changed, 243 insertions(+), 2 deletions(-)
tools/perf/perf.h +2 -0
@@ -54,8 +54,10 @@ struct record_opts {bool period;bool sample_intr_regs;bool running_time; +bool full_auxtrace;unsigned int freq;unsigned int mmap_pages; +unsigned int auxtrace_mmap_pages;unsigned int user_freq;u64 branch_stack;u64 default_interval;
tools/perf/util/auxtrace.c +176 -0
191 lines not on this page · raw message
tools/perf/util/auxtrace.h +55 -1
78 lines not on this page · raw message
tools/perf/util/record.c +10 -1
@@ -119,7 +119,16 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) evsel->attr.comm_exec =1 ; } -if (evlist->nr_entries >1 ) { +if (opts->full_auxtrace) { +/* +* Need to be able to synthesize and parse selected events with +* arbitrary sample types, which requires always being able to +* match the id. +*/ + use_sample_identifier =perf_can_sample_identifier (); +evlist__for_each (evlist, evsel) +perf_evsel__set_sample_id (evsel, use_sample_identifier); + }else if (evlist->nr_entries >1 ) {struct perf_evsel *first =perf_evlist__first (evlist);evlist__for_each (evlist, evsel) {
Signature · 1 line
1.9.1
Re: [PATCH V7 04/25] perf tools: Add support for AUX area recording
Quoted 16 lines · Adrian Hunter
Add support for reading from the AUX area tracing mmap and synthesizing AUX area tracing events.
This patch introduces an abstraction for recording AUX area data. Recording is initialized
byauxtrace_record__init()which is a weak function to be implemented by the architecture to provide recording callbacks. Recording is mainly handled byauxtrace_mmap__read()andperf_event__synthesize_auxtrace()but there are callbacks for miscellaneous needs including validating and processing user options, populating private data inauxtrace_info_event, and freeing the structure when finished.
Quoted 1 line
Signed-off-by Adrian Hunter <[email protected]>
Quoted 330 lines
--- tools/perf/perf.h | 2 + tools/perf/util/auxtrace.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 56 ++++++++++++++- tools/perf/util/record.c | 11 ++- 4 files changed, 243 insertions(+), 2 deletions(-)tools/perf/perf.h +2
-0@@ -54,8 +54,10 @@ struct record_opts {bool period;bool sample_intr_regs;bool running_time; +bool full_auxtrace;unsigned int freq;unsigned int mmap_pages; +unsigned int auxtrace_mmap_pages;unsigned int user_freq;u64 branch_stack;u64 default_interval;tools/perf/util/auxtrace.c +176
-0@@ -23,6 +23,10 @@#include <linux/bitops.h> #include <linux/log2.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "../perf.h" #include "util.h" #include "evlist.h" @@ -31,6 +35,9 @@#include "asm/bug.h" #include "auxtrace.h" +#include "event.h" +#include "debug.h" +int auxtrace_mmap__mmap (struct auxtrace_mmap *mm,struct auxtrace_mmap_params *mp,void *userpg,int fd)@@ -106,3 +113,172 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, mp->tid = evlist->threads->map[idx]; } } + +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +{ +if (itr) +return itr->info_priv_size (itr); +return 0 ; +} + +static int auxtrace_not_supported (void ) +{ +pr_err ("AUX area tracing is not supported on this architecture\n" ); +return -EINVAL ; +} + +int auxtrace_record__info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +if (itr) +return itr->info_fill (itr, session, auxtrace_info, priv_size); +return auxtrace_not_supported (); +} + +void auxtrace_record__free (struct auxtrace_record *itr) +{ +if (itr) + itr->free (itr); +} + +int auxtrace_record__options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +if (itr) +return itr->recording_options (itr, evlist, opts); +return 0 ; +} + +u64 auxtrace_record__reference (struct auxtrace_record *itr) +{ +if (itr) +return itr->reference (itr); +return 0 ; +} + +struct auxtrace_record *__weak +auxtrace_record__init (struct perf_evlist *evlist__maybe_unused ,int *err) +{ + *err =0 ; +return NULL ; +} + +int perf_event__synthesize_auxtrace_info (struct auxtrace_record *itr, +struct perf_tool *tool, +struct perf_session *session, +perf_event__handler_t process) +{ +union perf_event *ev; +size_t priv_size; +int err; + +pr_debug2 ("Synthesizing auxtrace information\n" ); + priv_size =auxtrace_record__info_priv_size (itr); + ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size); +if (!ev) +return -ENOMEM ; + + ev->auxtrace_info.header.type =PERF_RECORD_AUXTRACE_INFO ; + ev->auxtrace_info.header.size =sizeof (struct auxtrace_info_event ) + + priv_size; + err =auxtrace_record__info_fill (itr, session, &ev->auxtrace_info, + priv_size); +if (err) + goto out_free; + + err =process (tool, ev,NULL ,NULL ); +out_free: +free (ev); +return err; +} + +int auxtrace_mmap__read (struct auxtrace_mmap *mm,struct auxtrace_record *itr, +struct perf_tool *tool,process_auxtrace_t fn) +{ +u64 head =auxtrace_mmap__read_head (mm); +u64 old = mm->prev, offset, ref; +unsigned char *data = mm->base; +size_t size, head_off, old_off, len1, len2, padding; +union perf_event ev; +void *data1, *data2; + +if (old == head) +return 0 ; + +pr_debug3 ("auxtrace idx %d old %#" PRIx64" head %#" PRIx64" diff %#" PRIx64"\n" , + mm->idx, old, head, head - old); + +if (mm->mask) { + head_off = head & mm->mask; + old_off = old & mm->mask; + }else { + head_off = head % mm->len; + old_off = old % mm->len; + } + +if (head_off > old_off) + size = head_off - old_off; +else + size = mm->len - (old_off - head_off); + + ref =auxtrace_record__reference (itr); + +if (head > old || size <= head || mm->mask) { + offset = head - size; + }else { +/* +* When the buffer size is not a power of 2, 'head' wraps at the +* highest multiple of the buffer size, so we have to subtract +* the remainder here. +*/ +u64 rem = (0ULL - mm->len) % mm->len; + + offset = head - size - rem; + } + +if (size > head_off) { + len1 = size - head_off; + data1 = &data[mm->len - len1]; + len2 = head_off; + data2 = &data[0 ]; + }else { + len1 = size; + data1 = &data[head_off - len1]; + len2 =0 ; + data2 =NULL ; + } + +/* padding must be written by fn() e.g. record__process_auxtrace() */ + padding = size &7 ; +if (padding) + padding =8 - padding; + +memset (&ev,0 ,sizeof (ev)); + ev.auxtrace.header.type =PERF_RECORD_AUXTRACE ; + ev.auxtrace.header.size =sizeof (ev.auxtrace); + ev.auxtrace.size = size + padding; + ev.auxtrace.offset = offset; + ev.auxtrace.reference = ref; + ev.auxtrace.idx = mm->idx; + ev.auxtrace.tid = mm->tid; + ev.auxtrace.cpu = mm->cpu; + +if (fn (tool, &ev, data1, len1, data2, len2)) +return -1 ; + + mm->prev = head; + +auxtrace_mmap__write_tail (mm, head); +if (itr->read_finish) { +int err; + + err = itr->read_finish (itr, mm->idx); +if (err <0 ) +return err; + } + +return 1 ; +}tools/perf/util/auxtrace.h +55
-1@@ -18,13 +18,18 @@#include <sys/types.h> #include <stdbool.h> - +#include <stddef.h> #include <linux/perf_event.h> #include <linux/types.h> #include "../perf.h" +union perf_event ; +struct perf_session ;struct perf_evlist ; +struct perf_tool ; +struct record_opts ; +struct auxtrace_info_event ;/** * struct auxtrace_mmap - records an mmap of the auxtrace buffer. @@ -70,6 +75,29 @@ struct auxtrace_mmap_params {int cpu; }; +/** +* struct auxtrace_record - callbacks for recording AUX area data. +* @recording_options: validate and process recording options +* @info_priv_size: return the size of the private data in auxtrace_info_event +* @info_fill: fill-in the private data in auxtrace_info_event +* @free: free this auxtrace record structure +* @reference: provide a 64-bit reference number for auxtrace_event +* @read_finish: called after reading from an auxtrace mmap +*/ +struct auxtrace_record { +int (*recording_options)(struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts); +size_t (*info_priv_size)(struct auxtrace_record *itr); +int (*info_fill)(struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size); +void (*free)(struct auxtrace_record *itr); +u64 (*reference)(struct auxtrace_record *itr); +int (*read_finish)(struct auxtrace_record *itr,int idx); +}; +static inline u64 auxtrace_mmap__read_head (struct auxtrace_mmap *mm__maybe_unused ) {/* Not yet implemented */ @@ -94,4 +122,30 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, struct perf_evlist *evlist, int idx, bool per_cpu); +typedef int (*process_auxtrace_t )(struct perf_tool *tool, +union perf_event *event,void *data1, +size_t len1,void *data2,size_t len2); + +int auxtrace_mmap__read (struct auxtrace_mmap *mm,struct auxtrace_record *itr, +struct perf_tool *tool,process_auxtrace_t fn); + +struct auxtrace_record *auxtrace_record__init (struct perf_evlist *evlist, +int *err); + +int auxtrace_record__options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +int auxtrace_record__info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size); +void auxtrace_record__free (struct auxtrace_record *itr); +u64 auxtrace_record__reference (struct auxtrace_record *itr); + +int perf_event__synthesize_auxtrace_info (struct auxtrace_record *itr, +struct perf_tool *tool, +struct perf_session *session, +perf_event__handler_t process); +#endif tools/perf/util/record.c +10
-1@@ -119,7 +119,16 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) evsel->attr.comm_exec =1 ; } -if (evlist->nr_entries >1 ) { +if (opts->full_auxtrace) { +/* +* Need to be able to synthesize and parse selected events with +* arbitrary sample types, which requires always being able to +* match the id. +*/ + use_sample_identifier =perf_can_sample_identifier (); +evlist__for_each (evlist, evsel) +perf_evsel__set_sample_id (evsel, use_sample_identifier); + }else if (evlist->nr_entries >1 ) {struct perf_evsel *first =perf_evlist__first (evlist);evlist__for_each (evlist, evsel) {Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 5/25 perf record: Add basic AUX area tracing support
In reply to Adrian HunterAmend the perf record tool to read the
AUX area tracing mmap and synthesize
AUX area tracing events.
--- tools/perf/builtin-record.c | 81 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 4 deletions(-)
tools/perf/builtin-record.c +77 -4
@@ -27,6 +27,7 @@#include "util/cpumap.h" #include "util/thread_map.h" #include "util/data.h" +#include "util/auxtrace.h" #include <unistd.h> #include <sched.h>
@@ -38,6 +39,7 @@ struct record {struct record_opts opts;u64 bytes_written;struct perf_data_file file; +struct auxtrace_record *itr;struct perf_evlist *evlist;struct perf_session *session;const char *progname;
@@ -110,6 +112,44 @@ out:return rc; } +static int record__process_auxtrace (struct perf_tool *tool, +union perf_event *event,void *data1, +size_t len1,void *data2,size_t len2) +{ + struct record *rec = container_of(tool, struct record, tool); +size_t padding; +u8 pad[8 ] = {0 }; + +/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ + padding = (len1 + len2) &7 ; +if (padding) + padding =8 - padding; + +record__write (rec, event, event->header.size); +record__write (rec, data1, len1); +if (len2) +record__write (rec, data2, len2); +record__write (rec, &pad, padding); + +return 0 ; +} + +static int record__auxtrace_mmap_read (struct record *rec, +struct auxtrace_mmap *mm) +{ +int ret; + + ret =auxtrace_mmap__read (mm, rec->itr, &rec->tool, + record__process_auxtrace); +if (ret <0 ) +return ret; + +if (ret) + rec->samples++; + +return 0 ; +} +static volatile int done =0 ;static volatile int signr =-1 ;static volatile int child_finished =0 ;
@@ -169,13 +209,15 @@ try_again: goto out; } -if (perf_evlist__mmap (evlist, opts->mmap_pages, false) <0 ) { +if (perf_evlist__mmap_ex (evlist, opts->mmap_pages, false, + opts->auxtrace_mmap_pages, false) <0 ) {if (errno ==EPERM ) {pr_err ("Permission error mapping pages.\n" "Consider increasing " "/proc/sys/kernel/perf_event_mlock_kb,\n" "or try again with a smaller value of -m/--mmap_pages.\n" -"(current value: %u)\n" , opts->mmap_pages); +"(current value: %u,%u)\n" , + opts->mmap_pages, opts->auxtrace_mmap_pages); rc = -errno; }else { pr_err("failed to mmap with %d (%s)\n", errno,
@@ -270,12 +312,20 @@ static int record__mmap_read_all(struct record *rec)int rc =0 ;for (i =0 ; i < rec->evlist->nr_mmaps; i++) { +struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; +if (rec->evlist->mmap[i].base) {if (record__mmap_read (rec, i) !=0 ) { rc =-1 ; goto out; } } + +if (mm->base && +record__auxtrace_mmap_read (rec, mm) !=0 ) { + rc =-1 ; + goto out; + } }/*
@@ -305,6 +355,9 @@ static void record__init_features(struct record *rec)if (!rec->opts.branch_stack)perf_header__clear_feat (&session->header,HEADER_BRANCH_STACK ); + +if (!rec->opts.full_auxtrace) +perf_header__clear_feat (&session->header,HEADER_AUXTRACE ); }static volatile int workload_exec_errno;
@@ -421,6 +474,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } } +if (rec->opts.full_auxtrace) { + err =perf_event__synthesize_auxtrace_info (rec->itr, tool, + session, process_synthesized_event); +if (err) + goto out_delete_session; + } + err =perf_event__synthesize_kernel_mmap (tool, process_synthesized_event, machine);if (err <0 )
@@ -553,7 +613,7 @@ out_child:if (!err && !quiet) {char samples[128 ]; -if (rec->samples) +if (rec->samples && !rec->opts.full_auxtrace)scnprintf (samples,sizeof (samples)," (%" PRIu64" samples)" , rec->samples);else
@@ -849,7 +909,7 @@ struct option *record_options = __record_options;int cmd_record (int argc,const char **argv,const char *prefix__maybe_unused ) { -int err = -ENOMEM ; +int err;struct record *rec = &record;char errbuf[BUFSIZ ];
@@ -870,6 +930,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)usage_with_options (record_usage, record_options); } +if (!rec->itr) { + rec->itr =auxtrace_record__init (rec->evlist, &err); +if (err) +return err; + } + + err = -ENOMEM ; +symbol__init (NULL );if (symbol_conf.kptr_restrict)
@@ -915,6 +983,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (perf_evlist__create_maps (rec->evlist, &rec->opts.target) <0 )usage_with_options (record_usage, record_options); + err =auxtrace_record__options (rec->itr, rec->evlist, &rec->opts); +if (err) + goto out_symbol_exit; +if (record_opts__config (&rec->opts)) { err = -EINVAL ; goto out_symbol_exit;
@@ -924,5 +996,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) out_symbol_exit:perf_evlist__delete (rec->evlist);symbol__exit (); +auxtrace_record__free (rec->itr);return err; }
Signature · 1 line
1.9.1
Re: [PATCH V7 05/25] perf record: Add basic AUX area tracing support
Quoted 5 lines · Adrian Hunter
Amend the perf record tool to read the
AUX area tracing mmap and synthesize
AUX area tracing events.Signed-off-by Adrian Hunter <[email protected]>
Quoted 186 lines
--- tools/perf/builtin-record.c | 81 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 4 deletions(-)tools/perf/builtin-record.c +77
-4@@ -27,6 +27,7 @@#include "util/cpumap.h" #include "util/thread_map.h" #include "util/data.h" +#include "util/auxtrace.h" #include <unistd.h> #include <sched.h> @@ -38,6 +39,7 @@ struct record {struct record_opts opts;u64 bytes_written;struct perf_data_file file; +struct auxtrace_record *itr;struct perf_evlist *evlist;struct perf_session *session;const char *progname;@@ -110,6 +112,44 @@ out:return rc; } +static int record__process_auxtrace (struct perf_tool *tool, +union perf_event *event,void *data1, +size_t len1,void *data2,size_t len2) +{ + struct record *rec = container_of(tool, struct record, tool); +size_t padding; +u8 pad[8 ] = {0 }; + +/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ + padding = (len1 + len2) &7 ; +if (padding) + padding =8 - padding; + +record__write (rec, event, event->header.size); +record__write (rec, data1, len1); +if (len2) +record__write (rec, data2, len2); +record__write (rec, &pad, padding); + +return 0 ; +} + +static int record__auxtrace_mmap_read (struct record *rec, +struct auxtrace_mmap *mm) +{ +int ret; + + ret =auxtrace_mmap__read (mm, rec->itr, &rec->tool, + record__process_auxtrace); +if (ret <0 ) +return ret; + +if (ret) + rec->samples++; + +return 0 ; +} +static volatile int done =0 ;static volatile int signr =-1 ;static volatile int child_finished =0 ;@@ -169,13 +209,15 @@ try_again: goto out; } -if (perf_evlist__mmap (evlist, opts->mmap_pages, false) <0 ) { +if (perf_evlist__mmap_ex (evlist, opts->mmap_pages, false, + opts->auxtrace_mmap_pages, false) <0 ) {if (errno ==EPERM ) {pr_err ("Permission error mapping pages.\n" "Consider increasing " "/proc/sys/kernel/perf_event_mlock_kb,\n" "or try again with a smaller value of -m/--mmap_pages.\n" -"(current value: %u)\n" , opts->mmap_pages); +"(current value: %u,%u)\n" , + opts->mmap_pages, opts->auxtrace_mmap_pages); rc = -errno; }else { pr_err("failed to mmap with %d (%s)\n", errno,@@ -270,12 +312,20 @@ static int record__mmap_read_all(struct record *rec)int rc =0 ;for (i =0 ; i < rec->evlist->nr_mmaps; i++) { +struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; +if (rec->evlist->mmap[i].base) {if (record__mmap_read (rec, i) !=0 ) { rc =-1 ; goto out; } } + +if (mm->base && +record__auxtrace_mmap_read (rec, mm) !=0 ) { + rc =-1 ; + goto out; + } }/* @@ -305,6 +355,9 @@ static void record__init_features(struct record *rec)if (!rec->opts.branch_stack)perf_header__clear_feat (&session->header,HEADER_BRANCH_STACK ); + +if (!rec->opts.full_auxtrace) +perf_header__clear_feat (&session->header,HEADER_AUXTRACE ); }static volatile int workload_exec_errno;@@ -421,6 +474,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } } +if (rec->opts.full_auxtrace) { + err =perf_event__synthesize_auxtrace_info (rec->itr, tool, + session, process_synthesized_event); +if (err) + goto out_delete_session; + } + err =perf_event__synthesize_kernel_mmap (tool, process_synthesized_event, machine);if (err <0 )@@ -553,7 +613,7 @@ out_child:if (!err && !quiet) {char samples[128 ]; -if (rec->samples) +if (rec->samples && !rec->opts.full_auxtrace)scnprintf (samples,sizeof (samples)," (%" PRIu64" samples)" , rec->samples);else @@ -849,7 +909,7 @@ struct option *record_options = __record_options;int cmd_record (int argc,const char **argv,const char *prefix__maybe_unused ) { -int err = -ENOMEM ; +int err;struct record *rec = &record;char errbuf[BUFSIZ ];@@ -870,6 +930,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)usage_with_options (record_usage, record_options); } +if (!rec->itr) { + rec->itr =auxtrace_record__init (rec->evlist, &err); +if (err) +return err; + } + + err = -ENOMEM ; +symbol__init (NULL );if (symbol_conf.kptr_restrict)@@ -915,6 +983,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (perf_evlist__create_maps (rec->evlist, &rec->opts.target) <0 )usage_with_options (record_usage, record_options); + err =auxtrace_record__options (rec->itr, rec->evlist, &rec->opts); +if (err) + goto out_symbol_exit; +if (record_opts__config (&rec->opts)) { err = -EINVAL ; goto out_symbol_exit;@@ -924,5 +996,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) out_symbol_exit:perf_evlist__delete (rec->evlist);symbol__exit (); +auxtrace_record__free (rec->itr);return err; }Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 6/25 perf record: Extend -m option for AUX area tracing mmap pages
In reply to Adrian HunterExtend the -m option so that the number of mmap pages for AUX area tracing can be specified by adding a comma followed by the number of pages.
--- tools/perf/Documentation/perf-record.txt | 2 ++ tools/perf/builtin-record.c | 49 ++++++++++++++++++++++++++++++-- tools/perf/util/evlist.c | 10 +++++-- tools/perf/util/evlist.h | 1 + 4 files changed, 56 insertions(+), 6 deletions(-)
tools/perf/Documentation/perf-record.txt +2 -0
@@ -108,6 +108,8 @@ OPTIONS Number of mmap data pages (must be a power of two) or size specification with appended unit character - B/K/M/G. The size is rounded up to have nearest pages power of two value. + Also, by adding a comma, the number of mmap pages for AUX + area tracing can be specified. --group:: Put all events in a single event group. This precedes the --event
tools/perf/builtin-record.c +46 -3
61 lines not on this page · raw message
tools/perf/util/evlist.c +7 -3
@@ -1000,10 +1000,8 @@ static long parse_pages_arg(const char *str, unsigned long min,return pages; } -int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str, -int unset__maybe_unused ) +int __perf_evlist__parse_mmap_pages (unsigned int *mmap_pages,const char *str) { -unsigned int *mmap_pages = opt->value;unsigned long max =UINT_MAX ;long pages;
@@ -1020,6 +1018,12 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,return 0 ; } +int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str, +int unset__maybe_unused ) +{ +return __perf_evlist__parse_mmap_pages (opt->value, str); +} +/** * perf_evlist__mmap_ex - Create mmaps to receive events. * @evlist: list of events
tools/perf/util/evlist.h +1 -0
@@ -124,6 +124,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist);struct option ; +int __perf_evlist__parse_mmap_pages (unsigned int *mmap_pages,const char *str);int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str,int unset);
Signature · 1 line
1.9.1
Re: [PATCH V7 06/25] perf record: Extend -m option for AUX area tracing mmap pages
Quoted 4 lines · Adrian Hunter
Extend the -m option so that the number of mmap pages for AUX area tracing can be specified by adding a comma followed by the number of pages.
Quoted 133 lines
Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/Documentation/perf-record.txt | 2 ++ tools/perf/builtin-record.c | 49 ++++++++++++++++++++++++++++++-- tools/perf/util/evlist.c | 10 +++++-- tools/perf/util/evlist.h | 1 + 4 files changed, 56 insertions(+), 6 deletions(-)tools/perf/Documentation/perf-record.txt +2
-0@@ -108,6 +108,8 @@ OPTIONS Number of mmap data pages (must be a power of two) or size specification with appended unit character - B/K/M/G. The size is rounded up to have nearest pages power of two value. + Also, by adding a comma, the number of mmap pages for AUX + area tracing can be specified. --group:: Put all events in a single event group. This precedes the --eventtools/perf/builtin-record.c +46
-3@@ -771,6 +771,49 @@ static int perf_record_config(const char *var, const char *value, void *cb)return perf_default_config (var, value, cb); } +static int record__parse_mmap_pages (const struct option *opt, +const char *str, +int unset__maybe_unused ) +{ +struct record_opts *opts = opt->value; +char *s, *p; +unsigned int mmap_pages; +int ret; + +if (!str) +return -EINVAL ; + + s =strdup (str); +if (!s) +return -ENOMEM ; + + p =strchr (s,',' ); +if (p) + *p ='\0' ; + +if (*s) { + ret =__perf_evlist__parse_mmap_pages (&mmap_pages, s); +if (ret) + goto out_free; + opts->mmap_pages = mmap_pages; + } + +if (!p) { + ret =0 ; + goto out_free; + } + + ret =__perf_evlist__parse_mmap_pages (&mmap_pages, p +1 ); +if (ret) + goto out_free; + + opts->auxtrace_mmap_pages = mmap_pages; + +out_free: +free (s); +return ret; +} +static const char *const __record_usage[] = {"perf record [<options>] [<command>]" ,"perf record [<options>] -- <command> [<options>]" ,@@ -851,9 +894,9 @@ struct option __record_options[] = { &record.opts.no_inherit_set, "child tasks do not inherit counters"),OPT_UINTEGER ('F' ,"freq" , &record.opts.user_freq,"profile at this frequency" ), -OPT_CALLBACK ('m' ,"mmap-pages" , &record.opts.mmap_pages,"pages" , -"number of mmap data pages" , - perf_evlist__parse_mmap_pages), +OPT_CALLBACK ('m' ,"mmap-pages" , &record.opts,"pages[,pages]" , +"number of mmap data pages and AUX area tracing mmap pages" , + record__parse_mmap_pages),OPT_BOOLEAN (0 ,"group" , &record.opts.group,"put the counters into a counter group" ), OPT_CALLBACK_NOOPT('g', NULL, &record.opts,tools/perf/util/evlist.c +7
-3@@ -1000,10 +1000,8 @@ static long parse_pages_arg(const char *str, unsigned long min,return pages; } -int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str, -int unset__maybe_unused ) +int __perf_evlist__parse_mmap_pages (unsigned int *mmap_pages,const char *str) { -unsigned int *mmap_pages = opt->value;unsigned long max =UINT_MAX ;long pages;@@ -1020,6 +1018,12 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,return 0 ; } +int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str, +int unset__maybe_unused ) +{ +return __perf_evlist__parse_mmap_pages (opt->value, str); +} +/** * perf_evlist__mmap_ex - Create mmaps to receive events. * @evlist: list of events tools/perf/util/evlist.h +1
-0@@ -124,6 +124,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist);struct option ; +int __perf_evlist__parse_mmap_pages (unsigned int *mmap_pages,const char *str);int perf_evlist__parse_mmap_pages (const struct option *opt,const char *str,int unset);Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 7/25 perf tools: Add a user event for AUX area tracing errors
In reply to Adrian HunterErrors encountered when decoding an AUX area trace need to be reported to the user. However the "user" might be a script or another tool, so provide a new user event to capture those errors.
--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 16 ++++++++++++++++ tools/perf/util/session.c | 25 +++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 44 insertions(+), 1 deletion(-)
tools/perf/util/event.c +1 -0
@@ -31,6 +31,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_ID_INDEX] = "ID_INDEX", [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", [PERF_RECORD_AUXTRACE] = "AUXTRACE", + [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +16 -0
@@ -217,6 +217,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_ID_INDEX =69 ,PERF_RECORD_AUXTRACE_INFO =70 ,PERF_RECORD_AUXTRACE =71 , +PERF_RECORD_AUXTRACE_ERROR =72 , PERF_RECORD_HEADER_MAX };
@@ -301,6 +302,20 @@ struct auxtrace_event {u32 reserved__;/* For alignment */ }; +#define MAX_AUXTRACE_ERROR_MSG 64 + +struct auxtrace_error_event { +struct perf_event_header header; +u32 type; +u32 code; +u32 cpu; +u32 pid; +u32 tid; +u32 reserved__;/* For alignment */ +u64 ip; +char msg[MAX_AUXTRACE_ERROR_MSG ]; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -318,6 +333,7 @@ union perf_event {struct id_index_event id_index;struct auxtrace_info_event auxtrace_info;struct auxtrace_event auxtrace; +struct auxtrace_error_event auxtrace_error; };void perf_event__print_totals (void );
tools/perf/util/session.c +25 -0
@@ -288,6 +288,15 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } +static +int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )
@@ -328,6 +337,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->auxtrace_info = process_event_auxtrace_info_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub; +if (tool->auxtrace_error ==NULL ) + tool->auxtrace_error = process_event_auxtrace_error_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -531,6 +542,17 @@ static void perf_event__auxtrace_swap(union perf_event *event, event->auxtrace.cpu =bswap_32 (event->auxtrace.cpu); } +static void perf_event__auxtrace_error_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->auxtrace_error.type =bswap_32 (event->auxtrace_error.type); + event->auxtrace_error.code =bswap_32 (event->auxtrace_error.code); + event->auxtrace_error.cpu =bswap_32 (event->auxtrace_error.cpu); + event->auxtrace_error.pid =bswap_32 (event->auxtrace_error.pid); + event->auxtrace_error.tid =bswap_32 (event->auxtrace_error.tid); + event->auxtrace_error.ip =bswap_64 (event->auxtrace_error.ip); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);
@@ -552,6 +574,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, + [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1041,6 +1064,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,/* setup for reading amidst mmap */ lseek (fd, file_offset + event->header.size,SEEK_SET );return tool->auxtrace (tool, event, session); +case PERF_RECORD_AUXTRACE_ERROR : +return tool->auxtrace_error (tool, event, session);default :return -EINVAL ; }
tools/perf/util/tool.h +2 -1
@@ -50,7 +50,8 @@ struct perf_tool {event_oe finished_round;event_op2 build_id, id_index, - auxtrace_info; + auxtrace_info, + auxtrace_error;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;
Signature · 1 line
1.9.1
Re: [PATCH V7 07/25] perf tools: Add a user event for AUX area tracing errors
Quoted 7 lines · Adrian Hunter
Errors encountered when decoding an AUX area trace need to be reported to the user. However the "user" might be a script or another tool, so provide a new user event to capture those errors.
Signed-off-by Adrian Hunter <[email protected]>
Quoted 141 lines
--- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 16 ++++++++++++++++ tools/perf/util/session.c | 25 +++++++++++++++++++++++++ tools/perf/util/tool.h | 3 ++- 4 files changed, 44 insertions(+), 1 deletion(-)tools/perf/util/event.c +1
-0@@ -31,6 +31,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_ID_INDEX] = "ID_INDEX", [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", [PERF_RECORD_AUXTRACE] = "AUXTRACE", + [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +16
-0@@ -217,6 +217,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_ID_INDEX =69 ,PERF_RECORD_AUXTRACE_INFO =70 ,PERF_RECORD_AUXTRACE =71 , +PERF_RECORD_AUXTRACE_ERROR =72 , PERF_RECORD_HEADER_MAX };@@ -301,6 +302,20 @@ struct auxtrace_event {u32 reserved__;/* For alignment */ }; +#define MAX_AUXTRACE_ERROR_MSG 64 + +struct auxtrace_error_event { +struct perf_event_header header; +u32 type; +u32 code; +u32 cpu; +u32 pid; +u32 tid; +u32 reserved__;/* For alignment */ +u64 ip; +char msg[MAX_AUXTRACE_ERROR_MSG ]; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;@@ -318,6 +333,7 @@ union perf_event {struct id_index_event id_index;struct auxtrace_info_event auxtrace_info;struct auxtrace_event auxtrace; +struct auxtrace_error_event auxtrace_error; };void perf_event__print_totals (void );tools/perf/util/session.c +25
-0@@ -288,6 +288,15 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } +static +int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +void perf_tool__fill_defaults (struct perf_tool *tool) {if (tool->sample ==NULL )@@ -328,6 +337,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->auxtrace_info = process_event_auxtrace_info_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub; +if (tool->auxtrace_error ==NULL ) + tool->auxtrace_error = process_event_auxtrace_error_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -531,6 +542,17 @@ static void perf_event__auxtrace_swap(union perf_event *event, event->auxtrace.cpu =bswap_32 (event->auxtrace.cpu); } +static void perf_event__auxtrace_error_swap (union perf_event *event, +bool sample_id_all__maybe_unused ) +{ + event->auxtrace_error.type =bswap_32 (event->auxtrace_error.type); + event->auxtrace_error.code =bswap_32 (event->auxtrace_error.code); + event->auxtrace_error.cpu =bswap_32 (event->auxtrace_error.cpu); + event->auxtrace_error.pid =bswap_32 (event->auxtrace_error.pid); + event->auxtrace_error.tid =bswap_32 (event->auxtrace_error.tid); + event->auxtrace_error.ip =bswap_64 (event->auxtrace_error.ip); +} +typedef void (*perf_event__swap_op )(union perf_event *event,bool sample_id_all);@@ -552,6 +574,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, + [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1041,6 +1064,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,/* setup for reading amidst mmap */ lseek (fd, file_offset + event->header.size,SEEK_SET );return tool->auxtrace (tool, event, session); +case PERF_RECORD_AUXTRACE_ERROR : +return tool->auxtrace_error (tool, event, session);default :return -EINVAL ; }tools/perf/util/tool.h +2
-1@@ -50,7 +50,8 @@ struct perf_tool {event_oe finished_round;event_op2 build_id, id_index, - auxtrace_info; + auxtrace_info, + auxtrace_error;event_op3 auxtrace;bool ordered_events;bool ordering_requires_timestamps;Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 8/25 perf session: Add hooks to allow transparent decoding of AUX area tracing data
In reply to Adrian HunterHook into session processing so that AUX area decoding can synthesize events transparently to the tools.
The advantages of transparent decoding are that tools can be used directly with perf.data files containing AUX area tracing data, which is easier for the user and more efficient than having a separate decoding tool.
This will work as follows:
1. Tools will feed auxtrace events to the decoder using perf_tool->auxtrace() (support for that still to come).
2. The decoder can process side-band events as needed due to the auxtrace->process_event() hook.
3. The decoder can deliver synthesized events into the event stream using perf_session__deliver_synth_event().
Note the expectation is that decoding will work on data that is time-ordered with respect to the per-cpu or per-thread contexts that were recorded.
--- tools/perf/util/auxtrace.h | 55 ++++++++++++++++++++++++++++++++++++ tools/perf/util/session.c | 70 +++++++++++++++++++++++++++++++++++----------- tools/perf/util/session.h | 3 ++ 3 files changed, 111 insertions(+), 17 deletions(-)
tools/perf/util/auxtrace.h +55 -0
@@ -23,6 +23,7 @@#include <linux/types.h> #include "../perf.h" +#include "session.h" union perf_event ;struct perf_session ;
@@ -32,6 +33,24 @@ struct record_opts;struct auxtrace_info_event ;/** +* struct auxtrace - session callbacks to allow AUX area data decoding. +* @process_event: lets the decoder see all session events +* @flush_events: process any remaining data +* @free_events: free resources associated with event processing +* @free: free resources associated with the session +*/ +struct auxtrace { +int (*process_event)(struct perf_session *session, +union perf_event *event, +struct perf_sample *sample, +struct perf_tool *tool); +int (*flush_events)(struct perf_session *session, +struct perf_tool *tool); +void (*free_events)(struct perf_session *session); +void (*free)(struct perf_session *session); +}; + +/** * struct auxtrace_mmap - records an mmap of the auxtrace buffer. * @base: address of mapped area * @userpg: pointer to buffer's perf_event_mmap_page
@@ -148,4 +167,40 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,struct perf_session *session, perf_event__handler_t process); +static inline int auxtrace__process_event (struct perf_session *session, +union perf_event *event, +struct perf_sample *sample, +struct perf_tool *tool) +{ +if (!session->auxtrace) +return 0 ; + +return session->auxtrace->process_event (session, event, sample, tool); +} + +static inline int auxtrace__flush_events (struct perf_session *session, +struct perf_tool *tool) +{ +if (!session->auxtrace) +return 0 ; + +return session->auxtrace->flush_events (session, tool); +} + +static inline void auxtrace__free_events (struct perf_session *session) +{ +if (!session->auxtrace) +return ; + +return session->auxtrace->free_events (session); +} + +static inline void auxtrace__free (struct perf_session *session) +{ +if (!session->auxtrace) +return ; + +return session->auxtrace->free (session); +} +#endif
tools/perf/util/session.c +53 -17
132 lines not on this page · raw message
tools/perf/util/session.h +3 -0
@@ -15,10 +15,13 @@struct ip_callchain ;struct thread ; +struct auxtrace ; +struct perf_session {struct perf_header header;struct machines machines;struct perf_evlist *evlist; +struct auxtrace *auxtrace;struct trace_event tevent;bool repipe;bool one_mmap;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 9/25 perf session: Add instruction tracing options
In reply to Adrian HunterIt is assumed that AUX area decoding will synthesize events for consumption by other tools. At this time, the main use of AUX area tracing will be to capture instruction trace (aka processor trace) data. The nature of instruction tracing suggests the initial inclusion of options for "instructions" and "branches" events, but more could be added as needed.
--- tools/perf/util/auxtrace.c | 131 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 43 +++++++++++++++ tools/perf/util/session.h | 2 + 3 files changed, 176 insertions(+)
tools/perf/util/auxtrace.c +131 -0
@@ -37,6 +37,7 @@#include "event.h" #include "debug.h" +#include "parse-options.h" int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, struct auxtrace_mmap_params *mp,
@@ -195,6 +196,136 @@ out_free:return err; } +#define PERF_ITRACE_DEFAULT_PERIOD_TYPE PERF_ITRACE_PERIOD_NANOSECS +#define PERF_ITRACE_DEFAULT_PERIOD 100000 +#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16 +#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024 + +void itrace_synth_opts__set_default (struct itrace_synth_opts *synth_opts) +{ + synth_opts->instructions = true; + synth_opts->branches = true; + synth_opts->errors = true; + synth_opts->period_type =PERF_ITRACE_DEFAULT_PERIOD_TYPE ; + synth_opts->period =PERF_ITRACE_DEFAULT_PERIOD ; + synth_opts->callchain_sz =PERF_ITRACE_DEFAULT_CALLCHAIN_SZ ; +} + +int itrace_parse_synth_opts (const struct option *opt,const char *str, +int unset) +{ +struct itrace_synth_opts *synth_opts = opt->value; +const char *p; +char *endptr; + + synth_opts->set = true; + +if (unset) { + synth_opts->dont_decode = true; +return 0 ; + } + +if (!str) { +itrace_synth_opts__set_default (synth_opts); +return 0 ; + } + +for (p = str; *p;) { +switch (*p++) { +case 'i' : + synth_opts->instructions = true; +while (*p ==' ' || *p ==',' ) + p +=1 ; +if (isdigit (*p)) { + synth_opts->period =strtoull (p, &endptr,10 ); + p = endptr; +while (*p ==' ' || *p ==',' ) + p +=1 ; +switch (*p++) { +case 'i' : + synth_opts->period_type = +PERF_ITRACE_PERIOD_INSTRUCTIONS ; +break ; +case 't' : + synth_opts->period_type = +PERF_ITRACE_PERIOD_TICKS ; +break ; +case 'm' : + synth_opts->period *=1000 ; +/* Fall through */ +case 'u' : + synth_opts->period *=1000 ; +/* Fall through */ +case 'n' : +if (*p++ !='s' ) + goto out_err; + synth_opts->period_type = +PERF_ITRACE_PERIOD_NANOSECS ; +break ; +case '\0' : + goto out; +default : + goto out_err; + } + } +break ; +case 'b' : + synth_opts->branches = true; +break ; +case 'e' : + synth_opts->errors = true; +break ; +case 'd' : + synth_opts->log = true; +break ; +case 'c' : + synth_opts->branches = true; + synth_opts->calls = true; +break ; +case 'r' : + synth_opts->branches = true; + synth_opts->returns = true; +break ; +case 'g' : + synth_opts->instructions = true; + synth_opts->callchain = true; + synth_opts->callchain_sz = +PERF_ITRACE_DEFAULT_CALLCHAIN_SZ ; +while (*p ==' ' || *p ==',' ) + p +=1 ; +if (isdigit (*p)) { +unsigned int val; + + val =strtoul (p, &endptr,10 ); + p = endptr; +if (!val || val >PERF_ITRACE_MAX_CALLCHAIN_SZ ) + goto out_err; + synth_opts->callchain_sz = val; + } +break ; +case ' ' : +case ',' : +break ; +default : + goto out_err; + } + } +out: +if (synth_opts->instructions) { +if (!synth_opts->period_type) + synth_opts->period_type = +PERF_ITRACE_DEFAULT_PERIOD_TYPE ; +if (!synth_opts->period) + synth_opts->period =PERF_ITRACE_DEFAULT_PERIOD ; + } + +return 0 ; + +out_err: +pr_err ("Bad Instruction Tracing options '%s'\n" , str); +return -EINVAL ; +} +int auxtrace_mmap__read (struct auxtrace_mmap *mm,struct auxtrace_record *itr,struct perf_tool *tool,process_auxtrace_t fn) {
tools/perf/util/auxtrace.h +43 -0
58 lines not on this page · raw message
tools/perf/util/session.h +2 -0
@@ -16,12 +16,14 @@ struct ip_callchain;struct thread ;struct auxtrace ; +struct itrace_synth_opts ;struct perf_session {struct perf_header header;struct machines machines;struct perf_evlist *evlist;struct auxtrace *auxtrace; +struct itrace_synth_opts *itrace_synth_opts;struct trace_event tevent;bool repipe;bool one_mmap;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 10/25 perf auxtrace: Add helpers for AUX area tracing errors
In reply to Adrian HunterAdd functions to synthesize, count and print
AUX area tracing error events.
--- tools/perf/util/auxtrace.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 14 ++++++++ tools/perf/util/event.h | 6 ++++ tools/perf/util/session.c | 3 ++ 4 files changed, 104 insertions(+)
tools/perf/util/auxtrace.c +81 -0
@@ -24,6 +24,7 @@#include <linux/log2.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <errno.h>
@@ -36,6 +37,7 @@#include "auxtrace.h" #include "event.h" +#include "session.h" #include "debug.h" #include "parse-options.h"
@@ -167,6 +169,28 @@ auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)return NULL ; } +void auxtrace_synth_error (struct auxtrace_error_event *auxtrace_error,int type, +int code,int cpu,pid_t pid,pid_t tid,u64 ip, +const char *msg) +{ +size_t size; + +memset (auxtrace_error,0 ,sizeof (struct auxtrace_error_event )); + + auxtrace_error->header.type =PERF_RECORD_AUXTRACE_ERROR ; + auxtrace_error->type = type; + auxtrace_error->code = code; + auxtrace_error->cpu = cpu; + auxtrace_error->pid = pid; + auxtrace_error->tid = tid; + auxtrace_error->ip = ip; +strlcpy (auxtrace_error->msg, msg,MAX_AUXTRACE_ERROR_MSG ); + + size = (void *)auxtrace_error->msg - (void *)auxtrace_error + +strlen (auxtrace_error->msg) +1 ; + auxtrace_error->header.size =PERF_ALIGN (size,sizeof (u64)); +} + int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, struct perf_tool *tool, struct perf_session *session,
@@ -326,6 +350,63 @@ out_err:return -EINVAL ; } +static const char *const auxtrace_error_type_name[] = { + [PERF_AUXTRACE_ERROR_ITRACE ] ="instruction trace" , +}; + +static const char *auxtrace_error_name (int type) +{ +const char *error_type_name =NULL ; + +if (type <PERF_AUXTRACE_ERROR_MAX ) + error_type_name = auxtrace_error_type_name[type]; +if (!error_type_name) + error_type_name ="unknown AUX" ; +return error_type_name; +} + +size_t perf_event__fprintf_auxtrace_error (union perf_event *event,FILE *fp) +{ +struct auxtrace_error_event *e = &event->auxtrace_error; +int ret; + + ret =fprintf (fp," %s error type %u" , +auxtrace_error_name (e->type), e->type); + ret +=fprintf (fp," cpu %d pid %d tid %d ip %#" PRIx64" code %u: %s\n" , + e->cpu, e->pid, e->tid, e->ip, e->code, e->msg); +return ret; +} + +void perf_session__auxtrace_error_inc (struct perf_session *session, +union perf_event *event) +{ +struct auxtrace_error_event *e = &event->auxtrace_error; + +if (e->type <PERF_AUXTRACE_ERROR_MAX ) + session->evlist->stats.nr_auxtrace_errors[e->type] +=1 ; +} + +void events_stats__auxtrace_error_warn (const struct events_stats *stats) +{ +int i; + +for (i =0 ; i <PERF_AUXTRACE_ERROR_MAX ; i++) { +if (!stats->nr_auxtrace_errors[i]) +continue ; +ui__warning ("%u %s errors\n" , + stats->nr_auxtrace_errors[i], +auxtrace_error_name (i)); + } +} + +int perf_event__process_auxtrace_error (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ +perf_event__fprintf_auxtrace_error (event, stdout); +return 0 ; +} +int auxtrace_mmap__read (struct auxtrace_mmap *mm,struct auxtrace_record *itr,struct perf_tool *tool,process_auxtrace_t fn) {
tools/perf/util/auxtrace.h +14 -0
@@ -23,6 +23,7 @@#include <linux/types.h> #include "../perf.h" +#include "event.h" #include "session.h" union perf_event ;
@@ -32,6 +33,7 @@ struct perf_tool;struct option ;struct record_opts ;struct auxtrace_info_event ; +struct events_stats ;enum itrace_period_type {PERF_ITRACE_PERIOD_INSTRUCTIONS ,
@@ -202,14 +204,26 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,void auxtrace_record__free (struct auxtrace_record *itr);u64 auxtrace_record__reference (struct auxtrace_record *itr); +void auxtrace_synth_error (struct auxtrace_error_event *auxtrace_error,int type, +int code,int cpu,pid_t pid,pid_t tid,u64 ip, +const char *msg); +int perf_event__synthesize_auxtrace_info (struct auxtrace_record *itr,struct perf_tool *tool,struct perf_session *session,perf_event__handler_t process); +int perf_event__process_auxtrace_error (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session);int itrace_parse_synth_opts (const struct option *opt,const char *str,int unset);void itrace_synth_opts__set_default (struct itrace_synth_opts *synth_opts); +size_t perf_event__fprintf_auxtrace_error (union perf_event *event,FILE *fp); +void perf_session__auxtrace_error_inc (struct perf_session *session, +union perf_event *event); +void events_stats__auxtrace_error_warn (const struct events_stats *stats); + static inline int auxtrace__process_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample,
tools/perf/util/event.h +6 -0
@@ -221,6 +221,11 @@ enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_MAX }; +enum auxtrace_error_type { +PERF_AUXTRACE_ERROR_ITRACE =1 , +PERF_AUXTRACE_ERROR_MAX +}; +/* * The kernel collects the number of events it couldn't send in a stretch and * when possible sends this number in a PERF_RECORD_LOST event. The number of
@@ -246,6 +251,7 @@ struct events_stats {u32 nr_unknown_id;u32 nr_unprocessable_samples;u32 nr_unordered_events; +u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX ]; };struct attr_event {
tools/perf/util/session.c +3 -0
@@ -1087,6 +1087,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,lseek (fd, file_offset + event->header.size,SEEK_SET );return tool->auxtrace (tool, event, session);case PERF_RECORD_AUXTRACE_ERROR : +perf_session__auxtrace_error_inc (session, event);return tool->auxtrace_error (tool, event, session);default :return -EINVAL ;
@@ -1274,6 +1275,8 @@ static void perf_tool__warn_about_errors(const struct perf_tool *tool,if (stats->nr_unordered_events !=0 )ui__warning ("%u out of order events recorded.\n" , stats->nr_unordered_events); + +events_stats__auxtrace_error_warn (stats); }volatile int session_done;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 11/25 perf auxtrace: Add helpers for queuing AUX area tracing data
In reply to Adrian HunterProvide functions to queue AUX area tracing data buffers for processing. A AUX area decoder need not use the queues, however Intel BTS and Intel PT will use them.
There is one queue for each of the mmap buffers that were used for recording. Because those mmaps were associated with per-cpu or per-thread contexts, the data is time-ordered with respect to those contexts.
--- tools/perf/util/auxtrace.c | 305 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 87 +++++++++++++ 2 files changed, 392 insertions(+)
tools/perf/util/auxtrace.c +305 -0
@@ -22,11 +22,15 @@#include <linux/types.h> #include <linux/bitops.h> #include <linux/log2.h> +#include <linux/string.h> +#include <sys/param.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <limits.h> #include <errno.h> +#include <linux/list.h> #include "../perf.h" #include "util.h"
@@ -117,6 +121,241 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, } } +#define AUXTRACE_INIT_NR_QUEUES 32 + +static struct auxtrace_queue *auxtrace_alloc_queue_array (unsigned int nr_queues) +{ +struct auxtrace_queue *queue_array; +unsigned int max_nr_queues, i; + + max_nr_queues =MIN (UINT_MAX ,SIZE_MAX ) /sizeof (struct auxtrace_queue ); +if (nr_queues > max_nr_queues) +return NULL ; + + queue_array =calloc (nr_queues,sizeof (struct auxtrace_queue )); +if (!queue_array) +return NULL ; + +for (i =0 ; i < nr_queues; i++) { +INIT_LIST_HEAD (&queue_array[i].head); + queue_array[i].priv =NULL ; + } + +return queue_array; +} + +int auxtrace_queues__init (struct auxtrace_queues *queues) +{ + queues->nr_queues =AUXTRACE_INIT_NR_QUEUES ; + queues->queue_array =auxtrace_alloc_queue_array (queues->nr_queues); +if (!queues->queue_array) +return -ENOMEM ; +return 0 ; +} + +static int auxtrace_queues__grow (struct auxtrace_queues *queues, +unsigned int new_nr_queues) +{ +unsigned int nr_queues = queues->nr_queues; +struct auxtrace_queue *queue_array; +unsigned int i; + +if (!nr_queues) + nr_queues =AUXTRACE_INIT_NR_QUEUES ; + +while (nr_queues && nr_queues < new_nr_queues) + nr_queues <<=1 ; + +if (nr_queues < queues->nr_queues || nr_queues < new_nr_queues) +return -EINVAL ; + + queue_array =auxtrace_alloc_queue_array (nr_queues); +if (!queue_array) +return -ENOMEM ; + +for (i =0 ; i < queues->nr_queues; i++) { +list_splice_tail (&queues->queue_array[i].head, + &queue_array[i].head); + queue_array[i].priv = queues->queue_array[i].priv; + } + + queues->nr_queues = nr_queues; + queues->queue_array = queue_array; + +return 0 ; +} + +static void *auxtrace_copy_data (u64 size,struct perf_session *session) +{ +int fd =perf_data_file__fd (session->file); +void *p; +ssize_t ret; + +if (size >SSIZE_MAX ) +return NULL ; + + p =malloc (size); +if (!p) +return NULL ; + + ret =readn (fd, p, size); +if (ret != (ssize_t )size) { +free (p); +return NULL ; + } + +return p; +} + +static int auxtrace_queues__add_buffer (struct auxtrace_queues *queues, +unsigned int idx, +struct auxtrace_buffer *buffer) +{ +struct auxtrace_queue *queue; +int err; + +if (idx >= queues->nr_queues) { + err =auxtrace_queues__grow (queues, idx +1 ); +if (err) +return err; + } + + queue = &queues->queue_array[idx]; + +if (!queue->set) { + queue->set = true; + queue->tid = buffer->tid; + queue->cpu = buffer->cpu; + }else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) { +pr_err ("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n" , + queue->cpu, queue->tid, buffer->cpu, buffer->tid); +return -EINVAL ; + } + + buffer->buffer_nr = queues->next_buffer_nr++; + +list_add_tail (&buffer->list, &queue->head); + + queues->new_data = true; + queues->populated = true; + +return 0 ; +} + +/* Limit buffers to 32MiB on 32-bit */ +#define BUFFER_LIMIT_FOR_32_BIT (32 * 1024 * 1024) + +static int auxtrace_queues__split_buffer (struct auxtrace_queues *queues, +unsigned int idx, +struct auxtrace_buffer *buffer) +{ +u64 sz = buffer->size; +bool consecutive = false; +struct auxtrace_buffer *b; +int err; + +while (sz >BUFFER_LIMIT_FOR_32_BIT ) { + b =memdup (buffer,sizeof (struct auxtrace_buffer )); +if (!b) +return -ENOMEM ; + b->size =BUFFER_LIMIT_FOR_32_BIT ; + b->consecutive = consecutive; + err =auxtrace_queues__add_buffer (queues, idx, b); +if (err) { +auxtrace_buffer__free (b); +return err; + } + buffer->data_offset +=BUFFER_LIMIT_FOR_32_BIT ; + sz -=BUFFER_LIMIT_FOR_32_BIT ; + consecutive = true; + } + + buffer->size = sz; + buffer->consecutive = consecutive; + +return 0 ; +} + +static int auxtrace_queues__add_event_buffer (struct auxtrace_queues *queues, +struct perf_session *session, +unsigned int idx, +struct auxtrace_buffer *buffer) +{ +if (session->one_mmap) { + buffer->data = buffer->data_offset - session->one_mmap_offset + + session->one_mmap_addr; + }else if (perf_data_file__is_pipe (session->file)) { + buffer->data =auxtrace_copy_data (buffer->size, session); +if (!buffer->data) +return -ENOMEM ; + buffer->data_needs_freeing = true; + }else if (BITS_PER_LONG ==32 && + buffer->size >BUFFER_LIMIT_FOR_32_BIT ) { +int err; + + err =auxtrace_queues__split_buffer (queues, idx, buffer); +if (err) +return err; + } + +return auxtrace_queues__add_buffer (queues, idx, buffer); +} + +int auxtrace_queues__add_event (struct auxtrace_queues *queues, +struct perf_session *session, +union perf_event *event,off_t data_offset, +struct auxtrace_buffer **buffer_ptr) +{ +struct auxtrace_buffer *buffer; +unsigned int idx; +int err; + + buffer =zalloc (sizeof (struct auxtrace_buffer )); +if (!buffer) +return -ENOMEM ; + + buffer->pid =-1 ; + buffer->tid = event->auxtrace.tid; + buffer->cpu = event->auxtrace.cpu; + buffer->data_offset = data_offset; + buffer->offset = event->auxtrace.offset; + buffer->reference = event->auxtrace.reference; + buffer->size = event->auxtrace.size; + idx = event->auxtrace.idx; + + err =auxtrace_queues__add_event_buffer (queues, session, idx, buffer); +if (err) + goto out_err; + +if (buffer_ptr) + *buffer_ptr = buffer; + +return 0 ; + +out_err: +auxtrace_buffer__free (buffer); +return err; +} + +void auxtrace_queues__free (struct auxtrace_queues *queues) +{ +unsigned int i; + +for (i =0 ; i < queues->nr_queues; i++) { +while (!list_empty (&queues->queue_array[i].head)) { +struct auxtrace_buffer *buffer; + + buffer =list_entry (queues->queue_array[i].head.next, + struct auxtrace_buffer, list); +list_del (&buffer->list); +auxtrace_buffer__free (buffer); + } + } + +zfree (&queues->queue_array); + queues->nr_queues =0 ; +} +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) {if (itr)
@@ -169,6 +408,72 @@ auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)return NULL ; } +struct auxtrace_buffer *auxtrace_buffer__next (struct auxtrace_queue *queue, +struct auxtrace_buffer *buffer) +{ +if (buffer) { +if (list_is_last (&buffer->list, &queue->head)) +return NULL ; + return list_entry(buffer->list.next, struct auxtrace_buffer, + list); + }else { +if (list_empty (&queue->head)) +return NULL ; + return list_entry(queue->head.next, struct auxtrace_buffer, + list); + } +} + +void *auxtrace_buffer__get_data (struct auxtrace_buffer *buffer,int fd) +{ +size_t adj = buffer->data_offset & (page_size -1 ); +size_t size = buffer->size + adj; +off_t file_offset = buffer->data_offset - adj; +void *addr; + +if (buffer->data) +return buffer->data; + + addr =mmap (NULL , size,PROT_READ ,MAP_SHARED , fd, file_offset); +if (addr ==MAP_FAILED ) +return NULL ; + + buffer->mmap_addr = addr; + buffer->mmap_size = size; + + buffer->data = addr + adj; + +return buffer->data; +} + +void auxtrace_buffer__put_data (struct auxtrace_buffer *buffer) +{ +if (!buffer->data || !buffer->mmap_addr) +return ; +munmap (buffer->mmap_addr, buffer->mmap_size); + buffer->mmap_addr =NULL ; + buffer->mmap_size =0 ; + buffer->data =NULL ; + buffer->use_data =NULL ; +} + +void auxtrace_buffer__drop_data (struct auxtrace_buffer *buffer) +{ +auxtrace_buffer__put_data (buffer); +if (buffer->data_needs_freeing) { + buffer->data_needs_freeing = false; +zfree (&buffer->data); + buffer->use_data =NULL ; + buffer->size =0 ; + } +} + +void auxtrace_buffer__free (struct auxtrace_buffer *buffer) +{ +auxtrace_buffer__drop_data (buffer); +free (buffer); +} +void auxtrace_synth_error (struct auxtrace_error_event *auxtrace_error,int type,int code,int cpu,pid_t pid,pid_t tid,u64 ip,const char *msg)
tools/perf/util/auxtrace.h +87 -0
105 lines not on this page · raw message
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 12/25 perf auxtrace: Add a heap for sorting AUX area tracing queues
In reply to Adrian HunterIn order to process AUX area tracing data in time order, the queue with data with the lowest timestamp must be processed first. Provide a heap to keep track of which queue that is.
As with the queues, a decoder does not have to use the heap, but Intel BTS and Intel PT will use it.
--- tools/perf/util/auxtrace.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 29 ++++++++++++++++ 2 files changed, 114 insertions(+)
tools/perf/util/auxtrace.c +85 -0
@@ -356,6 +356,91 @@ void auxtrace_queues__free(struct auxtrace_queues *queues) queues->nr_queues =0 ; } +static void auxtrace_heapify (struct auxtrace_heap_item *heap_array, +unsigned int pos,unsigned int queue_nr, +u64 ordinal) +{ +unsigned int parent; + +while (pos) { + parent = (pos -1 ) >>1 ; +if (heap_array[parent].ordinal <= ordinal) +break ; + heap_array[pos] = heap_array[parent]; + pos = parent; + } + heap_array[pos].queue_nr = queue_nr; + heap_array[pos].ordinal = ordinal; +} + +int auxtrace_heap__add (struct auxtrace_heap *heap,unsigned int queue_nr, +u64 ordinal) +{ +struct auxtrace_heap_item *heap_array; + +if (queue_nr >= heap->heap_sz) { +unsigned int heap_sz =AUXTRACE_INIT_NR_QUEUES ; + +while (heap_sz <= queue_nr) + heap_sz <<=1 ; + heap_array =realloc (heap->heap_array, + heap_sz *sizeof (struct auxtrace_heap_item )); +if (!heap_array) +return -ENOMEM ; + heap->heap_array = heap_array; + heap->heap_sz = heap_sz; + } + +auxtrace_heapify (heap->heap_array, heap->heap_cnt++, queue_nr, ordinal); + +return 0 ; +} + +void auxtrace_heap__free (struct auxtrace_heap *heap) +{ +zfree (&heap->heap_array); + heap->heap_cnt =0 ; + heap->heap_sz =0 ; +} + +void auxtrace_heap__pop (struct auxtrace_heap *heap) +{ +unsigned int pos, last, heap_cnt = heap->heap_cnt; +struct auxtrace_heap_item *heap_array; + +if (!heap_cnt) +return ; + + heap->heap_cnt -=1 ; + + heap_array = heap->heap_array; + + pos =0 ; +while (1 ) { +unsigned int left, right; + + left = (pos <<1 ) +1 ; +if (left >= heap_cnt) +break ; + right = left +1 ; +if (right >= heap_cnt) { + heap_array[pos] = heap_array[left]; +return ; + } +if (heap_array[left].ordinal < heap_array[right].ordinal) { + heap_array[pos] = heap_array[left]; + pos = left; + }else { + heap_array[pos] = heap_array[right]; + pos = right; + } + } + + last = heap_cnt -1 ; +auxtrace_heapify (heap_array, pos, heap_array[last].queue_nr, + heap_array[last].ordinal); +} +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) {if (itr)
tools/perf/util/auxtrace.h +29 -0
@@ -168,6 +168,29 @@ struct auxtrace_queues { };/** +* struct auxtrace_heap_item - element of struct auxtrace_heap. +* @queue_nr: queue number +* @ordinal: value used for sorting (lowest ordinal is top of the heap) expected +* to be a timestamp +*/ +struct auxtrace_heap_item { +unsigned int queue_nr; +u64 ordinal; +}; + +/** +* struct auxtrace_heap - a heap suitable for sorting AUX area tracing queues. +* @heap_array: the heap +* @heap_cnt: the number of elements in the heap +* @heap_sz: maximum number of elements (grows as needed) +*/ +struct auxtrace_heap { +struct auxtrace_heap_item *heap_array; +unsigned int heap_cnt; +unsigned int heap_sz; +}; + +/** * struct auxtrace_mmap - records an mmap of the auxtrace buffer. * @base: address of mapped area * @userpg: pointer to buffer's perf_event_mmap_page
@@ -277,6 +300,12 @@ void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd);void auxtrace_buffer__put_data (struct auxtrace_buffer *buffer);void auxtrace_buffer__drop_data (struct auxtrace_buffer *buffer);void auxtrace_buffer__free (struct auxtrace_buffer *buffer); + +int auxtrace_heap__add (struct auxtrace_heap *heap,unsigned int queue_nr, +u64 ordinal); +void auxtrace_heap__pop (struct auxtrace_heap *heap); +void auxtrace_heap__free (struct auxtrace_heap *heap); +struct auxtrace_record *auxtrace_record__init (struct perf_evlist *evlist,int *err);
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 13/25 perf auxtrace: Add processing for AUX area tracing events
In reply to Adrian HunterProvide hooks so that an AUX area
decoder can process AUX area tracing
events.
--- tools/perf/util/auxtrace.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/auxtrace.h | 13 ++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-)
tools/perf/util/auxtrace.c +51 -1
@@ -610,6 +610,53 @@ out_free:return err; } +static bool auxtrace__dont_decode (struct perf_session *session) +{ +return !session->itrace_synth_opts || + session->itrace_synth_opts->dont_decode; +} + +int perf_event__process_auxtrace_info (struct perf_tool *tool__maybe_unused , +union perf_event *event, +struct perf_session *session__maybe_unused ) +{ +enum auxtrace_type type = event->auxtrace_info.type; + +if (dump_trace) +fprintf (stdout," type: %u\n" , type); + +switch (type) { +case PERF_AUXTRACE_UNKNOWN : +default : +return -EINVAL ; + } +} + +s64 perf_event__process_auxtrace (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session) +{ +s64 err; + +if (dump_trace) +fprintf (stdout," size: %#" PRIx64" offset: %#" PRIx64" ref: %#" PRIx64" idx: %u tid: %d cpu: %d\n" , + event->auxtrace.size, event->auxtrace.offset, + event->auxtrace.reference, event->auxtrace.idx, + event->auxtrace.tid, event->auxtrace.cpu); + +if (auxtrace__dont_decode (session)) +return event->auxtrace.size; + +if (!session->auxtrace || event->header.type !=PERF_RECORD_AUXTRACE ) +return -EINVAL ; + + err = session->auxtrace->process_auxtrace_event (session, event, tool); +if (err <0 ) +return err; + +return event->auxtrace.size; +} +#define PERF_ITRACE_DEFAULT_PERIOD_TYPE PERF_ITRACE_PERIOD_NANOSECS#define PERF_ITRACE_DEFAULT_PERIOD 100000#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
@@ -791,8 +838,11 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats)int perf_event__process_auxtrace_error (struct perf_tool *tool__maybe_unused ,union perf_event *event, -struct perf_session *session__maybe_unused ) +struct perf_session *session) { +if (auxtrace__dont_decode (session)) +return 0 ; +perf_event__fprintf_auxtrace_error (event, stdout);return 0 ; }
tools/perf/util/auxtrace.h +13 -0
@@ -36,6 +36,10 @@ struct record_opts;struct auxtrace_info_event ;struct events_stats ; +enum auxtrace_type { +PERF_AUXTRACE_UNKNOWN , +}; +enum itrace_period_type {PERF_ITRACE_PERIOD_INSTRUCTIONS ,PERF_ITRACE_PERIOD_TICKS ,
@@ -87,6 +91,9 @@ struct auxtrace {union perf_event *event, struct perf_sample *sample, struct perf_tool *tool); +int (*process_auxtrace_event)(struct perf_session *session, +union perf_event *event, +struct perf_tool *tool);int (*flush_events)(struct perf_session *session,struct perf_tool *tool);void (*free_events)(struct perf_session *session);
@@ -328,6 +335,12 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,struct perf_tool *tool, struct perf_session *session, perf_event__handler_t process); +int perf_event__process_auxtrace_info (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session); +s64 perf_event__process_auxtrace (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session);int perf_event__process_auxtrace_error (struct perf_tool *tool,union perf_event *event,struct perf_session *session);
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 14/25 perf auxtrace: Add a hashtable for caching
In reply to Adrian HunterDecoding AUX area data may involve walking object code. Rather than repetitively decoding the same instructions, a cache can be used to cache the results.
This patch implements a fairly generic hashtable with a 32-bit key that could be used for other purposes as well.
--- tools/perf/util/auxtrace.c | 123 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 14 ++++++ 2 files changed, 137 insertions(+)
tools/perf/util/auxtrace.c +123 -0
@@ -40,6 +40,8 @@#include "asm/bug.h" #include "auxtrace.h" +#include <linux/hash.h> +#include "event.h" #include "session.h" #include "debug.h"
@@ -934,3 +936,124 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,return 1 ; } + +/** +* struct auxtrace_cache - hash table to implement a cache +* @hashtable: the hashtable +* @sz: hashtable size (number of hlists) +* @entry_size: size of an entry +* @limit: limit the number of entries to this maximum, when reached the cache +* is dropped and caching begins again with an empty cache +* @cnt: current number of entries +* @bits: hashtable size (@sz = 2^@bits) +*/ +struct auxtrace_cache { +struct hlist_head *hashtable; +size_t sz; +size_t entry_size; +size_t limit; +size_t cnt; +unsigned int bits; +}; + +struct auxtrace_cache *auxtrace_cache__new (unsigned int bits,size_t entry_size, +unsigned int limit_percent) +{ +struct auxtrace_cache *c; +struct hlist_head *ht; +size_t sz, i; + + c =zalloc (sizeof (struct auxtrace_cache )); +if (!c) +return NULL ; + + sz =1UL << bits; + + ht =calloc (sz,sizeof (struct hlist_head )); +if (!ht) + goto out_free; + +for (i =0 ; i < sz; i++) +INIT_HLIST_HEAD (&ht[i]); + + c->hashtable = ht; + c->sz = sz; + c->entry_size = entry_size; + c->limit = (c->sz * limit_percent) /100 ; + c->bits = bits; + +return c; + +out_free: +free (c); +return NULL ; +} + +static void auxtrace_cache__drop (struct auxtrace_cache *c) +{ +struct auxtrace_cache_entry *entry; +struct hlist_node *tmp; +size_t i; + +if (!c) +return ; + +for (i =0 ; i < c->sz; i++) { +hlist_for_each_entry_safe (entry, tmp, &c->hashtable[i], hash) { +hlist_del (&entry->hash); +auxtrace_cache__free_entry (c, entry); + } + } + + c->cnt =0 ; +} + +void auxtrace_cache__free (struct auxtrace_cache *c) +{ +if (!c) +return ; + +auxtrace_cache__drop (c); +free (c->hashtable); +free (c); +} + +void *auxtrace_cache__alloc_entry (struct auxtrace_cache *c) +{ +return malloc (c->entry_size); +} + +void auxtrace_cache__free_entry (struct auxtrace_cache *c__maybe_unused , +void *entry) +{ +free (entry); +} + +int auxtrace_cache__add (struct auxtrace_cache *c,u32 key, +struct auxtrace_cache_entry *entry) +{ +if (c->limit && ++c->cnt > c->limit) +auxtrace_cache__drop (c); + + entry->key = key; +hlist_add_head (&entry->hash, &c->hashtable[hash_32 (key, c->bits)]); + +return 0 ; +} + +void *auxtrace_cache__lookup (struct auxtrace_cache *c,u32 key) +{ +struct auxtrace_cache_entry *entry; +struct hlist_head *hlist; + +if (!c) +return NULL ; + + hlist = &c->hashtable[hash_32 (key, c->bits)]; +hlist_for_each_entry (entry, hlist, hash) { +if (entry->key == key) +return entry; + } + +return NULL ; +}
tools/perf/util/auxtrace.h +14 -0
@@ -313,6 +313,20 @@ int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,void auxtrace_heap__pop (struct auxtrace_heap *heap);void auxtrace_heap__free (struct auxtrace_heap *heap); +struct auxtrace_cache_entry { +struct hlist_node hash; +u32 key; +}; + +struct auxtrace_cache *auxtrace_cache__new (unsigned int bits,size_t entry_size, +unsigned int limit_percent); +void auxtrace_cache__free (struct auxtrace_cache *auxtrace_cache); +void *auxtrace_cache__alloc_entry (struct auxtrace_cache *c); +void auxtrace_cache__free_entry (struct auxtrace_cache *c,void *entry); +int auxtrace_cache__add (struct auxtrace_cache *c,u32 key, +struct auxtrace_cache_entry *entry); +void *auxtrace_cache__lookup (struct auxtrace_cache *c,u32 key); +struct auxtrace_record *auxtrace_record__init (struct perf_evlist *evlist,int *err);
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 15/25 perf tools: Add member to struct dso for an instruction cache
In reply to Adrian HunterAdd a member to struct dso that can be used by Instruction Trace implementations to hold a cache for decoded instructions.
--- tools/perf/util/dso.c | 2 ++ tools/perf/util/dso.h | 3 +++ 2 files changed, 5 insertions(+)
tools/perf/util/dso.c +2 -0
@@ -4,6 +4,7 @@#include "symbol.h" #include "dso.h" #include "machine.h" +#include "auxtrace.h" #include "util.h" #include "debug.h"
@@ -961,6 +962,7 @@ void dso__delete(struct dso *dso) }dso__data_close (dso); +auxtrace_cache__free (dso->auxtrace_cache);dso_cache__free (&dso->data.cache);dso__free_a2l (dso);zfree (&dso->symsrc_filename);
tools/perf/util/dso.h +3 -0
@@ -126,6 +126,8 @@ struct dsos {struct rb_root root;/* rbtree root sorted by long name */ }; +struct auxtrace_cache ; +struct dso {struct list_head node;struct rb_node rb_node;/* rbtree node sorted by long name */
@@ -156,6 +158,7 @@ struct dso {u16 long_name_len;u16 short_name_len;void *dwfl;/* DWARF debug info */ +struct auxtrace_cache *auxtrace_cache;/* dso data file */ struct {
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 16/25 perf script: Add Instruction Tracing support
In reply to Adrian HunterAdd support for decoding an AUX area assuming
it contains instruction tracing data.
--- tools/perf/Documentation/perf-script.txt | 28 ++++++++++++++++++++++++++++ tools/perf/builtin-script.c | 11 +++++++++++ 2 files changed, 39 insertions(+)
tools/perf/Documentation/perf-script.txt +28 -0
@@ -221,6 +221,34 @@ OPTIONS --header-only Show only perf.data header. +-Z:: +--itrace:: + Options for decoding instruction tracing data. The options are: + + i synthesize instructions events + b synthesize branches events + c synthesize branches events (calls only) + r synthesize branches events (returns only) + e synthesize error events + d create a debug log + g synthesize a call chain for instructions events + + The default is all events i.e. the same as -Zibe + + In addition, the period (default 100000) for instructions events + can be specified in units of: + + i instructions + t ticks + ms milliseconds + us microseconds + ns nanoseconds (default) + + Also the call chain size (default 16, max. 1024) for instructions + events can be specified. + + To disable decoding entirely, use --no-itrace. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-script-perl[1],
tools/perf/builtin-script.c +11 -0
@@ -16,6 +16,7 @@#include "util/evsel.h" #include "util/sort.h" #include "util/data.h" +#include "util/auxtrace.h" #include <linux/bitmap.h> static char const *script_name;
@@ -1505,6 +1506,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)char *rec_script_path =NULL ;char *rep_script_path =NULL ;struct perf_session *session; +struct itrace_synth_opts itrace_synth_opts = {0 };char *script_path =NULL ;const char **__argv;int i, j, err =0 ;
@@ -1519,6 +1521,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) .attr = process_attr, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, + .id_index = perf_event__process_id_index, + .auxtrace_info = perf_event__process_auxtrace_info, + .auxtrace = perf_event__process_auxtrace, + .auxtrace_error = perf_event__process_auxtrace_error, .ordered_events = true, .ordering_requires_timestamps = true, },
@@ -1574,6 +1580,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "Show the fork/comm/exit events"),OPT_BOOLEAN ('\0' ,"show-mmap-events" , &script.show_mmap_events,"Show the mmap events" ), +OPT_CALLBACK_OPTARG ('Z' ,"itrace" , &itrace_synth_opts,NULL ,"opts" , +"Instruction Tracing options" , + itrace_parse_synth_opts), OPT_END() };const char *const script_subcommands[] = {"record" ,"report" ,NULL };
@@ -1772,6 +1781,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) script.session = session; + session->itrace_synth_opts = &itrace_synth_opts; +if (cpu_list) { err =perf_session__cpu_bitmap (session, cpu_list, cpu_bitmap);if (err <0 )
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 17/25 perf script: Always allow fields 'addr' and 'cpu' for auxtrace
In reply to Adrian HunterIf a file contains AUX area tracing data then always allow fields 'addr' and 'cpu' to be selected as options for perf script. This is necessary because AUX area decoding may synthesize events with that information.
--- tools/perf/builtin-script.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
tools/perf/builtin-script.c +22 -7
@@ -147,9 +147,10 @@ static const char *output_field2str(enum perf_output_field field)#define PRINT_FIELD (x) (output[attr->type].fields & PERF_OUTPUT_##x) -static int perf_evsel__check_stype (struct perf_evsel *evsel, -u64 sample_type,const char *sample_msg, -enum perf_output_field field) +static int perf_evsel__do_check_stype (struct perf_evsel *evsel, +u64 sample_type,const char *sample_msg, +enum perf_output_field field, +bool allow_user_set) {struct perf_event_attr *attr = &evsel->attr;int type = attr->type;
@@ -159,6 +160,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,return 0 ;if (output[type].user_set) { +if (allow_user_set) +return 0 ; evname =perf_evsel__name (evsel); pr_err("Samples for '%s' event do not have %s attribute set. " "Cannot print '%s' field.\n",
@@ -176,10 +179,22 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,return 0 ; } +static int perf_evsel__check_stype (struct perf_evsel *evsel, +u64 sample_type,const char *sample_msg, +enum perf_output_field field) +{ +return perf_evsel__do_check_stype (evsel, sample_type, sample_msg, field, + false); +} +static int perf_evsel__check_attr (struct perf_evsel *evsel,struct perf_session *session) {struct perf_event_attr *attr = &evsel->attr; +bool allow_user_set; + + allow_user_set =perf_header__has_feat (&session->header, +HEADER_AUXTRACE );if (PRINT_FIELD (TRACE ) && !perf_session__has_traces (session,"record -R" ))
@@ -192,8 +207,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, }if (PRINT_FIELD (ADDR ) && -perf_evsel__check_stype (evsel,PERF_SAMPLE_ADDR ,"ADDR" , -PERF_OUTPUT_ADDR )) +perf_evsel__do_check_stype (evsel,PERF_SAMPLE_ADDR ,"ADDR" , +PERF_OUTPUT_ADDR , allow_user_set))return -EINVAL ;if (PRINT_FIELD (SYM ) && !PRINT_FIELD (IP ) && !PRINT_FIELD (ADDR )) {
@@ -230,8 +245,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,return -EINVAL ;if (PRINT_FIELD (CPU ) && -perf_evsel__check_stype (evsel,PERF_SAMPLE_CPU ,"CPU" , -PERF_OUTPUT_CPU )) +perf_evsel__do_check_stype (evsel,PERF_SAMPLE_CPU ,"CPU" , +PERF_OUTPUT_CPU , allow_user_set))return -EINVAL ; if (PRINT_FIELD(PERIOD) &&
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 18/25 perf report: Add Instruction Tracing support
In reply to Adrian HunterAdd support for decoding an AUX area assuming
it contains instruction tracing data.
--- tools/perf/Documentation/perf-report.txt | 28 ++++++++++++++++++++++++++++ tools/perf/builtin-report.c | 11 +++++++++++ 2 files changed, 39 insertions(+)
tools/perf/Documentation/perf-report.txt +28 -0
@@ -323,6 +323,34 @@ OPTIONS --header-only:: Show only perf.data header (forces --stdio). +-Z:: +--itrace:: + Options for decoding AUX area tracing data. The options are: + + i synthesize instructions events + b synthesize branches events + c synthesize branches events (calls only) + r synthesize branches events (returns only) + e synthesize error events + d create a debug log + g synthesize a call chain for instructions events + + The default is all events i.e. the same as -Zibe + + In addition, the period (default 100000) for instructions events + can be specified in units of: + + i instructions + t ticks + ms milliseconds + us microseconds + ns nanoseconds (default) + + Also the call chain size (default 16, max. 1024) for instructions + events can be specified. + + To disable decoding entirely, use --no-itrace. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-annotate[1]
tools/perf/builtin-report.c +11 -0
@@ -36,6 +36,8 @@#include "util/data.h" #include "arch/common.h" +#include "util/auxtrace.h" +#include <dlfcn.h> #include <linux/bitmap.h>
@@ -585,6 +587,7 @@ parse_percent_limit(const struct option *opt, const char *str,int cmd_report (int argc,const char **argv,const char *prefix__maybe_unused ) {struct perf_session *session; +struct itrace_synth_opts itrace_synth_opts = {0 };struct stat st;bool has_br_stack = false;int branch_mode =-1 ;
@@ -607,6 +610,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .attr = perf_event__process_attr, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, + .id_index = perf_event__process_id_index, + .auxtrace_info = perf_event__process_auxtrace_info, + .auxtrace = perf_event__process_auxtrace, .ordered_events = true, .ordering_requires_timestamps = true, },
@@ -717,6 +723,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Don't show entries under that percent", parse_percent_limit),OPT_CALLBACK (0 ,"percentage" ,NULL ,"relative|absolute" ,"how to display percentage of filtered entries" , parse_filter_percentage), +OPT_CALLBACK_OPTARG ('Z' ,"itrace" , &itrace_synth_opts,NULL ,"opts" , +"Instruction Tracing options" , + itrace_parse_synth_opts),OPT_END () }; struct perf_data_file file = {
@@ -761,6 +770,8 @@ repeat: report.queue_size); } + session->itrace_synth_opts = &itrace_synth_opts; + report.session = session; has_br_stack = perf_header__has_feat(&session->header,
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 19/25 perf inject: Re-pipe AUX area tracing events
In reply to Adrian HunterNew AUX area tracing events must be re-piped by default.
--- tools/perf/builtin-inject.c | 63 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-)
tools/perf/builtin-inject.c +58 -5
@@ -38,14 +38,11 @@ struct event_entry {union perf_event event[0 ]; }; -static int perf_event__repipe_synth (struct perf_tool *tool, -union perf_event *event) +static int output_bytes (struct perf_inject *inject,void *buf,size_t sz) { - struct perf_inject *inject = container_of(tool, struct perf_inject, tool);ssize_t size; - size =perf_data_file__write (&inject->output, event, - event->header.size); + size =perf_data_file__write (&inject->output, buf, sz);if (size <0 )return -errno;
@@ -53,6 +50,34 @@ static int perf_event__repipe_synth(struct perf_tool *tool,return 0 ; } +static int copy_bytes (struct perf_inject *inject,int fd,off_t size) +{ +char buf[4096 ]; +ssize_t ssz; +int ret; + +while (size >0 ) { + ssz =read (fd, buf,MIN (size,sizeof (buf))); +if (ssz <0 ) +return -errno; + ret =output_bytes (inject, buf, ssz); +if (ret) +return ret; + size -= ssz; + } + +return 0 ; +} + +static int perf_event__repipe_synth (struct perf_tool *tool, +union perf_event *event) +{ + struct perf_inject *inject = container_of(tool, struct perf_inject, + tool); + +return output_bytes (inject, event, event->header.size); +} +static int perf_event__repipe_oe_synth (struct perf_tool *tool,union perf_event *event,struct ordered_events *oe__maybe_unused )
@@ -86,6 +111,31 @@ static int perf_event__repipe_attr(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } +static s64 perf_event__repipe_auxtrace (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session +__maybe_unused ) +{ + struct perf_inject *inject = container_of(tool, struct perf_inject, + tool); +int ret; + +if (perf_data_file__is_pipe (session->file) || !session->one_mmap) { + ret =output_bytes (inject, event, event->header.size); +if (ret <0 ) +return ret; + ret =copy_bytes (inject,perf_data_file__fd (session->file), + event->auxtrace.size); + }else { + ret =output_bytes (inject, event, + event->header.size + event->auxtrace.size); + } +if (ret <0 ) +return ret; + +return event->auxtrace.size; +} + static int perf_event__repipe(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused,
@@ -413,6 +463,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .unthrottle = perf_event__repipe, .attr = perf_event__repipe_attr, .tracing_data = perf_event__repipe_op2_synth, + .auxtrace_info = perf_event__repipe_op2_synth, + .auxtrace = perf_event__repipe_auxtrace, + .auxtrace_error = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 20/25 perf inject: Add Instruction Tracing support
In reply to Adrian HunterAdd support for decoding an AUX area assuming
it contains instruction tracing data. The
AUX area tracing events are stripped and replaced
by synthesized events.
--- tools/perf/Documentation/perf-inject.txt | 27 ++++++++++++ tools/perf/builtin-inject.c | 71 +++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-inject.txt +27 -0
@@ -44,6 +44,33 @@ OPTIONS --kallsyms=<file>:: kallsyms pathname +-Z:: +--itrace:: + Decode Instruction Tracing data, replacing it with synthesized events. + Options are: + + i synthesize instructions events + b synthesize branches events + c synthesize branches events (calls only) + r synthesize branches events (returns only) + e synthesize error events + d create a debug log + g synthesize a call chain for instructions events + + The default is all events i.e. the same as -Zibe + + In addition, the period (default 100000) for instructions events + can be specified in units of: + + i instructions + t ticks + ms milliseconds + us microseconds + ns nanoseconds (default) + + Also the call chain size (default 16, max. 1024) for instructions + events can be specified. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
tools/perf/builtin-inject.c +69 -2
131 lines not on this page · raw message
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 21/25 perf tools: Add AUX area tracing index
In reply to Adrian HunterAdd an index of AUX area tracing events within a perf.data file.
perf record uses a special user event PERF_RECORD_FINISHED_ROUND to enable sorting of events in chunks instead of having to sort all events altogether.
AUX area tracing events contain data that can span back to the very beginning of the recording period. i.e. they do not obey the rules of PERF_RECORD_FINISHED_ROUND.
By adding an index, AUX area tracing events can be found in advance and the PERF_RECORD_FINISHED_ROUND approach works as usual.
The index is recorded with the auxtrace feature in the perf.data file. A session reads the index but does not process it. An AUX area decoder can queue all the AUX area data in advance using auxtrace_queues__process_index() or otherwise process the index in some custom manner.
--- tools/perf/builtin-inject.c | 15 +++ tools/perf/builtin-record.c | 15 +++ tools/perf/util/auxtrace.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 35 +++++++ tools/perf/util/header.c | 31 ++++++- tools/perf/util/session.c | 2 + tools/perf/util/session.h | 1 + 7 files changed, 311 insertions(+), 4 deletions(-)
tools/perf/builtin-inject.c +15 -0
@@ -122,6 +122,18 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, tool);int ret; +if (!inject->output.is_pipe) { +off_t offset; + + offset =lseek (inject->output.fd,0 ,SEEK_CUR ); +if (offset ==-1 ) +return -errno; + ret =auxtrace_index__auxtrace_event (&session->auxtrace_index, + event, offset); +if (ret <0 ) +return ret; + } +if (perf_data_file__is_pipe (session->file) || !session->one_mmap) { ret =output_bytes (inject, event, event->header.size);if (ret <0 )
@@ -487,6 +499,9 @@ static int __cmd_inject(struct perf_inject *inject) output_data_offset =4096 ; } +if (!inject->itrace_synth_opts.set) +auxtrace_index__free (&session->auxtrace_index); +if (!file_out->is_pipe)lseek (fd, output_data_offset,SEEK_SET );
tools/perf/builtin-record.c +15 -0
@@ -117,9 +117,24 @@ static int record__process_auxtrace(struct perf_tool *tool, size_t len1, void *data2, size_t len2) { struct record *rec = container_of(tool, struct record, tool); +struct perf_data_file *file = &rec->file;size_t padding;u8 pad[8 ] = {0 }; +if (!perf_data_file__is_pipe (file)) { +off_t file_offset; +int fd =perf_data_file__fd (file); +int err; + + file_offset =lseek (fd,0 ,SEEK_CUR ); +if (file_offset ==-1 ) +return -1 ; + err =auxtrace_index__auxtrace_event (&rec->session->auxtrace_index, + event, file_offset); +if (err) +return err; + } +/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ padding = (len1 + len2) &7 ;if (padding)
tools/perf/util/auxtrace.c +216 -0
228 lines not on this page · raw message
tools/perf/util/auxtrace.h +35 -0
@@ -80,6 +80,32 @@ struct itrace_synth_opts { };/** +* struct auxtrace_index_entry - indexes a AUX area tracing event within a +* perf.data file. +* @file_offset: offset within the perf.data file +* @sz: size of the event +*/ +struct auxtrace_index_entry { +u64 file_offset; +u64 sz; +}; + +#define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256 + +/** +* struct auxtrace_index - index of AUX area tracing events within a perf.data +* file. +* @list: linking a number of arrays of entries +* @nr: number of entries +* @entries: array of entries +*/ +struct auxtrace_index { +struct list_head list; +size_t nr; +struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT ]; +}; + +/** * struct auxtrace - session callbacks to allow AUX area data decoding. * @process_event: lets the decoder see all session events * @flush_events: process any remaining data
@@ -301,6 +327,8 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, union perf_event *event, off_t data_offset, struct auxtrace_buffer **buffer_ptr);void auxtrace_queues__free (struct auxtrace_queues *queues); +int auxtrace_queues__process_index (struct auxtrace_queues *queues, +struct perf_session *session);struct auxtrace_buffer *auxtrace_buffer__next (struct auxtrace_queue *queue,struct auxtrace_buffer *buffer);void *auxtrace_buffer__get_data (struct auxtrace_buffer *buffer,int fd);
@@ -341,6 +369,13 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,void auxtrace_record__free (struct auxtrace_record *itr);u64 auxtrace_record__reference (struct auxtrace_record *itr); +int auxtrace_index__auxtrace_event (struct list_head *head,union perf_event *event, +off_t file_offset); +int auxtrace_index__write (int fd,struct list_head *head); +int auxtrace_index__process (int fd,u64 size,struct perf_session *session, +bool needs_swap); +void auxtrace_index__free (struct list_head *head); +void auxtrace_synth_error (struct auxtrace_error_event *auxtrace_error,int type,int code,int cpu,pid_t pid,pid_t tid,u64 ip,const char *msg);
tools/perf/util/header.c +27 -4
@@ -869,11 +869,18 @@ static int write_branch_stack(int fd __maybe_unused,return 0 ; } -static int write_auxtrace (int fd__maybe_unused , -struct perf_header *h__maybe_unused , +static int write_auxtrace (int fd,struct perf_header *h,struct perf_evlist *evlist__maybe_unused ) { -return 0 ; +struct perf_session *session; +int err; + + session = container_of(h, struct perf_session, header); + + err =auxtrace_index__write (fd, &session->auxtrace_index); +if (err <0 ) +pr_err ("Failed to write auxtrace index\n" ); +return err; } static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
@@ -1846,6 +1853,22 @@ out_free:return ret; } +static int process_auxtrace (struct perf_file_section *section, +struct perf_header *ph,int fd, +void *data__maybe_unused ) +{ +struct perf_session *session; +int err; + + session = container_of(ph, struct perf_session, header); + + err =auxtrace_index__process (fd, section->size, session, + ph->needs_swap); +if (err <0 ) +pr_err ("Failed to process auxtrace index\n" ); +return err; +} +struct feature_ops {int (*write)(int fd,struct perf_header *h,struct perf_evlist *evlist);void (*print)(struct perf_header *h,int fd,FILE *fp);
@@ -1886,7 +1909,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPA (HEADER_BRANCH_STACK , branch_stack),FEAT_OPP (HEADER_PMU_MAPPINGS , pmu_mappings),FEAT_OPP (HEADER_GROUP_DESC , group_desc), - FEAT_OPA(HEADER_AUXTRACE, auxtrace), + FEAT_OPP(HEADER_AUXTRACE, auxtrace), }; struct header_print_data {
tools/perf/util/session.c +2 -0
@@ -100,6 +100,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, goto out; session->repipe = repipe; +INIT_LIST_HEAD (&session->auxtrace_index);machines__init (&session->machines);if (file) {
@@ -170,6 +171,7 @@ static void perf_session_env__delete(struct perf_session_env *env)void perf_session__delete (struct perf_session *session) {auxtrace__free (session); +auxtrace_index__free (&session->auxtrace_index);perf_session__destroy_kernel_maps (session);perf_session__delete_threads (session);perf_session_env__delete (&session->header.env);
tools/perf/util/session.h +1 -0
@@ -24,6 +24,7 @@ struct perf_session {struct perf_evlist *evlist;struct auxtrace *auxtrace;struct itrace_synth_opts *itrace_synth_opts; +struct list_head auxtrace_index;struct trace_event tevent;bool repipe;bool one_mmap;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 22/25 perf tools: Hit all build ids when AUX area tracing
In reply to Adrian HunterWe need to include all buildids when a perf.data file contains AUX area tracing data because we do not decode the trace for that purpose because it would take too long.
--- tools/perf/builtin-buildid-list.c | 9 +++++++++ tools/perf/builtin-inject.c | 8 +++++++- tools/perf/builtin-record.c | 10 +++++++++- 3 files changed, 25 insertions(+), 2 deletions(-)
tools/perf/builtin-buildid-list.c +9 -0
@@ -69,6 +69,15 @@ static int perf_session__list_build_ids(bool force, bool with_hits) session =perf_session__new (&file, false, &build_id__mark_dso_hit_ops);if (session ==NULL )return -1 ; + +/* +* We take all buildids when the file contains AUX area tracing data +* because we do not decode the trace because it would take too long. +*/ +if (!perf_data_file__is_pipe (&file) && +perf_header__has_feat (&session->header,HEADER_AUXTRACE )) + with_hits = false; +/* * in pipe-mode, the only way to get the buildids is to parse * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
tools/perf/builtin-inject.c +7 -1
@@ -27,6 +27,7 @@ struct perf_inject {struct perf_session *session;bool build_ids;bool sched_stat; +bool have_auxtrace;const char *input_name;struct perf_data_file output;u64 bytes_written;
@@ -122,6 +123,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, tool);int ret; + inject->have_auxtrace = true; +if (!inject->output.is_pipe) {off_t offset;
@@ -508,9 +511,12 @@ static int __cmd_inject(struct perf_inject *inject) ret =perf_session__process_events (session);if (!file_out->is_pipe) { -if (inject->build_ids) +if (inject->build_ids) {perf_header__set_feat (&session->header,HEADER_BUILD_ID ); +if (inject->have_auxtrace) +dsos__hit_all (session); + }/* * The AUX areas have been removed and replaced with * synthesized hardware events, so clear the feature flag.
tools/perf/builtin-record.c +9 -1
@@ -620,8 +620,16 @@ out_child:if (!err && !file->is_pipe) { rec->session->header.data_size += rec->bytes_written; -if (!rec->no_buildid) +if (!rec->no_buildid) {process_buildids (rec); +/* +* We take all buildids when the file contains +* AUX area tracing data because we do not decode the +* trace because it would take too long. +*/ +if (rec->opts.full_auxtrace) +dsos__hit_all (rec->session); + }perf_session__write_header (rec->session, rec->evlist, fd, true); }
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 23/25 perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing
In reply to Adrian HunterAdd build option NO_AUXTRACE to exclude compiling support for AUX area tracing. Support for both recording and processing is excluded and by implication any future additions such as Intel PT and Intel BTS will also not be compiled in with this option.
--- tools/perf/Makefile.perf | 2 + tools/perf/builtin-inject.c | 53 +++++++++++------- tools/perf/builtin-record.c | 13 +++++ tools/perf/config/Makefile | 5 ++ tools/perf/tests/make | 2 + tools/perf/util/Build | 2 +- tools/perf/util/auxtrace.h | 128 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 20 deletions(-)
tools/perf/Makefile.perf +2 -0
@@ -73,6 +73,8 @@ include config/utilities.mak # for CTF data format. # # Define NO_LZMA if you do not want to support compressed (xz) kernel modules +# +# Define NO_AUXTRACE if you do not want AUX area tracing support ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
tools/perf/builtin-inject.c +34 -19
71 lines not on this page · raw message
tools/perf/builtin-record.c +13 -0
@@ -112,6 +112,8 @@ out:return rc; } +#ifdef HAVE_AUXTRACE_SUPPORT +static int record__process_auxtrace (struct perf_tool *tool,union perf_event *event,void *data1,size_t len1,void *data2,size_t len2)
@@ -165,6 +167,17 @@ static int record__auxtrace_mmap_read(struct record *rec, return 0; } +#else + +static inline +int record__auxtrace_mmap_read (struct record *rec__maybe_unused , +struct auxtrace_mmap *mm__maybe_unused ) +{ +return 0 ; +} + +#endif +static volatile int done =0 ;static volatile int signr =-1 ;static volatile int child_finished =0 ;
tools/perf/config/Makefile +5 -0
@@ -610,6 +610,11 @@ ifdef LIBBABELTRACE endif endif +ifndef NO_AUXTRACE + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT +endif + # Among the variables below, these: # perfexecdir # template_dir
tools/perf/tests/make +2 -0
@@ -32,6 +32,7 @@ make_no_backtrace := NO_BACKTRACE=1 make_no_libnuma := NO_LIBNUMA=1 make_no_libaudit := NO_LIBAUDIT=1 make_no_libbionic := NO_LIBBIONIC=1 +make_no_auxtrace := NO_AUXTRACE=1 make_tags := tags make_cscope := cscope make_help := help
@@ -74,6 +75,7 @@ run += make_no_backtrace run += make_no_libnuma run += make_no_libaudit run += make_no_libbionic +run += make_no_auxtrace run += make_help run += make_doc run += make_perf_o
tools/perf/util/Build +1 -1
@@ -74,7 +74,7 @@ libperf-y += data.o libperf-$(CONFIG_X86) += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o -libperf-y += auxtrace.o +libperf-$(CONFIG_AUXTRACE) += auxtrace.o libperf-$(CONFIG_LIBELF) += symbol-elf.o libperf-$(CONFIG_LIBELF) += probe-event.o
tools/perf/util/auxtrace.h +128 -0
144 lines not on this page · raw message
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 24/25 perf auxtrace: Add option to synthesize events for transactions
In reply to Adrian HunterAdd AUX area tracing option 'x' to synthesize events for transactions. This will be used by Intel PT to synthesize an event record for each TSX start, commit or abort.
--- tools/perf/Documentation/perf-report.txt | 9 +++++---- tools/perf/Documentation/perf-script.txt | 9 +++++---- tools/perf/util/auxtrace.c | 5 ++++- tools/perf/util/auxtrace.h | 2 ++ 4 files changed, 16 insertions(+), 9 deletions(-)
tools/perf/Documentation/perf-report.txt +5 -4
@@ -331,11 +331,12 @@ OPTIONS b synthesize branches events c synthesize branches events (calls only) r synthesize branches events (returns only) + x synthesize transactions events e synthesize error events d create a debug log - g synthesize a call chain for instructions events + g synthesize a call chain (use with i or x) - The default is all events i.e. the same as -Zibe + The default is all events i.e. the same as -Zibxe In addition, the period (default 100000) for instructions events can be specified in units of:
@@ -346,8 +347,8 @@ OPTIONS us microseconds ns nanoseconds (default) - Also the call chain size (default 16, max. 1024) for instructions - events can be specified. + Also the call chain size (default 16, max. 1024) for instructions or + transactions events can be specified. To disable decoding entirely, use --no-itrace.
tools/perf/Documentation/perf-script.txt +5 -4
@@ -229,11 +229,12 @@ OPTIONS b synthesize branches events c synthesize branches events (calls only) r synthesize branches events (returns only) + x synthesize transactions events e synthesize error events d create a debug log - g synthesize a call chain for instructions events + g synthesize a call chain (use with i or x) - The default is all events i.e. the same as -Zibe + The default is all events i.e. the same as -Zibxe In addition, the period (default 100000) for instructions events can be specified in units of:
@@ -244,8 +245,8 @@ OPTIONS us microseconds ns nanoseconds (default) - Also the call chain size (default 16, max. 1024) for instructions - events can be specified. + Also the call chain size (default 16, max. 1024) for instructions or + transactions events can be specified. To disable decoding entirely, use --no-itrace.
tools/perf/util/auxtrace.c +4 -1
@@ -884,6 +884,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) { synth_opts->instructions = true; synth_opts->branches = true; + synth_opts->transactions = true; synth_opts->errors = true; synth_opts->period_type =PERF_ITRACE_DEFAULT_PERIOD_TYPE ; synth_opts->period =PERF_ITRACE_DEFAULT_PERIOD ;
@@ -951,6 +952,9 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,case 'b' : synth_opts->branches = true;break ; +case 'x' : + synth_opts->transactions = true; +break ;case 'e' : synth_opts->errors = true;break ;
@@ -966,7 +970,6 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, synth_opts->returns = true;break ;case 'g' : - synth_opts->instructions = true; synth_opts->callchain = true; synth_opts->callchain_sz =PERF_ITRACE_DEFAULT_CALLCHAIN_SZ ;
tools/perf/util/auxtrace.h +2 -0
@@ -54,6 +54,7 @@ enum itrace_period_type {* because 'perf inject' will write it out * @instructions: whether to synthesize 'instructions' events * @branches: whether to synthesize 'branches' events +* @transactions: whether to synthesize events for transactions * @errors: whether to synthesize decoder error events * @dont_decode: whether to skip decoding entirely * @log: write a decoding log
@@ -69,6 +70,7 @@ struct itrace_synth_opts {bool inject;bool instructions;bool branches; +bool transactions;bool errors;bool dont_decode;bool log;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v7 25/25 perf script: Add field option 'flags' to print sample flags
In reply to Adrian HunterInstruction tracing will typically have access to information about the instruction being executed for a particular ip sample. Some of that information will be available in the 'flags' member of struct perf_sample.
With the addition of transactions events synthesis to Instruction Tracing options, there is a need to be able easily to see the flags because they show whether the ip is at the start, commit or abort of a tranasaction.
Consequently add an option to display the flags.
The flags are "bcrosyiABEx" which stand for branch, call, return, conditional, system, asynchronous, interrupt, transaction abort, trace begin, trace end, and in transaction, respectively.
Example using Intel PT:
perf script -fip,time,event,sym,addr,flags
...
1288.721584105: branches:u: bo 401146 main => 401152 main
1288.721584105: transactions: x 0 401164 main
1288.721584105: branches:u: bx 40117c main => 40119b main 1288.721584105: branches:u: box 4011a4 main => 40117e main 1288.721584105: branches:u: bcx 401187 main => 401094 g ... 1288.721591645: branches:u: bx 4010c4 g => 4010cb g 1288.721591645: branches:u: brx 4010cc g => 401189 main 1288.721591645: transactions: 0 4011a6 main 1288.721593199: branches:u: b 4011a9 main => 4011af main 1288.721593199: branches:u: bo 4011bc main => 40113e main 1288.721593199: branches:u: b 401150 main => 40115a main 1288.721593199: transactions: x 0 401164 main 1288.721593199: branches:u: bx 40117c main => 40119b main 1288.721593199: branches:u: box 4011a4 main => 40117e main 1288.721593199: branches:u: bcx 401187 main => 40105e f ... 1288.722284747: branches:u: brx 401093 f => 401189 main 1288.722284747: branches:u: box 4011a4 main => 40117e main 1288.722284747: branches:u: bcx 401187 main => 40105e f 1288.722285883: transactions: bA 0 401071 f 1288.722285883: branches:u: bA 401071 f => 40116a main 1288.722285883: branches:u: bE 40116a main => 0 [unknown] 1288.722297174: branches:u: bB 0 [unknown] => 40116a main
...
--- tools/perf/Documentation/perf-script.txt | 9 ++++++++- tools/perf/builtin-script.c | 34 +++++++++++++++++++++++++++----- tools/perf/util/event.h | 2 ++ 3 files changed, 39 insertions(+), 6 deletions(-)
tools/perf/Documentation/perf-script.txt +8 -1
@@ -115,7 +115,8 @@ OPTIONS -f:: --fields:: Comma separated list of fields to print. Options are: - comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period. + comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, + srcline, period, flags. Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -165,6 +166,12 @@ OPTIONS At this point usage is displayed, and perf-script exits. + The flags field is synthesized and may have a value when Instruction + Trace decoding. The flags are "bcrosyiABEx" which stand for branch, + call, return, conditional, system, asynchronous, interrupt, + transaction abort, trace begin, trace end, and in transaction, + respectively. + Finally, a user may not set fields to none for all event types. i.e., -f "" is not allowed.
tools/perf/builtin-script.c +29 -5
@@ -27,6 +27,7 @@ static u64 nr_unordered;static bool no_callchain;static bool latency_format;static bool system_wide; +static bool print_flags;static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -461,6 +462,25 @@ static void print_sample_bts(union perf_event *event,printf ("\n" ); } +static void print_sample_flags (u32 flags) +{ +const char *chars =PERF_IP_FLAG_CHARS ; +const int n =strlen (PERF_IP_FLAG_CHARS ); +char str[33 ]; +int i, pos =0 ; + +for (i =0 ; i < n; i++, flags >>=1 ) { +if (flags &1 ) + str[pos++] = chars[i]; + } +for (; i <32 ; i++, flags >>=1 ) { +if (flags &1 ) + str[pos++] ='?' ; + } + str[pos] =0 ; +printf (" %-4s " , str); +} +static void process_event (union perf_event *event,struct perf_sample *sample,struct perf_evsel *evsel,struct thread *thread,struct addr_location *al)
@@ -480,6 +500,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,printf ("%s: " , evname ? evname :"[unknown]" ); } +if (print_flags) +print_sample_flags (sample->flags); +if (is_bts_event (attr)) {print_sample_bts (event, sample, evsel, thread, al);return ;
@@ -1023,12 +1046,15 @@ static int parse_output_fields(const struct option *opt __maybe_unused, } } - tok =strtok (tok,"," ); -while (tok) { +for (tok =strtok (tok,"," ); tok; tok =strtok (NULL ,"," )) {for (i =0 ; i < imax; ++i) {if (strcmp (tok, all_output_options[i].str) ==0 )break ; } +if (i == imax &&strcmp (tok,"flags" ) ==0 ) { + print_flags = true; +continue ; + }if (i == imax) {fprintf (stderr,"Invalid field requested.\n" ); rc = -EINVAL ;
@@ -1056,8 +1082,6 @@ static int parse_output_fields(const struct option *opt __maybe_unused, } output[type].fields |= all_output_options[i].field; } - - tok =strtok (NULL ,"," ); }if (type >=0 ) {
@@ -1575,7 +1599,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "comma separated output fields prepend with 'type:'. " "Valid types: hw,sw,trace,raw. " "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," - "addr,symoff,period", parse_output_fields), + "addr,symoff,period,flags", parse_output_fields),OPT_BOOLEAN ('a' ,"all-cpus" , &system_wide,"system-wide collection from all CPUs" ), OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
tools/perf/util/event.h +2 -0
@@ -157,6 +157,8 @@ enum { PERF_IP_FLAG_IN_TX = 1ULL << 10, }; +#define PERF_IP_FLAG_CHARS "bcrosyiABEx" +#define PERF_BRANCH_MASK (\ PERF_IP_FLAG_BRANCH |\ PERF_IP_FLAG_CALL |\
Signature · 1 line
1.9.1
On Tue, Mar 31, 2015 at 02:38:29PM +0300, Adrian Hunter wrote:
SNIP
Quoted 12 lines
Changes in V7:
Changes requested by Jiri:
perf evlist: Add initial support for mmapping an AUX area buffer
WARN_ONCEifmm->baseis not NULL when mmappingperf tools: Add support for AUX area recording
Useperf_can_sample_identifier()consistently Drop unused functionperf_event__synthesize_auxtrace()
Quoted 5 lines
perf record: Add basic AUX area tracing support
Check length before callingrecord__writea second timeperf record: Extend -m option for AUX area tracing mmap pages
Update change log with -m option change syntax
I sent some acks, I'll continue the review the rest
thanks,
jirka
Adrian Hunter
reviewerQuoted 16 lines · Jiri Olsa
On Tue, Mar 31, 2015 at 02:38:29PM +0300, Adrian Hunter wrote:
SNIP
Quoted 12 lines
Changes in V7:
Changes requested by Jiri:
perf evlist: Add initial support for mmapping an AUX area buffer
WARN_ONCEifmm->baseis not NULL when mmappingperf tools: Add support for AUX area recording
Useperf_can_sample_identifier()consistently Drop unused functionperf_event__synthesize_auxtrace()
Quoted 7 lines
Quoted 5 lines
perf record: Add basic AUX area tracing support
Check length before callingrecord__writea second timeperf record: Extend -m option for AUX area tracing mmap pages
Update change log with -m option change syntaxI sent some acks, I'll continue the review the rest
Thank you! :-)
Arnaldo Carvalho de Melo
maintainerEm Tue, Mar 31, 2015 at 02:38:29PM +0300, Adrian Hunter escreveu:
Quoted 9 lines
Hi
Here is V7 of some more preparatory patches for Intel PT that introduce an abstraction for using the AUX area and Instruction tracing.
The master branch of the tree:
git://git.infradead.org/users/ahunter/linux-perf.git
So, please take a look at my perf/core branch, I processed I think 50% of this, need to take a break to process some more patches, then dedicate some time to those patches related to FINISHED_ROUND.
Also, if possible, would be nice to have access to some perf.data file with those records, so that I can do some testing here, since I have no hardware at least some parts of the code I could test, and not just do code reviews.
- Arnaldo
Adrian Hunter
reviewerQuoted 7 lines · Arnaldo Carvalho de Melo
Em Tue, Mar 31, 2015 at 02:38:29PM +0300, Adrian Hunter escreveu:
Quoted 6 lines
Hi
Here is V7 of some more preparatory patches for Intel PT that introduce an abstraction for using the AUX area and Instruction tracing.
Quoted 5 lines
Quoted 3 lines
The master branch of the tree:
git://git.infradead.org/users/ahunter/linux-perf.gitSo, please take a look at my perf/core branch, I processed I think 50%
Looks fine. Thank you!
Quoted 7 lines
of this, need to take a break to process some more patches, then dedicate some time to those patches related to
FINISHED_ROUND.Also, if possible, would be nice to have access to some perf.data file with those records, so that I can do some testing here, since I have no hardware at least some parts of the code I could test, and not just do code reviews.
I have re-based, plus amended the later documentation to match the removal of -Z, and also moved some stuff under arch/x86. I will create some perf.data files for you and send the revised patches hopefully later today.