Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

Infrastructure changes:

 o More prep work to support Intel PT: (Adrian Hunter)
   - Polishing 'script' BTS output
   - 'inject' can specify --kallsym
   - VDSO is per machine, not a global var
   - Expose data addr lookup functions previously private to 'script'
   - Large mmap fixes in events processing

 o Fix build on gcc 4.4.7 (Arnaldo Carvalho de Melo)

 o Event ordering fixes (Jiri Olsa)

 o Include standard stringify macros in power pc code (Sukadev Bhattiprolu)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Jul 28, 2014
2 parents f4be073 + dcabb50 commit 068f1d3
Show file tree
Hide file tree
Showing 29 changed files with 470 additions and 115 deletions.
3 changes: 3 additions & 0 deletions tools/perf/Documentation/perf-inject.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ OPTIONS
tasks slept. sched_switch contains a callchain where a task slept and
sched_stat contains a timeslice how long a task slept.

--kallsyms=<file>::
kallsyms pathname

SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
4 changes: 1 addition & 3 deletions tools/perf/arch/powerpc/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#include <string.h>

#include "../../util/header.h"

#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
#include "../../util/util.h"

#define mfspr(rn) ({unsigned long rval; \
asm volatile("mfspr %0," __stringify(rn) \
Expand Down
9 changes: 9 additions & 0 deletions tools/perf/arch/x86/util/tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,

return 0;
}

u64 rdtsc(void)
{
unsigned int low, high;

asm volatile("rdtsc" : "=a" (low), "=d" (high));

return low | ((u64)high) << 32;
}
2 changes: 2 additions & 0 deletions tools/perf/builtin-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
"where and how long tasks slept"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show build ids, etc)"),
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
"kallsyms pathname"),
OPT_END()
};
const char * const inject_usage[] = {
Expand Down
7 changes: 6 additions & 1 deletion tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ static struct perf_event_header finished_round_event = {

static int record__mmap_read_all(struct record *rec)
{
u64 bytes_written = rec->bytes_written;
int i;
int rc = 0;

Expand All @@ -250,7 +251,11 @@ static int record__mmap_read_all(struct record *rec)
}
}

if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
/*
* Mark the round finished in case we wrote
* at least one event.
*/
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));

out:
Expand Down
60 changes: 19 additions & 41 deletions tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,52 +358,20 @@ static void print_sample_start(struct perf_sample *sample,
}
}

static bool is_bts_event(struct perf_event_attr *attr)
{
return ((attr->type == PERF_TYPE_HARDWARE) &&
(attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
(attr->sample_period == 1));
}

static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
{
if ((attr->type == PERF_TYPE_SOFTWARE) &&
((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
return true;

if (is_bts_event(attr))
return true;

return false;
}

static void print_sample_addr(union perf_event *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread,
struct perf_event_attr *attr)
{
struct addr_location al;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

printf("%16" PRIx64, sample->addr);

if (!sample_addr_correlates_sym(attr))
return;

thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
sample->addr, &al);
if (!al.map)
thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
sample->addr, &al);

al.cpu = sample->cpu;
al.sym = NULL;

if (al.map)
al.sym = map__find_symbol(al.map, al.addr, NULL);
perf_event__preprocess_sample_addr(event, sample, machine, thread, &al);

if (PRINT_FIELD(SYM)) {
printf(" ");
Expand All @@ -427,25 +395,35 @@ static void print_sample_bts(union perf_event *event,
struct addr_location *al)
{
struct perf_event_attr *attr = &evsel->attr;
bool print_srcline_last = false;

/* print branch_from information */
if (PRINT_FIELD(IP)) {
if (!symbol_conf.use_callchain)
printf(" ");
else
unsigned int print_opts = output[attr->type].print_ip_opts;

if (symbol_conf.use_callchain && sample->callchain) {
printf("\n");
perf_evsel__print_ip(evsel, sample, al,
output[attr->type].print_ip_opts,
} else {
printf(" ");
if (print_opts & PRINT_IP_OPT_SRCLINE) {
print_srcline_last = true;
print_opts &= ~PRINT_IP_OPT_SRCLINE;
}
}
perf_evsel__print_ip(evsel, sample, al, print_opts,
PERF_MAX_STACK_DEPTH);
}

printf(" => ");

/* print branch_to information */
if (PRINT_FIELD(ADDR) ||
((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
!output[attr->type].user_set))
!output[attr->type].user_set)) {
printf(" => ");
print_sample_addr(event, sample, al->machine, thread, attr);
}

if (print_srcline_last)
map__fprintf_srcline(al->map, al->addr, "\n ", stdout);

printf("\n");
}
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1994,10 +1994,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.mmap_data = 1,
.sample_period = 1,
};

attr.config = config;
attr.sample_period = 1;

event_attr_init(&attr);

Expand Down
9 changes: 0 additions & 9 deletions tools/perf/tests/perf-time-to-tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@
} \
}

static u64 rdtsc(void)
{
unsigned int low, high;

asm volatile("rdtsc" : "=a" (low), "=d" (high));

return low | ((u64)high) << 32;
}

/**
* test__perf_time_to_tsc - test converting perf time to TSC.
*
Expand Down
9 changes: 7 additions & 2 deletions tools/perf/util/cloexec.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <sched.h>
#include "util.h"
#include "../perf.h"
#include "cloexec.h"
Expand All @@ -14,9 +15,13 @@ static int perf_flag_probe(void)
};
int fd;
int err;
int cpu = sched_getcpu();

if (cpu < 0)
cpu = 0;

/* check cloexec flag */
fd = sys_perf_event_open(&attr, 0, -1, -1,
fd = sys_perf_event_open(&attr, -1, cpu, -1,
PERF_FLAG_FD_CLOEXEC);
err = errno;

Expand All @@ -30,7 +35,7 @@ static int perf_flag_probe(void)
err, strerror(err));

/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
err = errno;

if (WARN_ONCE(fd < 0,
Expand Down
70 changes: 61 additions & 9 deletions tools/perf/util/dso.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ static int open_dso(struct dso *dso, struct machine *machine)
{
int fd = __open_dso(dso, machine);

if (fd > 0) {
if (fd >= 0) {
dso__list_add(dso);
/*
* Check if we crossed the allowed number
Expand Down Expand Up @@ -331,26 +331,44 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
};
int i = 0;

if (dso->data.status == DSO_DATA_STATUS_ERROR)
return -1;

if (dso->data.fd >= 0)
return dso->data.fd;
goto out;

if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
dso->data.fd = open_dso(dso, machine);
return dso->data.fd;
goto out;
}

do {
int fd;

dso->binary_type = binary_type_data[i++];

fd = open_dso(dso, machine);
if (fd >= 0)
return dso->data.fd = fd;
dso->data.fd = open_dso(dso, machine);
if (dso->data.fd >= 0)
goto out;

} while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
out:
if (dso->data.fd >= 0)
dso->data.status = DSO_DATA_STATUS_OK;
else
dso->data.status = DSO_DATA_STATUS_ERROR;

return -EINVAL;
return dso->data.fd;
}

bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
{
u32 flag = 1 << by;

if (dso->data.status_seen & flag)
return true;

dso->data.status_seen |= flag;

return false;
}

static void
Expand Down Expand Up @@ -526,6 +544,28 @@ static int data_file_size(struct dso *dso)
return 0;
}

/**
* dso__data_size - Return dso data size
* @dso: dso object
* @machine: machine object
*
* Return: dso data size
*/
off_t dso__data_size(struct dso *dso, struct machine *machine)
{
int fd;

fd = dso__data_fd(dso, machine);
if (fd < 0)
return fd;

if (data_file_size(dso))
return -1;

/* For now just estimate dso data size is close to file size */
return dso->data.file_size;
}

static ssize_t data_read_offset(struct dso *dso, u64 offset,
u8 *data, ssize_t size)
{
Expand Down Expand Up @@ -701,6 +741,7 @@ struct dso *dso__new(const char *name)
dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
dso->data.cache = RB_ROOT;
dso->data.fd = -1;
dso->data.status = DSO_DATA_STATUS_UNKNOWN;
dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
dso->is_64_bit = (sizeof(void *) == 8);
Expand Down Expand Up @@ -899,3 +940,14 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)

return ret;
}

enum dso_type dso__type(struct dso *dso, struct machine *machine)
{
int fd;

fd = dso__data_fd(dso, machine);
if (fd < 0)
return DSO__TYPE_UNKNOWN;

return dso__type_fd(fd);
}
Loading

0 comments on commit 068f1d3

Please sign in to comment.