/* * 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 #include #include #include #include #include #include #include #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) { struct perf_event_mmap_page *pc = userpg; #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; } pc->aux_offset = mp->offset; pc->aux_size = mp->len; 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]; } }