|
@@ -17,6 +17,7 @@
|
|
|
#include "strlist.h"
|
|
|
#include <elf.h>
|
|
|
|
|
|
+#include "tsc.h"
|
|
|
#include "session.h"
|
|
|
#include "jit.h"
|
|
|
#include "jitdump.h"
|
|
@@ -33,6 +34,7 @@ struct jit_buf_desc {
|
|
|
size_t bufsize;
|
|
|
FILE *in;
|
|
|
bool needs_bswap; /* handles cross-endianess */
|
|
|
+ bool use_arch_timestamp;
|
|
|
void *debug_data;
|
|
|
size_t nr_debug_entries;
|
|
|
uint32_t code_load_count;
|
|
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name)
|
|
|
header.flags = bswap_64(header.flags);
|
|
|
}
|
|
|
|
|
|
+ jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
|
|
|
+
|
|
|
if (verbose > 2)
|
|
|
- pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n",
|
|
|
+ pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
|
|
|
header.version,
|
|
|
header.total_size,
|
|
|
(unsigned long long)header.timestamp,
|
|
|
header.pid,
|
|
|
- header.elf_mach);
|
|
|
+ header.elf_mach,
|
|
|
+ jd->use_arch_timestamp);
|
|
|
|
|
|
if (header.flags & JITDUMP_FLAGS_RESERVED) {
|
|
|
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)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
+ if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
|
|
|
+ pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* validate event is using the correct clockid
|
|
|
*/
|
|
|
- if (jit_validate_events(jd->session)) {
|
|
|
+ if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
|
|
|
pr_err("error, jitted code must be sampled with perf record -k 1\n");
|
|
|
goto error;
|
|
|
}
|
|
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
|
|
|
+{
|
|
|
+ struct perf_tsc_conversion tc;
|
|
|
+
|
|
|
+ if (!jd->use_arch_timestamp)
|
|
|
+ return timestamp;
|
|
|
+
|
|
|
+ tc.time_shift = jd->session->time_conv.time_shift;
|
|
|
+ tc.time_mult = jd->session->time_conv.time_mult;
|
|
|
+ tc.time_zero = jd->session->time_conv.time_zero;
|
|
|
+
|
|
|
+ if (!tc.time_mult)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return tsc_to_perf_time(timestamp, &tc);
|
|
|
+}
|
|
|
+
|
|
|
static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
|
|
|
{
|
|
|
struct perf_sample sample;
|
|
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
|
|
|
id->tid = tid;
|
|
|
}
|
|
|
if (jd->sample_type & PERF_SAMPLE_TIME)
|
|
|
- id->time = jr->load.p.timestamp;
|
|
|
+ id->time = convert_timestamp(jd, jr->load.p.timestamp);
|
|
|
|
|
|
/*
|
|
|
* 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)
|
|
|
id->tid = tid;
|
|
|
}
|
|
|
if (jd->sample_type & PERF_SAMPLE_TIME)
|
|
|
- id->time = jr->load.p.timestamp;
|
|
|
+ id->time = convert_timestamp(jd, jr->load.p.timestamp);
|
|
|
|
|
|
/*
|
|
|
* create pseudo sample to induce dso hit increment
|