Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4aa84fc authored by Ingo Molnar's avatar Ingo Molnar
Browse files

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

Merge tag 'perf-core-for-mingo' 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:

User visible changes:

  o Prep patches to support 'perf kvm stat' on s390 (Alexander Yarygin)

  o Add pagefault statistics in 'trace' (Stanislav Fomichev)

  o Add header for columns in 'top' and 'report' TUI browsers (Jiri Olsa)

  o Add pagefault statistics in 'trace' (Stanislav Fomichev)

Build fixes:

  o Fix build on 32-bit systems (Arnaldo Carvalho de Melo)

Cleanups:

  o Convert open coded equivalents to asprintf() (Andy Shevchenko)

Plumbing changes:

  o Allow reserving a row for header purposes in the hists browser (Arnaldo Carvalho de Melo)

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents fbe26abe 4414a3c5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
+28 −0
Original line number Diff line number Diff line
/*
 * Implementation of get_cpuid().
 *
 * Copyright 2014 IBM Corp.
 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (version 2 only)
 * as published by the Free Software Foundation.
 */

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#include "../../util/header.h"

int get_cpuid(char *buffer, size_t sz)
{
	const char *cpuid = "IBM/S390";

	if (strlen(cpuid) + 1 > sz)
		return -1;

	strcpy(buffer, cpuid);
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -15,3 +15,4 @@ endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
LIB_H += arch/$(ARCH)/util/tsc.h
HAVE_KVM_STAT_SUPPORT := 1
+38 −34
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@
#include <pthread.h>
#include <math.h>

#if defined(__i386__) || defined(__x86_64__)
#ifdef HAVE_KVM_STAT_SUPPORT
#include <asm/svm.h>
#include <asm/vmx.h>
#include <asm/kvm.h>
@@ -99,7 +99,6 @@ struct perf_kvm_stat {
	int trace_vcpu;

	struct exit_reasons_table *exit_reasons;
	int exit_reasons_size;
	const char *exit_reasons_isa;

	struct kvm_events_ops *events_ops;
@@ -158,20 +157,19 @@ static bool exit_event_end(struct perf_evsel *evsel,
	return kvm_entry_event(evsel);
}

static struct exit_reasons_table vmx_exit_reasons[] = {
	VMX_EXIT_REASONS
};
#define define_exit_reasons_table(name, symbols)	\
	static struct exit_reasons_table name[] = {	\
		symbols, { -1, NULL }			\
	}

static struct exit_reasons_table svm_exit_reasons[] = {
	SVM_EXIT_REASONS
};
define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);

static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
static const char *get_exit_reason(struct perf_kvm_stat *kvm,
				   struct exit_reasons_table *tbl,
				   u64 exit_code)
{
	int i = kvm->exit_reasons_size;
	struct exit_reasons_table *tbl = kvm->exit_reasons;

	while (i--) {
	while (tbl->reason != NULL) {
		if (tbl->exit_code == exit_code)
			return tbl->reason;
		tbl++;
@@ -186,7 +184,8 @@ static void exit_event_decode_key(struct perf_kvm_stat *kvm,
				  struct event_key *key,
				  char decode[20])
{
	const char *exit_reason = get_exit_reason(kvm, key->key);
	const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons,
						  key->key);

	scnprintf(decode, 20, "%s", exit_reason);
}
@@ -836,37 +835,45 @@ static int process_sample_event(struct perf_tool *tool,
	return 0;
}

static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
{
	if (strstr(cpuid, "Intel")) {
		kvm->exit_reasons = vmx_exit_reasons;
		kvm->exit_reasons_isa = "VMX";
	} else if (strstr(cpuid, "AMD")) {
		kvm->exit_reasons = svm_exit_reasons;
		kvm->exit_reasons_isa = "SVM";
	} else
		return -ENOTSUP;

	return 0;
}

static int cpu_isa_config(struct perf_kvm_stat *kvm)
{
	char buf[64], *cpuid;
	int err, isa;
	int err;

	if (kvm->live) {
		err = get_cpuid(buf, sizeof(buf));
		if (err != 0) {
			pr_err("Failed to look up CPU type (Intel or AMD)\n");
			pr_err("Failed to look up CPU type\n");
			return err;
		}
		cpuid = buf;
	} else
		cpuid = kvm->session->header.env.cpuid;

	if (strstr(cpuid, "Intel"))
		isa = 1;
	else if (strstr(cpuid, "AMD"))
		isa = 0;
	else {
		pr_err("CPU %s is not supported.\n", cpuid);
		return -ENOTSUP;
	if (!cpuid) {
		pr_err("Failed to look up CPU type\n");
		return -EINVAL;
	}

	if (isa == 1) {
		kvm->exit_reasons = vmx_exit_reasons;
		kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
		kvm->exit_reasons_isa = "VMX";
	}
	err = cpu_isa_init(kvm, cpuid);
	if (err == -ENOTSUP)
		pr_err("CPU %s is not supported.\n", cpuid);

	return 0;
	return err;
}

static bool verify_vcpu(int vcpu)
@@ -1585,9 +1592,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
		.report_event	= "vmexit",
		.sort_key	= "sample",

		.exit_reasons = svm_exit_reasons,
		.exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
		.exit_reasons_isa = "SVM",
	};

	if (argc == 1) {
@@ -1609,7 +1613,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
perf_stat:
	return cmd_stat(argc, argv, NULL);
}
#endif
#endif /* HAVE_KVM_STAT_SUPPORT */

static int __cmd_record(const char *file_name, int argc, const char **argv)
{
@@ -1726,7 +1730,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
		return cmd_top(argc, argv, NULL);
	else if (!strncmp(argv[0], "buildid-list", 12))
		return __cmd_buildid_list(file_name, argc, argv);
#if defined(__i386__) || defined(__x86_64__)
#ifdef HAVE_KVM_STAT_SUPPORT
	else if (!strncmp(argv[0], "stat", 4))
		return kvm_cmd_stat(file_name, argc, argv);
#endif
+20 −3
Original line number Diff line number Diff line
@@ -1133,6 +1133,7 @@ struct thread_trace {
	u64		  exit_time;
	bool		  entry_pending;
	unsigned long	  nr_events;
	unsigned long	  pfmaj, pfmin;
	char		  *entry_str;
	double		  runtime_ms;
	struct {
@@ -1787,12 +1788,12 @@ static void print_location(FILE *f, struct perf_sample *sample,
		fprintf(f, "%s@", al->map->dso->long_name);

	if ((verbose || print_sym) && al->sym)
		fprintf(f, "%s+0x%lx", al->sym->name,
		fprintf(f, "%s+0x%" PRIx64, al->sym->name,
			al->addr - al->sym->start);
	else if (al->map)
		fprintf(f, "0x%lx", al->addr);
		fprintf(f, "0x%" PRIx64, al->addr);
	else
		fprintf(f, "0x%lx", sample->addr);
		fprintf(f, "0x%" PRIx64, sample->addr);
}

static int trace__pgfault(struct trace *trace,
@@ -1804,8 +1805,20 @@ static int trace__pgfault(struct trace *trace,
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
	struct addr_location al;
	char map_type = 'd';
	struct thread_trace *ttrace;

	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
	ttrace = thread__trace(thread, trace->output);
	if (ttrace == NULL)
		return -1;

	if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
		ttrace->pfmaj++;
	else
		ttrace->pfmin++;

	if (trace->summary_only)
		return 0;

	thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION,
			      sample->ip, &al);
@@ -2346,6 +2359,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
	printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
	printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
	printed += fprintf(fp, "%.1f%%", ratio);
	if (ttrace->pfmaj)
		printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
	if (ttrace->pfmin)
		printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
	printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
	printed += thread__dump_stats(ttrace, trace, fp);

Loading