Skip to content

Commit

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

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

New features:

 - Add support to measure SMI cost in 'perf stat' (Kan Liang)

 - Add support for unwinding callchains in powerpc with libdw (Paolo Bonzini)

Fixes:

 - Fix message: cpu list option is -C not -c (Adrian Hunter)

 - Fix 'perf script' message: field list option is -F not -f (Adrian Hunter)

 - Intel PT fixes: (Adrian Hunter)

   o Fix missing stack clear
   o Ensure IP is zero when state is INTEL_PT_STATE_NO_IP
   o Fix last_ip usage
   o Ensure never to set 'last_ip' when packet 'count' is zero
   o Clear FUP flag on error
   o Fix transactions_sample_type

Infrastructure changes:

 - Intel PT cleanups/refactorings (Adrian Hunter)

   o Use FUP always when scanning for an IP
   o Add missing __fallthrough
   o Remove redundant initial_skip checks
   o Allow decoding with branch tracing disabled
   o Add default config for pass-through branch enable
   o Add documentation for new config terms
   o Add decoder support for ptwrite and power event packets
   o Add reserved byte to CBR packet payload
   o Add decoder support for CBR events

 - Move  find_process() to the only place that uses it, skimming some
   more fat from util.[ch] (Arnaldo Carvalho de Melo)

 - Do parameter validation earlier on fetch_kernel_version() (Arnaldo Carvalho de Melo)

 - Remove unused _ALL_SOURCE define (Arnaldo Carvalho de Melo)

 - Add sysfs__write_int function (Kan Liang)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Jun 21, 2017
2 parents 007b811 + 701516a commit 8e70e84
Show file tree
Hide file tree
Showing 22 changed files with 710 additions and 83 deletions.
30 changes: 30 additions & 0 deletions tools/lib/api/fs/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,22 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
return err;
}

int filename__write_int(const char *filename, int value)
{
int fd = open(filename, O_WRONLY), err = -1;
char buf[64];

if (fd < 0)
return err;

sprintf(buf, "%d", value);
if (write(fd, buf, sizeof(buf)) == sizeof(buf))
err = 0;

close(fd);
return err;
}

int procfs__read_str(const char *entry, char **buf, size_t *sizep)
{
char path[PATH_MAX];
Expand Down Expand Up @@ -480,3 +496,17 @@ int sysctl__read_int(const char *sysctl, int *value)

return filename__read_int(path, value);
}

int sysfs__write_int(const char *entry, int value)
{
char path[PATH_MAX];
const char *sysfs = sysfs__mountpoint();

if (!sysfs)
return -1;

if (snprintf(path, sizeof(path), "%s/%s", sysfs, entry) >= PATH_MAX)
return -1;

return filename__write_int(path, value);
}
4 changes: 4 additions & 0 deletions tools/lib/api/fs/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ int filename__read_int(const char *filename, int *value);
int filename__read_ull(const char *filename, unsigned long long *value);
int filename__read_str(const char *filename, char **buf, size_t *sizep);

int filename__write_int(const char *filename, int value);

int procfs__read_str(const char *entry, char **buf, size_t *sizep);

int sysctl__read_int(const char *sysctl, int *value);
int sysfs__read_int(const char *entry, int *value);
int sysfs__read_ull(const char *entry, unsigned long long *value);
int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
int sysfs__read_bool(const char *entry, bool *value);

int sysfs__write_int(const char *entry, int value);
#endif /* __API_FS__ */
36 changes: 36 additions & 0 deletions tools/perf/Documentation/intel-pt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,42 @@ cyc_thresh Specifies how frequently CYC packets are produced - see cyc

CYC packets are not requested by default.

pt Specifies pass-through which enables the 'branch' config term.

The default config selects 'pt' if it is available, so a user will
never need to specify this term.

branch Enable branch tracing. Branch tracing is enabled by default so to
disable branch tracing use 'branch=0'.

The default config selects 'branch' if it is available.

ptw Enable PTWRITE packets which are produced when a ptwrite instruction
is executed.

Support for this feature is indicated by:

/sys/bus/event_source/devices/intel_pt/caps/ptwrite

which contains "1" if the feature is supported and
"0" otherwise.

fup_on_ptw Enable a FUP packet to follow the PTWRITE packet. The FUP packet
provides the address of the ptwrite instruction. In the absence of
fup_on_ptw, the decoder will use the address of the previous branch
if branch tracing is enabled, otherwise the address will be zero.
Note that fup_on_ptw will work even when branch tracing is disabled.

pwr_evt Enable power events. The power events provide information about
changes to the CPU C-state.

Support for this feature is indicated by:

/sys/bus/event_source/devices/intel_pt/caps/power_event_trace

which contains "1" if the feature is supported and
"0" otherwise.


new snapshot option
-------------------
Expand Down
14 changes: 14 additions & 0 deletions tools/perf/Documentation/perf-stat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,20 @@ taskset.
--no-merge::
Do not merge results from same PMUs.

--smi-cost::
Measure SMI cost if msr/aperf/ and msr/smi/ events are supported.

During the measurement, the /sys/device/cpu/freeze_on_smi will be set to
freeze core counters on SMI.
The aperf counter will not be effected by the setting.
The cost of SMI can be measured by (aperf - unhalted core cycles).

In practice, the percentages of SMI cycles is very useful for performance
oriented analysis. --metric_only will be applied by default.
The output is SMI cycles%, equals to (aperf - unhalted core cycles) / aperf

Users who wants to get the actual value can apply --no-metric-only.

EXAMPLES
--------

Expand Down
2 changes: 1 addition & 1 deletion tools/perf/Makefile.config
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ endif
# Disable it on all other architectures in case libdw unwind
# support is detected in system. Add supported architectures
# to the check.
ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm))
ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc))
NO_LIBDW_DWARF_UNWIND := 1
endif

Expand Down
2 changes: 2 additions & 0 deletions tools/perf/arch/powerpc/util/Build
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ libperf-y += perf_regs.o

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

libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
73 changes: 73 additions & 0 deletions tools/perf/arch/powerpc/util/unwind-libdw.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <elfutils/libdwfl.h>
#include "../../util/unwind-libdw.h"
#include "../../util/perf_regs.h"
#include "../../util/event.h"

/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils. */
static const int special_regs[3][2] = {
{ 65, PERF_REG_POWERPC_LINK },
{ 101, PERF_REG_POWERPC_XER },
{ 109, PERF_REG_POWERPC_CTR },
};

bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
{
struct unwind_info *ui = arg;
struct regs_dump *user_regs = &ui->sample->user_regs;
Dwarf_Word dwarf_regs[32], dwarf_nip;
size_t i;

#define REG(r) ({ \
Dwarf_Word val = 0; \
perf_reg_value(&val, user_regs, PERF_REG_POWERPC_##r); \
val; \
})

dwarf_regs[0] = REG(R0);
dwarf_regs[1] = REG(R1);
dwarf_regs[2] = REG(R2);
dwarf_regs[3] = REG(R3);
dwarf_regs[4] = REG(R4);
dwarf_regs[5] = REG(R5);
dwarf_regs[6] = REG(R6);
dwarf_regs[7] = REG(R7);
dwarf_regs[8] = REG(R8);
dwarf_regs[9] = REG(R9);
dwarf_regs[10] = REG(R10);
dwarf_regs[11] = REG(R11);
dwarf_regs[12] = REG(R12);
dwarf_regs[13] = REG(R13);
dwarf_regs[14] = REG(R14);
dwarf_regs[15] = REG(R15);
dwarf_regs[16] = REG(R16);
dwarf_regs[17] = REG(R17);
dwarf_regs[18] = REG(R18);
dwarf_regs[19] = REG(R19);
dwarf_regs[20] = REG(R20);
dwarf_regs[21] = REG(R21);
dwarf_regs[22] = REG(R22);
dwarf_regs[23] = REG(R23);
dwarf_regs[24] = REG(R24);
dwarf_regs[25] = REG(R25);
dwarf_regs[26] = REG(R26);
dwarf_regs[27] = REG(R27);
dwarf_regs[28] = REG(R28);
dwarf_regs[29] = REG(R29);
dwarf_regs[30] = REG(R30);
dwarf_regs[31] = REG(R31);
if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
return false;

dwarf_nip = REG(NIP);
dwfl_thread_state_register_pc(thread, dwarf_nip);
for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
Dwarf_Word val = 0;
perf_reg_value(&val, user_regs, special_regs[i][1]);
if (!dwfl_thread_state_registers(thread,
special_regs[i][0], 1,
&val))
return false;
}

return true;
}
5 changes: 5 additions & 0 deletions tools/perf/arch/x86/util/intel-pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
int psb_cyc, psb_periods, psb_period;
int pos = 0;
u64 config;
char c;

pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc");

Expand Down Expand Up @@ -225,6 +226,10 @@ static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
}
}

if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
perf_pmu__scan_file(intel_pt_pmu, "format/branch", "%c", &c) == 1)
pos += scnprintf(buf + pos, sizeof(buf) - pos, ",pt,branch");

pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf);

intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config);
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
*/
if (!evsel && output[j].user_set && !output[j].wildcard_set) {
pr_err("%s events do not exist. "
"Remove corresponding -f option to proceed.\n",
"Remove corresponding -F option to proceed.\n",
event_type(j));
return -1;
}
Expand Down
49 changes: 49 additions & 0 deletions tools/perf/builtin-stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#define DEFAULT_SEPARATOR " "
#define CNTR_NOT_SUPPORTED "<not supported>"
#define CNTR_NOT_COUNTED "<not counted>"
#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"

static void print_counters(struct timespec *ts, int argc, const char **argv);

Expand Down Expand Up @@ -122,6 +123,14 @@ static const char * topdown_attrs[] = {
NULL,
};

static const char *smi_cost_attrs = {
"{"
"msr/aperf/,"
"msr/smi/,"
"cycles"
"}"
};

static struct perf_evlist *evsel_list;

static struct target target = {
Expand All @@ -137,6 +146,8 @@ static bool null_run = false;
static int detailed_run = 0;
static bool transaction_run;
static bool topdown_run = false;
static bool smi_cost = false;
static bool smi_reset = false;
static bool big_num = true;
static int big_num_opt = -1;
static const char *csv_sep = NULL;
Expand Down Expand Up @@ -1782,6 +1793,8 @@ static const struct option stat_options[] = {
"Only print computed metrics. No raw values", enable_metric_only),
OPT_BOOLEAN(0, "topdown", &topdown_run,
"measure topdown level 1 statistics"),
OPT_BOOLEAN(0, "smi-cost", &smi_cost,
"measure SMI cost"),
OPT_END()
};

Expand Down Expand Up @@ -2160,6 +2173,39 @@ static int add_default_attributes(void)
return 0;
}

if (smi_cost) {
int smi;

if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {
fprintf(stderr, "freeze_on_smi is not supported.\n");
return -1;
}

if (!smi) {
if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) {
fprintf(stderr, "Failed to set freeze_on_smi.\n");
return -1;
}
smi_reset = true;
}

if (pmu_have_event("msr", "aperf") &&
pmu_have_event("msr", "smi")) {
if (!force_metric_only)
metric_only = true;
err = parse_events(evsel_list, smi_cost_attrs, NULL);
} else {
fprintf(stderr, "To measure SMI cost, it needs "
"msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
return -1;
}
if (err) {
fprintf(stderr, "Cannot set up SMI cost events\n");
return -1;
}
return 0;
}

if (topdown_run) {
char *str = NULL;
bool warn = false;
Expand Down Expand Up @@ -2742,6 +2788,9 @@ int cmd_stat(int argc, const char **argv)
perf_stat__exit_aggr_mode();
perf_evlist__free_stats(evsel_list);
out:
if (smi_cost && smi_reset)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);

perf_evlist__delete(evsel_list);
return status;
}
39 changes: 39 additions & 0 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <errno.h>
#include <inttypes.h>
#include <linux/bitops.h>
#include <api/fs/fs.h>
#include <api/fs/tracing_path.h>
#include <traceevent/event-parse.h>
#include <linux/hw_breakpoint.h>
Expand All @@ -19,6 +20,8 @@
#include <linux/err.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <dirent.h>
#include "asm/bug.h"
#include "callchain.h"
#include "cgroup.h"
Expand Down Expand Up @@ -2472,6 +2475,42 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
return false;
}

static bool find_process(const char *name)
{
size_t len = strlen(name);
DIR *dir;
struct dirent *d;
int ret = -1;

dir = opendir(procfs__mountpoint());
if (!dir)
return false;

/* Walk through the directory. */
while (ret && (d = readdir(dir)) != NULL) {
char path[PATH_MAX];
char *data;
size_t size;

if ((d->d_type != DT_DIR) ||
!strcmp(".", d->d_name) ||
!strcmp("..", d->d_name))
continue;

scnprintf(path, sizeof(path), "%s/%s/comm",
procfs__mountpoint(), d->d_name);

if (filename__read_str(path, &data, &size))
continue;

ret = strncmp(name, data, len);
free(data);
}

closedir(dir);
return ret ? false : true;
}

int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
int err, char *msg, size_t size)
{
Expand Down
Loading

0 comments on commit 8e70e84

Please sign in to comment.