From b6160607dc025a0bef89ecda75c94fc5a3801dcc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 5 Nov 2009 16:20:09 +0900 Subject: [PATCH] --- yaml --- r: 173481 b: refs/heads/master c: 830fafecc211bef5bc6e253ab7e39c9e7560f758 h: refs/heads/master i: 173479: 65c739641aa13dae94cc4d6de8fcb6a341a517f9 v: v3 --- [refs] | 2 +- trunk/arch/sh/kernel/Makefile | 2 +- trunk/arch/sh/kernel/perf_callchain.c | 98 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 trunk/arch/sh/kernel/perf_callchain.c diff --git a/[refs] b/[refs] index e0f7e71b3b9b..583c0a60dbd1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d1b261ef85bf63383b80b46b7cee525e0a63b3d3 +refs/heads/master: 830fafecc211bef5bc6e253ab7e39c9e7560f758 diff --git a/trunk/arch/sh/kernel/Makefile b/trunk/arch/sh/kernel/Makefile index 0a67bafce425..8edb927a1f30 100644 --- a/trunk/arch/sh/kernel/Makefile +++ b/trunk/arch/sh/kernel/Makefile @@ -39,7 +39,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o -obj-$(CONFIG_PERF_EVENTS) += perf_event.o +obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o diff --git a/trunk/arch/sh/kernel/perf_callchain.c b/trunk/arch/sh/kernel/perf_callchain.c new file mode 100644 index 000000000000..24ea837eac5b --- /dev/null +++ b/trunk/arch/sh/kernel/perf_callchain.c @@ -0,0 +1,98 @@ +/* + * Performance event callchain support - SuperH architecture code + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) +{ + if (entry->nr < PERF_MAX_STACK_DEPTH) + entry->ip[entry->nr++] = ip; +} + +static void callchain_warning(void *data, char *msg) +{ +} + +static void +callchain_warning_symbol(void *data, char *msg, unsigned long symbol) +{ +} + +static int callchain_stack(void *data, char *name) +{ + return 0; +} + +static void callchain_address(void *data, unsigned long addr, int reliable) +{ + struct perf_callchain_entry *entry = data; + + if (reliable) + callchain_store(entry, addr); +} + +static const struct stacktrace_ops callchain_ops = { + .warning = callchain_warning, + .warning_symbol = callchain_warning_symbol, + .stack = callchain_stack, + .address = callchain_address, +}; + +static void +perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) +{ + callchain_store(entry, PERF_CONTEXT_KERNEL); + callchain_store(entry, regs->pc); + + unwind_stack(NULL, regs, NULL, &callchain_ops, entry); +} + +static void +perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry) +{ + int is_user; + + if (!regs) + return; + + is_user = user_mode(regs); + + if (!current || current->pid == 0) + return; + + if (is_user && current->state != TASK_RUNNING) + return; + + /* + * Only the kernel side is implemented for now. + */ + if (!is_user) + perf_callchain_kernel(regs, entry); +} + +/* + * No need for separate IRQ and NMI entries. + */ +static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); + +struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) +{ + struct perf_callchain_entry *entry = &__get_cpu_var(callchain); + + entry->nr = 0; + + perf_do_callchain(regs, entry); + + return entry; +}