Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 367226
b: refs/heads/master
c: 00e6c92
h: refs/heads/master
v: v3
  • Loading branch information
James Hogan committed Mar 15, 2013
1 parent 2e1cd3c commit 2c89781
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f27086f5dcb0c7e9622f724d5279e4dfe4e844a2
refs/heads/master: 00e6c92304ce38ff48029471c929d31a25e5cf10
4 changes: 4 additions & 0 deletions trunk/arch/metag/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ config METAG
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
select HAVE_MOD_ARCH_SPECIFIC
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
select HAVE_SYSCALL_TRACEPOINTS
select IRQ_DOMAIN
Expand Down Expand Up @@ -209,6 +210,9 @@ config METAG_PERFCOUNTER_IRQS
When disabled, Performance Counters information will be collected
based on Timer Interrupt.

config HW_PERF_EVENTS
def_bool METAG_PERFCOUNTER_IRQS && PERF_EVENTS

config METAG_DA
bool "DA support"
help
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/metag/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ core-y += arch/metag/mm/
libs-y += arch/metag/lib/
libs-y += arch/metag/tbx/

drivers-$(CONFIG_OPROFILE) += arch/metag/oprofile/

boot := arch/metag/boot

boot_targets += uImage
Expand Down
17 changes: 17 additions & 0 deletions trunk/arch/metag/oprofile/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
obj-$(CONFIG_OPROFILE) += oprofile.o

oprofile-core-y += buffer_sync.o
oprofile-core-y += cpu_buffer.o
oprofile-core-y += event_buffer.o
oprofile-core-y += oprof.o
oprofile-core-y += oprofile_files.o
oprofile-core-y += oprofile_stats.o
oprofile-core-y += oprofilefs.o
oprofile-core-y += timer_int.o
oprofile-core-$(CONFIG_HW_PERF_EVENTS) += oprofile_perf.o

oprofile-y += backtrace.o
oprofile-y += common.o
oprofile-y += $(addprefix ../../../drivers/oprofile/,$(oprofile-core-y))

ccflags-y += -Werror
63 changes: 63 additions & 0 deletions trunk/arch/metag/oprofile/backtrace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2010-2013 Imagination Technologies Ltd.
*
* 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 <linux/oprofile.h>
#include <linux/uaccess.h>
#include <asm/processor.h>
#include <asm/stacktrace.h>

#include "backtrace.h"

static void user_backtrace_fp(unsigned long __user *fp, unsigned int depth)
{
while (depth-- && access_ok(VERIFY_READ, fp, 8)) {
unsigned long addr;
unsigned long __user *fpnew;
if (__copy_from_user_inatomic(&addr, fp + 1, sizeof(addr)))
break;
addr -= 4;

oprofile_add_trace(addr);

/* stack grows up, so frame pointers must decrease */
if (__copy_from_user_inatomic(&fpnew, fp + 0, sizeof(fpnew)))
break;
if (fpnew >= fp)
break;
fp = fpnew;
}
}

static int kernel_backtrace_frame(struct stackframe *frame, void *data)
{
unsigned int *depth = data;

oprofile_add_trace(frame->pc);

/* decrement depth and stop if we reach 0 */
if ((*depth)-- == 0)
return 1;

/* otherwise onto the next frame */
return 0;
}

void metag_backtrace(struct pt_regs * const regs, unsigned int depth)
{
if (user_mode(regs)) {
unsigned long *fp = (unsigned long *)regs->ctx.AX[1].U0;
user_backtrace_fp((unsigned long __user __force *)fp, depth);
} else {
struct stackframe frame;
frame.fp = regs->ctx.AX[1].U0; /* A0FrP */
frame.sp = user_stack_pointer(regs); /* A0StP */
frame.lr = 0; /* from stack */
frame.pc = regs->ctx.CurrPC; /* PC */
walk_stackframe(&frame, &kernel_backtrace_frame, &depth);
}
}
6 changes: 6 additions & 0 deletions trunk/arch/metag/oprofile/backtrace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _METAG_OPROFILE_BACKTRACE_H
#define _METAG_OPROFILE_BACKTRACE_H

void metag_backtrace(struct pt_regs * const regs, unsigned int depth);

#endif
66 changes: 66 additions & 0 deletions trunk/arch/metag/oprofile/common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* arch/metag/oprofile/common.c
*
* Copyright (C) 2013 Imagination Technologies Ltd.
*
* Based on arch/sh/oprofile/common.c:
*
* Copyright (C) 2003 - 2010 Paul Mundt
*
* Based on arch/mips/oprofile/common.c:
*
* Copyright (C) 2004, 2005 Ralf Baechle
* Copyright (C) 2005 MIPS Technologies, Inc.
*
* 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 <linux/errno.h>
#include <linux/init.h>
#include <linux/oprofile.h>
#include <linux/perf_event.h>
#include <linux/slab.h>

#include "backtrace.h"

#ifdef CONFIG_HW_PERF_EVENTS
/*
* This will need to be reworked when multiple PMUs are supported.
*/
static char *metag_pmu_op_name;

char *op_name_from_perf_id(void)
{
return metag_pmu_op_name;
}

int __init oprofile_arch_init(struct oprofile_operations *ops)
{
ops->backtrace = metag_backtrace;

if (perf_num_counters() == 0)
return -ENODEV;

metag_pmu_op_name = kasprintf(GFP_KERNEL, "metag/%s",
perf_pmu_name());
if (unlikely(!metag_pmu_op_name))
return -ENOMEM;

return oprofile_perf_init(ops);
}

void oprofile_arch_exit(void)
{
oprofile_perf_exit();
kfree(metag_pmu_op_name);
}
#else
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
ops->backtrace = metag_backtrace;
/* fall back to timer interrupt PC sampling */
return -ENODEV;
}
void oprofile_arch_exit(void) {}
#endif /* CONFIG_HW_PERF_EVENTS */

0 comments on commit 2c89781

Please sign in to comment.