Commit 3617660e authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core

Pull perf/core improvements and fixes from Jiri Olsa:

  * Wire up perf_regs and unwind support for ARM64 (Jean Pihet)

  * Move u64_swap union to its single user's header, evsel.h (Borislav Petkov)

  * Fix for s390 to properly parse tracepoints plus test code (Alexander Yarygin)

  * Handle EINTR error for readn/writen (Namhyung Kim)
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents aeffe2ab 8ab596af
ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
endif
#ifndef ARCH_PERF_REGS_H
#define ARCH_PERF_REGS_H
#include <stdlib.h>
#include "../../util/types.h"
#include <asm/perf_regs.h>
#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
#define PERF_REG_IP PERF_REG_ARM64_PC
#define PERF_REG_SP PERF_REG_ARM64_SP
static inline const char *perf_reg_name(int id)
{
switch (id) {
case PERF_REG_ARM64_X0:
return "x0";
case PERF_REG_ARM64_X1:
return "x1";
case PERF_REG_ARM64_X2:
return "x2";
case PERF_REG_ARM64_X3:
return "x3";
case PERF_REG_ARM64_X4:
return "x4";
case PERF_REG_ARM64_X5:
return "x5";
case PERF_REG_ARM64_X6:
return "x6";
case PERF_REG_ARM64_X7:
return "x7";
case PERF_REG_ARM64_X8:
return "x8";
case PERF_REG_ARM64_X9:
return "x9";
case PERF_REG_ARM64_X10:
return "x10";
case PERF_REG_ARM64_X11:
return "x11";
case PERF_REG_ARM64_X12:
return "x12";
case PERF_REG_ARM64_X13:
return "x13";
case PERF_REG_ARM64_X14:
return "x14";
case PERF_REG_ARM64_X15:
return "x15";
case PERF_REG_ARM64_X16:
return "x16";
case PERF_REG_ARM64_X17:
return "x17";
case PERF_REG_ARM64_X18:
return "x18";
case PERF_REG_ARM64_X19:
return "x19";
case PERF_REG_ARM64_X20:
return "x20";
case PERF_REG_ARM64_X21:
return "x21";
case PERF_REG_ARM64_X22:
return "x22";
case PERF_REG_ARM64_X23:
return "x23";
case PERF_REG_ARM64_X24:
return "x24";
case PERF_REG_ARM64_X25:
return "x25";
case PERF_REG_ARM64_X26:
return "x26";
case PERF_REG_ARM64_X27:
return "x27";
case PERF_REG_ARM64_X28:
return "x28";
case PERF_REG_ARM64_X29:
return "x29";
case PERF_REG_ARM64_SP:
return "sp";
case PERF_REG_ARM64_LR:
return "lr";
case PERF_REG_ARM64_PC:
return "pc";
default:
return NULL;
}
return NULL;
}
#endif /* ARCH_PERF_REGS_H */
/*
* Mapping of DWARF debug register numbers into register names.
*
* Copyright (C) 2010 Will Deacon, ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stddef.h>
#include <dwarf-regs.h>
struct pt_regs_dwarfnum {
const char *name;
unsigned int dwarfnum;
};
#define STR(s) #s
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
#define GPR_DWARFNUM_NAME(num) \
{.name = STR(%x##num), .dwarfnum = num}
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
/*
* Reference:
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
*/
static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
GPR_DWARFNUM_NAME(0),
GPR_DWARFNUM_NAME(1),
GPR_DWARFNUM_NAME(2),
GPR_DWARFNUM_NAME(3),
GPR_DWARFNUM_NAME(4),
GPR_DWARFNUM_NAME(5),
GPR_DWARFNUM_NAME(6),
GPR_DWARFNUM_NAME(7),
GPR_DWARFNUM_NAME(8),
GPR_DWARFNUM_NAME(9),
GPR_DWARFNUM_NAME(10),
GPR_DWARFNUM_NAME(11),
GPR_DWARFNUM_NAME(12),
GPR_DWARFNUM_NAME(13),
GPR_DWARFNUM_NAME(14),
GPR_DWARFNUM_NAME(15),
GPR_DWARFNUM_NAME(16),
GPR_DWARFNUM_NAME(17),
GPR_DWARFNUM_NAME(18),
GPR_DWARFNUM_NAME(19),
GPR_DWARFNUM_NAME(20),
GPR_DWARFNUM_NAME(21),
GPR_DWARFNUM_NAME(22),
GPR_DWARFNUM_NAME(23),
GPR_DWARFNUM_NAME(24),
GPR_DWARFNUM_NAME(25),
GPR_DWARFNUM_NAME(26),
GPR_DWARFNUM_NAME(27),
GPR_DWARFNUM_NAME(28),
GPR_DWARFNUM_NAME(29),
REG_DWARFNUM_NAME("%lr", 30),
REG_DWARFNUM_NAME("%sp", 31),
REG_DWARFNUM_END,
};
/**
* get_arch_regstr() - lookup register name from it's DWARF register number
* @n: the DWARF register number
*
* get_arch_regstr() returns the name of the register in struct
* regdwarfnum_table from it's DWARF register number. If the register is not
* found in the table, this returns NULL;
*/
const char *get_arch_regstr(unsigned int n)
{
const struct pt_regs_dwarfnum *roff;
for (roff = regdwarfnum_table; roff->name != NULL; roff++)
if (roff->dwarfnum == n)
return roff->name;
return NULL;
}
#include <errno.h>
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"
int libunwind__arch_reg_id(int regnum)
{
switch (regnum) {
case UNW_AARCH64_X0:
return PERF_REG_ARM64_X0;
case UNW_AARCH64_X1:
return PERF_REG_ARM64_X1;
case UNW_AARCH64_X2:
return PERF_REG_ARM64_X2;
case UNW_AARCH64_X3:
return PERF_REG_ARM64_X3;
case UNW_AARCH64_X4:
return PERF_REG_ARM64_X4;
case UNW_AARCH64_X5:
return PERF_REG_ARM64_X5;
case UNW_AARCH64_X6:
return PERF_REG_ARM64_X6;
case UNW_AARCH64_X7:
return PERF_REG_ARM64_X7;
case UNW_AARCH64_X8:
return PERF_REG_ARM64_X8;
case UNW_AARCH64_X9:
return PERF_REG_ARM64_X9;
case UNW_AARCH64_X10:
return PERF_REG_ARM64_X10;
case UNW_AARCH64_X11:
return PERF_REG_ARM64_X11;
case UNW_AARCH64_X12:
return PERF_REG_ARM64_X12;
case UNW_AARCH64_X13:
return PERF_REG_ARM64_X13;
case UNW_AARCH64_X14:
return PERF_REG_ARM64_X14;
case UNW_AARCH64_X15:
return PERF_REG_ARM64_X15;
case UNW_AARCH64_X16:
return PERF_REG_ARM64_X16;
case UNW_AARCH64_X17:
return PERF_REG_ARM64_X17;
case UNW_AARCH64_X18:
return PERF_REG_ARM64_X18;
case UNW_AARCH64_X19:
return PERF_REG_ARM64_X19;
case UNW_AARCH64_X20:
return PERF_REG_ARM64_X20;
case UNW_AARCH64_X21:
return PERF_REG_ARM64_X21;
case UNW_AARCH64_X22:
return PERF_REG_ARM64_X22;
case UNW_AARCH64_X23:
return PERF_REG_ARM64_X23;
case UNW_AARCH64_X24:
return PERF_REG_ARM64_X24;
case UNW_AARCH64_X25:
return PERF_REG_ARM64_X25;
case UNW_AARCH64_X26:
return PERF_REG_ARM64_X26;
case UNW_AARCH64_X27:
return PERF_REG_ARM64_X27;
case UNW_AARCH64_X28:
return PERF_REG_ARM64_X28;
case UNW_AARCH64_X29:
return PERF_REG_ARM64_X29;
case UNW_AARCH64_X30:
return PERF_REG_ARM64_LR;
case UNW_AARCH64_SP:
return PERF_REG_ARM64_SP;
case UNW_AARCH64_PC:
return PERF_REG_ARM64_PC;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return -EINVAL;
}
...@@ -29,11 +29,17 @@ ifeq ($(ARCH),x86) ...@@ -29,11 +29,17 @@ ifeq ($(ARCH),x86)
endif endif
NO_PERF_REGS := 0 NO_PERF_REGS := 0
endif endif
ifeq ($(ARCH),arm) ifeq ($(ARCH),arm)
NO_PERF_REGS := 0 NO_PERF_REGS := 0
LIBUNWIND_LIBS = -lunwind -lunwind-arm LIBUNWIND_LIBS = -lunwind -lunwind-arm
endif endif
ifeq ($(ARCH),arm64)
NO_PERF_REGS := 0
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
endif
# So far there's only x86 libdw unwind support merged in perf. # So far there's only x86 libdw unwind support merged in perf.
# Disable it on all other architectures in case libdw unwind # Disable it on all other architectures in case libdw unwind
# support is detected in system. Add supported architectures # support is detected in system. Add supported architectures
...@@ -370,7 +376,7 @@ else ...@@ -370,7 +376,7 @@ else
endif endif
ifndef NO_LIBUNWIND ifndef NO_LIBUNWIND
ifeq ($(ARCH),arm) ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
$(call feature_check,libunwind-debug-frame) $(call feature_check,libunwind-debug-frame)
ifneq ($(feature-libunwind-debug-frame), 1) ifneq ($(feature-libunwind-debug-frame), 1)
msg := $(warning No debug_frame support found in libunwind); msg := $(warning No debug_frame support found in libunwind);
......
...@@ -1174,188 +1174,240 @@ static int test__all_tracepoints(struct perf_evlist *evlist) ...@@ -1174,188 +1174,240 @@ static int test__all_tracepoints(struct perf_evlist *evlist)
struct evlist_test { struct evlist_test {
const char *name; const char *name;
__u32 type; __u32 type;
const int id;
int (*check)(struct perf_evlist *evlist); int (*check)(struct perf_evlist *evlist);
}; };
static struct evlist_test test__events[] = { static struct evlist_test test__events[] = {
[0] = { {
.name = "syscalls:sys_enter_open", .name = "syscalls:sys_enter_open",
.check = test__checkevent_tracepoint, .check = test__checkevent_tracepoint,
.id = 0,
}, },
[1] = { {
.name = "syscalls:*", .name = "syscalls:*",
.check = test__checkevent_tracepoint_multi, .check = test__checkevent_tracepoint_multi,
.id = 1,
}, },
[2] = { {
.name = "r1a", .name = "r1a",
.check = test__checkevent_raw, .check = test__checkevent_raw,
.id = 2,
}, },
[3] = { {
.name = "1:1", .name = "1:1",
.check = test__checkevent_numeric, .check = test__checkevent_numeric,
.id = 3,
}, },
[4] = { {
.name = "instructions", .name = "instructions",
.check = test__checkevent_symbolic_name, .check = test__checkevent_symbolic_name,
.id = 4,
}, },
[5] = { {
.name = "cycles/period=100000,config2/", .name = "cycles/period=100000,config2/",
.check = test__checkevent_symbolic_name_config, .check = test__checkevent_symbolic_name_config,
.id = 5,
}, },
[6] = { {
.name = "faults", .name = "faults",
.check = test__checkevent_symbolic_alias, .check = test__checkevent_symbolic_alias,
.id = 6,
}, },
[7] = { {
.name = "L1-dcache-load-miss", .name = "L1-dcache-load-miss",
.check = test__checkevent_genhw, .check = test__checkevent_genhw,
.id = 7,
}, },
[8] = { {
.name = "mem:0", .name = "mem:0",
.check = test__checkevent_breakpoint, .check = test__checkevent_breakpoint,
.id = 8,
}, },
[9] = { {
.name = "mem:0:x", .name = "mem:0:x",
.check = test__checkevent_breakpoint_x, .check = test__checkevent_breakpoint_x,
.id = 9,
}, },
[10] = { {
.name = "mem:0:r", .name = "mem:0:r",
.check = test__checkevent_breakpoint_r, .check = test__checkevent_breakpoint_r,
.id = 10,
}, },
[11] = { {
.name = "mem:0:w", .name = "mem:0:w",
.check = test__checkevent_breakpoint_w, .check = test__checkevent_breakpoint_w,
.id = 11,
}, },
[12] = { {
.name = "syscalls:sys_enter_open:k", .name = "syscalls:sys_enter_open:k",
.check = test__checkevent_tracepoint_modifier, .check = test__checkevent_tracepoint_modifier,
.id = 12,
}, },
[13] = { {
.name = "syscalls:*:u", .name = "syscalls:*:u",
.check = test__checkevent_tracepoint_multi_modifier, .check = test__checkevent_tracepoint_multi_modifier,
.id = 13,
}, },
[14] = { {
.name = "r1a:kp", .name = "r1a:kp",
.check = test__checkevent_raw_modifier, .check = test__checkevent_raw_modifier,
.id = 14,
}, },
[15] = { {
.name = "1:1:hp", .name = "1:1:hp",
.check = test__checkevent_numeric_modifier, .check = test__checkevent_numeric_modifier,
.id = 15,
}, },
[16] = { {
.name = "instructions:h", .name = "instructions:h",
.check = test__checkevent_symbolic_name_modifier, .check = test__checkevent_symbolic_name_modifier,
.id = 16,
}, },
[17] = { {
.name = "faults:u", .name = "faults:u",
.check = test__checkevent_symbolic_alias_modifier, .check = test__checkevent_symbolic_alias_modifier,
.id = 17,
}, },
[18] = { {
.name = "L1-dcache-load-miss:kp", .name = "L1-dcache-load-miss:kp",
.check = test__checkevent_genhw_modifier, .check = test__checkevent_genhw_modifier,
.id = 18,
}, },
[19] = { {
.name = "mem:0:u", .name = "mem:0:u",
.check = test__checkevent_breakpoint_modifier, .check = test__checkevent_breakpoint_modifier,
.id = 19,
}, },
[20] = { {
.name = "mem:0:x:k", .name = "mem:0:x:k",
.check = test__checkevent_breakpoint_x_modifier, .check = test__checkevent_breakpoint_x_modifier,
.id = 20,
}, },
[21] = { {
.name = "mem:0:r:hp", .name = "mem:0:r:hp",
.check = test__checkevent_breakpoint_r_modifier, .check = test__checkevent_breakpoint_r_modifier,
.id = 21,
}, },
[22] = { {
.name = "mem:0:w:up", .name = "mem:0:w:up",
.check = test__checkevent_breakpoint_w_modifier, .check = test__checkevent_breakpoint_w_modifier,
.id = 22,
}, },
[23] = { {
.name = "r1,syscalls:sys_enter_open:k,1:1:hp", .name = "r1,syscalls:sys_enter_open:k,1:1:hp",
.check = test__checkevent_list, .check = test__checkevent_list,
.id = 23,
}, },
[24] = { {
.name = "instructions:G", .name = "instructions:G",
.check = test__checkevent_exclude_host_modifier, .check = test__checkevent_exclude_host_modifier,
.id = 24,
}, },
[25] = { {
.name = "instructions:H", .name = "instructions:H",
.check = test__checkevent_exclude_guest_modifier, .check = test__checkevent_exclude_guest_modifier,
.id = 25,
}, },
[26] = { {
.name = "mem:0:rw", .name = "mem:0:rw",
.check = test__checkevent_breakpoint_rw, .check = test__checkevent_breakpoint_rw,
.id = 26,
}, },
[27] = { {
.name = "mem:0:rw:kp", .name = "mem:0:rw:kp",
.check = test__checkevent_breakpoint_rw_modifier, .check = test__checkevent_breakpoint_rw_modifier,
.id = 27,
}, },
[28] = { {
.name = "{instructions:k,cycles:upp}", .name = "{instructions:k,cycles:upp}",
.check = test__group1, .check = test__group1,
.id = 28,
}, },
[29] = { {
.name = "{faults:k,cache-references}:u,cycles:k", .name = "{faults:k,cache-references}:u,cycles:k",
.check = test__group2, .check = test__group2,
.id = 29,
}, },
[30] = { {
.name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u", .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
.check = test__group3, .check = test__group3,
.id = 30,
}, },
[31] = { {
.name = "{cycles:u,instructions:kp}:p", .name = "{cycles:u,instructions:kp}:p",
.check = test__group4, .check = test__group4,
.id = 31,
}, },
[32] = { {
.name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles", .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
.check = test__group5, .check = test__group5,
.id = 32,
}, },
[33] = { {
.name = "*:*", .name = "*:*",
.check = test__all_tracepoints, .check = test__all_tracepoints,
.id = 33,
}, },
[34] = { {
.name = "{cycles,cache-misses:G}:H", .name = "{cycles,cache-misses:G}:H",
.check = test__group_gh1, .check = test__group_gh1,
.id = 34,
}, },
[35] = { {
.name = "{cycles,cache-misses:H}:G", .name = "{cycles,cache-misses:H}:G",
.check = test__group_gh2, .check = test__group_gh2,
.id = 35,
}, },
[36] = { {
.name = "{cycles:G,cache-misses:H}:u", .name = "{cycles:G,cache-misses:H}:u",
.check = test__group_gh3, .check = test__group_gh3,
.id = 36,
}, },
[37] = { {
.name = "{cycles:G,cache-misses:H}:uG", .name = "{cycles:G,cache-misses:H}:uG",
.check = test__group_gh4, .check = test__group_gh4,
.id = 37,
}, },
[38] = { {
.name = "{cycles,cache-misses,branch-misses}:S", .name = "{cycles,cache-misses,branch-misses}:S",
.check = test__leader_sample1, .check = test__leader_sample1,
.id = 38,
}, },
[39] = { {
.name = "{instructions,branch-misses}:Su", .name = "{instructions,branch-misses}:Su",
.check = test__leader_sample2, .check = test__leader_sample2,
.id = 39,
}, },
[40] = { {
.name = "instructions:uDp", .name = "instructions:uDp",
.check = test__checkevent_pinned_modifier, .check = test__checkevent_pinned_modifier,
.id = 40,
}, },
[41] = { {
.name = "{cycles,cache-misses,branch-misses}:D", .name = "{cycles,cache-misses,branch-misses}:D",
.check = test__pinned_group, .check = test__pinned_group,
.id = 41,
},
#if defined(__s390x__)
{
.name = "kvm-s390:kvm_s390_create_vm",
.check = test__checkevent_tracepoint,
.id = 100,
}, },
#endif
}; };
static struct evlist_test test__events_pmu[] = { static struct evlist_test test__events_pmu[] = {
[0] = { {
.name = "cpu/config=10,config1,config2=3,period=1000/u", .name = "cpu/config=10,config1,config2=3,period=1000/u",
.check = test__checkevent_pmu, .check = test__checkevent_pmu,
.id = 0,
}, },
[1] = { {
.name = "cpu/config=1,name=krava/u,cpu/config=2/u", .name = "cpu/config=1,name=krava/u,cpu/config=2/u",
.check = test__checkevent_pmu_name, .check = test__checkevent_pmu_name,
.id = 1,
}, },
}; };
...@@ -1402,7 +1454,7 @@ static int test_events(struct evlist_test *events, unsigned cnt) ...@@ -1402,7 +1454,7 @@ static int test_events(struct evlist_test *events, unsigned cnt)
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
struct evlist_test *e = &events[i]; struct evlist_test *e = &events[i];
pr_debug("running test %d '%s'\n", i, e->name); pr_debug("running test %d '%s'\n", e->id, e->name);
ret1 = test_event(e); ret1 = test_event(e);
if (ret1) if (ret1)
ret2 = ret1; ret2 = ret1;
......
...@@ -91,6 +91,11 @@ struct perf_evsel { ...@@ -91,6 +91,11 @@ struct perf_evsel {
char *group_name; char *group_name;
}; };
union u64_swap {
u64 val64;
u32 val32[2];
};
#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists) #define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
struct cpu_map; struct cpu_map;
......
...@@ -299,6 +299,18 @@ PE_PREFIX_MEM PE_VALUE sep_dc ...@@ -299,6 +299,18 @@ PE_PREFIX_MEM PE_VALUE sep_dc
} }
event_legacy_tracepoint: event_legacy_tracepoint:
PE_NAME '-' PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
struct list_head *list;
char sys_name[128];
snprintf(&sys_name, 128, "%s-%s", $1, $3);
ALLOC_LIST(list);
ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5));
$$ = list;
}
|
PE_NAME ':' PE_NAME PE_NAME ':' PE_NAME
{ {
struct parse_events_evlist *data = _data; struct parse_events_evlist *data = _data;
......
...@@ -16,9 +16,4 @@ typedef signed short s16; ...@@ -16,9 +16,4 @@ typedef signed short s16;
typedef unsigned char u8; typedef unsigned char u8;
typedef signed char s8; typedef signed char s8;
union u64_swap {
u64 val64;
u32 val32[2];
};
#endif /* __PERF_TYPES_H */ #endif /* __PERF_TYPES_H */
...@@ -166,6 +166,8 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n) ...@@ -166,6 +166,8 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
ssize_t ret = is_read ? read(fd, buf, left) : ssize_t ret = is_read ? read(fd, buf, left) :
write(fd, buf, left); write(fd, buf, left);
if (ret < 0 && errno == EINTR)
continue;
if (ret <= 0) if (ret <= 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment