Skip to content

Commit

Permalink
tracing, perf: Convert the power tracer into an event tracer
Browse files Browse the repository at this point in the history
This patch converts the existing power tracer into an event tracer,
so that power events (C states and frequency changes) can be
tracked via "perf".

This also removes the perl script that was used to demo the tracer;
its functionality is being replaced entirely with timechart.

Signed-off-by: Arjan van de Ven <[email protected]>
Acked-by: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
fenrus75 authored and Ingo Molnar committed Sep 19, 2009
1 parent fd39e05 commit 6161352
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 388 deletions.
17 changes: 0 additions & 17 deletions Documentation/trace/power.txt

This file was deleted.

7 changes: 2 additions & 5 deletions arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <linux/cpufreq.h>
#include <linux/compiler.h>
#include <linux/dmi.h>
#include <trace/power.h>
#include <trace/events/power.h>

#include <linux/acpi.h>
#include <linux/io.h>
Expand Down Expand Up @@ -72,8 +72,6 @@ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data);

static DEFINE_PER_CPU(struct aperfmperf, old_perf);

DEFINE_TRACE(power_mark);

/* acpi_perf_data is a pointer to percpu data. */
static struct acpi_processor_performance *acpi_perf_data;

Expand Down Expand Up @@ -332,7 +330,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
unsigned int next_perf_state = 0; /* Index into perf table */
unsigned int i;
int result = 0;
struct power_trace it;

dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);

Expand Down Expand Up @@ -364,7 +361,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
}
}

trace_power_mark(&it, POWER_PSTATE, next_perf_state);
trace_power_frequency(POWER_PSTATE, data->freq_table[next_state].frequency);

switch (data->cpu_feature) {
case SYSTEM_INTEL_MSR_CAPABLE:
Expand Down
28 changes: 9 additions & 19 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <linux/pm.h>
#include <linux/clockchips.h>
#include <linux/random.h>
#include <trace/power.h>
#include <trace/events/power.h>
#include <asm/system.h>
#include <asm/apic.h>
#include <asm/syscalls.h>
Expand All @@ -25,9 +25,6 @@ EXPORT_SYMBOL(idle_nomwait);

struct kmem_cache *task_xstate_cachep;

DEFINE_TRACE(power_start);
DEFINE_TRACE(power_end);

int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
*dst = *src;
Expand Down Expand Up @@ -299,9 +296,7 @@ static inline int hlt_use_halt(void)
void default_idle(void)
{
if (hlt_use_halt()) {
struct power_trace it;

trace_power_start(&it, POWER_CSTATE, 1);
trace_power_start(POWER_CSTATE, 1);
current_thread_info()->status &= ~TS_POLLING;
/*
* TS_POLLING-cleared state must be visible before we
Expand All @@ -314,7 +309,7 @@ void default_idle(void)
else
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
trace_power_end(&it);
trace_power_end(0);
} else {
local_irq_enable();
/* loop is done by the caller */
Expand Down Expand Up @@ -372,9 +367,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
{
struct power_trace it;

trace_power_start(&it, POWER_CSTATE, (ax>>4)+1);
trace_power_start(POWER_CSTATE, (ax>>4)+1);
if (!need_resched()) {
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags);
Expand All @@ -384,15 +377,14 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
if (!need_resched())
__mwait(ax, cx);
}
trace_power_end(&it);
trace_power_end(0);
}

/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
struct power_trace it;
if (!need_resched()) {
trace_power_start(&it, POWER_CSTATE, 1);
trace_power_start(POWER_CSTATE, 1);
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags);

Expand All @@ -402,7 +394,7 @@ static void mwait_idle(void)
__sti_mwait(0, 0);
else
local_irq_enable();
trace_power_end(&it);
trace_power_end(0);
} else
local_irq_enable();
}
Expand All @@ -414,13 +406,11 @@ static void mwait_idle(void)
*/
static void poll_idle(void)
{
struct power_trace it;

trace_power_start(&it, POWER_CSTATE, 0);
trace_power_start(POWER_CSTATE, 0);
local_irq_enable();
while (!need_resched())
cpu_relax();
trace_power_end(&it);
trace_power_end(0);
}

/*
Expand Down
81 changes: 81 additions & 0 deletions include/trace/events/power.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM power

#if !defined(_TRACE_POWER_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_POWER_H

#include <linux/ktime.h>
#include <linux/tracepoint.h>

#ifndef _TRACE_POWER_ENUM_
#define _TRACE_POWER_ENUM_
enum {
POWER_NONE = 0,
POWER_CSTATE = 1,
POWER_PSTATE = 2,
};
#endif



TRACE_EVENT(power_start,

TP_PROTO(unsigned int type, unsigned int state),

TP_ARGS(type, state),

TP_STRUCT__entry(
__field( u64, type )
__field( u64, state )
),

TP_fast_assign(
__entry->type = type;
__entry->state = state;
),

TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long)__entry->state)
);

TRACE_EVENT(power_end,

TP_PROTO(int dummy),

TP_ARGS(dummy),

TP_STRUCT__entry(
__field( u64, dummy )
),

TP_fast_assign(
__entry->dummy = 0xffff;
),

TP_printk("dummy=%lu", (unsigned long)__entry->dummy)

);


TRACE_EVENT(power_frequency,

TP_PROTO(unsigned int type, unsigned int state),

TP_ARGS(type, state),

TP_STRUCT__entry(
__field( u64, type )
__field( u64, state )
),

TP_fast_assign(
__entry->type = type;
__entry->state = state;
),

TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long) __entry->state)
);

#endif /* _TRACE_POWER_H */

/* This part must be outside protection */
#include <trace/define_trace.h>
2 changes: 1 addition & 1 deletion kernel/trace/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ obj-$(CONFIG_BOOT_TRACER) += trace_boot.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o
obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o
obj-$(CONFIG_HW_BRANCH_TRACER) += trace_hw_branches.o
obj-$(CONFIG_POWER_TRACER) += trace_power.o
obj-$(CONFIG_KMEMTRACE) += kmemtrace.o
obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o
obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
Expand All @@ -54,5 +53,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_export.o
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
obj-$(CONFIG_EVENT_TRACING) += power-traces.o

libftrace-y := ftrace.o
20 changes: 20 additions & 0 deletions kernel/trace/power-traces.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Power trace points
*
* Copyright (C) 2009 Arjan van de Ven <[email protected]>
*/

#include <linux/string.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/slab.h>

#define CREATE_TRACE_POINTS
#include <trace/events/power.h>

EXPORT_TRACEPOINT_SYMBOL_GPL(power_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(power_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(power_frequency);

3 changes: 0 additions & 3 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <linux/ftrace.h>
#include <trace/boot.h>
#include <linux/kmemtrace.h>
#include <trace/power.h>

#include <linux/trace_seq.h>
#include <linux/ftrace_event.h>
Expand All @@ -37,7 +36,6 @@ enum trace_type {
TRACE_HW_BRANCHES,
TRACE_KMEM_ALLOC,
TRACE_KMEM_FREE,
TRACE_POWER,
TRACE_BLK,

__TRACE_LAST_TYPE,
Expand Down Expand Up @@ -207,7 +205,6 @@ extern void __ftrace_bad_type(void);
IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \
TRACE_GRAPH_RET); \
IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\
IF_ASSIGN(var, ent, struct trace_power, TRACE_POWER); \
IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \
TRACE_KMEM_ALLOC); \
IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
Expand Down
17 changes: 0 additions & 17 deletions kernel/trace/trace_entries.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,23 +330,6 @@ FTRACE_ENTRY(hw_branch, hw_branch_entry,
F_printk("from: %llx to: %llx", __entry->from, __entry->to)
);

FTRACE_ENTRY(power, trace_power,

TRACE_POWER,

F_STRUCT(
__field_struct( struct power_trace, state_data )
__field_desc( s64, state_data, stamp )
__field_desc( s64, state_data, end )
__field_desc( int, state_data, type )
__field_desc( int, state_data, state )
),

F_printk("%llx->%llx type:%u state:%u",
__entry->stamp, __entry->end,
__entry->type, __entry->state)
);

FTRACE_ENTRY(kmem_alloc, kmemtrace_alloc_entry,

TRACE_KMEM_ALLOC,
Expand Down
Loading

0 comments on commit 6161352

Please sign in to comment.