From patchwork Sat Jun 27 11:22:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Fleming X-Patchwork-Id: 32673 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n5RBMYif023526 for ; Sat, 27 Jun 2009 11:22:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750757AbZF0LW3 (ORCPT ); Sat, 27 Jun 2009 07:22:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751919AbZF0LW3 (ORCPT ); Sat, 27 Jun 2009 07:22:29 -0400 Received: from cs20.apochromatic.org ([204.152.189.161]:63681 "EHLO cs20.apochromatic.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750757AbZF0LW2 (ORCPT ); Sat, 27 Jun 2009 07:22:28 -0400 Received: from localhost (localhost [127.0.0.1]) by cs20.apochromatic.org (Postfix) with ESMTP id A071EAD724; Sat, 27 Jun 2009 04:22:29 -0700 (PDT) Date: Sat, 27 Jun 2009 12:22:15 +0100 From: Matt Fleming To: Stuart MENEFY Cc: Nobuhiro Iwamatsu , Linux-sh , Paul Mundt Subject: Re: [BUG] Error in copy_process, when enable CONFIG_PROVE_LOCKING. Message-ID: <20090627112215.GD6396@console-pimps.org> References: <29ab51dc0905112140v3187b462qcc8a9e5385de8ef6@mail.gmail.com> <4A09685A.2070105@st.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <4A09685A.2070105@st.com> User-Agent: Mutt/1.5.17 (2007-11-01) Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org On Tue, May 12, 2009 at 01:15:22PM +0100, Stuart MENEFY wrote: > Nobuhiro Iwamatsu wrote: > > Error in copy_process, when enable CONFIG_PROVE_LOCKING. > > This error has p->hardirqs_enabled in kernel.fork.c > > > > 987 #ifdef CONFIG_PROVE_LOCKING > > 988 DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); > > 989 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); > > 990 #endif > > 991 retval = -EAGAIN; > > > > The error message is as follows. > > I am debuging this. Please teach if you know the revision method of > > this problem. > > As it happens I was looking at this recently. I think there are some > missing calls to trace_hardirqs_on/off in the assembly > code. Unfortunately my kernel is quite different from the mainline in > this area, but you could try this patch which is an *untested* forward > port of the code I'm currently running successfully. > Stuart, I took your patch and applied it to 2.6.31-rc1 and reworked it until it stopped crashing qemu. I've attached the patch, can you just give it a once over to make sure that nothing seems broken? It boots fine with and without CONFIG_PREEMPT. Paul, Nobuhiro, can you please test the attached patch to make sure that it gets rid of the lockdep warnings and doesn't deadlock your machines? I'll respin this patch into a proper series once everyone's happy with it. diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 3a4752a..0f0d4b4 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S @@ -31,6 +31,78 @@ #endif .endm +#ifdef CONFIG_TRACE_IRQFLAGS + + .macro TRACE_IRQS_ON + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + + mov.l 7834f, r0 + jsr @r0 + nop + + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + mov.l 7834f, r0 + + bra 7835f + nop + .balign 4 +7834: .long trace_hardirqs_on +7835: + .endm + .macro TRACE_IRQS_OFF + + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + + mov.l 7834f, r0 + jsr @r0 + nop + + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + mov.l 7834f, r0 + + bra 7835f + nop + .balign 4 +7834: .long trace_hardirqs_off +7835: + .endm + +#else + .macro TRACE_IRQS_ON + .endm + + .macro TRACE_IRQS_OFF + .endm +#endif + #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) # define PREF(x) pref @x #else diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index d62359c..30cfbed 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -45,7 +45,7 @@ */ #if defined(CONFIG_PREEMPT) -# define preempt_stop() cli +# define preempt_stop() cli ; TRACE_IRQS_OFF #else # define preempt_stop() # define resume_kernel __restore_all @@ -55,11 +55,7 @@ .align 2 ENTRY(exception_error) ! -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 2f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_ON sti mov.l 1f, r0 jmp @r0 @@ -67,22 +63,23 @@ ENTRY(exception_error) .align 2 1: .long do_exception_error -#ifdef CONFIG_TRACE_IRQFLAGS -2: .long trace_hardirqs_on -#endif .align 2 ret_from_exception: preempt_stop() -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 4f, r0 - jsr @r0 - nop -#endif ENTRY(ret_from_irq) ! mov #OFF_SR, r0 mov.l @(r0,r15), r0 ! get status register + + shlr2 r0 + and #0x3c, r0 + cmp/eq #0x3c, r0 + bt 9f + TRACE_IRQS_ON +9: + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register shll r0 shll r0 ! kernel space? get_current_thread_info r8, r0 @@ -125,11 +122,7 @@ noresched: ENTRY(resume_userspace) ! r8: current_thread_info cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OfF mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 bt/s __restore_all @@ -156,11 +149,7 @@ work_resched: jsr @r1 ! schedule nop cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OFF ! mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 @@ -172,10 +161,6 @@ work_resched: 1: .long schedule 2: .long do_notify_resume 3: .long resume_userspace -#ifdef CONFIG_TRACE_IRQFLAGS -4: .long trace_hardirqs_on -5: .long trace_hardirqs_off -#endif .align 2 syscall_exit_work: @@ -184,11 +169,7 @@ syscall_exit_work: tst #_TIF_WORK_SYSCALL_MASK, r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_ON sti mov r15, r4 mov.l 8f, r0 ! do_syscall_trace_leave @@ -321,11 +302,7 @@ ENTRY(system_call) bt/s debug_trap ! it's a debug trap.. nop -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r10 - jsr @r10 - nop -#endif + TRACE_IRQS_ON sti ! @@ -351,11 +328,7 @@ syscall_call: ! syscall_exit: cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 6f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OFF ! get_current_thread_info r8, r0 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags @@ -369,9 +342,5 @@ syscall_exit: #endif 2: .long NR_syscalls 3: .long sys_call_table -#ifdef CONFIG_TRACE_IRQFLAGS -5: .long trace_hardirqs_on -6: .long trace_hardirqs_off -#endif 7: .long do_syscall_trace_enter 8: .long do_syscall_trace_leave diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c index 77dfecb..e27a19e 100644 --- a/arch/sh/kernel/io_trapped.c +++ b/arch/sh/kernel/io_trapped.c @@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list, struct trapped_io *tiop; struct resource *res; int k, len; + unsigned long flags; - spin_lock_irq(&trapped_lock); + spin_lock_irqsave(&trapped_lock, flags); list_for_each_entry(tiop, list, list) { voffs = 0; for (k = 0; k < tiop->num_resources; k++) { res = tiop->resource + k; if (res->start == offset) { - spin_unlock_irq(&trapped_lock); + spin_unlock_irqrestore(&trapped_lock, flags); return tiop->virt_base + voffs; } @@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list, voffs += roundup(len, PAGE_SIZE); } } - spin_unlock_irq(&trapped_lock); + spin_unlock_irqrestore(&trapped_lock, flags); return NULL; } EXPORT_SYMBOL_GPL(match_trapped_io_handler); diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 66f5267..879eb6c 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -662,10 +662,11 @@ static irqreturn_t sci_rx_interrupt(int irq, void *port) static irqreturn_t sci_tx_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; + unsigned long flags; - spin_lock_irq(&port->lock); + spin_lock_irqsave(&port->lock, flags); sci_transmit_chars(port); - spin_unlock_irq(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; }