-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'perf-core-for-mingo-20161125' of git://git.kernel.org/pub/…
…scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Improve ARM support in the annotation code, affecting 'perf annotate', 'perf report' and live annotation in 'perf top' (Kim Phillips) - Initial support for PowerPC in the annotation code (Ravi Bangoria) - Skip repetitive scheduler function on the top of the stack in 'perf sched timehist' (Namhyung Kim) Fixes: - Fix maps resolution in libbpf (Eric Leblond) - Get the kernel signature via /proc/version_signature, available on Ubuntu systems, to make sure BPF proggies works, as the one provided via 'uname -r' doesn't (Wang Nan) - Fix segfault in 'perf record' when running with suid and kptr_restrict is 1 (Wang Nan) Infrastructure changes: - Support per-arch instruction tables, kept via a static or dynamic table (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
- Loading branch information
Showing
13 changed files
with
431 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,59 @@ | ||
static struct ins arm__instructions[] = { | ||
{ .name = "add", .ops = &mov_ops, }, | ||
{ .name = "addl", .ops = &mov_ops, }, | ||
{ .name = "addq", .ops = &mov_ops, }, | ||
{ .name = "addw", .ops = &mov_ops, }, | ||
{ .name = "and", .ops = &mov_ops, }, | ||
{ .name = "b", .ops = &jump_ops, }, // might also be a call | ||
{ .name = "bcc", .ops = &jump_ops, }, | ||
{ .name = "bcs", .ops = &jump_ops, }, | ||
{ .name = "beq", .ops = &jump_ops, }, | ||
{ .name = "bge", .ops = &jump_ops, }, | ||
{ .name = "bgt", .ops = &jump_ops, }, | ||
{ .name = "bhi", .ops = &jump_ops, }, | ||
{ .name = "bl", .ops = &call_ops, }, | ||
{ .name = "bls", .ops = &jump_ops, }, | ||
{ .name = "blt", .ops = &jump_ops, }, | ||
{ .name = "blx", .ops = &call_ops, }, | ||
{ .name = "bne", .ops = &jump_ops, }, | ||
{ .name = "bts", .ops = &mov_ops, }, | ||
{ .name = "call", .ops = &call_ops, }, | ||
{ .name = "callq", .ops = &call_ops, }, | ||
{ .name = "cmp", .ops = &mov_ops, }, | ||
{ .name = "cmpb", .ops = &mov_ops, }, | ||
{ .name = "cmpl", .ops = &mov_ops, }, | ||
{ .name = "cmpq", .ops = &mov_ops, }, | ||
{ .name = "cmpw", .ops = &mov_ops, }, | ||
{ .name = "cmpxch", .ops = &mov_ops, }, | ||
{ .name = "dec", .ops = &dec_ops, }, | ||
{ .name = "decl", .ops = &dec_ops, }, | ||
{ .name = "imul", .ops = &mov_ops, }, | ||
{ .name = "inc", .ops = &dec_ops, }, | ||
{ .name = "incl", .ops = &dec_ops, }, | ||
{ .name = "ja", .ops = &jump_ops, }, | ||
{ .name = "jae", .ops = &jump_ops, }, | ||
{ .name = "jb", .ops = &jump_ops, }, | ||
{ .name = "jbe", .ops = &jump_ops, }, | ||
{ .name = "jc", .ops = &jump_ops, }, | ||
{ .name = "jcxz", .ops = &jump_ops, }, | ||
{ .name = "je", .ops = &jump_ops, }, | ||
{ .name = "jecxz", .ops = &jump_ops, }, | ||
{ .name = "jg", .ops = &jump_ops, }, | ||
{ .name = "jge", .ops = &jump_ops, }, | ||
{ .name = "jl", .ops = &jump_ops, }, | ||
{ .name = "jle", .ops = &jump_ops, }, | ||
{ .name = "jmp", .ops = &jump_ops, }, | ||
{ .name = "jmpq", .ops = &jump_ops, }, | ||
{ .name = "jna", .ops = &jump_ops, }, | ||
{ .name = "jnae", .ops = &jump_ops, }, | ||
{ .name = "jnb", .ops = &jump_ops, }, | ||
{ .name = "jnbe", .ops = &jump_ops, }, | ||
{ .name = "jnc", .ops = &jump_ops, }, | ||
{ .name = "jne", .ops = &jump_ops, }, | ||
{ .name = "jng", .ops = &jump_ops, }, | ||
{ .name = "jnge", .ops = &jump_ops, }, | ||
{ .name = "jnl", .ops = &jump_ops, }, | ||
{ .name = "jnle", .ops = &jump_ops, }, | ||
{ .name = "jno", .ops = &jump_ops, }, | ||
{ .name = "jnp", .ops = &jump_ops, }, | ||
{ .name = "jns", .ops = &jump_ops, }, | ||
{ .name = "jnz", .ops = &jump_ops, }, | ||
{ .name = "jo", .ops = &jump_ops, }, | ||
{ .name = "jp", .ops = &jump_ops, }, | ||
{ .name = "jpe", .ops = &jump_ops, }, | ||
{ .name = "jpo", .ops = &jump_ops, }, | ||
{ .name = "jrcxz", .ops = &jump_ops, }, | ||
{ .name = "js", .ops = &jump_ops, }, | ||
{ .name = "jz", .ops = &jump_ops, }, | ||
{ .name = "lea", .ops = &mov_ops, }, | ||
{ .name = "lock", .ops = &lock_ops, }, | ||
{ .name = "mov", .ops = &mov_ops, }, | ||
{ .name = "movb", .ops = &mov_ops, }, | ||
{ .name = "movdqa", .ops = &mov_ops, }, | ||
{ .name = "movl", .ops = &mov_ops, }, | ||
{ .name = "movq", .ops = &mov_ops, }, | ||
{ .name = "movslq", .ops = &mov_ops, }, | ||
{ .name = "movzbl", .ops = &mov_ops, }, | ||
{ .name = "movzwl", .ops = &mov_ops, }, | ||
{ .name = "nop", .ops = &nop_ops, }, | ||
{ .name = "nopl", .ops = &nop_ops, }, | ||
{ .name = "nopw", .ops = &nop_ops, }, | ||
{ .name = "or", .ops = &mov_ops, }, | ||
{ .name = "orl", .ops = &mov_ops, }, | ||
{ .name = "test", .ops = &mov_ops, }, | ||
{ .name = "testb", .ops = &mov_ops, }, | ||
{ .name = "testl", .ops = &mov_ops, }, | ||
{ .name = "xadd", .ops = &mov_ops, }, | ||
{ .name = "xbeginl", .ops = &jump_ops, }, | ||
{ .name = "xbeginq", .ops = &jump_ops, }, | ||
{ .name = "retq", .ops = &ret_ops, }, | ||
#include <sys/types.h> | ||
#include <regex.h> | ||
|
||
struct arm_annotate { | ||
regex_t call_insn, | ||
jump_insn; | ||
}; | ||
|
||
static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name) | ||
{ | ||
struct arm_annotate *arm = arch->priv; | ||
struct ins_ops *ops; | ||
regmatch_t match[2]; | ||
|
||
if (!regexec(&arm->call_insn, name, 2, match, 0)) | ||
ops = &call_ops; | ||
else if (!regexec(&arm->jump_insn, name, 2, match, 0)) | ||
ops = &jump_ops; | ||
else | ||
return NULL; | ||
|
||
arch__associate_ins_ops(arch, name, ops); | ||
return ops; | ||
} | ||
|
||
static int arm__annotate_init(struct arch *arch) | ||
{ | ||
struct arm_annotate *arm; | ||
int err; | ||
|
||
if (arch->initialized) | ||
return 0; | ||
|
||
arm = zalloc(sizeof(*arm)); | ||
if (!arm) | ||
return -1; | ||
|
||
#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)" | ||
err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED); | ||
if (err) | ||
goto out_free_arm; | ||
err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED); | ||
if (err) | ||
goto out_free_call; | ||
#undef ARM_CONDS | ||
|
||
arch->initialized = true; | ||
arch->priv = arm; | ||
arch->associate_instruction_ops = arm__associate_instruction_ops; | ||
arch->objdump.comment_char = ';'; | ||
arch->objdump.skip_functions_char = '+'; | ||
return 0; | ||
|
||
out_free_call: | ||
regfree(&arm->call_insn); | ||
out_free_arm: | ||
free(arm); | ||
return -1; | ||
} |
Oops, something went wrong.