Skip to content

Commit

Permalink
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "Tooling fixes plus a handful of late arriving tooling changes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf tools: Fix link time error with sample_reg_masks on non x86
  perf build: Fix Intel PT instruction decoder dependency problem
  perf dwarf: Fix potential array out of bounds access
  perf record: Add ability to name registers to record
  perf/x86: Add list of register names
  perf script: Enable printing of interrupted machine state
  perf evlist: Open event on evsel cpus and threads
  bpf tools: New API to get name from a BPF object
  perf tools: Fix build on powerpc broken by pt/bts
  • Loading branch information
torvalds committed Sep 3, 2015
2 parents ca520ca + 5b92356 commit 79b0691
Show file tree
Hide file tree
Showing 22 changed files with 201 additions and 16 deletions.
25 changes: 22 additions & 3 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,15 +880,26 @@ struct bpf_object *bpf_object__open(const char *path)
}

struct bpf_object *bpf_object__open_buffer(void *obj_buf,
size_t obj_buf_sz)
size_t obj_buf_sz,
const char *name)
{
char tmp_name[64];

/* param validation */
if (!obj_buf || obj_buf_sz <= 0)
return NULL;

pr_debug("loading object from buffer\n");
if (!name) {
snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx",
(unsigned long)obj_buf,
(unsigned long)obj_buf_sz);
tmp_name[sizeof(tmp_name) - 1] = '\0';
name = tmp_name;
}
pr_debug("loading object '%s' from buffer\n",
name);

return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
return __bpf_object__open(name, obj_buf, obj_buf_sz);
}

int bpf_object__unload(struct bpf_object *obj)
Expand Down Expand Up @@ -975,6 +986,14 @@ bpf_object__next(struct bpf_object *prev)
return next;
}

const char *
bpf_object__get_name(struct bpf_object *obj)
{
if (!obj)
return NULL;
return obj->path;
}

struct bpf_program *
bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
{
Expand Down
4 changes: 3 additions & 1 deletion tools/lib/bpf/libbpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ struct bpf_object;

struct bpf_object *bpf_object__open(const char *path);
struct bpf_object *bpf_object__open_buffer(void *obj_buf,
size_t obj_buf_sz);
size_t obj_buf_sz,
const char *name);
void bpf_object__close(struct bpf_object *object);

/* Load/unload object into/from kernel */
int bpf_object__load(struct bpf_object *obj);
int bpf_object__unload(struct bpf_object *obj);
const char *bpf_object__get_name(struct bpf_object *obj);

struct bpf_object *bpf_object__next(struct bpf_object *prev);
#define bpf_object__for_each_safe(pos, tmp) \
Expand Down
6 changes: 5 additions & 1 deletion tools/perf/Documentation/perf-record.txt
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,11 @@ filter out the startup phase of the program, which is often very different.
--intr-regs::
Capture machine state (registers) at interrupt, i.e., on counter overflows for
each sample. List of captured registers depends on the architecture. This option
is off by default.
is off by default. It is possible to select the registers to sample using their
symbolic names, e.g. on x86, ax, si. To list the available registers use
--intr-regs=\?. To name registers, pass a comma separated list such as
--intr-regs=ax,bx. The list of register is architecture dependent.


--running-time::
Record running and enabled time for read events (:S)
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/Documentation/perf-script.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ OPTIONS
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
srcline, period, flags.
srcline, period, iregs, flags.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/arch/sh/util/dwarf-regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ const char *sh_regs_table[SH_MAX_REGS] = {
/* Return architecture dependent register string (for kprobe-tracer) */
const char *get_arch_regstr(unsigned int n)
{
return (n <= SH_MAX_REGS) ? sh_regs_table[n] : NULL;
return (n < SH_MAX_REGS) ? sh_regs_table[n] : NULL;
}
2 changes: 1 addition & 1 deletion tools/perf/arch/sparc/util/dwarf-regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ const char *sparc_regs_table[SPARC_MAX_REGS] = {
*/
const char *get_arch_regstr(unsigned int n)
{
return (n <= SPARC_MAX_REGS) ? sparc_regs_table[n] : NULL;
return (n < SPARC_MAX_REGS) ? sparc_regs_table[n] : NULL;
}
1 change: 1 addition & 0 deletions tools/perf/arch/x86/util/Build
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ libperf-y += header.o
libperf-y += tsc.o
libperf-y += pmu.o
libperf-y += kvm-stat.o
libperf-y += perf_regs.o

libperf-$(CONFIG_DWARF) += dwarf-regs.o

Expand Down
2 changes: 1 addition & 1 deletion tools/perf/arch/x86/util/dwarf-regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ const char *x86_64_regs_table[X86_64_MAX_REGS] = {
/* Return architecture dependent register string (for kprobe-tracer) */
const char *get_arch_regstr(unsigned int n)
{
return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
return (n < ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
}
28 changes: 28 additions & 0 deletions tools/perf/arch/x86/util/perf_regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "../../perf.h"
#include "../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
SMPL_REG(AX, PERF_REG_X86_AX),
SMPL_REG(BX, PERF_REG_X86_BX),
SMPL_REG(CX, PERF_REG_X86_CX),
SMPL_REG(DX, PERF_REG_X86_DX),
SMPL_REG(SI, PERF_REG_X86_SI),
SMPL_REG(DI, PERF_REG_X86_DI),
SMPL_REG(BP, PERF_REG_X86_BP),
SMPL_REG(SP, PERF_REG_X86_SP),
SMPL_REG(IP, PERF_REG_X86_IP),
SMPL_REG(FLAGS, PERF_REG_X86_FLAGS),
SMPL_REG(CS, PERF_REG_X86_CS),
SMPL_REG(SS, PERF_REG_X86_SS),
#ifdef HAVE_ARCH_X86_64_SUPPORT
SMPL_REG(R8, PERF_REG_X86_R8),
SMPL_REG(R9, PERF_REG_X86_R9),
SMPL_REG(R10, PERF_REG_X86_R10),
SMPL_REG(R11, PERF_REG_X86_R11),
SMPL_REG(R12, PERF_REG_X86_R12),
SMPL_REG(R13, PERF_REG_X86_R13),
SMPL_REG(R14, PERF_REG_X86_R14),
SMPL_REG(R15, PERF_REG_X86_R15),
#endif
SMPL_REG_END
};
9 changes: 6 additions & 3 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
#include "util/cpumap.h"
#include "util/thread_map.h"
#include "util/data.h"
#include "util/perf_regs.h"
#include "util/auxtrace.h"
#include "util/parse-branch-options.h"
#include "util/parse-regs-options.h"

#include <unistd.h>
#include <sched.h>
Expand Down Expand Up @@ -279,7 +281,7 @@ static int record__open(struct record *rec)

evlist__for_each(evlist, pos) {
try_again:
if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
if (verbose)
ui__warning("%s\n", msg);
Expand Down Expand Up @@ -1080,8 +1082,9 @@ struct option __record_options[] = {
"sample transaction flags (special events only)"),
OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
"use per-thread mmaps"),
OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
"Sample machine registers on interrupt"),
OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
"sample selected machine registers on interrupt,"
" use -I ? to list register names", parse_regs),
OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
"Record running/enabled time of read (:S) events"),
OPT_CALLBACK('k', "clockid", &record.opts,
Expand Down
31 changes: 30 additions & 1 deletion tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "util/exec_cmd.h"
#include "util/header.h"
#include "util/parse-options.h"
#include "util/perf_regs.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/symbol.h"
Expand Down Expand Up @@ -46,6 +47,7 @@ enum perf_output_field {
PERF_OUTPUT_SYMOFFSET = 1U << 11,
PERF_OUTPUT_SRCLINE = 1U << 12,
PERF_OUTPUT_PERIOD = 1U << 13,
PERF_OUTPUT_IREGS = 1U << 14,
};

struct output_option {
Expand All @@ -66,6 +68,7 @@ struct output_option {
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
{.str = "period", .field = PERF_OUTPUT_PERIOD},
{.str = "iregs", .field = PERF_OUTPUT_IREGS},
};

/* default set to maintain compatibility with current format */
Expand Down Expand Up @@ -255,6 +258,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
PERF_OUTPUT_PERIOD))
return -EINVAL;

if (PRINT_FIELD(IREGS) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
PERF_OUTPUT_IREGS))
return -EINVAL;

return 0;
}

Expand Down Expand Up @@ -352,6 +360,24 @@ static int perf_session__check_output_opt(struct perf_session *session)
return 0;
}

static void print_sample_iregs(union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct thread *thread __maybe_unused,
struct perf_event_attr *attr)
{
struct regs_dump *regs = &sample->intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;

if (!regs)
return;

for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
}

static void print_sample_start(struct perf_sample *sample,
struct thread *thread,
struct perf_evsel *evsel)
Expand Down Expand Up @@ -525,6 +551,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
PERF_MAX_STACK_DEPTH);
}

if (PRINT_FIELD(IREGS))
print_sample_iregs(event, sample, thread, attr);

printf("\n");
}

Expand Down Expand Up @@ -1643,7 +1672,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,flags", parse_output_fields),
"addr,symoff,period,iregs,flags", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/perf.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ struct record_opts {
bool sample_time_set;
bool callgraph_set;
bool period;
bool sample_intr_regs;
bool running_time;
bool full_auxtrace;
bool auxtrace_snapshot_mode;
Expand All @@ -64,6 +63,7 @@ struct record_opts {
unsigned int auxtrace_mmap_pages;
unsigned int user_freq;
u64 branch_stack;
u64 sample_intr_regs;
u64 default_interval;
u64 user_interval;
size_t auxtrace_snapshot_size;
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/tests/llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
{
struct bpf_object *obj;

obj = bpf_object__open_buffer(obj_buf, obj_buf_sz);
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
if (!obj)
return -1;
bpf_object__close(obj);
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/Build
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ libperf-y += record.o
libperf-y += srcline.o
libperf-y += data.o
libperf-$(CONFIG_X86) += tsc.o
libperf-$(CONFIG_AUXTRACE) += tsc.o
libperf-y += cloexec.o
libperf-y += thread-stack.o
libperf-$(CONFIG_AUXTRACE) += auxtrace.o
libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
libperf-$(CONFIG_AUXTRACE) += intel-pt.o
libperf-$(CONFIG_AUXTRACE) += intel-bts.o
libperf-y += parse-branch-options.o
libperf-y += parse-regs-options.o

libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-file.o
Expand Down
4 changes: 4 additions & 0 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,10 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
if (evsel->filter == NULL)
continue;

/*
* filters only work for tracepoint event, which doesn't have cpu limit.
* So evlist and evsel should always be same.
*/
err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter);
if (err) {
*err_evsel = evsel;
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
perf_evsel__config_callgraph(evsel, opts, &callchain_param);

if (opts->sample_intr_regs) {
attr->sample_regs_intr = PERF_REGS_MASK;
attr->sample_regs_intr = opts->sample_intr_regs;
perf_evsel__set_sample_bit(evsel, REGS_INTR);
}

Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/intel-pt-decoder/Build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk
inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt

$(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
$(call rule_mkdir)
@$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@

$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ static void intel_pt_insn_decoder(struct insn *insn,
case 4:
intel_pt_insn->rel = bswap_32(insn->immediate.value);
break;
default:
intel_pt_insn->rel = 0;
break;
}
#else
intel_pt_insn->rel = insn->immediate.value;
Expand Down
Loading

0 comments on commit 79b0691

Please sign in to comment.