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

Commit 652953b7 authored by Robert Richter's avatar Robert Richter
Browse files

Merge branch 'oprofile/core' (early part) into oprofile/perf



Conflicts:
	arch/arm/oprofile/common.c

Signed-off-by: default avatarRobert Richter <robert.richter@amd.com>
parents 81771974 5140434d
Loading
Loading
Loading
Loading
+59 −11
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/stacktrace.h>
#include <linux/compat.h>

static void backtrace_warning_symbol(void *data, char *msg,
				     unsigned long symbol)
@@ -48,14 +49,12 @@ static struct stacktrace_ops backtrace_ops = {
	.walk_stack	= print_context_stack,
};

struct frame_head {
	struct frame_head *bp;
	unsigned long ret;
} __attribute__((packed));

static struct frame_head *dump_user_backtrace(struct frame_head *head)
#ifdef CONFIG_COMPAT
static struct stack_frame_ia32 *
dump_user_backtrace_32(struct stack_frame_ia32 *head)
{
	struct frame_head bufhead[2];
	struct stack_frame_ia32 bufhead[2];
	struct stack_frame_ia32 *fp;

	/* Also check accessibility of one struct frame_head beyond */
	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
@@ -63,20 +62,66 @@ static struct frame_head *dump_user_backtrace(struct frame_head *head)
	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
		return NULL;

	oprofile_add_trace(bufhead[0].ret);
	fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);

	oprofile_add_trace(bufhead[0].return_address);

	/* frame pointers should strictly progress back up the stack
	* (towards higher addresses) */
	if (head >= fp)
		return NULL;

	return fp;
}

static inline int
x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
{
	struct stack_frame_ia32 *head;

	/* User process is 32-bit */
	if (!current || !test_thread_flag(TIF_IA32))
		return 0;

	head = (struct stack_frame_ia32 *) regs->bp;
	while (depth-- && head)
		head = dump_user_backtrace_32(head);

	return 1;
}

#else
static inline int
x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
{
	return 0;
}
#endif /* CONFIG_COMPAT */

static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
{
	struct stack_frame bufhead[2];

	/* Also check accessibility of one struct stack_frame beyond */
	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
		return NULL;
	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
		return NULL;

	oprofile_add_trace(bufhead[0].return_address);

	/* frame pointers should strictly progress back up the stack
	 * (towards higher addresses) */
	if (head >= bufhead[0].bp)
	if (head >= bufhead[0].next_frame)
		return NULL;

	return bufhead[0].bp;
	return bufhead[0].next_frame;
}

void
x86_backtrace(struct pt_regs * const regs, unsigned int depth)
{
	struct frame_head *head = (struct frame_head *)frame_pointer(regs);
	struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);

	if (!user_mode_vm(regs)) {
		unsigned long stack = kernel_stack_pointer(regs);
@@ -86,6 +131,9 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
		return;
	}

	if (x86_backtrace_32(regs, depth))
		return;

	while (depth-- && head)
		head = dump_user_backtrace(head);
}
+1 −8
Original line number Diff line number Diff line
@@ -695,9 +695,6 @@ static int __init ppro_init(char **cpu_type)
	return 1;
}

/* in order to get sysfs right */
static int using_nmi;

int __init op_nmi_init(struct oprofile_operations *ops)
{
	__u8 vendor = boot_cpu_data.x86_vendor;
@@ -705,8 +702,6 @@ int __init op_nmi_init(struct oprofile_operations *ops)
	char *cpu_type = NULL;
	int ret = 0;

	using_nmi = 0;

	if (!cpu_has_apic)
		return -ENODEV;

@@ -790,13 +785,11 @@ int __init op_nmi_init(struct oprofile_operations *ops)
	if (ret)
		return ret;

	using_nmi = 1;
	printk(KERN_INFO "oprofile: using NMI interrupt.\n");
	return 0;
}

void op_nmi_exit(void)
{
	if (using_nmi)
	exit_sysfs();
}