1*718c602dSAdrian Hunter /* 2*718c602dSAdrian Hunter * auxtrace.c: AUX area trace support 3*718c602dSAdrian Hunter * Copyright (c) 2013-2015, Intel Corporation. 4*718c602dSAdrian Hunter * 5*718c602dSAdrian Hunter * This program is free software; you can redistribute it and/or modify it 6*718c602dSAdrian Hunter * under the terms and conditions of the GNU General Public License, 7*718c602dSAdrian Hunter * version 2, as published by the Free Software Foundation. 8*718c602dSAdrian Hunter * 9*718c602dSAdrian Hunter * This program is distributed in the hope it will be useful, but WITHOUT 10*718c602dSAdrian Hunter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*718c602dSAdrian Hunter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*718c602dSAdrian Hunter * more details. 13*718c602dSAdrian Hunter * 14*718c602dSAdrian Hunter */ 15*718c602dSAdrian Hunter 16*718c602dSAdrian Hunter #include <sys/types.h> 17*718c602dSAdrian Hunter #include <sys/mman.h> 18*718c602dSAdrian Hunter #include <stdbool.h> 19*718c602dSAdrian Hunter 20*718c602dSAdrian Hunter #include <linux/kernel.h> 21*718c602dSAdrian Hunter #include <linux/perf_event.h> 22*718c602dSAdrian Hunter #include <linux/types.h> 23*718c602dSAdrian Hunter #include <linux/bitops.h> 24*718c602dSAdrian Hunter #include <linux/log2.h> 25*718c602dSAdrian Hunter 26*718c602dSAdrian Hunter #include "../perf.h" 27*718c602dSAdrian Hunter #include "util.h" 28*718c602dSAdrian Hunter #include "evlist.h" 29*718c602dSAdrian Hunter #include "cpumap.h" 30*718c602dSAdrian Hunter #include "thread_map.h" 31*718c602dSAdrian Hunter #include "asm/bug.h" 32*718c602dSAdrian Hunter #include "auxtrace.h" 33*718c602dSAdrian Hunter 34*718c602dSAdrian Hunter int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 35*718c602dSAdrian Hunter struct auxtrace_mmap_params *mp, 36*718c602dSAdrian Hunter void *userpg, int fd) 37*718c602dSAdrian Hunter { 38*718c602dSAdrian Hunter struct perf_event_mmap_page *pc = userpg; 39*718c602dSAdrian Hunter 40*718c602dSAdrian Hunter #if BITS_PER_LONG != 64 && !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT) 41*718c602dSAdrian Hunter pr_err("Cannot use AUX area tracing mmaps\n"); 42*718c602dSAdrian Hunter return -1; 43*718c602dSAdrian Hunter #endif 44*718c602dSAdrian Hunter 45*718c602dSAdrian Hunter WARN_ONCE(mm->base, "Uninitialized auxtrace_mmap\n"); 46*718c602dSAdrian Hunter 47*718c602dSAdrian Hunter mm->userpg = userpg; 48*718c602dSAdrian Hunter mm->mask = mp->mask; 49*718c602dSAdrian Hunter mm->len = mp->len; 50*718c602dSAdrian Hunter mm->prev = 0; 51*718c602dSAdrian Hunter mm->idx = mp->idx; 52*718c602dSAdrian Hunter mm->tid = mp->tid; 53*718c602dSAdrian Hunter mm->cpu = mp->cpu; 54*718c602dSAdrian Hunter 55*718c602dSAdrian Hunter if (!mp->len) { 56*718c602dSAdrian Hunter mm->base = NULL; 57*718c602dSAdrian Hunter return 0; 58*718c602dSAdrian Hunter } 59*718c602dSAdrian Hunter 60*718c602dSAdrian Hunter pc->aux_offset = mp->offset; 61*718c602dSAdrian Hunter pc->aux_size = mp->len; 62*718c602dSAdrian Hunter 63*718c602dSAdrian Hunter mm->base = mmap(NULL, mp->len, mp->prot, MAP_SHARED, fd, mp->offset); 64*718c602dSAdrian Hunter if (mm->base == MAP_FAILED) { 65*718c602dSAdrian Hunter pr_debug2("failed to mmap AUX area\n"); 66*718c602dSAdrian Hunter mm->base = NULL; 67*718c602dSAdrian Hunter return -1; 68*718c602dSAdrian Hunter } 69*718c602dSAdrian Hunter 70*718c602dSAdrian Hunter return 0; 71*718c602dSAdrian Hunter } 72*718c602dSAdrian Hunter 73*718c602dSAdrian Hunter void auxtrace_mmap__munmap(struct auxtrace_mmap *mm) 74*718c602dSAdrian Hunter { 75*718c602dSAdrian Hunter if (mm->base) { 76*718c602dSAdrian Hunter munmap(mm->base, mm->len); 77*718c602dSAdrian Hunter mm->base = NULL; 78*718c602dSAdrian Hunter } 79*718c602dSAdrian Hunter } 80*718c602dSAdrian Hunter 81*718c602dSAdrian Hunter void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, 82*718c602dSAdrian Hunter off_t auxtrace_offset, 83*718c602dSAdrian Hunter unsigned int auxtrace_pages, 84*718c602dSAdrian Hunter bool auxtrace_overwrite) 85*718c602dSAdrian Hunter { 86*718c602dSAdrian Hunter if (auxtrace_pages) { 87*718c602dSAdrian Hunter mp->offset = auxtrace_offset; 88*718c602dSAdrian Hunter mp->len = auxtrace_pages * (size_t)page_size; 89*718c602dSAdrian Hunter mp->mask = is_power_of_2(mp->len) ? mp->len - 1 : 0; 90*718c602dSAdrian Hunter mp->prot = PROT_READ | (auxtrace_overwrite ? 0 : PROT_WRITE); 91*718c602dSAdrian Hunter pr_debug2("AUX area mmap length %zu\n", mp->len); 92*718c602dSAdrian Hunter } else { 93*718c602dSAdrian Hunter mp->len = 0; 94*718c602dSAdrian Hunter } 95*718c602dSAdrian Hunter } 96*718c602dSAdrian Hunter 97*718c602dSAdrian Hunter void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, 98*718c602dSAdrian Hunter struct perf_evlist *evlist, int idx, 99*718c602dSAdrian Hunter bool per_cpu) 100*718c602dSAdrian Hunter { 101*718c602dSAdrian Hunter mp->idx = idx; 102*718c602dSAdrian Hunter 103*718c602dSAdrian Hunter if (per_cpu) { 104*718c602dSAdrian Hunter mp->cpu = evlist->cpus->map[idx]; 105*718c602dSAdrian Hunter if (evlist->threads) 106*718c602dSAdrian Hunter mp->tid = evlist->threads->map[0]; 107*718c602dSAdrian Hunter else 108*718c602dSAdrian Hunter mp->tid = -1; 109*718c602dSAdrian Hunter } else { 110*718c602dSAdrian Hunter mp->cpu = -1; 111*718c602dSAdrian Hunter mp->tid = evlist->threads->map[idx]; 112*718c602dSAdrian Hunter } 113*718c602dSAdrian Hunter } 114