linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* powerpc stacktrace and lockdep support
@ 2007-01-08 13:54 Christoph Hellwig
  2007-06-26 22:47 ` Johannes Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2007-01-08 13:54 UTC (permalink / raw)
  To: linuxppc-dev

I recently tried to work on lockdep for powerpc.  I have preliminary
version of the stacktrace code, but had to give up on trace irqflags
support because I'm not that knowledgeable on lowlevel ppc details.

Maybe someone more faimilar with the code wants to give it another try?

My stacktrace code is below:


Index: linux-2.6/arch/powerpc/Kconfig
===================================================================
--- linux-2.6.orig/arch/powerpc/Kconfig	2006-12-25 13:47:19.000000000 +0100
+++ linux-2.6/arch/powerpc/Kconfig	2006-12-25 13:47:53.000000000 +0100
@@ -34,6 +34,10 @@
 	bool
 	default y
 
+config STACKTRACE_SUPPORT
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
Index: linux-2.6/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/Makefile	2006-12-25 13:47:19.000000000 +0100
+++ linux-2.6/arch/powerpc/kernel/Makefile	2006-12-25 13:47:53.000000000 +0100
@@ -58,6 +58,7 @@
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
+obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
Index: linux-2.6/arch/powerpc/kernel/stacktrace.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/arch/powerpc/kernel/stacktrace.c	2006-12-25 13:51:06.000000000 +0100
@@ -0,0 +1,52 @@
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+
+
+#ifdef CONFIG_PPC64
+#define MIN_STACK_FRAME 112     /* same as STACK_FRAME_OVERHEAD, in fact */
+#define FRAME_LR_SAVE   2
+#define INT_FRAME_SIZE  (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)
+#define REGS_MARKER     0x7265677368657265ul
+#define FRAME_MARKER    12
+#else
+#define MIN_STACK_FRAME 16
+#define FRAME_LR_SAVE   1
+#define INT_FRAME_SIZE  (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
+#define REGS_MARKER     0x72656773ul
+#define FRAME_MARKER    2
+#endif
+
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ * If all_contexts is set, all contexts (hardirq, softirq and process)
+ * are saved. If not set then only the current context is saved.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long sp;
+
+	asm("mr %0,1" : "=r" (sp));
+
+	for (;;) {
+		unsigned long *stack = (unsigned long *) sp;
+		unsigned long newsp, ip;
+
+		if (!validate_sp(sp, current, MIN_STACK_FRAME))
+			return;
+
+		newsp = stack[0];
+		ip = stack[FRAME_LR_SAVE];
+
+		if (!trace->skip)
+			trace->entries[trace->nr_entries++] = ip;
+		else
+			trace->skip--;
+
+		if (trace->nr_entries >= trace->max_entries)
+			return;
+
+		sp = newsp;
+	}
+}

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

* Re: powerpc stacktrace and lockdep support
  2007-01-08 13:54 powerpc stacktrace and lockdep support Christoph Hellwig
@ 2007-06-26 22:47 ` Johannes Berg
  2007-06-27 19:00   ` Johannes Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2007-06-26 22:47 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev

On Mon, 2007-01-08 at 14:54 +0100, Christoph Hellwig wrote:
> I recently tried to work on lockdep for powerpc.  I have preliminary
> version of the stacktrace code

That seems to work.

> , but had to give up on trace irqflags
> support because I'm not that knowledgeable on lowlevel ppc details.

I gave it a try. Actually what I had wanted to do was add lockdep
support for things like

function A:
lock()
flush_scheduled_work()
unlock()

function B: (work function that is scheduled)
...
lock()
...
unlock()
...

which can obviously deadlock but isn't caught by any debugging
mechanisms right now.

So anyway, lockdep doesn't work here since I only own powerpc machines,
hence I tried to make it work. Below is the patch, it's quite ugly and
only works on 64-bit right now, it'll probably totally screw up on
32-bit (though hopefully it only makes lockdep complain and stop itself
on 32-bit).

I currently get a lockdep report in XFS with this code. Not sure if
there's a bug in this code or if it actually complains rightfully, the
self-tests all pass...

---
 arch/powerpc/Kconfig            |    8 +++++
 arch/powerpc/kernel/Makefile    |    1 
 arch/powerpc/kernel/entry_64.S  |   23 ++++++++++++++++
 arch/powerpc/kernel/head_64.S   |   55 ++++++++++++++++++++++++++++++++--------
 arch/powerpc/kernel/irq.c       |    2 -
 arch/powerpc/kernel/irqtrace.S  |   42 ++++++++++++++++++++++++++++++
 arch/powerpc/kernel/ppc_ksyms.c |    2 -
 arch/powerpc/kernel/setup_64.c  |    6 ++++
 include/asm-powerpc/hw_irq.h    |   34 +++++++++++++-----------
 include/asm-powerpc/irqflags.h  |   11 ++++----
 include/asm-powerpc/rwsem.h     |   34 ++++++++++++++++++------
 include/asm-powerpc/spinlock.h  |    1 
 12 files changed, 177 insertions(+), 42 deletions(-)

--- linux-2.6-git.orig/arch/powerpc/Kconfig	2007-06-26 18:12:10.424850274 +0200
+++ linux-2.6-git/arch/powerpc/Kconfig	2007-06-26 20:01:50.544814034 +0200
@@ -38,6 +38,14 @@ config STACKTRACE_SUPPORT
 	bool
 	default y
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default y
+
+config LOCKDEP_SUPPORT
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
--- linux-2.6-git.orig/arch/powerpc/kernel/irq.c	2007-06-26 18:12:10.491850274 +0200
+++ linux-2.6-git/arch/powerpc/kernel/irq.c	2007-06-26 18:12:11.376850274 +0200
@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsi
 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-void local_irq_restore(unsigned long en)
+void raw_local_irq_restore(unsigned long en)
 {
 	/*
 	 * get_paca()->soft_enabled = en;
--- linux-2.6-git.orig/arch/powerpc/kernel/ppc_ksyms.c	2007-06-26 18:12:10.513850274 +0200
+++ linux-2.6-git/arch/powerpc/kernel/ppc_ksyms.c	2007-06-26 18:12:11.377850274 +0200
@@ -50,7 +50,7 @@
 #endif
 
 #ifdef CONFIG_PPC64
-EXPORT_SYMBOL(local_irq_restore);
+EXPORT_SYMBOL(raw_local_irq_restore);
 #endif
 
 #ifdef CONFIG_PPC32
--- linux-2.6-git.orig/include/asm-powerpc/hw_irq.h	2007-06-26 18:12:10.618850274 +0200
+++ linux-2.6-git/include/asm-powerpc/hw_irq.h	2007-06-26 18:12:11.443850274 +0200
@@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
 	return flags;
 }
 
-static inline unsigned long local_irq_disable(void)
+static inline unsigned long raw_local_irq_disable(void)
 {
 	unsigned long flags, zero;
 
@@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
 	return flags;
 }
 
-extern void local_irq_restore(unsigned long);
+extern void raw_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define local_irq_enable()	local_irq_restore(1)
-#define local_save_flags(flags)	((flags) = local_get_flags())
-#define local_irq_save(flags)	((flags) = local_irq_disable())
+#define raw_local_irq_enable()	raw_local_irq_restore(1)
+#define raw_local_save_flags(flags)	((flags) = local_get_flags())
+#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
 
-#define irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled_flags(flags)		((flags) == 0)
 
 #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -62,13 +63,13 @@ extern void iseries_handle_interrupts(vo
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
 #else
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	mtmsr(flags)
+#define raw_local_irq_restore(flags)	mtmsr(flags)
 #endif
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 0": : :"memory");
@@ -80,7 +81,7 @@ static inline void local_irq_disable(voi
 #endif
 }
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 1": : :"memory");
@@ -92,7 +93,7 @@ static inline void local_irq_enable(void
 #endif
 }
 
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
 {
 	unsigned long msr;
 	msr = mfmsr();
@@ -105,12 +106,13 @@ static inline void local_irq_save_ptr(un
 	__asm__ __volatile__("": : :"memory");
 }
 
-#define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_save(flags)	local_irq_save_ptr(&flags)
-#define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags)	((flags) = mfmsr())
+#define raw_local_irq_save(flags)	raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
 
-#define hard_irq_enable()	local_irq_enable()
-#define hard_irq_disable()	local_irq_disable()
+#define hard_irq_enable()	raw_local_irq_enable()
+#define hard_irq_disable()	raw_local_irq_disable()
 
 #endif /* CONFIG_PPC64 */
 
--- linux-2.6-git.orig/include/asm-powerpc/irqflags.h	2007-06-26 18:12:10.669850274 +0200
+++ linux-2.6-git/include/asm-powerpc/irqflags.h	2007-06-27 00:35:50.806820710 +0200
@@ -10,19 +10,20 @@
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
+#ifndef __ASSEMBLY__
 /*
  * Get definitions for raw_local_save_flags(x), etc.
  */
 #include <asm-powerpc/hw_irq.h>
+#endif
 
 /*
- * Do the CPU's IRQ-state tracing from assembly code. We call a
- * C function, so save all the C-clobbered registers:
+ * Do the CPU's IRQ-state tracing from assembly code. Also
+ * note the code in arch/powerpc/kernel/irqtrace.S.
  */
 #ifdef CONFIG_TRACE_IRQFLAGS
-
-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
-
+# define TRACE_IRQS_ON		bl .powerpc_trace_irqs_on
+# define TRACE_IRQS_OFF		bl .powerpc_trace_irqs_off
 #else
 # define TRACE_IRQS_ON
 # define TRACE_IRQS_OFF
--- linux-2.6-git.orig/include/asm-powerpc/rwsem.h	2007-06-26 18:12:10.747850274 +0200
+++ linux-2.6-git/include/asm-powerpc/rwsem.h	2007-06-27 00:13:57.397341965 +0200
@@ -28,11 +28,21 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
 	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name)		\
 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -42,12 +52,15 @@ extern struct rw_semaphore *rwsem_down_w
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)					\
+	do {						\
+		static struct lock_class_key __key;	\
+							\
+		__init_rwsem((sem), #sem, &__key);	\
+	} while (0)
 
 /*
  * lock for reading
@@ -74,7 +87,7 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write(struct rw_semaphore *sem)
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	int tmp;
 
@@ -84,6 +97,11 @@ static inline void __down_write(struct r
 		rwsem_down_write_failed(sem);
 }
 
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	__down_write_nested(sem, 0);
+}
+
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
 	int tmp;
--- linux-2.6-git.orig/include/asm-powerpc/spinlock.h	2007-06-26 18:12:10.639850274 +0200
+++ linux-2.6-git/include/asm-powerpc/spinlock.h	2007-06-26 18:12:11.446850274 +0200
@@ -19,6 +19,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/hvcall.h>
--- linux-2.6-git.orig/arch/powerpc/kernel/head_64.S	2007-06-26 18:12:10.537850274 +0200
+++ linux-2.6-git/arch/powerpc/kernel/head_64.S	2007-06-27 00:34:57.402820710 +0200
@@ -34,6 +34,7 @@
 #include <asm/iseries/lpar_map.h>
 #include <asm/thread_info.h>
 #include <asm/firmware.h>
+#include <asm/irqflags.h>
 
 #define DO_SOFT_DISABLE
 
@@ -394,6 +395,12 @@ label##_iSeries:							\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+#define TRACE_DISABLE_INTS bl .powerpc_trace_irqs_off
+#else
+#define TRACE_DISABLE_INTS
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS				\
 	li	r11,0;				\
@@ -405,14 +412,15 @@ BEGIN_FW_FTR_SECTION;				\
 	mfmsr	r10;				\
 	ori	r10,r10,MSR_EE;			\
 	mtmsrd	r10,1;				\
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
+	TRACE_DISABLE_INTS
 
 #else
 #define DISABLE_INTS				\
 	li	r11,0;				\
 	stb	r11,PACASOFTIRQEN(r13);		\
-	stb	r11,PACAHARDIRQEN(r13)
-
+	stb	r11,PACAHARDIRQEN(r13);		\
+	TRACE_DISABLE_INTS
 #endif /* CONFIG_PPC_ISERIES */
 
 #define ENABLE_INTS				\
@@ -965,24 +973,38 @@ bad_stack:
  */
 fast_exc_return_irq:			/* restores irq state too */
 	ld	r3,SOFTE(r1)
-	ld	r12,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	1f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+1:
 	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+	cmpdi	r3,0
+	bne	2f
+	bl	.trace_hardirqs_off
+	ld	r3,SOFTE(r1)
+2:
+#else
+	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+#endif
+	ld	r12,_MSR(r1)
 	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
 	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
+	b	3f
 
 	.globl	fast_exception_return
 fast_exception_return:
 	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
+3:	ld	r11,_NIP(r1)
 	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	andi.	r3,r12,MSR_PR
-	beq	2f
+	beq	4f
 	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
+4:
 #endif
 
 	ld	r3,_CCR(r1)
@@ -1387,11 +1409,24 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISER
 
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .local_irq_restore
+	 * to what it was before the trap.  Note that .raw_local_irq_restore
 	 * handles any interrupts pending at this point.
 	 */
 	ld	r3,SOFTE(r1)
-	bl	.local_irq_restore
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	14f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+14:
+	bl	.raw_local_irq_restore
+	cmpdi	r3,0
+	bne	15f
+	bl	.trace_hardirqs_off
+15:
+#else
+	bl	.raw_local_irq_restore
+#endif
 	b	11f
 
 /* Here we have a page fault that hash_page can't handle. */
--- linux-2.6-git.orig/arch/powerpc/kernel/setup_64.c	2007-06-26 18:12:10.594850274 +0200
+++ linux-2.6-git/arch/powerpc/kernel/setup_64.c	2007-06-26 18:12:11.451850274 +0200
@@ -33,6 +33,7 @@
 #include <linux/serial_8250.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/lockdep.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -359,6 +360,11 @@ void __init setup_system(void)
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
+	 * start lockdep
+	 */
+	lockdep_init();
+
+	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
 	unflatten_device_tree();
--- linux-2.6-git.orig/arch/powerpc/kernel/entry_64.S	2007-06-26 18:20:59.030850274 +0200
+++ linux-2.6-git/arch/powerpc/kernel/entry_64.S	2007-06-26 21:25:58.630569893 +0200
@@ -29,6 +29,7 @@
 #include <asm/cputable.h>
 #include <asm/firmware.h>
 #include <asm/bug.h>
+#include <asm/irqflags.h>
 
 /*
  * System calls.
@@ -91,6 +92,13 @@ system_call_common:
 	li	r10,1
 	stb	r10,PACASOFTIRQEN(r13)
 	stb	r10,PACAHARDIRQEN(r13)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.trace_hardirqs_on
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+#endif
 	std	r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
@@ -491,8 +499,20 @@ BEGIN_FW_FTR_SECTION
 4:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r5,0
+	beq	5f
+	bl	.trace_hardirqs_on
+	ld	r5,SOFTE(r1)
 	stb	r5,PACASOFTIRQEN(r13)
-
+	b	6f
+5:
+	stb	r5,PACASOFTIRQEN(r13)
+	bl	.trace_hardirqs_off
+6:
+#else
+	stb	r5,PACASOFTIRQEN(r13)
+#endif
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
@@ -560,6 +580,7 @@ do_work:
 	bne	restore
 	/* here we are preempting the current task */
 1:
+	TRACE_IRQS_ON
 	li	r0,1
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-06-26 19:27:54.032776841 +0200
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-06-27 00:30:19.115820710 +0200
@@ -62,6 +62,7 @@ obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_TRACE_IRQFLAGS)	+= irqtrace.o
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/irqtrace.S	2007-06-27 00:32:07.125820710 +0200
@@ -0,0 +1,42 @@
+/*
+ * crappy helper for irq-trace
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+#define STACKSPACE	GPR0 + 16*8
+
+#ifdef __powerpc64__
+#define ST	std
+#define L	ld
+#else
+#define ST	stw
+#define L	lw
+#endif
+
+#define PRE				\
+	subi	r1,r1,STACKSPACE ;	\
+	SAVE_GPR(0, r1) ;		\
+	SAVE_8GPRS(2, r1) ;		\
+	SAVE_4GPRS(10, r1) ;		\
+	mfcr	r0 ;			\
+	ST	r0, (14*8)(r1) ;	\
+	mflr	r0 ;			\
+	ST	r0, (15*8)(r1)
+
+#define POST				\
+	REST_8GPRS(2, r1) ;		\
+	REST_4GPRS(10, r1) ;		\
+	L	r0, (14*8)(r1) ;	\
+	mtcr	r0 ;			\
+	L	r0, (15*8)(r1) ;	\
+	mtlr	r0 ;			\
+	REST_GPR(0, r1) ;		\
+	addi	r1,r1,STACKSPACE
+
+_GLOBAL(powerpc_trace_irqs_off)
+	PRE
+	bl .trace_hardirqs_off
+	POST
+	blr

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

* Re: powerpc stacktrace and lockdep support
  2007-06-26 22:47 ` Johannes Berg
@ 2007-06-27 19:00   ` Johannes Berg
  2007-06-28 16:20     ` Johannes Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2007-06-27 19:00 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev

Here's a somewhat cleaned-up version that also works with preempt, still
64-bit only, still breaks 32-bit compile (I think, untested).

Works fine on my quad G5 and I've actually made a patch to lockdep to
support flagging my workqueue deadlock, that works too. And the XFS
report I had previously was also "correct" in the sense that it occurs
on all machines and has been patched (although there never was a
possible deadlock.)

---
 arch/powerpc/Kconfig            |    8 +++++
 arch/powerpc/kernel/Makefile    |    1 
 arch/powerpc/kernel/entry_64.S  |   24 +++++++++++++++++
 arch/powerpc/kernel/head_64.S   |   54 ++++++++++++++++++++++++++++++++--------
 arch/powerpc/kernel/irq.c       |    2 -
 arch/powerpc/kernel/irqtrace.S  |   47 ++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/ppc_ksyms.c |    2 -
 arch/powerpc/kernel/setup_64.c  |    6 ++++
 include/asm-powerpc/hw_irq.h    |   34 +++++++++++++------------
 include/asm-powerpc/irqflags.h  |   13 ---------
 include/asm-powerpc/rwsem.h     |   34 +++++++++++++++++++------
 include/asm-powerpc/spinlock.h  |    1 
 12 files changed, 176 insertions(+), 50 deletions(-)

--- linux-2.6-git.orig/arch/powerpc/Kconfig	2007-06-27 17:37:39.884965668 +0200
+++ linux-2.6-git/arch/powerpc/Kconfig	2007-06-27 17:38:07.929965668 +0200
@@ -38,6 +38,14 @@ config STACKTRACE_SUPPORT
 	bool
 	default y
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default y
+
+config LOCKDEP_SUPPORT
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
--- linux-2.6-git.orig/arch/powerpc/kernel/irq.c	2007-06-27 17:37:39.907965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/irq.c	2007-06-27 17:38:07.953965668 +0200
@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsi
 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-void local_irq_restore(unsigned long en)
+void raw_local_irq_restore(unsigned long en)
 {
 	/*
 	 * get_paca()->soft_enabled = en;
--- linux-2.6-git.orig/arch/powerpc/kernel/ppc_ksyms.c	2007-06-27 17:37:39.930965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/ppc_ksyms.c	2007-06-27 17:38:07.954965668 +0200
@@ -50,7 +50,7 @@
 #endif
 
 #ifdef CONFIG_PPC64
-EXPORT_SYMBOL(local_irq_restore);
+EXPORT_SYMBOL(raw_local_irq_restore);
 #endif
 
 #ifdef CONFIG_PPC32
--- linux-2.6-git.orig/include/asm-powerpc/hw_irq.h	2007-06-27 17:37:40.209965668 +0200
+++ linux-2.6-git/include/asm-powerpc/hw_irq.h	2007-06-27 17:38:08.025965668 +0200
@@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
 	return flags;
 }
 
-static inline unsigned long local_irq_disable(void)
+static inline unsigned long raw_local_irq_disable(void)
 {
 	unsigned long flags, zero;
 
@@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
 	return flags;
 }
 
-extern void local_irq_restore(unsigned long);
+extern void raw_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define local_irq_enable()	local_irq_restore(1)
-#define local_save_flags(flags)	((flags) = local_get_flags())
-#define local_irq_save(flags)	((flags) = local_irq_disable())
+#define raw_local_irq_enable()	raw_local_irq_restore(1)
+#define raw_local_save_flags(flags)	((flags) = local_get_flags())
+#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
 
-#define irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled_flags(flags)		((flags) == 0)
 
 #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -62,13 +63,13 @@ extern void iseries_handle_interrupts(vo
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
 #else
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	mtmsr(flags)
+#define raw_local_irq_restore(flags)	mtmsr(flags)
 #endif
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 0": : :"memory");
@@ -80,7 +81,7 @@ static inline void local_irq_disable(voi
 #endif
 }
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 1": : :"memory");
@@ -92,7 +93,7 @@ static inline void local_irq_enable(void
 #endif
 }
 
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
 {
 	unsigned long msr;
 	msr = mfmsr();
@@ -105,12 +106,13 @@ static inline void local_irq_save_ptr(un
 	__asm__ __volatile__("": : :"memory");
 }
 
-#define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_save(flags)	local_irq_save_ptr(&flags)
-#define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags)	((flags) = mfmsr())
+#define raw_local_irq_save(flags)	raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
 
-#define hard_irq_enable()	local_irq_enable()
-#define hard_irq_disable()	local_irq_disable()
+#define hard_irq_enable()	raw_local_irq_enable()
+#define hard_irq_disable()	raw_local_irq_disable()
 
 #endif /* CONFIG_PPC64 */
 
--- linux-2.6-git.orig/include/asm-powerpc/irqflags.h	2007-06-27 17:37:40.234965668 +0200
+++ linux-2.6-git/include/asm-powerpc/irqflags.h	2007-06-27 17:39:18.499965668 +0200
@@ -15,17 +15,4 @@
  */
 #include <asm-powerpc/hw_irq.h>
 
-/*
- * Do the CPU's IRQ-state tracing from assembly code. We call a
- * C function, so save all the C-clobbered registers:
- */
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
-
-#else
-# define TRACE_IRQS_ON
-# define TRACE_IRQS_OFF
-#endif
-
 #endif
--- linux-2.6-git.orig/include/asm-powerpc/rwsem.h	2007-06-27 17:37:40.256965668 +0200
+++ linux-2.6-git/include/asm-powerpc/rwsem.h	2007-06-27 17:38:08.051965668 +0200
@@ -28,11 +28,21 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
 	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name)		\
 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -42,12 +52,15 @@ extern struct rw_semaphore *rwsem_down_w
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)					\
+	do {						\
+		static struct lock_class_key __key;	\
+							\
+		__init_rwsem((sem), #sem, &__key);	\
+	} while (0)
 
 /*
  * lock for reading
@@ -74,7 +87,7 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write(struct rw_semaphore *sem)
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	int tmp;
 
@@ -84,6 +97,11 @@ static inline void __down_write(struct r
 		rwsem_down_write_failed(sem);
 }
 
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	__down_write_nested(sem, 0);
+}
+
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
 	int tmp;
--- linux-2.6-git.orig/include/asm-powerpc/spinlock.h	2007-06-27 17:37:40.293965668 +0200
+++ linux-2.6-git/include/asm-powerpc/spinlock.h	2007-06-27 17:38:08.056965668 +0200
@@ -19,6 +19,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/hvcall.h>
--- linux-2.6-git.orig/arch/powerpc/kernel/head_64.S	2007-06-27 17:37:39.953965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/head_64.S	2007-06-27 17:52:08.742965668 +0200
@@ -394,6 +394,12 @@ label##_iSeries:							\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
+#else
+#define TRACE_DISABLE_INTS
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS				\
 	li	r11,0;				\
@@ -405,14 +411,15 @@ BEGIN_FW_FTR_SECTION;				\
 	mfmsr	r10;				\
 	ori	r10,r10,MSR_EE;			\
 	mtmsrd	r10,1;				\
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
+	TRACE_DISABLE_INTS
 
 #else
 #define DISABLE_INTS				\
 	li	r11,0;				\
 	stb	r11,PACASOFTIRQEN(r13);		\
-	stb	r11,PACAHARDIRQEN(r13)
-
+	stb	r11,PACAHARDIRQEN(r13);		\
+	TRACE_DISABLE_INTS
 #endif /* CONFIG_PPC_ISERIES */
 
 #define ENABLE_INTS				\
@@ -965,24 +972,38 @@ bad_stack:
  */
 fast_exc_return_irq:			/* restores irq state too */
 	ld	r3,SOFTE(r1)
-	ld	r12,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	1f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+1:
 	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+	cmpdi	r3,0
+	bne	2f
+	bl	.trace_hardirqs_off
+	ld	r3,SOFTE(r1)
+2:
+#else
+	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+#endif
+	ld	r12,_MSR(r1)
 	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
 	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
+	b	3f
 
 	.globl	fast_exception_return
 fast_exception_return:
 	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
+3:	ld	r11,_NIP(r1)
 	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	andi.	r3,r12,MSR_PR
-	beq	2f
+	beq	4f
 	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
+4:
 #endif
 
 	ld	r3,_CCR(r1)
@@ -1387,11 +1408,24 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISER
 
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .local_irq_restore
+	 * to what it was before the trap.  Note that .raw_local_irq_restore
 	 * handles any interrupts pending at this point.
 	 */
 	ld	r3,SOFTE(r1)
-	bl	.local_irq_restore
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	14f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+14:
+	bl	.raw_local_irq_restore
+	cmpdi	r3,0
+	bne	15f
+	bl	.trace_hardirqs_off
+15:
+#else
+	bl	.raw_local_irq_restore
+#endif
 	b	11f
 
 /* Here we have a page fault that hash_page can't handle. */
--- linux-2.6-git.orig/arch/powerpc/kernel/setup_64.c	2007-06-27 17:37:39.976965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/setup_64.c	2007-06-27 17:38:08.062965668 +0200
@@ -33,6 +33,7 @@
 #include <linux/serial_8250.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/lockdep.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -359,6 +360,11 @@ void __init setup_system(void)
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
+	 * start lockdep
+	 */
+	lockdep_init();
+
+	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
 	unflatten_device_tree();
--- linux-2.6-git.orig/arch/powerpc/kernel/entry_64.S	2007-06-27 17:37:40.045965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/entry_64.S	2007-06-27 17:50:16.499965668 +0200
@@ -91,6 +91,13 @@ system_call_common:
 	li	r10,1
 	stb	r10,PACASOFTIRQEN(r13)
 	stb	r10,PACAHARDIRQEN(r13)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.trace_hardirqs_on
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+#endif
 	std	r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
@@ -491,8 +498,20 @@ BEGIN_FW_FTR_SECTION
 4:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r5,0
+	beq	5f
+	bl	.trace_hardirqs_on
+	ld	r5,SOFTE(r1)
 	stb	r5,PACASOFTIRQEN(r13)
-
+	b	6f
+5:
+	stb	r5,PACASOFTIRQEN(r13)
+	bl	.trace_hardirqs_off
+6:
+#else
+	stb	r5,PACASOFTIRQEN(r13)
+#endif
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
@@ -560,6 +579,9 @@ do_work:
 	bne	restore
 	/* here we are preempting the current task */
 1:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.powerpc_trace_hardirqs_on
+#endif
 	li	r0,1
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-06-27 17:37:40.100965668 +0200
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-06-27 17:38:08.064965668 +0200
@@ -62,6 +62,7 @@ obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_TRACE_IRQFLAGS)	+= irqtrace.o
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/irqtrace.S	2007-06-27 17:49:15.650965668 +0200
@@ -0,0 +1,47 @@
+/*
+ * crappy helper for irq-trace
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+#define STACKSPACE	GPR0 + 16*8
+
+#ifdef __powerpc64__
+#define ST	std
+#define L	ld
+#else
+#define ST	stw
+#define L	lw
+#endif
+
+#define PRE				\
+	subi	r1,r1,STACKSPACE ;	\
+	SAVE_GPR(0, r1) ;		\
+	SAVE_8GPRS(2, r1) ;		\
+	SAVE_4GPRS(10, r1) ;		\
+	mfcr	r0 ;			\
+	ST	r0, (14*8)(r1) ;	\
+	mflr	r0 ;			\
+	ST	r0, (15*8)(r1)
+
+#define POST				\
+	REST_8GPRS(2, r1) ;		\
+	REST_4GPRS(10, r1) ;		\
+	L	r0, (14*8)(r1) ;	\
+	mtcr	r0 ;			\
+	L	r0, (15*8)(r1) ;	\
+	mtlr	r0 ;			\
+	REST_GPR(0, r1) ;		\
+	addi	r1,r1,STACKSPACE
+
+_GLOBAL(powerpc_trace_hardirqs_off)
+	PRE
+	bl .trace_hardirqs_off
+	POST
+	blr
+_GLOBAL(powerpc_trace_hardirqs_on)
+	PRE
+	bl .trace_hardirqs_on
+	POST
+	blr

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

* Re: powerpc stacktrace and lockdep support
  2007-06-27 19:00   ` Johannes Berg
@ 2007-06-28 16:20     ` Johannes Berg
  2007-06-30  8:58       ` Christoph Hellwig
  2007-07-05 19:26       ` Sergei Shtylyov
  0 siblings, 2 replies; 10+ messages in thread
From: Johannes Berg @ 2007-06-28 16:20 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev

This one doesn't break 32-bit build by simply disabling irqtrace for
32-bit.

---
 arch/powerpc/Kconfig            |    9 ++++++
 arch/powerpc/kernel/Makefile    |    1 
 arch/powerpc/kernel/entry_64.S  |   24 +++++++++++++++++
 arch/powerpc/kernel/head_64.S   |   54 ++++++++++++++++++++++++++++++++--------
 arch/powerpc/kernel/irq.c       |    2 -
 arch/powerpc/kernel/irqtrace.S  |   47 ++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/ppc_ksyms.c |    2 -
 arch/powerpc/kernel/setup_64.c  |    6 ++++
 include/asm-powerpc/hw_irq.h    |   14 +++++-----
 include/asm-powerpc/irqflags.h  |   13 ---------
 include/asm-powerpc/rwsem.h     |   34 +++++++++++++++++++------
 include/asm-powerpc/spinlock.h  |    1 
 12 files changed, 167 insertions(+), 40 deletions(-)

--- linux-2.6-git32.orig/arch/powerpc/Kconfig	2007-06-28 14:53:58.603430447 +0200
+++ linux-2.6-git32/arch/powerpc/Kconfig	2007-06-28 14:58:02.683430447 +0200
@@ -38,6 +38,15 @@ config STACKTRACE_SUPPORT
 	bool
 	default y
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	depends on PPC64
+	default y
+
+config LOCKDEP_SUPPORT
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
--- linux-2.6-git32.orig/arch/powerpc/kernel/irq.c	2007-06-28 14:53:58.604430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/irq.c	2007-06-28 14:48:38.709430447 +0200
@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsi
 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-void local_irq_restore(unsigned long en)
+void raw_local_irq_restore(unsigned long en)
 {
 	/*
 	 * get_paca()->soft_enabled = en;
--- linux-2.6-git32.orig/arch/powerpc/kernel/ppc_ksyms.c	2007-06-28 14:53:58.678430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/ppc_ksyms.c	2007-06-28 14:49:24.887430447 +0200
@@ -50,7 +50,7 @@
 #endif
 
 #ifdef CONFIG_PPC64
-EXPORT_SYMBOL(local_irq_restore);
+EXPORT_SYMBOL(raw_local_irq_restore);
 #endif
 
 #ifdef CONFIG_PPC32
--- linux-2.6-git32.orig/include/asm-powerpc/hw_irq.h	2007-06-28 14:53:58.730430447 +0200
+++ linux-2.6-git32/include/asm-powerpc/hw_irq.h	2007-06-28 14:58:41.508430447 +0200
@@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
 	return flags;
 }
 
-static inline unsigned long local_irq_disable(void)
+static inline unsigned long raw_local_irq_disable(void)
 {
 	unsigned long flags, zero;
 
@@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
 	return flags;
 }
 
-extern void local_irq_restore(unsigned long);
+extern void raw_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define local_irq_enable()	local_irq_restore(1)
-#define local_save_flags(flags)	((flags) = local_get_flags())
-#define local_irq_save(flags)	((flags) = local_irq_disable())
+#define raw_local_irq_enable()	raw_local_irq_restore(1)
+#define raw_local_save_flags(flags)	((flags) = local_get_flags())
+#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
 
-#define irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled_flags(flags)		((flags) == 0)
 
 #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -108,6 +109,7 @@ static inline void local_irq_save_ptr(un
 #define local_save_flags(flags)	((flags) = mfmsr())
 #define local_irq_save(flags)	local_irq_save_ptr(&flags)
 #define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
 
 #define hard_irq_enable()	local_irq_enable()
 #define hard_irq_disable()	local_irq_disable()
--- linux-2.6-git32.orig/include/asm-powerpc/irqflags.h	2007-06-28 14:53:58.779430447 +0200
+++ linux-2.6-git32/include/asm-powerpc/irqflags.h	2007-06-28 14:52:51.821430447 +0200
@@ -15,17 +15,4 @@
  */
 #include <asm-powerpc/hw_irq.h>
 
-/*
- * Do the CPU's IRQ-state tracing from assembly code. We call a
- * C function, so save all the C-clobbered registers:
- */
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
-
-#else
-# define TRACE_IRQS_ON
-# define TRACE_IRQS_OFF
-#endif
-
 #endif
--- linux-2.6-git32.orig/include/asm-powerpc/rwsem.h	2007-06-28 14:53:58.779430447 +0200
+++ linux-2.6-git32/include/asm-powerpc/rwsem.h	2007-06-28 14:52:51.588430447 +0200
@@ -28,11 +28,21 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
 	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name)		\
 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -42,12 +52,15 @@ extern struct rw_semaphore *rwsem_down_w
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)					\
+	do {						\
+		static struct lock_class_key __key;	\
+							\
+		__init_rwsem((sem), #sem, &__key);	\
+	} while (0)
 
 /*
  * lock for reading
@@ -74,7 +87,7 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write(struct rw_semaphore *sem)
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	int tmp;
 
@@ -84,6 +97,11 @@ static inline void __down_write(struct r
 		rwsem_down_write_failed(sem);
 }
 
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	__down_write_nested(sem, 0);
+}
+
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
 	int tmp;
--- linux-2.6-git32.orig/include/asm-powerpc/spinlock.h	2007-06-28 14:53:58.780430447 +0200
+++ linux-2.6-git32/include/asm-powerpc/spinlock.h	2007-06-28 14:52:51.641430447 +0200
@@ -19,6 +19,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/hvcall.h>
--- linux-2.6-git32.orig/arch/powerpc/kernel/head_64.S	2007-06-28 14:53:58.679430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/head_64.S	2007-06-28 14:48:33.858430447 +0200
@@ -394,6 +394,12 @@ label##_iSeries:							\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
+#else
+#define TRACE_DISABLE_INTS
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS				\
 	li	r11,0;				\
@@ -405,14 +411,15 @@ BEGIN_FW_FTR_SECTION;				\
 	mfmsr	r10;				\
 	ori	r10,r10,MSR_EE;			\
 	mtmsrd	r10,1;				\
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
+	TRACE_DISABLE_INTS
 
 #else
 #define DISABLE_INTS				\
 	li	r11,0;				\
 	stb	r11,PACASOFTIRQEN(r13);		\
-	stb	r11,PACAHARDIRQEN(r13)
-
+	stb	r11,PACAHARDIRQEN(r13);		\
+	TRACE_DISABLE_INTS
 #endif /* CONFIG_PPC_ISERIES */
 
 #define ENABLE_INTS				\
@@ -965,24 +972,38 @@ bad_stack:
  */
 fast_exc_return_irq:			/* restores irq state too */
 	ld	r3,SOFTE(r1)
-	ld	r12,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	1f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+1:
 	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+	cmpdi	r3,0
+	bne	2f
+	bl	.trace_hardirqs_off
+	ld	r3,SOFTE(r1)
+2:
+#else
+	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+#endif
+	ld	r12,_MSR(r1)
 	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
 	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
+	b	3f
 
 	.globl	fast_exception_return
 fast_exception_return:
 	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
+3:	ld	r11,_NIP(r1)
 	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	andi.	r3,r12,MSR_PR
-	beq	2f
+	beq	4f
 	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
+4:
 #endif
 
 	ld	r3,_CCR(r1)
@@ -1387,11 +1408,24 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISER
 
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .local_irq_restore
+	 * to what it was before the trap.  Note that .raw_local_irq_restore
 	 * handles any interrupts pending at this point.
 	 */
 	ld	r3,SOFTE(r1)
-	bl	.local_irq_restore
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	14f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+14:
+	bl	.raw_local_irq_restore
+	cmpdi	r3,0
+	bne	15f
+	bl	.trace_hardirqs_off
+15:
+#else
+	bl	.raw_local_irq_restore
+#endif
 	b	11f
 
 /* Here we have a page fault that hash_page can't handle. */
--- linux-2.6-git32.orig/arch/powerpc/kernel/setup_64.c	2007-06-28 14:53:58.729430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/setup_64.c	2007-06-28 14:49:08.305430447 +0200
@@ -33,6 +33,7 @@
 #include <linux/serial_8250.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/lockdep.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -359,6 +360,11 @@ void __init setup_system(void)
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
+	 * start lockdep
+	 */
+	lockdep_init();
+
+	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
 	unflatten_device_tree();
--- linux-2.6-git32.orig/arch/powerpc/kernel/entry_64.S	2007-06-28 14:53:58.729430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/entry_64.S	2007-06-28 14:49:13.125430447 +0200
@@ -91,6 +91,13 @@ system_call_common:
 	li	r10,1
 	stb	r10,PACASOFTIRQEN(r13)
 	stb	r10,PACAHARDIRQEN(r13)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.trace_hardirqs_on
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+#endif
 	std	r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
@@ -491,8 +498,20 @@ BEGIN_FW_FTR_SECTION
 4:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r5,0
+	beq	5f
+	bl	.trace_hardirqs_on
+	ld	r5,SOFTE(r1)
 	stb	r5,PACASOFTIRQEN(r13)
-
+	b	6f
+5:
+	stb	r5,PACASOFTIRQEN(r13)
+	bl	.trace_hardirqs_off
+6:
+#else
+	stb	r5,PACASOFTIRQEN(r13)
+#endif
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
@@ -560,6 +579,9 @@ do_work:
 	bne	restore
 	/* here we are preempting the current task */
 1:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.powerpc_trace_hardirqs_on
+#endif
 	li	r0,1
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
--- linux-2.6-git32.orig/arch/powerpc/kernel/Makefile	2007-06-28 14:53:58.729430447 +0200
+++ linux-2.6-git32/arch/powerpc/kernel/Makefile	2007-06-28 14:48:41.691430447 +0200
@@ -62,6 +62,7 @@ obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_TRACE_IRQFLAGS)	+= irqtrace.o
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git32/arch/powerpc/kernel/irqtrace.S	2007-06-28 14:49:25.754430447 +0200
@@ -0,0 +1,47 @@
+/*
+ * crappy helper for irq-trace
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+#define STACKSPACE	GPR0 + 16*8
+
+#ifdef __powerpc64__
+#define ST	std
+#define L	ld
+#else
+#define ST	stw
+#define L	lw
+#endif
+
+#define PRE				\
+	subi	r1,r1,STACKSPACE ;	\
+	SAVE_GPR(0, r1) ;		\
+	SAVE_8GPRS(2, r1) ;		\
+	SAVE_4GPRS(10, r1) ;		\
+	mfcr	r0 ;			\
+	ST	r0, (14*8)(r1) ;	\
+	mflr	r0 ;			\
+	ST	r0, (15*8)(r1)
+
+#define POST				\
+	REST_8GPRS(2, r1) ;		\
+	REST_4GPRS(10, r1) ;		\
+	L	r0, (14*8)(r1) ;	\
+	mtcr	r0 ;			\
+	L	r0, (15*8)(r1) ;	\
+	mtlr	r0 ;			\
+	REST_GPR(0, r1) ;		\
+	addi	r1,r1,STACKSPACE
+
+_GLOBAL(powerpc_trace_hardirqs_off)
+	PRE
+	bl .trace_hardirqs_off
+	POST
+	blr
+_GLOBAL(powerpc_trace_hardirqs_on)
+	PRE
+	bl .trace_hardirqs_on
+	POST
+	blr

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

* Re: powerpc stacktrace and lockdep support
  2007-06-28 16:20     ` Johannes Berg
@ 2007-06-30  8:58       ` Christoph Hellwig
  2007-07-04 22:40         ` Johannes Berg
  2007-07-05 19:26       ` Sergei Shtylyov
  1 sibling, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2007-06-30  8:58 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, Christoph Hellwig

On Thu, Jun 28, 2007 at 06:20:42PM +0200, Johannes Berg wrote:
> This one doesn't break 32-bit build by simply disabling irqtrace for
> 32-bit.

This looks really cool to me.  I'd love to see this in 2.6.23.

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

* Re: powerpc stacktrace and lockdep support
  2007-06-30  8:58       ` Christoph Hellwig
@ 2007-07-04 22:40         ` Johannes Berg
  2007-07-06  9:23           ` Johannes Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2007-07-04 22:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

On Sat, 2007-06-30 at 10:58 +0200, Christoph Hellwig wrote:
> On Thu, Jun 28, 2007 at 06:20:42PM +0200, Johannes Berg wrote:
> > This one doesn't break 32-bit build by simply disabling irqtrace for
> > 32-bit.
> 
> This looks really cool to me.  I'd love to see this in 2.6.23.

Hmm. Looks like I just found a case where I forgot to trace in some
place:

[  241.629380] hardirqs last  enabled at (1319): [<c0000000000b3718>] .get_page_from_freelist+0x298/0x620
[  241.629714] hardirqs last disabled at (1320): [<c000000000033690>] .native_hpte_invalidate+0x60/0x320
[  241.629732] softirqs last  enabled at (1282): [<c000000000059e28>] .__do_softirq+0x198/0x1e0
[  241.629748] softirqs last disabled at (1273): [<c00000000000c7e4>] .do_softirq+0xd4/0xe0

I'll look into it when I get around.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

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

* Re: powerpc stacktrace and lockdep support
  2007-06-28 16:20     ` Johannes Berg
  2007-06-30  8:58       ` Christoph Hellwig
@ 2007-07-05 19:26       ` Sergei Shtylyov
  2007-07-06 10:59         ` Johannes Berg
  1 sibling, 1 reply; 10+ messages in thread
From: Sergei Shtylyov @ 2007-07-05 19:26 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, Christoph Hellwig

Johannes Berg wrote:
> This one doesn't break 32-bit build by simply disabling irqtrace for
> 32-bit.

> --- linux-2.6-git32.orig/include/asm-powerpc/hw_irq.h	2007-06-28 14:53:58.730430447 +0200
> +++ linux-2.6-git32/include/asm-powerpc/hw_irq.h	2007-06-28 14:58:41.508430447 +0200
> @@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
>  	return flags;
>  }
>  
> -static inline unsigned long local_irq_disable(void)
> +static inline unsigned long raw_local_irq_disable(void)
>  {
>  	unsigned long flags, zero;
>  
> @@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
>  	return flags;
>  }
>  
> -extern void local_irq_restore(unsigned long);
> +extern void raw_local_irq_restore(unsigned long);
>  extern void iseries_handle_interrupts(void);
>  
> -#define local_irq_enable()	local_irq_restore(1)
> -#define local_save_flags(flags)	((flags) = local_get_flags())
> -#define local_irq_save(flags)	((flags) = local_irq_disable())
> +#define raw_local_irq_enable()	raw_local_irq_restore(1)
> +#define raw_local_save_flags(flags)	((flags) = local_get_flags())
> +#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
>  
> -#define irqs_disabled()		(local_get_flags() == 0)
> +#define raw_irqs_disabled()		(local_get_flags() == 0)
> +#define raw_irqs_disabled_flags(flags)		((flags) == 0)
>  
>  #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
>  #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
> @@ -108,6 +109,7 @@ static inline void local_irq_save_ptr(un
>  #define local_save_flags(flags)	((flags) = mfmsr())
>  #define local_irq_save(flags)	local_irq_save_ptr(&flags)
>  #define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
> +#define irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
>  
>  #define hard_irq_enable()	local_irq_enable()
>  #define hard_irq_disable()	local_irq_disable()
> --- linux-2.6-git32.orig/include/asm-powerpc/irqflags.h	2007-06-28 14:53:58.779430447 +0200
> +++ linux-2.6-git32/include/asm-powerpc/irqflags.h	2007-06-28 14:52:51.821430447 +0200
> @@ -15,17 +15,4 @@
>   */
>  #include <asm-powerpc/hw_irq.h>
>  
> -/*
> - * Do the CPU's IRQ-state tracing from assembly code. We call a
> - * C function, so save all the C-clobbered registers:
> - */
> -#ifdef CONFIG_TRACE_IRQFLAGS
> -
> -#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
> -
> -#else
> -# define TRACE_IRQS_ON
> -# define TRACE_IRQS_OFF
> -#endif
> -
>  #endif

    I suggest to also remove these 3 lines from the heading comment in this 
file -- they're not true anyway:

  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
  * raw_local_irq_*() macros from the lowlevel headers.

> --- linux-2.6-git32.orig/arch/powerpc/kernel/head_64.S	2007-06-28 14:53:58.679430447 +0200
> +++ linux-2.6-git32/arch/powerpc/kernel/head_64.S	2007-06-28 14:48:33.858430447 +0200
> @@ -394,6 +394,12 @@ label##_iSeries:							\
>  	EXCEPTION_PROLOG_ISERIES_2;					\
>  	b	label##_common;						\
>  
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
> +#else
> +#define TRACE_DISABLE_INTS
> +#endif
> +

    Erm, weren't those supposed to be in <asm-powerpc/irqflags.h>?

>  #ifdef CONFIG_PPC_ISERIES
>  #define DISABLE_INTS				\
>  	li	r11,0;				\
> @@ -405,14 +411,15 @@ BEGIN_FW_FTR_SECTION;				\
>  	mfmsr	r10;				\
>  	ori	r10,r10,MSR_EE;			\
>  	mtmsrd	r10,1;				\
> -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
> +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
> +	TRACE_DISABLE_INTS
>  
>  #else
>  #define DISABLE_INTS				\
>  	li	r11,0;				\
>  	stb	r11,PACASOFTIRQEN(r13);		\
> -	stb	r11,PACAHARDIRQEN(r13)
> -
> +	stb	r11,PACAHARDIRQEN(r13);		\
> +	TRACE_DISABLE_INTS
>  #endif /* CONFIG_PPC_ISERIES */
>  
>  #define ENABLE_INTS				\
> @@ -965,24 +972,38 @@ bad_stack:

    The following code seemed over-engineered:

>   */
>  fast_exc_return_irq:			/* restores irq state too */
>  	ld	r3,SOFTE(r1)
> -	ld	r12,_MSR(r1)
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r3,0
> +	beq	1f
> +	bl	.trace_hardirqs_on

	b 	2f
1:

> +	bl	.trace_hardirqs_off

2:

> +	ld	r3,SOFTE(r1)
> +#endif
	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
> +	ld	r12,_MSR(r1)
>  	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
>  	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
> -	b	1f
> +	b	3f

[...]

> --- linux-2.6-git32.orig/arch/powerpc/kernel/entry_64.S	2007-06-28 14:53:58.729430447 +0200
> +++ linux-2.6-git32/arch/powerpc/kernel/entry_64.S	2007-06-28 14:49:13.125430447 +0200
[...]
> @@ -491,8 +498,20 @@ BEGIN_FW_FTR_SECTION
>  4:
>  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
>  #endif
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r5,0
> +	beq	5f
> +	bl	.trace_hardirqs_on
> +	ld	r5,SOFTE(r1)
>  	stb	r5,PACASOFTIRQEN(r13)
> -
> +	b	6f
> +5:
> +	stb	r5,PACASOFTIRQEN(r13)
> +	bl	.trace_hardirqs_off
> +6:
> +#else
> +	stb	r5,PACASOFTIRQEN(r13)
> +#endif

    Again, could have been more compact... unless trace_hardirqs_*() calls 
need to be in certain order WRT writes to PACASOFTIRQEN -- if so, in the 1st 
case that I've pointed out the order was not identical (probably wrong?)...

> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6-git32/arch/powerpc/kernel/irqtrace.S	2007-06-28 14:49:25.754430447 +0200
> @@ -0,0 +1,47 @@
> +/*
> + * crappy helper for irq-trace
> + */
> +
> +#include <asm/ppc_asm.h>
> +#include <asm/asm-offsets.h>
> +
> +#define STACKSPACE	GPR0 + 16*8

    I guess this should be 16*4 for PPC32.

> +
> +#ifdef __powerpc64__
> +#define ST	std
> +#define L	ld
> +#else
> +#define ST	stw
> +#define L	lw
> +#endif
> +
> +#define PRE				\
> +	subi	r1,r1,STACKSPACE ;	\
> +	SAVE_GPR(0, r1) ;		\
> +	SAVE_8GPRS(2, r1) ;		\
> +	SAVE_4GPRS(10, r1) ;		\
> +	mfcr	r0 ;			\
> +	ST	r0, (14*8)(r1) ;	\
> +	mflr	r0 ;			\
> +	ST	r0, (15*8)(r1)

    Didn't you forget to add GPR0 to the offsets here?

> +#define POST				\
> +	REST_8GPRS(2, r1) ;		\
> +	REST_4GPRS(10, r1) ;		\
> +	L	r0, (14*8)(r1) ;	\
> +	mtcr	r0 ;			\
> +	L	r0, (15*8)(r1) ;	\
> +	mtlr	r0 ;			\
> +	REST_GPR(0, r1) ;		\
> +	addi	r1,r1,STACKSPACE

    You certainly did. I bet you're clobbering GPR11/12 (if I didn't miscount)...

WBR, Sergei

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

* Re: powerpc stacktrace and lockdep support
  2007-07-04 22:40         ` Johannes Berg
@ 2007-07-06  9:23           ` Johannes Berg
  2007-07-06  9:54             ` Johannes Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2007-07-06  9:23 UTC (permalink / raw)
  To: Christoph Hellwig, Benjamin Herrenschmidt; +Cc: linuxppc-dev

On Thu, 2007-07-05 at 00:40 +0200, Johannes Berg wrote:
> On Sat, 2007-06-30 at 10:58 +0200, Christoph Hellwig wrote:
> > On Thu, Jun 28, 2007 at 06:20:42PM +0200, Johannes Berg wrote:
> > > This one doesn't break 32-bit build by simply disabling irqtrace for
> > > 32-bit.
> > 
> > This looks really cool to me.  I'd love to see this in 2.6.23.
> 
> Hmm. Looks like I just found a case where I forgot to trace in some
> place:
> 
> [  241.629380] hardirqs last  enabled at (1319): [<c0000000000b3718>] .get_page_from_freelist+0x298/0x620
> [  241.629714] hardirqs last disabled at (1320): [<c000000000033690>] .native_hpte_invalidate+0x60/0x320
> [  241.629732] softirqs last  enabled at (1282): [<c000000000059e28>] .__do_softirq+0x198/0x1e0
> [  241.629748] softirqs last disabled at (1273): [<c00000000000c7e4>] .do_softirq+0xd4/0xe0

Not sure what that was, but I found one place where it could have come
from (do an interdiff if you want to know). Below patch is a bit nicer,
especially those trace_hardirqs wrappers. However, the presence of those
itself is indication that I haven't given most of the hooks I added much
thought. Though, in case somebody wants to develop it further I'll even
sign it off.

For me it's doing what I want, it allows me to develop with and for
lockdep, take advantage of lockdep and still use my machine (with forced
preemption) as expected; however I don't think I'd be comfortable with
anybody else using it except on test machines unless somebody else gives
it a thorough look first. Especially for say iSeries which is quite
different in the low-level code and I can't even test.

johannes

Subject: powerpc: 64-bit irqtrace support
From: Johannes Berg <johannes@sipsolutions.net>

This adds irqtrace support to 64-bit powerpc.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

---
 arch/powerpc/Kconfig            |    9 ++++
 arch/powerpc/kernel/Makefile    |    1 
 arch/powerpc/kernel/entry_64.S  |   24 +++++++++++
 arch/powerpc/kernel/head_64.S   |   54 +++++++++++++++++++++-----
 arch/powerpc/kernel/irq.c       |    2 
 arch/powerpc/kernel/irqtrace.S  |   82 ++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/ppc_ksyms.c |    2 
 arch/powerpc/kernel/setup_64.c  |    6 ++
 include/asm-powerpc/hw_irq.h    |   14 +++---
 include/asm-powerpc/irqflags.h  |   13 ------
 include/asm-powerpc/rwsem.h     |   34 ++++++++++++----
 include/asm-powerpc/spinlock.h  |    1 
 12 files changed, 202 insertions(+), 40 deletions(-)

--- linux-2.6-git.orig/arch/powerpc/Kconfig	2007-07-05 23:01:18.001397556 +0200
+++ linux-2.6-git/arch/powerpc/Kconfig	2007-07-05 23:01:18.068397556 +0200
@@ -38,6 +38,15 @@ config STACKTRACE_SUPPORT
 	bool
 	default y
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	depends on PPC64
+	default y
+
+config LOCKDEP_SUPPORT
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
--- linux-2.6-git.orig/arch/powerpc/kernel/irq.c	2007-07-05 23:01:11.727397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/irq.c	2007-07-05 23:01:18.084397556 +0200
@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsi
 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-void local_irq_restore(unsigned long en)
+void raw_local_irq_restore(unsigned long en)
 {
 	/*
 	 * get_paca()->soft_enabled = en;
--- linux-2.6-git.orig/arch/powerpc/kernel/ppc_ksyms.c	2007-07-05 23:01:11.759397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/ppc_ksyms.c	2007-07-05 23:01:18.094397556 +0200
@@ -50,7 +50,7 @@
 #endif
 
 #ifdef CONFIG_PPC64
-EXPORT_SYMBOL(local_irq_restore);
+EXPORT_SYMBOL(raw_local_irq_restore);
 #endif
 
 #ifdef CONFIG_PPC32
--- linux-2.6-git.orig/include/asm-powerpc/hw_irq.h	2007-07-05 23:01:11.985397556 +0200
+++ linux-2.6-git/include/asm-powerpc/hw_irq.h	2007-07-05 23:01:18.108397556 +0200
@@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
 	return flags;
 }
 
-static inline unsigned long local_irq_disable(void)
+static inline unsigned long raw_local_irq_disable(void)
 {
 	unsigned long flags, zero;
 
@@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
 	return flags;
 }
 
-extern void local_irq_restore(unsigned long);
+extern void raw_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define local_irq_enable()	local_irq_restore(1)
-#define local_save_flags(flags)	((flags) = local_get_flags())
-#define local_irq_save(flags)	((flags) = local_irq_disable())
+#define raw_local_irq_enable()	raw_local_irq_restore(1)
+#define raw_local_save_flags(flags)	((flags) = local_get_flags())
+#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
 
-#define irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled()		(local_get_flags() == 0)
+#define raw_irqs_disabled_flags(flags)		((flags) == 0)
 
 #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -108,6 +109,7 @@ static inline void local_irq_save_ptr(un
 #define local_save_flags(flags)	((flags) = mfmsr())
 #define local_irq_save(flags)	local_irq_save_ptr(&flags)
 #define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
 
 #define hard_irq_enable()	local_irq_enable()
 #define hard_irq_disable()	local_irq_disable()
--- linux-2.6-git.orig/include/asm-powerpc/irqflags.h	2007-07-05 23:01:12.018397556 +0200
+++ linux-2.6-git/include/asm-powerpc/irqflags.h	2007-07-05 23:01:18.141397556 +0200
@@ -15,17 +15,4 @@
  */
 #include <asm-powerpc/hw_irq.h>
 
-/*
- * Do the CPU's IRQ-state tracing from assembly code. We call a
- * C function, so save all the C-clobbered registers:
- */
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
-
-#else
-# define TRACE_IRQS_ON
-# define TRACE_IRQS_OFF
-#endif
-
 #endif
--- linux-2.6-git.orig/include/asm-powerpc/rwsem.h	2007-07-05 23:01:12.050397556 +0200
+++ linux-2.6-git/include/asm-powerpc/rwsem.h	2007-07-05 23:01:18.149397556 +0200
@@ -28,11 +28,21 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
 	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name)		\
 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -42,12 +52,15 @@ extern struct rw_semaphore *rwsem_down_w
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)					\
+	do {						\
+		static struct lock_class_key __key;	\
+							\
+		__init_rwsem((sem), #sem, &__key);	\
+	} while (0)
 
 /*
  * lock for reading
@@ -74,7 +87,7 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write(struct rw_semaphore *sem)
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	int tmp;
 
@@ -84,6 +97,11 @@ static inline void __down_write(struct r
 		rwsem_down_write_failed(sem);
 }
 
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	__down_write_nested(sem, 0);
+}
+
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
 	int tmp;
--- linux-2.6-git.orig/include/asm-powerpc/spinlock.h	2007-07-05 23:01:12.097397556 +0200
+++ linux-2.6-git/include/asm-powerpc/spinlock.h	2007-07-05 23:01:18.152397556 +0200
@@ -19,6 +19,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/hvcall.h>
--- linux-2.6-git.orig/arch/powerpc/kernel/head_64.S	2007-07-05 23:01:11.796397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/head_64.S	2007-07-05 23:01:18.173397556 +0200
@@ -394,6 +394,12 @@ label##_iSeries:							\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
+#else
+#define TRACE_DISABLE_INTS
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS				\
 	li	r11,0;				\
@@ -405,14 +411,15 @@ BEGIN_FW_FTR_SECTION;				\
 	mfmsr	r10;				\
 	ori	r10,r10,MSR_EE;			\
 	mtmsrd	r10,1;				\
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
+	TRACE_DISABLE_INTS
 
 #else
 #define DISABLE_INTS				\
 	li	r11,0;				\
 	stb	r11,PACASOFTIRQEN(r13);		\
-	stb	r11,PACAHARDIRQEN(r13)
-
+	stb	r11,PACAHARDIRQEN(r13);		\
+	TRACE_DISABLE_INTS
 #endif /* CONFIG_PPC_ISERIES */
 
 #define ENABLE_INTS				\
@@ -965,24 +972,38 @@ bad_stack:
  */
 fast_exc_return_irq:			/* restores irq state too */
 	ld	r3,SOFTE(r1)
-	ld	r12,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	1f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+1:
 	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+	cmpdi	r3,0
+	bne	2f
+	bl	.trace_hardirqs_off
+	ld	r3,SOFTE(r1)
+2:
+#else
+	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+#endif
+	ld	r12,_MSR(r1)
 	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
 	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
+	b	3f
 
 	.globl	fast_exception_return
 fast_exception_return:
 	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
+3:	ld	r11,_NIP(r1)
 	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	andi.	r3,r12,MSR_PR
-	beq	2f
+	beq	4f
 	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
+4:
 #endif
 
 	ld	r3,_CCR(r1)
@@ -1387,11 +1408,24 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISER
 
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .local_irq_restore
+	 * to what it was before the trap.  Note that .raw_local_irq_restore
 	 * handles any interrupts pending at this point.
 	 */
 	ld	r3,SOFTE(r1)
-	bl	.local_irq_restore
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r3,0
+	beq	14f
+	bl	.trace_hardirqs_on
+	ld	r3,SOFTE(r1)
+14:
+	bl	.raw_local_irq_restore
+	cmpdi	r3,0
+	bne	15f
+	bl	.trace_hardirqs_off
+15:
+#else
+	bl	.raw_local_irq_restore
+#endif
 	b	11f
 
 /* Here we have a page fault that hash_page can't handle. */
--- linux-2.6-git.orig/arch/powerpc/kernel/setup_64.c	2007-07-05 23:01:11.829397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/setup_64.c	2007-07-05 23:01:18.185397556 +0200
@@ -33,6 +33,7 @@
 #include <linux/serial_8250.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/lockdep.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -359,6 +360,11 @@ void __init setup_system(void)
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
+	 * start lockdep
+	 */
+	lockdep_init();
+
+	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
 	unflatten_device_tree();
--- linux-2.6-git.orig/arch/powerpc/kernel/entry_64.S	2007-07-05 23:01:11.864397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/entry_64.S	2007-07-05 23:01:18.211397556 +0200
@@ -88,6 +88,13 @@ system_call_common:
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	ld	r11,exception_marker@toc(r2)
 	std	r11,-16(r9)		/* "regshere" marker */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.trace_hardirqs_on
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+#endif
 	li	r10,1
 	stb	r10,PACASOFTIRQEN(r13)
 	stb	r10,PACAHARDIRQEN(r13)
@@ -491,8 +498,20 @@ BEGIN_FW_FTR_SECTION
 4:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	cmpdi	r5,0
+	beq	5f
+	bl	.trace_hardirqs_on
+	ld	r5,SOFTE(r1)
 	stb	r5,PACASOFTIRQEN(r13)
-
+	b	6f
+5:
+	stb	r5,PACASOFTIRQEN(r13)
+	bl	.trace_hardirqs_off
+6:
+#else
+	stb	r5,PACASOFTIRQEN(r13)
+#endif
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
@@ -560,6 +579,9 @@ do_work:
 	bne	restore
 	/* here we are preempting the current task */
 1:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	.powerpc_trace_hardirqs_on
+#endif
 	li	r0,1
 	stb	r0,PACASOFTIRQEN(r13)
 	stb	r0,PACAHARDIRQEN(r13)
--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-07-05 23:01:18.002397556 +0200
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-07-05 23:01:18.212397556 +0200
@@ -62,6 +62,7 @@ obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_TRACE_IRQFLAGS)	+= irqtrace.o
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/irqtrace.S	2007-07-06 02:11:15.110814034 +0200
@@ -0,0 +1,82 @@
+/*
+ * helpers for irq-trace
+ *
+ * We invoke the hardirq trace functions from various inconvenient
+ * places; these helpers save all callee-saved registers.
+ *
+ * Author: Johannes Berg <johannes@sipsolutions.net>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_PPC64
+#define ST	std
+#define STU	stdu
+#define L	ld
+#define WSZ	8
+#define FREE	32
+#else
+#error double-check please
+#define ST	stw
+#define STU	stwu
+#define L	lwz
+#define WSZ	4
+#define FREE	16
+#endif
+
+#define STACKSPACE	(FREE + 16*WSZ)
+#define SAVE(n)		(FREE + n*WSZ)
+
+_GLOBAL(powerpc_trace_hardirqs_on)
+	ST	r3, (SAVE(2)-STACKSPACE)(r1)
+	LOAD_REG_IMMEDIATE(r3, .trace_hardirqs_on)
+	b	powerpc_trace_hardirqs
+
+_GLOBAL(powerpc_trace_hardirqs_off)
+	ST	r3, (SAVE(2)-STACKSPACE)(r1)
+	LOAD_REG_IMMEDIATE(r3, .trace_hardirqs_off)
+
+powerpc_trace_hardirqs:
+	ST	r0, (SAVE(0)-STACKSPACE)(r1)
+	mflr	r0
+	ST	r0, LRSAVE(r1)
+	STU	r1, -STACKSPACE(r1)
+	mfctr	r0
+	ST	r0, SAVE(14)(r1)
+	mtctr	r3
+	ST	r2, SAVE(1)(r1)
+	ST	r4, SAVE(3)(r1)
+	ST	r5, SAVE(4)(r1)
+	ST	r6, SAVE(5)(r1)
+	ST	r7, SAVE(6)(r1)
+	ST	r8, SAVE(7)(r1)
+	ST	r9, SAVE(8)(r1)
+	ST	r10, SAVE(9)(r1)
+	ST	r11, SAVE(10)(r1)
+	ST	r12, SAVE(11)(r1)
+	ST	r13, SAVE(12)(r1)
+	mfcr	r0
+	ST	r0, SAVE(13)(r1)
+	bctrl
+	L	r2, SAVE(1)(r1)
+	L	r3, SAVE(2)(r1)
+	L	r4, SAVE(3)(r1)
+	L	r5, SAVE(4)(r1)
+	L	r6, SAVE(5)(r1)
+	L	r7, SAVE(6)(r1)
+	L	r8, SAVE(7)(r1)
+	L	r9, SAVE(8)(r1)
+	L	r10, SAVE(9)(r1)
+	L	r11, SAVE(10)(r1)
+	L	r12, SAVE(11)(r1)
+	L	r13, SAVE(12)(r1)
+	L	r0, SAVE(13)(r1)
+	mtcr	r0
+	L	r0, SAVE(14)(r1)
+	mtctr	r0
+	L	r1, 0(r1)
+	L	r0, LRSAVE(r1)
+	mtlr	r0
+	L	r0, (SAVE(0)-STACKSPACE)(r1)
+	blr

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

* Re: powerpc stacktrace and lockdep support
  2007-07-06  9:23           ` Johannes Berg
@ 2007-07-06  9:54             ` Johannes Berg
  0 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2007-07-06  9:54 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1464 bytes --]

*sigh* I really shouldn't have mailed this out in the first place. Every
time I look at it I find new bugs despite the fact that it actually
works on my machine.

>  	ld	r3,SOFTE(r1)
> -	bl	.local_irq_restore
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r3,0
> +	beq	14f
> +	bl	.trace_hardirqs_on
> +	ld	r3,SOFTE(r1)
> +14:
> +	bl	.raw_local_irq_restore
> +	cmpdi	r3,0

This should reload r3 before the second compare as raw_local_irq_restore
returns nothing (void). And why does it need a second compare anyway?
Just rewrite as

	ld	r3, SOFTE(r1)
#ifdef CONFIG_TRACE_IRQFLAGS
	cmpdi	r3, 0
	bne	14f
	bl	.raw_local_irq_restore
	bl	.trace_hardirqs_off
	b	15f
14:
	bl	.trace_hardirqs_on
	li	r3, 1
#endif
	bl	.raw_local_irq_restore
15:

which has the advantage of having only one conditional branch and less
preprocessor foo.

> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r5,0
> +	beq	5f
> +	bl	.trace_hardirqs_on
> +	ld	r5,SOFTE(r1)
>  	stb	r5,PACASOFTIRQEN(r13)
> -
> +	b	6f
> +5:
> +	stb	r5,PACASOFTIRQEN(r13)
> +	bl	.trace_hardirqs_off
> +6:
> +#else
> +	stb	r5,PACASOFTIRQEN(r13)
> +#endif

Similarly, that could be rewritten as

#ifdef CONFIG_TRACE_IRQFLAGS
	cmpdi	r5, 0
	bne	5f
	stb	r5, PACASOFTIRQEN(r13)
	bl	.trace_hardirqs_off
	b	6f
5:
	bl	.trace_hardirqs_on
	li	r5, 1
#endif
	stb	r5, PACASOFTIRQEN(r13)
6:

I can't test these modifications over the weekend but they should be
fine.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

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

* Re: powerpc stacktrace and lockdep support
  2007-07-05 19:26       ` Sergei Shtylyov
@ 2007-07-06 10:59         ` Johannes Berg
  0 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2007-07-06 10:59 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linuxppc-dev, Christoph Hellwig

[-- Attachment #1: Type: text/plain, Size: 1654 bytes --]

Sergei, Thanks for your review!

>     I suggest to also remove these 3 lines from the heading comment in this 
> file -- they're not true anyway:
> 
>   * This file gets included from lowlevel asm headers too, to provide
>   * wrapped versions of the local_irq_*() APIs, based on the
>   * raw_local_irq_*() macros from the lowlevel headers.

Good point.

> > +#ifdef CONFIG_TRACE_IRQFLAGS
> > +#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
> > +#else
> > +#define TRACE_DISABLE_INTS
> > +#endif
> > +
> 
>     Erm, weren't those supposed to be in <asm-powerpc/irqflags.h>?

I guess they could be there. I was mucking my way through ;)

>     The following code seemed over-engineered:

Yeah, perfectly correct. See my last mail to this thread from this
morning.

>     Again, could have been more compact... unless trace_hardirqs_*() calls 
> need to be in certain order WRT writes to PACASOFTIRQEN -- if so, in the 1st 
> case that I've pointed out the order was not identical (probably wrong?)...

Yeah, there is an ordering requirement and it was wrong in that version
of the patch.

> > +/*
> > + * crappy helper for irq-trace
> > + */
> > +
> > +#include <asm/ppc_asm.h>
> > +#include <asm/asm-offsets.h>
> > +
> > +#define STACKSPACE	GPR0 + 16*8
> 
>     I guess this should be 16*4 for PPC32.

>     Didn't you forget to add GPR0 to the offsets here?

>     You certainly did. I bet you're clobbering GPR11/12 (if I didn't miscount)...

All correct. That might even be why it didn't work on 32-bit for me and
then I gave up. In any case, I completely rewrote this file.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

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

end of thread, other threads:[~2007-07-06 10:58 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-08 13:54 powerpc stacktrace and lockdep support Christoph Hellwig
2007-06-26 22:47 ` Johannes Berg
2007-06-27 19:00   ` Johannes Berg
2007-06-28 16:20     ` Johannes Berg
2007-06-30  8:58       ` Christoph Hellwig
2007-07-04 22:40         ` Johannes Berg
2007-07-06  9:23           ` Johannes Berg
2007-07-06  9:54             ` Johannes Berg
2007-07-05 19:26       ` Sergei Shtylyov
2007-07-06 10:59         ` Johannes Berg

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).