aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-03-08 03:38:50 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-04-01 17:42:55 -0400
commit2a28e23049af99e1c810111ef5e56455cafeda45 (patch)
treec719c4c372e05c8906ab778b36f5801abc623039 /tools
parent46bc29b970f0011a9099077f1db8f3540aa829fe (diff)
perf jit: Add support for using TSC as a timestamp
Intel PT uses TSC as a timestamp, so add support for using TSC instead of the monotonic clock. Use of TSC is selected by an environment variable "JITDUMP_USE_ARCH_TIMESTAMP" and flagged in the jitdump file with flag JITDUMP_FLAGS_ARCH_TIMESTAMP. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: He Kuang <hekuang@huawei.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1457426330-30226-1-git-send-email-adrian.hunter@intel.com [ Added the fixup from He Kuang to make it build on other arches, ] [ such as aarch64, to avoid inserting this bisectiong breakage upstream ] Link: http://lkml.kernel.org/r/1459482572-129494-1-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/arch/x86/util/tsc.c1
-rw-r--r--tools/perf/arch/x86/util/tsc.h17
-rw-r--r--tools/perf/jvmti/jvmti_agent.c43
-rw-r--r--tools/perf/util/Build3
-rw-r--r--tools/perf/util/jitdump.c37
-rw-r--r--tools/perf/util/jitdump.h3
-rw-r--r--tools/perf/util/tsc.h11
7 files changed, 87 insertions, 28 deletions
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 70ff7c14bea6..357f1b13b5ae 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -7,7 +7,6 @@
7#include <linux/types.h> 7#include <linux/types.h>
8#include "../../util/debug.h" 8#include "../../util/debug.h"
9#include "../../util/tsc.h" 9#include "../../util/tsc.h"
10#include "tsc.h"
11 10
12int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 11int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
13 struct perf_tsc_conversion *tc) 12 struct perf_tsc_conversion *tc)
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h
deleted file mode 100644
index 2edc4d31065c..000000000000
--- a/tools/perf/arch/x86/util/tsc.h
+++ /dev/null
@@ -1,17 +0,0 @@
1#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
2#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
3
4#include <linux/types.h>
5
6struct perf_tsc_conversion {
7 u16 time_shift;
8 u32 time_mult;
9 u64 time_zero;
10};
11
12struct perf_event_mmap_page;
13
14int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
15 struct perf_tsc_conversion *tc);
16
17#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 6461e02ab940..3573f315f955 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -92,6 +92,22 @@ error:
92 return ret; 92 return ret;
93} 93}
94 94
95static int use_arch_timestamp;
96
97static inline uint64_t
98get_arch_timestamp(void)
99{
100#if defined(__i386__) || defined(__x86_64__)
101 unsigned int low, high;
102
103 asm volatile("rdtsc" : "=a" (low), "=d" (high));
104
105 return low | ((uint64_t)high) << 32;
106#else
107 return 0;
108#endif
109}
110
95#define NSEC_PER_SEC 1000000000 111#define NSEC_PER_SEC 1000000000
96static int perf_clk_id = CLOCK_MONOTONIC; 112static int perf_clk_id = CLOCK_MONOTONIC;
97 113
@@ -107,6 +123,9 @@ perf_get_timestamp(void)
107 struct timespec ts; 123 struct timespec ts;
108 int ret; 124 int ret;
109 125
126 if (use_arch_timestamp)
127 return get_arch_timestamp();
128
110 ret = clock_gettime(perf_clk_id, &ts); 129 ret = clock_gettime(perf_clk_id, &ts);
111 if (ret) 130 if (ret)
112 return 0; 131 return 0;
@@ -203,6 +222,17 @@ perf_close_marker_file(void)
203 munmap(marker_addr, pgsz); 222 munmap(marker_addr, pgsz);
204} 223}
205 224
225static void
226init_arch_timestamp(void)
227{
228 char *str = getenv("JITDUMP_USE_ARCH_TIMESTAMP");
229
230 if (!str || !*str || !strcmp(str, "0"))
231 return;
232
233 use_arch_timestamp = 1;
234}
235
206void *jvmti_open(void) 236void *jvmti_open(void)
207{ 237{
208 int pad_cnt; 238 int pad_cnt;
@@ -211,11 +241,17 @@ void *jvmti_open(void)
211 int fd; 241 int fd;
212 FILE *fp; 242 FILE *fp;
213 243
244 init_arch_timestamp();
245
214 /* 246 /*
215 * check if clockid is supported 247 * check if clockid is supported
216 */ 248 */
217 if (!perf_get_timestamp()) 249 if (!perf_get_timestamp()) {
218 warnx("jvmti: kernel does not support %d clock id", perf_clk_id); 250 if (use_arch_timestamp)
251 warnx("jvmti: arch timestamp not supported");
252 else
253 warnx("jvmti: kernel does not support %d clock id", perf_clk_id);
254 }
219 255
220 memset(&header, 0, sizeof(header)); 256 memset(&header, 0, sizeof(header));
221 257
@@ -263,6 +299,9 @@ void *jvmti_open(void)
263 299
264 header.timestamp = perf_get_timestamp(); 300 header.timestamp = perf_get_timestamp();
265 301
302 if (use_arch_timestamp)
303 header.flags |= JITDUMP_FLAGS_ARCH_TIMESTAMP;
304
266 if (!fwrite(&header, sizeof(header), 1, fp)) { 305 if (!fwrite(&header, sizeof(header), 1, fp)) {
267 warn("jvmti: cannot write dumpfile header"); 306 warn("jvmti: cannot write dumpfile header");
268 goto error; 307 goto error;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index da48fd843438..85ceff357769 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o
69libperf-y += record.o 69libperf-y += record.o
70libperf-y += srcline.o 70libperf-y += srcline.o
71libperf-y += data.o 71libperf-y += data.o
72libperf-$(CONFIG_X86) += tsc.o 72libperf-y += tsc.o
73libperf-$(CONFIG_AUXTRACE) += tsc.o
74libperf-y += cloexec.o 73libperf-y += cloexec.o
75libperf-y += thread-stack.o 74libperf-y += thread-stack.o
76libperf-$(CONFIG_AUXTRACE) += auxtrace.o 75libperf-$(CONFIG_AUXTRACE) += auxtrace.o
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index ad0c0bb1fbc7..52fcef3074fe 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -17,6 +17,7 @@
17#include "strlist.h" 17#include "strlist.h"
18#include <elf.h> 18#include <elf.h>
19 19
20#include "tsc.h"
20#include "session.h" 21#include "session.h"
21#include "jit.h" 22#include "jit.h"
22#include "jitdump.h" 23#include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc {
33 size_t bufsize; 34 size_t bufsize;
34 FILE *in; 35 FILE *in;
35 bool needs_bswap; /* handles cross-endianess */ 36 bool needs_bswap; /* handles cross-endianess */
37 bool use_arch_timestamp;
36 void *debug_data; 38 void *debug_data;
37 size_t nr_debug_entries; 39 size_t nr_debug_entries;
38 uint32_t code_load_count; 40 uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name)
158 header.flags = bswap_64(header.flags); 160 header.flags = bswap_64(header.flags);
159 } 161 }
160 162
163 jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
164
161 if (verbose > 2) 165 if (verbose > 2)
162 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n", 166 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
163 header.version, 167 header.version,
164 header.total_size, 168 header.total_size,
165 (unsigned long long)header.timestamp, 169 (unsigned long long)header.timestamp,
166 header.pid, 170 header.pid,
167 header.elf_mach); 171 header.elf_mach,
172 jd->use_arch_timestamp);
168 173
169 if (header.flags & JITDUMP_FLAGS_RESERVED) { 174 if (header.flags & JITDUMP_FLAGS_RESERVED) {
170 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", 175 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name)
172 goto error; 177 goto error;
173 } 178 }
174 179
180 if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
181 pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
182 goto error;
183 }
184
175 /* 185 /*
176 * validate event is using the correct clockid 186 * validate event is using the correct clockid
177 */ 187 */
178 if (jit_validate_events(jd->session)) { 188 if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
179 pr_err("error, jitted code must be sampled with perf record -k 1\n"); 189 pr_err("error, jitted code must be sampled with perf record -k 1\n");
180 goto error; 190 goto error;
181 } 191 }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
329 return 0; 339 return 0;
330} 340}
331 341
342static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
343{
344 struct perf_tsc_conversion tc;
345
346 if (!jd->use_arch_timestamp)
347 return timestamp;
348
349 tc.time_shift = jd->session->time_conv.time_shift;
350 tc.time_mult = jd->session->time_conv.time_mult;
351 tc.time_zero = jd->session->time_conv.time_zero;
352
353 if (!tc.time_mult)
354 return 0;
355
356 return tsc_to_perf_time(timestamp, &tc);
357}
358
332static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) 359static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
333{ 360{
334 struct perf_sample sample; 361 struct perf_sample sample;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
410 id->tid = tid; 437 id->tid = tid;
411 } 438 }
412 if (jd->sample_type & PERF_SAMPLE_TIME) 439 if (jd->sample_type & PERF_SAMPLE_TIME)
413 id->time = jr->load.p.timestamp; 440 id->time = convert_timestamp(jd, jr->load.p.timestamp);
414 441
415 /* 442 /*
416 * create pseudo sample to induce dso hit increment 443 * create pseudo sample to induce dso hit increment
@@ -499,7 +526,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
499 id->tid = tid; 526 id->tid = tid;
500 } 527 }
501 if (jd->sample_type & PERF_SAMPLE_TIME) 528 if (jd->sample_type & PERF_SAMPLE_TIME)
502 id->time = jr->load.p.timestamp; 529 id->time = convert_timestamp(jd, jr->load.p.timestamp);
503 530
504 /* 531 /*
505 * create pseudo sample to induce dso hit increment 532 * create pseudo sample to induce dso hit increment
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
index b66c1f503d9e..bcacd20d0c1c 100644
--- a/tools/perf/util/jitdump.h
+++ b/tools/perf/util/jitdump.h
@@ -23,9 +23,12 @@
23#define JITHEADER_VERSION 1 23#define JITHEADER_VERSION 1
24 24
25enum jitdump_flags_bits { 25enum jitdump_flags_bits {
26 JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT,
26 JITDUMP_FLAGS_MAX_BIT, 27 JITDUMP_FLAGS_MAX_BIT,
27}; 28};
28 29
30#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT)
31
29#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ 32#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \
30 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0) 33 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
31 34
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
index 280ddc067556..d5b11e2b85e0 100644
--- a/tools/perf/util/tsc.h
+++ b/tools/perf/util/tsc.h
@@ -4,7 +4,16 @@
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#include "event.h" 6#include "event.h"
7#include "../arch/x86/util/tsc.h" 7
8struct perf_tsc_conversion {
9 u16 time_shift;
10 u32 time_mult;
11 u64 time_zero;
12};
13struct perf_event_mmap_page;
14
15int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
16 struct perf_tsc_conversion *tc);
8 17
9u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 18u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
10u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 19u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);