perf/core improvements and fixes:

. 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: Jiri Olsa <jolsa@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJTX6nUAAoJEPZqUSBWB3s91VkP/0/vKV/4ZRsL8c6vnIKZ3ycn
 YI+YdilaZpe5F8bxy/EvO+rdM7PUjeLG4SEp0hibmz/ths2gzLlDN6PI/w0HkIv4
 6bf7uErC6iwus6VNx5OqS/mDOqxvTpWL50NAOZyAH//Zaa38d0/Ps/vrtJPe5pFX
 XZ2gVHDcWPfcWkjUVTVM/cxl1X78FAGVcoac432RniX7AlJrfr9wtfnl4IfEonA/
 evacDsd/87qWka/FLeQA5YFuR/iVBAUIk6T0eX9jHTkCKsJeLDoGn80E9Mu4A3GQ
 lGgj5pDBteFSuxyqiwS+kF9bUV/VBu2gSiVP738AIj3GNd/yOcgxLbgFyG0RZiJU
 ud4xdGP74mXERwi9Q5gQCF9DslC1hobyqdKNwWRSanFeo9KoIOiLxRDWgOPysOfh
 N3iHHnF4MbXzYrIKQdIOh8SB8mV8dfgiQuCThfNlTpP6F5WQlKnDI1X9zE98tvC/
 eTTSOKlvTCG0Bz6VOdHOw6/DWbVvbpn8HPFcZnGcZAfsnl3YzXOulK55v8DVuiKD
 3hQXj0rVbDhH7KWu1PQBooRtYikTCt662yQY+Km5N1HZXiRrpdMHLQ8mVIWO2q3E
 GwlN68WYl52KYZukpHBe971waidUM+e0OmL5BsmYjJ+mF2sLUT+NAktDedu4e7dG
 i9lOVcBZXmFYohGBAvhz
 =z16U
 -----END PGP SIGNATURE-----

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: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2014-05-01 08:24:59 +02:00
commit 3617660e4e
10 changed files with 380 additions and 51 deletions

View file

@ -0,0 +1,7 @@
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

View file

@ -0,0 +1,88 @@
#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 */

View file

@ -0,0 +1,80 @@
/*
* 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;
}

View file

@ -0,0 +1,82 @@
#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;
}

View file

@ -29,11 +29,17 @@ ifeq ($(ARCH),x86)
endif
NO_PERF_REGS := 0
endif
ifeq ($(ARCH),arm)
NO_PERF_REGS := 0
LIBUNWIND_LIBS = -lunwind -lunwind-arm
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.
# Disable it on all other architectures in case libdw unwind
# support is detected in system. Add supported architectures
@ -370,7 +376,7 @@ else
endif
ifndef NO_LIBUNWIND
ifeq ($(ARCH),arm)
ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
$(call feature_check,libunwind-debug-frame)
ifneq ($(feature-libunwind-debug-frame), 1)
msg := $(warning No debug_frame support found in libunwind);

View file

@ -1174,188 +1174,240 @@ static int test__all_tracepoints(struct perf_evlist *evlist)
struct evlist_test {
const char *name;
__u32 type;
const int id;
int (*check)(struct perf_evlist *evlist);
};
static struct evlist_test test__events[] = {
[0] = {
{
.name = "syscalls:sys_enter_open",
.check = test__checkevent_tracepoint,
.id = 0,
},
[1] = {
{
.name = "syscalls:*",
.check = test__checkevent_tracepoint_multi,
.id = 1,
},
[2] = {
{
.name = "r1a",
.check = test__checkevent_raw,
.id = 2,
},
[3] = {
{
.name = "1:1",
.check = test__checkevent_numeric,
.id = 3,
},
[4] = {
{
.name = "instructions",
.check = test__checkevent_symbolic_name,
.id = 4,
},
[5] = {
{
.name = "cycles/period=100000,config2/",
.check = test__checkevent_symbolic_name_config,
.id = 5,
},
[6] = {
{
.name = "faults",
.check = test__checkevent_symbolic_alias,
.id = 6,
},
[7] = {
{
.name = "L1-dcache-load-miss",
.check = test__checkevent_genhw,
.id = 7,
},
[8] = {
{
.name = "mem:0",
.check = test__checkevent_breakpoint,
.id = 8,
},
[9] = {
{
.name = "mem:0:x",
.check = test__checkevent_breakpoint_x,
.id = 9,
},
[10] = {
{
.name = "mem:0:r",
.check = test__checkevent_breakpoint_r,
.id = 10,
},
[11] = {
{
.name = "mem:0:w",
.check = test__checkevent_breakpoint_w,
.id = 11,
},
[12] = {
{
.name = "syscalls:sys_enter_open:k",
.check = test__checkevent_tracepoint_modifier,
.id = 12,
},
[13] = {
{
.name = "syscalls:*:u",
.check = test__checkevent_tracepoint_multi_modifier,
.id = 13,
},
[14] = {
{
.name = "r1a:kp",
.check = test__checkevent_raw_modifier,
.id = 14,
},
[15] = {
{
.name = "1:1:hp",
.check = test__checkevent_numeric_modifier,
.id = 15,
},
[16] = {
{
.name = "instructions:h",
.check = test__checkevent_symbolic_name_modifier,
.id = 16,
},
[17] = {
{
.name = "faults:u",
.check = test__checkevent_symbolic_alias_modifier,
.id = 17,
},
[18] = {
{
.name = "L1-dcache-load-miss:kp",
.check = test__checkevent_genhw_modifier,
.id = 18,
},
[19] = {
{
.name = "mem:0:u",
.check = test__checkevent_breakpoint_modifier,
.id = 19,
},
[20] = {
{
.name = "mem:0:x:k",
.check = test__checkevent_breakpoint_x_modifier,
.id = 20,
},
[21] = {
{
.name = "mem:0:r:hp",
.check = test__checkevent_breakpoint_r_modifier,
.id = 21,
},
[22] = {
{
.name = "mem:0:w:up",
.check = test__checkevent_breakpoint_w_modifier,
.id = 22,
},
[23] = {
{
.name = "r1,syscalls:sys_enter_open:k,1:1:hp",
.check = test__checkevent_list,
.id = 23,
},
[24] = {
{
.name = "instructions:G",
.check = test__checkevent_exclude_host_modifier,
.id = 24,
},
[25] = {
{
.name = "instructions:H",
.check = test__checkevent_exclude_guest_modifier,
.id = 25,
},
[26] = {
{
.name = "mem:0:rw",
.check = test__checkevent_breakpoint_rw,
.id = 26,
},
[27] = {
{
.name = "mem:0:rw:kp",
.check = test__checkevent_breakpoint_rw_modifier,
.id = 27,
},
[28] = {
{
.name = "{instructions:k,cycles:upp}",
.check = test__group1,
.id = 28,
},
[29] = {
{
.name = "{faults:k,cache-references}:u,cycles:k",
.check = test__group2,
.id = 29,
},
[30] = {
{
.name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
.check = test__group3,
.id = 30,
},
[31] = {
{
.name = "{cycles:u,instructions:kp}:p",
.check = test__group4,
.id = 31,
},
[32] = {
{
.name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
.check = test__group5,
.id = 32,
},
[33] = {
{
.name = "*:*",
.check = test__all_tracepoints,
.id = 33,
},
[34] = {
{
.name = "{cycles,cache-misses:G}:H",
.check = test__group_gh1,
.id = 34,
},
[35] = {
{
.name = "{cycles,cache-misses:H}:G",
.check = test__group_gh2,
.id = 35,
},
[36] = {
{
.name = "{cycles:G,cache-misses:H}:u",
.check = test__group_gh3,
.id = 36,
},
[37] = {
{
.name = "{cycles:G,cache-misses:H}:uG",
.check = test__group_gh4,
.id = 37,
},
[38] = {
{
.name = "{cycles,cache-misses,branch-misses}:S",
.check = test__leader_sample1,
.id = 38,
},
[39] = {
{
.name = "{instructions,branch-misses}:Su",
.check = test__leader_sample2,
.id = 39,
},
[40] = {
{
.name = "instructions:uDp",
.check = test__checkevent_pinned_modifier,
.id = 40,
},
[41] = {
{
.name = "{cycles,cache-misses,branch-misses}:D",
.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[] = {
[0] = {
{
.name = "cpu/config=10,config1,config2=3,period=1000/u",
.check = test__checkevent_pmu,
.id = 0,
},
[1] = {
{
.name = "cpu/config=1,name=krava/u,cpu/config=2/u",
.check = test__checkevent_pmu_name,
.id = 1,
},
};
@ -1402,7 +1454,7 @@ static int test_events(struct evlist_test *events, unsigned cnt)
for (i = 0; i < cnt; 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);
if (ret1)
ret2 = ret1;

View file

@ -91,6 +91,11 @@ struct perf_evsel {
char *group_name;
};
union u64_swap {
u64 val64;
u32 val32[2];
};
#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
struct cpu_map;

View file

@ -299,6 +299,18 @@ PE_PREFIX_MEM PE_VALUE sep_dc
}
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
{
struct parse_events_evlist *data = _data;

View file

@ -16,9 +16,4 @@ typedef signed short s16;
typedef unsigned char u8;
typedef signed char s8;
union u64_swap {
u64 val64;
u32 val32[2];
};
#endif /* __PERF_TYPES_H */

View file

@ -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) :
write(fd, buf, left);
if (ret < 0 && errno == EINTR)
continue;
if (ret <= 0)
return ret;