Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 97072
b: refs/heads/master
c: 93dae5b
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed May 20, 2008
1 parent 2815afc commit c83e3cb
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 88278ca27a43ae503572b52ea2c171fbf45db5a2
refs/heads/master: 93dae5b70e7c1c8e927d22e1c20a941ca376906a
117 changes: 116 additions & 1 deletion trunk/arch/sparc64/kernel/process.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1995, 1996, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
Expand Down Expand Up @@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/sysrq.h>

#include <asm/oplib.h>
#include <asm/uaccess.h>
Expand All @@ -49,6 +50,8 @@
#include <asm/sstate.h>
#include <asm/reboot.h>
#include <asm/syscalls.h>
#include <asm/irq_regs.h>
#include <asm/smp.h>

/* #define VERBOSE_SHOWREGS */

Expand Down Expand Up @@ -298,6 +301,118 @@ void show_regs(struct pt_regs *regs)
#endif
}

#ifdef CONFIG_MAGIC_SYSRQ
struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
static DEFINE_SPINLOCK(global_reg_snapshot_lock);

static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
int this_cpu)
{
flushw_all();

global_reg_snapshot[this_cpu].tstate = regs->tstate;
global_reg_snapshot[this_cpu].tpc = regs->tpc;
global_reg_snapshot[this_cpu].tnpc = regs->tnpc;
global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];

if (regs->tstate & TSTATE_PRIV) {
struct reg_window *rw;

rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);
global_reg_snapshot[this_cpu].i7 = rw->ins[6];
} else
global_reg_snapshot[this_cpu].i7 = 0;

global_reg_snapshot[this_cpu].thread = tp;
}

/* In order to avoid hangs we do not try to synchronize with the
* global register dump client cpus. The last store they make is to
* the thread pointer, so do a short poll waiting for that to become
* non-NULL.
*/
static void __global_reg_poll(struct global_reg_snapshot *gp)
{
int limit = 0;

while (!gp->thread && ++limit < 100) {
barrier();
udelay(1);
}
}

static void sysrq_handle_globreg(int key, struct tty_struct *tty)
{
struct thread_info *tp = current_thread_info();
struct pt_regs *regs = get_irq_regs();
#ifdef CONFIG_KALLSYMS
char buffer[KSYM_SYMBOL_LEN];
#endif
unsigned long flags;
int this_cpu, cpu;

if (!regs)
regs = tp->kregs;

spin_lock_irqsave(&global_reg_snapshot_lock, flags);

memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));

this_cpu = raw_smp_processor_id();

__global_reg_self(tp, regs, this_cpu);

smp_fetch_global_regs();

for_each_online_cpu(cpu) {
struct global_reg_snapshot *gp = &global_reg_snapshot[cpu];
struct thread_info *tp;

__global_reg_poll(gp);

tp = gp->thread;
printk("%c CPU[%3d]: TSTATE[%016lx] TPC[%016lx] TNPC[%016lx] TASK[%s:%d]\n",
(cpu == this_cpu ? '*' : ' '), cpu,
gp->tstate, gp->tpc, gp->tnpc,
((tp && tp->task) ? tp->task->comm : "NULL"),
((tp && tp->task) ? tp->task->pid : -1));
#ifdef CONFIG_KALLSYMS
if (gp->tstate & TSTATE_PRIV) {
sprint_symbol(buffer, gp->tpc);
printk(" TPC[%s] ", buffer);
sprint_symbol(buffer, gp->o7);
printk("O7[%s] ", buffer);
sprint_symbol(buffer, gp->i7);
printk("I7[%s]\n", buffer);
} else
#endif
{
printk(" TPC[%lx] O7[%lx] I7[%lx]\n",
gp->tpc, gp->o7, gp->i7);
}
}

memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));

spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
}

static struct sysrq_key_op sparc_globalreg_op = {
.handler = sysrq_handle_globreg,
.help_msg = "Globalregs",
.action_msg = "Show Global CPU Regs",
};

static int __init sparc_globreg_init(void)
{
return register_sysrq_key('y', &sparc_globalreg_op);
}

core_initcall(sparc_globreg_init);

#endif

unsigned long thread_saved_pc(struct task_struct *tsk)
{
struct thread_info *ti = task_thread_info(tsk);
Expand Down
10 changes: 10 additions & 0 deletions trunk/arch/sparc64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,9 @@ extern unsigned long xcall_flush_tlb_mm;
extern unsigned long xcall_flush_tlb_pending;
extern unsigned long xcall_flush_tlb_kernel_range;
extern unsigned long xcall_report_regs;
#ifdef CONFIG_MAGIC_SYSRQ
extern unsigned long xcall_fetch_glob_regs;
#endif
extern unsigned long xcall_receive_signal;
extern unsigned long xcall_new_mmu_context_version;
#ifdef CONFIG_KGDB
Expand Down Expand Up @@ -1080,6 +1083,13 @@ void smp_report_regs(void)
smp_cross_call(&xcall_report_regs, 0, 0, 0);
}

#ifdef CONFIG_MAGIC_SYSRQ
void smp_fetch_global_regs(void)
{
smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0);
}
#endif

/* We know that the window frames of the user have been flushed
* to the stack before we get here because all callers of us
* are flush_tlb_*() routines, and these run after flush_cache_*()
Expand Down
29 changes: 28 additions & 1 deletion trunk/arch/sparc64/mm/ultra.S
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
* Copyright (C) 1997, 2000, 2008 David S. Miller (davem@davemloft.net)
*/

#include <asm/asi.h>
Expand All @@ -15,6 +15,7 @@
#include <asm/thread_info.h>
#include <asm/cacheflush.h>
#include <asm/hypervisor.h>
#include <asm/cpudata.h>

/* Basically, most of the Spitfire vs. Cheetah madness
* has to do with the fact that Cheetah does not support
Expand Down Expand Up @@ -514,6 +515,32 @@ xcall_report_regs:
b rtrap_xcall
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1

#ifdef CONFIG_MAGIC_SYSRQ
.globl xcall_fetch_glob_regs
xcall_fetch_glob_regs:
sethi %hi(global_reg_snapshot), %g1
or %g1, %lo(global_reg_snapshot), %g1
__GET_CPUID(%g2)
sllx %g2, 6, %g3
add %g1, %g3, %g1
rdpr %tstate, %g7
stx %g7, [%g1 + GR_SNAP_TSTATE]
rdpr %tpc, %g7
stx %g7, [%g1 + GR_SNAP_TPC]
rdpr %tnpc, %g7
stx %g7, [%g1 + GR_SNAP_TNPC]
stx %o7, [%g1 + GR_SNAP_O7]
stx %i7, [%g1 + GR_SNAP_I7]
sethi %hi(trap_block), %g7
or %g7, %lo(trap_block), %g7
sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2
add %g7, %g2, %g7
ldx [%g7 + TRAP_PER_CPU_THREAD], %g3
membar #StoreStore
stx %g3, [%g1 + GR_SNAP_THREAD]
retry
#endif /* CONFIG_MAGIC_SYSRQ */

#ifdef DCACHE_ALIASING_POSSIBLE
.align 32
.globl xcall_flush_dcache_page_cheetah
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/char/sysrq.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
&sysrq_showstate_blocked_op, /* w */
/* x: May be registered on ppc/powerpc for xmon */
NULL, /* x */
/* y: May be registered on sparc64 for global register dump */
NULL, /* y */
NULL /* z */
};
Expand Down
21 changes: 21 additions & 0 deletions trunk/include/asm-sparc64/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ struct sparc_trapf {
#define TRACEREG32_SZ sizeof(struct pt_regs32)
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)

struct global_reg_snapshot {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned long o7;
unsigned long i7;
struct thread_info *thread;
unsigned long pad1;
unsigned long pad2;
};

#ifdef __KERNEL__

#define __ARCH_WANT_COMPAT_SYS_PTRACE
Expand Down Expand Up @@ -295,6 +306,16 @@ extern void __show_regs(struct pt_regs *);
#define SF_XARG5 0x58
#define SF_XXARG 0x5c

/* global_reg_snapshot offsets */
#define GR_SNAP_TSTATE 0x00
#define GR_SNAP_TPC 0x08
#define GR_SNAP_TNPC 0x10
#define GR_SNAP_O7 0x18
#define GR_SNAP_I7 0x20
#define GR_SNAP_THREAD 0x28
#define GR_SNAP_PAD1 0x30
#define GR_SNAP_PAD2 0x38

/* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12
Expand Down
5 changes: 4 additions & 1 deletion trunk/include/asm-sparc64/smp.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* smp.h: Sparc64 specific SMP stuff.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
*/

#ifndef _SPARC64_SMP_H
Expand Down Expand Up @@ -44,6 +44,8 @@ extern int hard_smp_processor_id(void);
extern void smp_fill_in_sib_core_maps(void);
extern void cpu_play_dead(void);

extern void smp_fetch_global_regs(void);

#ifdef CONFIG_HOTPLUG_CPU
extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu);
Expand All @@ -55,6 +57,7 @@ extern void __cpu_die(unsigned int cpu);

#define hard_smp_processor_id() 0
#define smp_fill_in_sib_core_maps() do { } while (0)
#define smp_fetch_global_regs() do { } while (0)

#endif /* !(CONFIG_SMP) */

Expand Down

0 comments on commit c83e3cb

Please sign in to comment.