From fd78a76aefb5bf28a11d6960d29e03a11db62320 Mon Sep 17 00:00:00 2001 From: Stuart Menefy Date: Wed, 29 Jul 2009 23:01:24 +0900 Subject: sh: Rework irqflags tracing to fix up CONFIG_PROVE_LOCKING. This cleans up the irqflags tracing code quite a bit and ties it in to various missing callsites that caused an imbalance when CONFIG_PROVE_LOCKING was enabled. Previously this was catching on: 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; with hardirqs being doubly enabled, and subsequently bailing out with the following call trace: Call trace: [<88035224>] __lock_acquire+0x616/0x6a6 [<88015a8c>] do_fork+0xf8/0x2b0 [<880331ec>] trace_hardirqs_on_caller+0xd4/0x114 [<88241074>] _spin_unlock_irq+0x20/0x64 [<88035224>] __lock_acquire+0x616/0x6a6 [<8800386c>] kernel_thread+0x48/0x70 [<88024ecc>] ____call_usermodehelper+0x0/0x110 [<88024ecc>] ____call_usermodehelper+0x0/0x110 [<88003894>] kernel_thread_helper+0x0/0x14 [<88024bac>] __call_usermodehelper+0x38/0x70 [<88025dc0>] worker_thread+0x150/0x274 [<88035b9c>] lock_release+0x0/0x198 [<88024b74>] __call_usermodehelper+0x0/0x70 [<88028cf0>] autoremove_wake_function+0x0/0x30 [<88028bf2>] kthread+0x3e/0x70 [<88025c70>] worker_thread+0x0/0x274 [<8800389c>] kernel_thread_helper+0x8/0x14 [<88028bb4>] kthread+0x0/0x70 [<88003894>] kernel_thread_helper+0x0/0x14 Reported-by: Nobuhiro Iwamatsu Signed-off-by: Stuart Menefy Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/entry-macros.S | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'arch/sh/include/asm/entry-macros.S') diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 3a4752a65722..1bdd93891cd7 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 -- cgit v1.2.3 From 0b930489b8606224b829c8a6037eac24249a97ec Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 2 Aug 2009 22:33:26 +0100 Subject: sh: Setup the frame register in asm code In order to use DWARF unwinder info the frame register has to contain a valid value. Whilst GCC takes care of this for C code, we have to do it ourselves for assembly. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/entry-macros.S | 12 ++++++++++++ arch/sh/kernel/cpu/sh3/entry.S | 1 + arch/sh/kernel/entry-common.S | 1 + 3 files changed, 14 insertions(+) (limited to 'arch/sh/include/asm/entry-macros.S') diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 1bdd93891cd7..64fd0de24daf 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S @@ -108,3 +108,15 @@ #else # define PREF(x) nop #endif + + /* + * Macro for use within assembly. Because the DWARF unwinder + * needs to use the frame register to unwind the stack, we + * need to setup r14 with the value of the stack pointer as + * the return address is usually on the stack somewhere. + */ + .macro setup_frame_reg +#ifdef CONFIG_DWARF_UNWINDER + mov r15, r14 +#endif + .endm diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3cb531f233f2..67ad6467c694 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -137,6 +137,7 @@ ENTRY(tlb_protection_violation_store) mov #1, r5 call_dpf: + setup_frame_reg mov.l 1f, r0 mov r5, r8 mov.l @r0, r6 diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index fc26ccd82789..b3b215fb21f7 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -285,6 +285,7 @@ ret_from_fork: * system calls and debug traps through their respective jump tables. */ ENTRY(system_call) + setup_frame_reg #if !defined(CONFIG_CPU_SH2) mov.l 1f, r9 mov.l @r9, r8 ! Read from TRA (Trap Address) Register -- cgit v1.2.3 From fea966f7564205fcf5919af9bde031e753419c96 Mon Sep 17 00:00:00 2001 From: Stuart Menefy Date: Mon, 24 Aug 2009 17:09:53 +0900 Subject: sh: Remove implicit sign extension from assembler immediates The SH instruction set has several instructions which accept an 8 bit immediate operand. For logical instructions this operand is zero extended, for arithmetic instructions the operand is sign extended. After adding an option to the assembler to check this, it was found that several pieces of assembly code were assuming this behaviour, and in one case getting it wrong. So this patch explicitly sign extends any immediate operands, which makes it obvious what is happening, and fixes the one case which got it wrong. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/head_32.S | 2 +- arch/sh/include/asm/entry-macros.S | 2 +- arch/sh/kernel/cpu/sh3/entry.S | 2 +- arch/sh/kernel/entry-common.S | 5 +++-- arch/sh/lib/clear_page.S | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/sh/include/asm/entry-macros.S') diff --git a/arch/sh/boot/compressed/head_32.S b/arch/sh/boot/compressed/head_32.S index 06ac31f3be88..02a30935f0b9 100644 --- a/arch/sh/boot/compressed/head_32.S +++ b/arch/sh/boot/compressed/head_32.S @@ -22,7 +22,7 @@ startup: bt clear_bss sub r0, r2 mov.l bss_start_addr, r0 - mov #0xe0, r1 + mov #0xffffffe0, r1 and r1, r0 ! align cache line mov.l text_start_addr, r3 mov r0, r1 diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 64fd0de24daf..cc43a55e1fcf 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S @@ -7,7 +7,7 @@ .endm .macro sti - mov #0xf0, r11 + mov #0xfffffff0, r11 extu.b r11, r11 not r11, r11 stc sr, r10 diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 8c19e21847d7..9421ec715fd2 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -257,7 +257,7 @@ restore_all: ! ! Calculate new SR value mov k3, k2 ! original SR value - mov #0xf0, k1 + mov #0xfffffff0, k1 extu.b k1, k1 not k1, k1 and k1, k2 ! Mask original SR value diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 700477601c6f..68d9223b145e 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -98,8 +98,9 @@ need_resched: mov #OFF_SR, r0 mov.l @(r0,r15), r0 ! get status register - and #0xf0, r0 ! interrupts off (exception path)? - cmp/eq #0xf0, r0 + shlr r0 + and #(0xf0>>1), r0 ! interrupts off (exception path)? + cmp/eq #(0xf0>>1), r0 bt noresched mov.l 3f, r0 jsr @r0 ! call preempt_schedule_irq diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S index 8342bfbde64c..c92244d4ff9d 100644 --- a/arch/sh/lib/clear_page.S +++ b/arch/sh/lib/clear_page.S @@ -57,7 +57,7 @@ ENTRY(clear_page) ENTRY(__clear_user) ! mov #0, r0 - mov #0xe0, r1 ! 0xffffffe0 + mov #0xffffffe0, r1 ! ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ] ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ] -- cgit v1.2.3