Skip to content

Commit

Permalink
[SPARC64]: Add irqtrace/stacktrace/lockdep support.
Browse files Browse the repository at this point in the history
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller authored and David S. Miller committed Dec 10, 2006
1 parent af1713e commit 10e2672
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 66 deletions.
8 changes: 8 additions & 0 deletions arch/sparc64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ config MMU
bool
default y

config STACKTRACE_SUPPORT
bool
default y

config LOCKDEP_SUPPORT
bool
default y

config TIME_INTERPOLATION
bool
default y
Expand Down
4 changes: 4 additions & 0 deletions arch/sparc64/Kconfig.debug
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
menu "Kernel hacking"

config TRACE_IRQFLAGS_SUPPORT
bool
default y

source "lib/Kconfig.debug"

config DEBUG_STACK_USAGE
Expand Down
1 change: 1 addition & 0 deletions arch/sparc64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
visemul.o prom.o of_device.o

obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
pci_psycho.o pci_sabre.o pci_schizo.o \
pci_sun4v.o pci_sun4v_asm.o
Expand Down
27 changes: 26 additions & 1 deletion arch/sparc64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,12 @@ __spitfire_cee_trap_continue:
1: ba,pt %xcc, etrap_irq
rd %pc, %g7

2: mov %l4, %o1
2:
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov %l4, %o1
mov %l5, %o2
call spitfire_access_error
add %sp, PTREGS_OFF, %o0
Expand Down Expand Up @@ -824,6 +829,10 @@ do_cheetah_plus_data_parity:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov 0x0, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
Expand Down Expand Up @@ -855,6 +864,10 @@ do_cheetah_plus_insn_parity:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov 0x1, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
Expand Down Expand Up @@ -1183,6 +1196,10 @@ c_fast_ecc:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_fecc_handler
Expand Down Expand Up @@ -1211,6 +1228,10 @@ c_cee:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_cee_handler
Expand Down Expand Up @@ -1239,6 +1260,10 @@ c_deferred:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_deferred_handler
Expand Down
8 changes: 8 additions & 0 deletions arch/sparc64/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,14 @@ tlb_fixup_done:
call __bzero
sub %o1, %o0, %o1

#ifdef CONFIG_LOCKDEP
/* We have this call this super early, as even prom_init can grab
* spinlocks and thus call into the lockdep code.
*/
call lockdep_init
nop
#endif

mov %l6, %o1 ! OpenPROM stack
call prom_init
mov %l7, %o0 ! OpenPROM cif handler
Expand Down
23 changes: 17 additions & 6 deletions arch/sparc64/kernel/rtrap.S
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,26 @@ rtrap:
__handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4
andcc %l1, TSTATE_PRIV, %l3
and %l1, %l4, %l4
andn %l1, %l4, %l1
srl %l4, 20, %l4
#ifdef CONFIG_TRACE_IRQFLAGS
brnz,pn %l4, rtrap_no_irq_enable
nop
call trace_hardirqs_on
nop
wrpr %l4, %pil
rtrap_no_irq_enable:
#endif
andcc %l1, TSTATE_PRIV, %l3
bne,pn %icc, to_kernel
andn %l1, %l4, %l1
nop

/* We must hold IRQs off and atomically test schedule+signal
* state, then hold them off all the way back to userspace.
* If we are returning to kernel, none of this matters.
* If we are returning to kernel, none of this matters. Note
* that we are disabling interrupts via PSTATE_IE, not using
* %pil.
*
* If we do not do this, there is a window where we would do
* the tests, later the signal/resched event arrives but we do
Expand Down Expand Up @@ -256,7 +268,6 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1

ld [%sp + PTREGS_OFF + PT_V9_Y], %o3
wr %o3, %g0, %y
srl %l4, 20, %l4
wrpr %l4, 0x0, %pil
wrpr %g0, 0x1, %tl
wrpr %l1, %g0, %tstate
Expand Down Expand Up @@ -374,8 +385,8 @@ to_kernel:
ldx [%g6 + TI_FLAGS], %l5
andcc %l5, _TIF_NEED_RESCHED, %g0
be,pt %xcc, kern_fpucheck
srl %l4, 20, %l5
cmp %l5, 0
nop
cmp %l4, 0
bne,pn %xcc, kern_fpucheck
sethi %hi(PREEMPT_ACTIVE), %l6
stw %l6, [%g6 + TI_PRE_COUNT]
Expand Down
41 changes: 41 additions & 0 deletions arch/sparc64/kernel/stacktrace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
#include <asm/ptrace.h>

void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
unsigned long ksp, fp, thread_base;
struct thread_info *tp;

if (!task)
task = current;
tp = task_thread_info(task);
if (task == current) {
flushw_all();
__asm__ __volatile__(
"mov %%fp, %0"
: "=r" (ksp)
);
} else
ksp = tp->ksp;

fp = ksp + STACK_BIAS;
thread_base = (unsigned long) tp;
do {
struct reg_window *rw;

/* Bogus frame pointer? */
if (fp < (thread_base + sizeof(struct thread_info)) ||
fp >= (thread_base + THREAD_SIZE))
break;

rw = (struct reg_window *) fp;
if (trace->skip > 0)
trace->skip--;
else
trace->entries[trace->nr_entries++] = rw->ins[7];

fp = rw->ins[6] + STACK_BIAS;
} while (trace->nr_entries < trace->max_entries);
}
20 changes: 16 additions & 4 deletions arch/sparc64/kernel/sun4v_ivec.S
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ sun4v_res_mondo:
mov %g1, %g4
ba,pt %xcc, etrap_irq
rd %pc, %g7

#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
/* Log the event. */
add %sp, PTREGS_OFF, %o0
call sun4v_resum_error
Expand All @@ -216,7 +219,10 @@ sun4v_res_mondo_queue_full:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7

#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
call sun4v_resum_overflow
add %sp, PTREGS_OFF, %o0

Expand Down Expand Up @@ -295,7 +301,10 @@ sun4v_nonres_mondo:
mov %g1, %g4
ba,pt %xcc, etrap_irq
rd %pc, %g7

#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
/* Log the event. */
add %sp, PTREGS_OFF, %o0
call sun4v_nonresum_error
Expand All @@ -321,7 +330,10 @@ sun4v_nonres_mondo_queue_full:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7

#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
call sun4v_nonresum_overflow
add %sp, PTREGS_OFF, %o0

Expand Down
8 changes: 8 additions & 0 deletions arch/sparc64/mm/ultra.S
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ xcall_sync_tick:
sethi %hi(109f), %g7
b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
call smp_synchronize_tick_client
nop
clr %l6
Expand Down Expand Up @@ -508,6 +512,10 @@ xcall_report_regs:
sethi %hi(109f), %g7
b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_off
nop
#endif
call __show_regs
add %sp, PTREGS_OFF, %o0
clr %l6
Expand Down
89 changes: 89 additions & 0 deletions include/asm-sparc64/irqflags.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* include/asm-sparc64/irqflags.h
*
* IRQ flags handling
*
* This file gets included from lowlevel asm headers too, to provide
* wrapped versions of the local_irq_*() APIs, based on the
* raw_local_irq_*() functions from the lowlevel headers.
*/
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H

#ifndef __ASSEMBLY__

static inline unsigned long __raw_local_save_flags(void)
{
unsigned long flags;

__asm__ __volatile__(
"rdpr %%pil, %0"
: "=r" (flags)
);

return flags;
}

#define raw_local_save_flags(flags) \
do { (flags) = __raw_local_save_flags(); } while (0)

static inline void raw_local_irq_restore(unsigned long flags)
{
__asm__ __volatile__(
"wrpr %0, %%pil"
: /* no output */
: "r" (flags)
: "memory"
);
}

static inline void raw_local_irq_disable(void)
{
__asm__ __volatile__(
"wrpr 15, %%pil"
: /* no outputs */
: /* no inputs */
: "memory"
);
}

static inline void raw_local_irq_enable(void)
{
__asm__ __volatile__(
"wrpr 0, %%pil"
: /* no outputs */
: /* no inputs */
: "memory"
);
}

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);
}

/*
* For spinlocks, etc:
*/
static inline unsigned long __raw_local_irq_save(void)
{
unsigned long flags = __raw_local_save_flags();

raw_local_irq_disable();

return flags;
}

#define raw_local_irq_save(flags) \
do { (flags) = __raw_local_irq_save(); } while (0)

#endif /* (__ASSEMBLY__) */

#endif /* !(_ASM_IRQFLAGS_H) */
Loading

0 comments on commit 10e2672

Please sign in to comment.