linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] powerpc: Remove some ifdefs in oprofile_impl.h
@ 2006-03-27  0:23 Anton Blanchard
  2006-03-27  0:46 ` [PATCH] powerpc: export validate_sp for oprofile calltrace Anton Blanchard
  0 siblings, 1 reply; 5+ messages in thread
From: Anton Blanchard @ 2006-03-27  0:23 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus


- No one uses op_counter_config.valid, so remove it
- No need to ifdef around function protypes.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: linux-2.6/include/asm-powerpc/oprofile_impl.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/oprofile_impl.h	2006-03-26 12:17:23.000000000 +1100
+++ linux-2.6/include/asm-powerpc/oprofile_impl.h	2006-03-26 12:21:13.000000000 +1100
@@ -17,9 +17,6 @@
 
 /* Per-counter configuration as set via oprofilefs.  */
 struct op_counter_config {
-#ifdef __powerpc64__
-	unsigned long valid;
-#endif
 	unsigned long enabled;
 	unsigned long event;
 	unsigned long count;
@@ -56,17 +53,12 @@ struct op_powerpc_model {
 	int num_counters;
 };
 
-#ifdef CONFIG_FSL_BOOKE
 extern struct op_powerpc_model op_model_fsl_booke;
-#else /* Otherwise, it's classic */
-
-#ifdef CONFIG_PPC64
 extern struct op_powerpc_model op_model_rs64;
 extern struct op_powerpc_model op_model_power4;
-
-#else /* Otherwise, CONFIG_PPC32 */
 extern struct op_powerpc_model op_model_7450;
-#endif
+
+#ifndef CONFIG_FSL_BOOKE
 
 /* All the classic PPC parts use these */
 static inline unsigned int ctr_read(unsigned int i)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] powerpc: export validate_sp for oprofile calltrace
  2006-03-27  0:23 [PATCH] powerpc: Remove some ifdefs in oprofile_impl.h Anton Blanchard
@ 2006-03-27  0:46 ` Anton Blanchard
  2006-03-27  0:57   ` [PATCH] powerpc: Add oprofile calltrace support Anton Blanchard
  0 siblings, 1 reply; 5+ messages in thread
From: Anton Blanchard @ 2006-03-27  0:46 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus


Export validate_sp so we can use it in the oprofile calltrace code.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: build/arch/powerpc/kernel/process.c
===================================================================
--- build.orig/arch/powerpc/kernel/process.c	2006-03-26 10:39:29.000000000 +1000
+++ build/arch/powerpc/kernel/process.c	2006-03-26 12:48:03.000000000 +1000
@@ -767,7 +767,7 @@ out:
 	return error;
 }
 
-static int validate_sp(unsigned long sp, struct task_struct *p,
+int validate_sp(unsigned long sp, struct task_struct *p,
 		       unsigned long nbytes)
 {
 	unsigned long stack_page = (unsigned long)task_stack_page(p);
@@ -805,6 +805,8 @@ static int validate_sp(unsigned long sp,
 #define FRAME_MARKER	2
 #endif
 
+EXPORT_SYMBOL(validate_sp);
+
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long ip, sp;
Index: build/include/asm-powerpc/processor.h
===================================================================
--- build.orig/include/asm-powerpc/processor.h	2006-03-24 15:51:22.000000000 +1100
+++ build/include/asm-powerpc/processor.h	2006-03-26 12:48:03.000000000 +1000
@@ -251,6 +251,10 @@ static inline unsigned long __pack_fe01(
 #define cpu_relax()	barrier()
 #endif
 
+/* Check that a certain kernel stack pointer is valid in task_struct p */
+int validate_sp(unsigned long sp, struct task_struct *p,
+                       unsigned long nbytes);
+
 /*
  * Prefetch macros.
  */

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] powerpc: Add oprofile calltrace support
  2006-03-27  0:46 ` [PATCH] powerpc: export validate_sp for oprofile calltrace Anton Blanchard
@ 2006-03-27  0:57   ` Anton Blanchard
  2006-03-27  1:00     ` [PATCH] powerpc: Remove oprofile spinlock backtrace code Anton Blanchard
  0 siblings, 1 reply; 5+ messages in thread
From: Anton Blanchard @ 2006-03-27  0:57 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: bcr6, paulus


From: Brian Rogan <bcr6@cornell.edu>

Add oprofile calltrace support to powerpc. Disable spinlock backtracing
now we can use calltrace info.

(Updated to work on both 32bit and 64bit by me).

Signed-off-by: Anton Blanchard <anton@samba.org>
---

This patch depends on a patch currently in -mm:

http://marc.theaimsgroup.com/?l=linux-kernel&m=114333745914386&w=2

Index: build/arch/powerpc/oprofile/backtrace.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ build/arch/powerpc/oprofile/backtrace.c	2006-03-26 15:13:57.000000000 +1000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+**/
+
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define STACK_SP(STACK)		*(STACK)
+
+#define STACK_LR64(STACK)	*((unsigned long *)(STACK) + 2)
+#define STACK_LR32(STACK)	*((unsigned int *)(STACK) + 1)
+
+#ifdef CONFIG_PPC64
+#define STACK_LR(STACK)		STACK_LR64(STACK)
+#else
+#define STACK_LR(STACK)		STACK_LR32(STACK)
+#endif
+
+static unsigned int user_getsp32(unsigned int sp, int is_first)
+{
+	unsigned int stack_frame[2];
+
+	if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+		return 0;
+
+	/*
+	 * The most likely reason for this is that we returned -EFAULT,
+	 * which means that we've done all that we can do from
+	 * interrupt context.
+	 */
+	if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp,
+					sizeof(stack_frame)))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR32(stack_frame));
+
+	/*
+	 * We do not enforce increasing stack addresses here because
+	 * we may transition to a different stack, eg a signal handler.
+	 */
+	return STACK_SP(stack_frame);
+}
+
+#ifdef CONFIG_PPC64
+static unsigned long user_getsp64(unsigned long sp, int is_first)
+{
+	unsigned long stack_frame[3];
+
+	if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+		return 0;
+
+	if (__copy_from_user_inatomic(stack_frame, (void *)sp,
+					sizeof(stack_frame)))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR64(stack_frame));
+
+	return STACK_SP(stack_frame);
+}
+#endif
+
+static unsigned long kernel_getsp(unsigned long sp, int is_first)
+{
+	unsigned long *stack_frame = (unsigned long *)sp;
+
+	if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR(stack_frame));
+
+	/*
+	 * We do not enforce increasing stack addresses here because
+	 * we might be transitioning from an interrupt stack to a kernel
+	 * stack. validate_sp() is designed to understand this, so just
+	 * use it.
+	 */
+	return STACK_SP(stack_frame);
+}
+
+void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+	unsigned long sp = regs->gpr[1];
+	int first_frame = 1;
+
+	/* We ditch the top stackframe so need to loop through an extra time */
+	depth += 1;
+
+	if (!user_mode(regs)) {
+		while (depth--) {
+			sp = kernel_getsp(sp, first_frame);
+			if (!sp)
+				break;
+			first_frame = 0;
+		}
+	} else {
+#ifdef CONFIG_PPC64
+		if (!test_thread_flag(TIF_32BIT)) {
+			while (depth--) {
+				sp = user_getsp64(sp, first_frame);
+				if (!sp)
+					break;
+				first_frame = 0;
+			}
+
+			return;
+		}
+#endif
+
+		while (depth--) {
+			sp = user_getsp32(sp, first_frame);
+			if (!sp)
+				break;
+			first_frame = 0;
+		}
+	}
+}
Index: build/arch/powerpc/oprofile/common.c
===================================================================
--- build.orig/arch/powerpc/oprofile/common.c	2006-01-16 00:05:48.000000000 +1100
+++ build/arch/powerpc/oprofile/common.c	2006-03-26 13:09:34.000000000 +1000
@@ -126,8 +126,7 @@ static int op_powerpc_create_files(struc
 	sys.enable_kernel = 1;
 	sys.enable_user = 1;
 #ifdef CONFIG_PPC64
-	/* Turn on backtracing through spinlocks by default */
-	sys.backtrace_spinlocks = 1;
+	sys.backtrace_spinlocks = 0;
 #endif
 
 	return 0;
@@ -168,6 +167,7 @@ int __init oprofile_arch_init(struct opr
 	ops->shutdown = op_powerpc_shutdown;
 	ops->start = op_powerpc_start;
 	ops->stop = op_powerpc_stop;
+	ops->backtrace = op_powerpc_backtrace;
 
 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
 	       ops->cpu_type);
Index: build/arch/powerpc/oprofile/Makefile
===================================================================
--- build.orig/arch/powerpc/oprofile/Makefile	2006-03-26 10:40:14.000000000 +1000
+++ build/arch/powerpc/oprofile/Makefile	2006-03-26 13:09:34.000000000 +1000
@@ -10,7 +10,7 @@ DRIVER_OBJS := $(addprefix ../../../driv
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
 oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
 oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
 oprofile-$(CONFIG_PPC32) += op_model_7450.o
Index: build/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- build.orig/arch/powerpc/oprofile/op_model_power4.c	2006-03-24 15:51:18.000000000 +1100
+++ build/arch/powerpc/oprofile/op_model_power4.c	2006-03-26 13:09:34.000000000 +1000
@@ -293,7 +293,7 @@ static void power4_handle_interrupt(stru
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
Index: build/include/asm-powerpc/oprofile_impl.h
===================================================================
--- build.orig/include/asm-powerpc/oprofile_impl.h	2006-03-26 12:48:01.000000000 +1000
+++ build/include/asm-powerpc/oprofile_impl.h	2006-03-26 13:09:34.000000000 +1000
@@ -126,5 +126,7 @@ static inline void ctr_write(unsigned in
 }
 #endif /* !CONFIG_FSL_BOOKE */
 
+extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_OPROFILE_IMPL_H */

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] powerpc: Remove oprofile spinlock backtrace code
  2006-03-27  0:57   ` [PATCH] powerpc: Add oprofile calltrace support Anton Blanchard
@ 2006-03-27  1:00     ` Anton Blanchard
  2006-03-27  1:03       ` [PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus Anton Blanchard
  0 siblings, 1 reply; 5+ messages in thread
From: Anton Blanchard @ 2006-03-27  1:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus


Remove oprofile spinlock backtrace code now we have proper calltrace
support. Also make MMCRA sihv and sipr bits a variable since they may
change in future cpus. Finally, MMCRA should be a 64bit quantity.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: linux-2.6/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_power4.c	2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_power4.c	2006-03-26 17:55:19.000000000 +1100
@@ -25,18 +25,14 @@ static unsigned long reset_value[OP_MAX_
 
 static int oprofile_running;
 static int mmcra_has_sihv;
+/* Unfortunately these bits vary between CPUs */
+static unsigned long mmcra_sihv = MMCRA_SIHV;
+static unsigned long mmcra_sipr = MMCRA_SIPR;
 
 /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
 static u32 mmcr0_val;
 static u64 mmcr1_val;
-static u32 mmcra_val;
-
-/*
- * Since we do not have an NMI, backtracing through spinlocks is
- * only a best guess. In light of this, allow it to be disabled at
- * runtime.
- */
-static int backtrace_spinlocks;
+static u64 mmcra_val;
 
 static void power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
@@ -63,8 +59,6 @@ static void power4_reg_setup(struct op_c
 	mmcr1_val = sys->mmcr1;
 	mmcra_val = sys->mmcra;
 
-	backtrace_spinlocks = sys->backtrace_spinlocks;
-
 	for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
@@ -197,25 +191,6 @@ static void __attribute_used__ kernel_un
 {
 }
 
-static unsigned long check_spinlock_pc(struct pt_regs *regs,
-				       unsigned long profile_pc)
-{
-	unsigned long pc = instruction_pointer(regs);
-
-	/*
-	 * If both the SIAR (sampled instruction) and the perfmon exception
-	 * occurred in a spinlock region then we account the sample to the
-	 * calling function. This isnt 100% correct, we really need soft
-	 * IRQ disable so we always get the perfmon exception at the
-	 * point at which the SIAR is set.
-	 */
-	if (backtrace_spinlocks && in_lock_functions(pc) &&
-			in_lock_functions(profile_pc))
-		return regs->link;
-	else
-		return profile_pc;
-}
-
 /*
  * On GQ and newer the MMCRA stores the HV and PR bits at the time
  * the SIAR was sampled. We use that to work out if the SIAR was sampled in
@@ -228,17 +203,17 @@ static unsigned long get_pc(struct pt_re
 
 	/* Cant do much about it */
 	if (!mmcra_has_sihv)
-		return check_spinlock_pc(regs, pc);
+		return pc;
 
 	mmcra = mfspr(SPRN_MMCRA);
 
 	/* Were we in the hypervisor? */
-	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
+	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
 		/* function descriptor madness */
 		return *((unsigned long *)hypervisor_bucket);
 
 	/* We were in userspace, nothing to do */
-	if (mmcra & MMCRA_SIPR)
+	if (mmcra & mmcra_sipr)
 		return pc;
 
 #ifdef CONFIG_PPC_RTAS
@@ -257,7 +232,7 @@ static unsigned long get_pc(struct pt_re
 		/* function descriptor madness */
 		return *((unsigned long *)kernel_unknown_bucket);
 
-	return check_spinlock_pc(regs, pc);
+	return pc;
 }
 
 static int get_kernel(unsigned long pc)
@@ -268,7 +243,7 @@ static int get_kernel(unsigned long pc)
 		is_kernel = is_kernel_addr(pc);
 	} else {
 		unsigned long mmcra = mfspr(SPRN_MMCRA);
-		is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+		is_kernel = ((mmcra & mmcra_sipr) == 0);
 	}
 
 	return is_kernel;
Index: linux-2.6/arch/powerpc/oprofile/common.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/common.c	2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/common.c	2006-03-26 17:55:19.000000000 +1100
@@ -117,17 +117,10 @@ static int op_powerpc_create_files(struc
 
 	oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 	oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef CONFIG_PPC64
-	oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
-				&sys.backtrace_spinlocks);
-#endif
 
 	/* Default to tracing both kernel and user */
 	sys.enable_kernel = 1;
 	sys.enable_user = 1;
-#ifdef CONFIG_PPC64
-	sys.backtrace_spinlocks = 0;
-#endif
 
 	return 0;
 }
Index: linux-2.6/include/asm-powerpc/oprofile_impl.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/oprofile_impl.h	2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/include/asm-powerpc/oprofile_impl.h	2006-03-26 17:55:19.000000000 +1100
@@ -35,9 +35,6 @@ struct op_system_config {
 #endif
 	unsigned long enable_kernel;
 	unsigned long enable_user;
-#ifdef CONFIG_PPC64
-	unsigned long backtrace_spinlocks;
-#endif
 };
 
 /* Per-arch configuration */

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus
  2006-03-27  1:00     ` [PATCH] powerpc: Remove oprofile spinlock backtrace code Anton Blanchard
@ 2006-03-27  1:03       ` Anton Blanchard
  0 siblings, 0 replies; 5+ messages in thread
From: Anton Blanchard @ 2006-03-27  1:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus


Add calltrace support for other powerpc cpus. Tested on 7450.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: linux-2.6/arch/powerpc/oprofile/op_model_7450.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_7450.c	2006-01-19 12:29:53.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_7450.c	2006-03-26 23:00:02.000000000 +1100
@@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(str
 	mtmsr(mfmsr() | MSR_PMM);
 
 	pc = mfspr(SPRN_SIAR);
-	is_kernel = (pc >= KERNELBASE);
+	is_kernel = is_kernel_addr(pc);
 
 	for (i = 0; i < NUM_CTRS; ++i) {
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
Index: linux-2.6/arch/powerpc/oprofile/op_model_fsl_booke.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_fsl_booke.c	2005-11-16 03:21:49.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_fsl_booke.c	2006-03-26 22:58:08.000000000 +1100
@@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(s
 	mtmsr(mfmsr() | MSR_PMM);
 
 	pc = regs->nip;
-	is_kernel = (pc >= KERNELBASE);
+	is_kernel = is_kernel_addr(pc);
 
 	for (i = 0; i < num_counters; ++i) {
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
Index: linux-2.6/arch/powerpc/oprofile/op_model_rs64.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_rs64.c	2006-01-19 12:29:53.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_rs64.c	2006-03-26 23:01:55.000000000 +1100
@@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct
 				  struct op_counter_config *ctr)
 {
 	unsigned int mmcr0;
+	int is_kernel;
 	int val;
 	int i;
 	unsigned long pc = mfspr(SPRN_SIAR);
 
+	is_kernel = is_kernel_addr(pc);
+
 	/* set the PMM bit (see comment below) */
 	mtmsrd(mfmsr() | MSR_PMM);
 
@@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct
 		val = ctr_read(i);
 		if (val < 0) {
 			if (ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel_addr(pc), i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-03-27  1:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-27  0:23 [PATCH] powerpc: Remove some ifdefs in oprofile_impl.h Anton Blanchard
2006-03-27  0:46 ` [PATCH] powerpc: export validate_sp for oprofile calltrace Anton Blanchard
2006-03-27  0:57   ` [PATCH] powerpc: Add oprofile calltrace support Anton Blanchard
2006-03-27  1:00     ` [PATCH] powerpc: Remove oprofile spinlock backtrace code Anton Blanchard
2006-03-27  1:03       ` [PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus Anton Blanchard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).