diff options
Diffstat (limited to 'pevent/include/pevent.h')
| -rw-r--r-- | pevent/include/pevent.h | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/pevent/include/pevent.h b/pevent/include/pevent.h new file mode 100644 index 000000000000..d41f078b812d --- /dev/null +++ b/pevent/include/pevent.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2014-2019, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PEVENT_H +#define PEVENT_H + +#include <linux/perf_event.h> + +#include "intel-pt.h" + +#include <stdint.h> +#include <stddef.h> +#include <string.h> + + +/* A perf event configuration. */ +struct pev_config { + /* The size of the config structure in bytes. */ + size_t size; + + /* The respective field in struct perf_event_attr. + * + * We require sample_id_all in struct perf_event_attr to be set. + */ + uint64_t sample_type; + + /* The respective fields in struct perf_event_mmap_page. */ + uint16_t time_shift; + uint32_t time_mult; + uint64_t time_zero; +}; + +static inline void pev_config_init(struct pev_config *config) +{ + memset(config, 0, sizeof(*config)); + config->size = sizeof(*config); +} + + +/* The MMAP perf event record. */ +struct pev_record_mmap { + uint32_t pid, tid; + uint64_t addr; + uint64_t len; + uint64_t pgoff; + char filename[]; +}; + +/* The LOST perf event record. */ +struct pev_record_lost { + uint64_t id; + uint64_t lost; +}; + +/* The COMM perf event record. */ +struct pev_record_comm { + uint32_t pid, tid; + char comm[]; +}; + +/* The EXIT perf event record. */ +struct pev_record_exit { + uint32_t pid, ppid; + uint32_t tid, ptid; + uint64_t time; +}; + +/* The THROTTLE and UNTHROTTLE perf event records. */ +struct pev_record_throttle { + uint64_t time; + uint64_t id; + uint64_t stream_id; +}; + +/* The FORK perf event record. */ +struct pev_record_fork { + uint32_t pid, ppid; + uint32_t tid, ptid; + uint64_t time; +}; + +/* The MMAP2 perf event record. */ +struct pev_record_mmap2 { + uint32_t pid, tid; + uint64_t addr; + uint64_t len; + uint64_t pgoff; + uint32_t maj, min; + uint64_t ino; + uint64_t ino_generation; + uint32_t prot, flags; + char filename[]; +}; + +/* The AUX perf event record. */ +struct pev_record_aux { + uint64_t aux_offset; + uint64_t aux_size; + uint64_t flags; +}; + +/* The ITRACE_START perf event record. */ +struct pev_record_itrace_start { + uint32_t pid, tid; +}; + +/* The LOST_SAMPLES perf event record. */ +struct pev_record_lost_samples { + uint64_t lost; +}; + +/* The SWITCH_CPU_WIDE perf event record. */ +struct pev_record_switch_cpu_wide { + uint32_t next_prev_pid; + uint32_t next_prev_tid; +}; + +/* A perf event record. */ +struct pev_event { + /* The record type (enum perf_event_type). */ + uint32_t type; + + /* The misc field of the perf event header. */ + uint16_t misc; + + /* The perf event record. */ + union { + /* @type = PERF_RECORD_MMAP. */ + const struct pev_record_mmap *mmap; + + /* @type = PERF_RECORD_LOST. */ + const struct pev_record_lost *lost; + + /* @type = PERF_RECORD_COMM. */ + const struct pev_record_comm *comm; + + /* @type = PERF_RECORD_EXIT. */ + const struct pev_record_exit *exit; + + /* @type = PERF_RECORD_(UN)THROTTLE. */ + const struct pev_record_throttle *throttle; + + /* @type = PERF_RECORD_FORK. */ + const struct pev_record_fork *fork; + + /* @type = PERF_RECORD_MMAP2. */ + const struct pev_record_mmap2 *mmap2; + + /* @type = PERF_RECORD_AUX. */ + const struct pev_record_aux *aux; + + /* @type = PERF_RECORD_ITRACE_START. */ + const struct pev_record_itrace_start *itrace_start; + + /* @type = PERF_RECORD_LOST_SAMPLES. */ + const struct pev_record_lost_samples *lost_samples; + + /* @type = PERF_RECORD_SWITCH_CPU_WIDE. */ + const struct pev_record_switch_cpu_wide *switch_cpu_wide; + } record; + + /* The additional samples. */ + struct { + /* The sampled pid and tid. */ + const uint32_t *pid; + const uint32_t *tid; + + /* The sampled time in perf_event format. */ + const uint64_t *time; + + /* The sampled time in TSC format - if @time is not NULL. */ + uint64_t tsc; + + /* The sampled id. */ + const uint64_t *id; + + /* The sampled stream id. */ + const uint64_t *stream_id; + + /* The sampled cpu. */ + const uint32_t *cpu; + + /* The sample identifier. */ + const uint64_t *identifier; + } sample; +}; + +static inline void pev_event_init(struct pev_event *event) +{ + memset(event, 0, sizeof(*event)); +} + +/* Convert perf_event time to TSC. + * + * Converts @time in perf_event format to @tsc. + * + * Returns zero on success, a negative error code otherwise. + * Returns -pte_bad_config if @config->size is too small. + * Returns -pte_bad_config if @config->time_mult is zero. + * Returns -pte_internal if @tsc or @config is NULL. + */ +extern int pev_time_to_tsc(uint64_t *tsc, uint64_t time, + const struct pev_config *config); + +/* Convert TSC to perf_event time. + * + * Converts @tsc into @time in perf_event format. + * + * Returns zero on success, a negative error code otherwise. + * Returns -pte_bad_config if @config->size is too small. + * Returns -pte_bad_config if @config->time_mult is zero. + * Returns -pte_internal if @time or @config is NULL. + */ +extern int pev_time_from_tsc(uint64_t *time, uint64_t tsc, + const struct pev_config *config); + +/* Read a perf_event record. + * + * Reads one perf_event record from [@begin; @end[ into @event. + * + * Returns the number of bytes read on success, a negative error code otherwise. + * Returns -pte_bad_config if @config->size is too small. + * Returns -pte_eos if the event does not fit into [@begin; @end[. + * Returns -pte_internal if @event, @config, @begin, or @end is NULL. + */ +extern int pev_read(struct pev_event *event, const uint8_t *begin, + const uint8_t *end, const struct pev_config *config); + +/* Write a perf_event record. + * + * Writes @event into [@begin; @end[. + * + * Returns the number of bytes written on success, a negative error code + * otherwise. + * Returns -pte_bad_config if @config->size is too small. + * Returns -pte_bad_opc if the event type is not known. + * Returns -pte_eos if the event does not fit into [@begin; @end[. + * Returns -pte_internal if @begin, @end, @event, or @config is NULL. + */ +extern int pev_write(const struct pev_event *event, uint8_t *begin, + uint8_t *end, const struct pev_config *config); + +#endif /* PEVENT_H */ |
