Wire up all of the essentials for lockdep..
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
config ARCH_MAY_HAVE_PC_FDC
bool
+config STACKTRACE_SUPPORT
+ bool
+ default y
+
+config LOCKDEP_SUPPORT
+ bool
+ default y
+
source "init/Kconfig"
menu "System type"
menu "Kernel hacking"
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
source "lib/Kconfig.debug"
config SH_STANDARD_BIOS
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
add r15,r8
mov.l r9,@r8
mov r9,r8
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r9
+ jsr @r9
+ nop
+#endif
sti
bra system_call
nop
2: .long break_point_trap_software
3: .long NR_syscalls
4: .long sys_call_table
+#ifdef CONFIG_TRACE_IRQFLAGS
+5: .long trace_hardirqs_on
+#endif
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
restore_all:
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
mov r15,r0
mov.l $cpu_mode,r2
mov #OFF_SR,r3
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .long trace_hardirqs_off
+#endif
! common exception handler
#include "../../entry-common.S"
mov.l 1f, r0
mov.l @r0, r6 ! address
mov.l 3f, r0
- sti
+
jmp @r0
mov r15, r4 ! regs
.align 2
ENTRY(exception_error)
!
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
sti
mov.l 2f, r0
jmp @r0
.align 2
1: .long break_point_trap_software
2: .long do_exception_error
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .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 1f, r0
mov.l r0, @(TI_PRE_COUNT,r8)
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
sti
mov.l 2f, r0
jsr @r0
mov #0, r0
mov.l r0, @(TI_PRE_COUNT,r8)
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 4f, r0
+ jsr @r0
+ nop
+#endif
bra need_resched
nop
+
noresched:
bra __restore_all
nop
.align 2
1: .long PREEMPT_ACTIVE
2: .long schedule
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .long trace_hardirqs_on
+4: .long trace_hardirqs_off
+#endif
#endif
ENTRY(resume_userspace)
! r8: current_thread_info
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt/s __restore_all
jsr @r1 ! schedule
nop
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
1: .long schedule
2: .long do_notify_resume
3: .long restore_all
+#ifdef CONFIG_TRACE_IRQFLAGS
+4: .long trace_hardirqs_on
+5: .long trace_hardirqs_off
+#endif
.align 2
syscall_exit_work:
tst #_TIF_SYSCALL_TRACE, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
sti
! XXX setup arguments...
mov.l 4f, r0 ! do_syscall_trace
mov.l r0, @(OFF_R0,r15) ! Return value
__restore_all:
- mov.l 1f,r0
+ mov.l 1f, r0
jmp @r0
nop
mov #OFF_TRA, r9
add r15, r9
mov.l r8, @r9 ! set TRA value to tra
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r10
+ jsr @r10
+ nop
+#endif
sti
+
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
!
syscall_exit:
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 6f, r0
+ jsr @r0
+ nop
+#endif
!
get_current_thread_info r8, r0
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2: .long NR_syscalls
3: .long sys_call_table
4: .long do_syscall_trace
+#ifdef CONFIG_TRACE_IRQFLAGS
+5: .long trace_hardirqs_on
+6: .long trace_hardirqs_off
+#endif
--- /dev/null
+/*
+ * arch/sh/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+ unsigned long *sp;
+
+ if (!task)
+ task = current;
+ if (task == current)
+ sp = (unsigned long *)current_stack_pointer;
+ else
+ sp = (unsigned long *)task->thread.sp;
+
+ while (!kstack_end(sp)) {
+ unsigned long addr = *sp++;
+
+ if (__kernel_text_address(addr)) {
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+ trace->entries[trace->nr_entries++] = addr;
+ if (trace->nr_entries >= trace->max_entries)
+ break;
+ }
+ }
+}
int si_code;
siginfo_t info;
+ trace_hardirqs_on();
+ local_irq_enable();
+
#ifdef CONFIG_SH_KGDB
if (kgdb_nofault && kgdb_bus_err_hook)
kgdb_bus_err_hook();
--- /dev/null
+#ifndef __ASM_SH_IRQFLAGS_H
+#define __ASM_SH_IRQFLAGS_H
+
+static inline void raw_local_irq_enable(void)
+{
+ unsigned long __dummy0, __dummy1;
+
+ __asm__ __volatile__ (
+ "stc sr, %0\n\t"
+ "and %1, %0\n\t"
+#ifdef CONFIG_CPU_HAS_SR_RB
+ "stc r6_bank, %1\n\t"
+ "or %1, %0\n\t"
+#endif
+ "ldc %0, sr\n\t"
+ : "=&r" (__dummy0), "=r" (__dummy1)
+ : "1" (~0x000000f0)
+ : "memory"
+ );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+ unsigned long flags;
+
+ __asm__ __volatile__ (
+ "stc sr, %0\n\t"
+ "or #0xf0, %0\n\t"
+ "ldc %0, sr\n\t"
+ : "=&z" (flags)
+ : /* no inputs */
+ : "memory"
+ );
+}
+
+static inline void set_bl_bit(void)
+{
+ unsigned long __dummy0, __dummy1;
+
+ __asm__ __volatile__ (
+ "stc sr, %0\n\t"
+ "or %2, %0\n\t"
+ "and %3, %0\n\t"
+ "ldc %0, sr\n\t"
+ : "=&r" (__dummy0), "=r" (__dummy1)
+ : "r" (0x10000000), "r" (0xffffff0f)
+ : "memory"
+ );
+}
+
+static inline void clear_bl_bit(void)
+{
+ unsigned long __dummy0, __dummy1;
+
+ __asm__ __volatile__ (
+ "stc sr, %0\n\t"
+ "and %2, %0\n\t"
+ "ldc %0, sr\n\t"
+ : "=&r" (__dummy0), "=r" (__dummy1)
+ : "1" (~0x10000000)
+ : "memory"
+ );
+}
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+ unsigned long flags;
+
+ __asm__ __volatile__ (
+ "stc sr, %0\n\t"
+ "and #0xf0, %0\n\t"
+ : "=&z" (flags)
+ : /* no inputs */
+ : "memory"
+ );
+
+ return flags;
+}
+
+#define raw_local_save_flags(flags) \
+ do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags != 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+ unsigned long flags = __raw_local_save_flags();
+
+ return raw_irqs_disabled_flags(flags);
+}
+
+static inline unsigned long __raw_local_irq_save(void)
+{
+ unsigned long flags, __dummy;
+
+ __asm__ __volatile__ (
+ "stc sr, %1\n\t"
+ "mov %1, %0\n\t"
+ "or #0xf0, %0\n\t"
+ "ldc %0, sr\n\t"
+ "mov %1, %0\n\t"
+ "and #0xf0, %0\n\t"
+ : "=&z" (flags), "=&r" (__dummy)
+ : /* no inputs */
+ : "memory"
+ );
+
+ return flags;
+}
+
+#define raw_local_irq_save(flags) \
+ do { (flags) = __raw_local_irq_save(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+ if ((flags & 0xf0) != 0xf0)
+ raw_local_irq_enable();
+}
+
+#endif /* __ASM_SH_IRQFLAGS_H */
#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)
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+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)
+
static inline void init_rwsem(struct rw_semaphore *sem)
{
sem->count = RWSEM_UNLOCKED_VALUE;
rwsem_downgrade_wake(sem);
}
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+ __down_write(sem);
+}
+
/*
* implement exchange and add functionality
*/
* Copyright (C) 2002 Paul Mundt
*/
+#include <linux/irqflags.h>
#include <asm/types.h>
/*
#define set_mb(var, value) do { xchg(&var, value); } while (0)
-/* Interrupt Control */
-#ifdef CONFIG_CPU_HAS_SR_RB
-static inline void local_irq_enable(void)
-{
- unsigned long __dummy0, __dummy1;
-
- __asm__ __volatile__("stc sr, %0\n\t"
- "and %1, %0\n\t"
- "stc r6_bank, %1\n\t"
- "or %1, %0\n\t"
- "ldc %0, sr"
- : "=&r" (__dummy0), "=r" (__dummy1)
- : "1" (~0x000000f0)
- : "memory");
-}
-#else
-static inline void local_irq_enable(void)
-{
- unsigned long __dummy0, __dummy1;
-
- __asm__ __volatile__ (
- "stc sr, %0\n\t"
- "and %1, %0\n\t"
- "ldc %0, sr\n\t"
- : "=&r" (__dummy0), "=r" (__dummy1)
- : "1" (~0x000000f0)
- : "memory");
-}
-#endif
-
-static inline void local_irq_disable(void)
-{
- unsigned long __dummy;
- __asm__ __volatile__("stc sr, %0\n\t"
- "or #0xf0, %0\n\t"
- "ldc %0, sr"
- : "=&z" (__dummy)
- : /* no inputs */
- : "memory");
-}
-
-static inline void set_bl_bit(void)
-{
- unsigned long __dummy0, __dummy1;
-
- __asm__ __volatile__ ("stc sr, %0\n\t"
- "or %2, %0\n\t"
- "and %3, %0\n\t"
- "ldc %0, sr"
- : "=&r" (__dummy0), "=r" (__dummy1)
- : "r" (0x10000000), "r" (0xffffff0f)
- : "memory");
-}
-
-static inline void clear_bl_bit(void)
-{
- unsigned long __dummy0, __dummy1;
-
- __asm__ __volatile__ ("stc sr, %0\n\t"
- "and %2, %0\n\t"
- "ldc %0, sr"
- : "=&r" (__dummy0), "=r" (__dummy1)
- : "1" (~0x10000000)
- : "memory");
-}
-
-#define local_save_flags(x) \
- __asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" )
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- (flags != 0); \
-})
-
-static inline unsigned long local_irq_save(void)
-{
- unsigned long flags, __dummy;
-
- __asm__ __volatile__("stc sr, %1\n\t"
- "mov %1, %0\n\t"
- "or #0xf0, %0\n\t"
- "ldc %0, sr\n\t"
- "mov %1, %0\n\t"
- "and #0xf0, %0"
- : "=&z" (flags), "=&r" (__dummy)
- :/**/
- : "memory" );
- return flags;
-}
-
-#define local_irq_restore(x) do { \
- if ((x & 0x000000f0) != 0x000000f0) \
- local_irq_enable(); \
-} while (0)
-
/*
* Jump to P2 area.
* When handling TLB or caches, we need to do it from P2 area.
: "=&r" (__dummy)); \
} while (0)
-/* For spinlocks etc */
-#define local_irq_save(x) x = local_irq_save()
-
static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
{
unsigned long flags, retval;