mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
sh: stacktrace/lockdep/irqflags tracing support.
Wire up all of the essentials for lockdep.. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
c03c69610b
commit
afbfb52e47
@ -51,6 +51,14 @@ config GENERIC_TIME
|
||||
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"
|
||||
|
@ -1,5 +1,9 @@
|
||||
menu "Kernel hacking"
|
||||
|
||||
config TRACE_IRQFLAGS_SUPPORT
|
||||
bool
|
||||
default y
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config SH_STANDARD_BIOS
|
||||
|
@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_APM) += apm.o
|
||||
obj-$(CONFIG_PM) += pm.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
|
@ -184,6 +184,11 @@ trap_entry:
|
||||
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
|
||||
@ -193,6 +198,9 @@ trap_entry:
|
||||
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 */
|
||||
@ -255,6 +263,11 @@ ENTRY(address_error_handler)
|
||||
|
||||
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
|
||||
@ -307,6 +320,9 @@ $current_thread_info:
|
||||
.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"
|
||||
|
@ -140,7 +140,7 @@ call_dpf:
|
||||
mov.l 1f, r0
|
||||
mov.l @r0, r6 ! address
|
||||
mov.l 3f, r0
|
||||
sti
|
||||
|
||||
jmp @r0
|
||||
mov r15, r4 ! regs
|
||||
|
||||
|
@ -100,6 +100,11 @@ debug_trap:
|
||||
.align 2
|
||||
ENTRY(exception_error)
|
||||
!
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
mov.l 3f, r0
|
||||
jsr @r0
|
||||
nop
|
||||
#endif
|
||||
sti
|
||||
mov.l 2f, r0
|
||||
jmp @r0
|
||||
@ -109,10 +114,18 @@ ENTRY(exception_error)
|
||||
.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
|
||||
@ -143,6 +156,11 @@ need_resched:
|
||||
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
|
||||
@ -150,9 +168,15 @@ need_resched:
|
||||
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
|
||||
@ -160,11 +184,20 @@ noresched:
|
||||
.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
|
||||
@ -210,6 +243,11 @@ work_resched:
|
||||
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
|
||||
@ -221,6 +259,10 @@ work_resched:
|
||||
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:
|
||||
@ -229,6 +271,11 @@ 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
|
||||
@ -265,7 +312,7 @@ syscall_trace_entry:
|
||||
mov.l r0, @(OFF_R0,r15) ! Return value
|
||||
|
||||
__restore_all:
|
||||
mov.l 1f,r0
|
||||
mov.l 1f, r0
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
@ -331,7 +378,13 @@ ENTRY(system_call)
|
||||
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
|
||||
@ -355,6 +408,11 @@ syscall_call:
|
||||
!
|
||||
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
|
||||
@ -369,3 +427,7 @@ syscall_exit:
|
||||
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
|
||||
|
43
arch/sh/kernel/stacktrace.c
Normal file
43
arch/sh/kernel/stacktrace.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,9 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
||||
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();
|
||||
|
123
include/asm-sh/irqflags.h
Normal file
123
include/asm-sh/irqflags.h
Normal file
@ -0,0 +1,123 @@
|
||||
#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 */
|
@ -25,11 +25,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)
|
||||
@ -39,6 +49,16 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
|
||||
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;
|
||||
@ -141,6 +161,11 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
|
||||
rwsem_downgrade_wake(sem);
|
||||
}
|
||||
|
||||
static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
|
||||
{
|
||||
__down_write(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* implement exchange and add functionality
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Copyright (C) 2002 Paul Mundt
|
||||
*/
|
||||
|
||||
#include <linux/irqflags.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
/*
|
||||
@ -131,103 +132,6 @@ static inline unsigned long tas(volatile int *m)
|
||||
|
||||
#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.
|
||||
@ -264,9 +168,6 @@ do { \
|
||||
: "=&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;
|
||||
|
Loading…
Reference in New Issue
Block a user