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

Commit 3bd5a5fc authored by Adrian Hunter's avatar Adrian Hunter Committed by Ingo Molnar
Browse files

perf tools: Add test for converting perf time to/from TSC



The test uses the newly added cap_usr_time_zero and time_zero of
perf_event_mmap_page.  TSC from rdtsc is compared with the time
from 2 perf events.  The test passes if the calculated times are
all in the correct order.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1372425741-1676-4-git-send-email-adrian.hunter@intel.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent c73deb6a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -389,6 +389,9 @@ LIB_OBJS += $(OUTPUT)tests/bp_signal.o
LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
LIB_OBJS += $(OUTPUT)tests/task-exit.o
LIB_OBJS += $(OUTPUT)tests/sw-clock.o
ifeq ($(ARCH),x86)
LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
endif

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
+2 −0
Original line number Diff line number Diff line
@@ -6,3 +6,5 @@ ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
LIB_H += arch/$(ARCH)/util/tsc.h
+59 −0
Original line number Diff line number Diff line
#include <stdbool.h>
#include <errno.h>

#include <linux/perf_event.h>

#include "../../perf.h"
#include "../../util/types.h"
#include "../../util/debug.h"
#include "tsc.h"

u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
{
	u64 time, quot, rem;

	time = ns - tc->time_zero;
	quot = time / tc->time_mult;
	rem  = time % tc->time_mult;
	return (quot << tc->time_shift) +
	       (rem << tc->time_shift) / tc->time_mult;
}

u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
{
	u64 quot, rem;

	quot = cyc >> tc->time_shift;
	rem  = cyc & ((1 << tc->time_shift) - 1);
	return tc->time_zero + quot * tc->time_mult +
	       ((rem * tc->time_mult) >> tc->time_shift);
}

int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
			     struct perf_tsc_conversion *tc)
{
	bool cap_usr_time_zero;
	u32 seq;
	int i = 0;

	while (1) {
		seq = pc->lock;
		rmb();
		tc->time_mult = pc->time_mult;
		tc->time_shift = pc->time_shift;
		tc->time_zero = pc->time_zero;
		cap_usr_time_zero = pc->cap_usr_time_zero;
		rmb();
		if (pc->lock == seq && !(seq & 1))
			break;
		if (++i > 10000) {
			pr_debug("failed to get perf_event_mmap_page lock\n");
			return -EINVAL;
		}
	}

	if (!cap_usr_time_zero)
		return -EOPNOTSUPP;

	return 0;
}
+20 −0
Original line number Diff line number Diff line
#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__

#include "../../util/types.h"

struct perf_tsc_conversion {
	u16 time_shift;
	u32 time_mult;
	u64 time_zero;
};

struct perf_event_mmap_page;

int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
			     struct perf_tsc_conversion *tc);

u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);

#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
+6 −0
Original line number Diff line number Diff line
@@ -93,6 +93,12 @@ static struct test {
		.desc = "Test software clock events have valid period values",
		.func = test__sw_clock_freq,
	},
#if defined(__x86_64__) || defined(__i386__)
	{
		.desc = "Test converting perf time to TSC",
		.func = test__perf_time_to_tsc,
	},
#endif
	{
		.func = NULL,
	},
Loading