xref: /linux/tools/perf/util/auxtrace.c (revision 718c602d67aac04a48cd8e444e778cc3d5d9027f)
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