Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 334446
b: refs/heads/master
c: 985c9e6
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Oct 17, 2012
1 parent d82ca3f commit 39fbe4e
Show file tree
Hide file tree
Showing 19 changed files with 254 additions and 54 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: bb2bab177408e44079ba6bd37242fa8b26dfc2a7
refs/heads/master: 985c9e615a605041d728c08b83d3dda19ae7def8
1 change: 1 addition & 0 deletions trunk/Documentation/sysrq.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
'w' - Dumps tasks that are in uninterruptable (blocked) state.

'x' - Used by xmon interface on ppc/powerpc platforms.
Show global PMU Registers on sparc64.

'y' - Show global CPU Registers [SPARC-64 specific]

Expand Down
14 changes: 14 additions & 0 deletions trunk/MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5019,6 +5019,20 @@ F: net/ipv6/
F: include/net/ip*
F: arch/x86/net/*

NETWORKING [IPSEC]
M: Steffen Klassert <steffen.klassert@secunet.com>
M: Herbert Xu <herbert@gondor.apana.org.au>
M: "David S. Miller" <davem@davemloft.net>
L: netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
S: Maintained
F: net/xfrm/
F: net/key/
F: net/ipv4/xfrm*
F: net/ipv6/xfrm*
F: include/uapi/linux/xfrm.h
F: include/net/xfrm.h

NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
M: Paul Moore <paul@paul-moore.com>
L: netdev@vger.kernel.org
Expand Down
13 changes: 12 additions & 1 deletion trunk/arch/sparc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,18 @@ struct global_reg_snapshot {
struct thread_info *thread;
unsigned long pad1;
};
extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];

struct global_pmu_snapshot {
unsigned long pcr[4];
unsigned long pic[4];
};

union global_cpu_snapshot {
struct global_reg_snapshot reg;
struct global_pmu_snapshot pmu;
};

extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];

#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/sparc/include/asm/smp_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ extern void smp_fill_in_sib_core_maps(void);
extern void cpu_play_dead(void);

extern void smp_fetch_global_regs(void);
extern void smp_fetch_global_pmu(void);

struct seq_file;
void smp_bogo(struct seq_file *);
Expand All @@ -65,6 +66,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)
#define smp_fetch_global_pmu() do { } while (0)

#endif /* !(CONFIG_SMP) */

Expand Down
15 changes: 9 additions & 6 deletions trunk/arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,15 +817,17 @@ static u64 nop_for_index(int idx)

static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
{
u64 val, mask = mask_for_index(idx);
u64 enc, val, mask = mask_for_index(idx);
int pcr_index = 0;

if (sparc_pmu->num_pcrs > 1)
pcr_index = idx;

enc = perf_event_get_enc(cpuc->events[idx]);

val = cpuc->pcr[pcr_index];
val &= ~mask;
val |= hwc->config;
val |= event_encoding(enc, idx);
cpuc->pcr[pcr_index] = val;

pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]);
Expand Down Expand Up @@ -1738,8 +1740,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
{
unsigned long ufp;

perf_callchain_store(entry, regs->tpc);

ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
do {
struct sparc_stackf *usf, sf;
Expand All @@ -1760,8 +1760,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
{
unsigned long ufp;

perf_callchain_store(entry, regs->tpc);

ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
do {
struct sparc_stackf32 *usf, sf;
Expand All @@ -1780,6 +1778,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
void
perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
perf_callchain_store(entry, regs->tpc);

if (!current->mm)
return;

flushw_user();
if (test_thread_flag(TIF_32BIT))
perf_callchain_user_32(entry, regs);
Expand Down
120 changes: 100 additions & 20 deletions trunk/arch/sparc/kernel/process_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/tick.h>
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/perf_event.h>
#include <linux/elfcore.h>
#include <linux/sysrq.h>
#include <linux/nmi.h>
Expand All @@ -47,6 +48,7 @@
#include <asm/syscalls.h>
#include <asm/irq_regs.h>
#include <asm/smp.h>
#include <asm/pcr.h>

#include "kstack.h"

Expand Down Expand Up @@ -204,36 +206,40 @@ void show_regs(struct pt_regs *regs)
show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]);
}

struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
static DEFINE_SPINLOCK(global_reg_snapshot_lock);
union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
static DEFINE_SPINLOCK(global_cpu_snapshot_lock);

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

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];
rp = &global_cpu_snapshot[this_cpu].reg;

rp->tstate = regs->tstate;
rp->tpc = regs->tpc;
rp->tnpc = regs->tnpc;
rp->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);
if (kstack_valid(tp, (unsigned long) rw)) {
global_reg_snapshot[this_cpu].i7 = rw->ins[7];
rp->i7 = rw->ins[7];
rw = (struct reg_window *)
(rw->ins[6] + STACK_BIAS);
if (kstack_valid(tp, (unsigned long) rw))
global_reg_snapshot[this_cpu].rpc = rw->ins[7];
rp->rpc = rw->ins[7];
}
} else {
global_reg_snapshot[this_cpu].i7 = 0;
global_reg_snapshot[this_cpu].rpc = 0;
rp->i7 = 0;
rp->rpc = 0;
}
global_reg_snapshot[this_cpu].thread = tp;
rp->thread = tp;
}

/* In order to avoid hangs we do not try to synchronize with the
Expand Down Expand Up @@ -261,9 +267,9 @@ void arch_trigger_all_cpu_backtrace(void)
if (!regs)
regs = tp->kregs;

spin_lock_irqsave(&global_reg_snapshot_lock, flags);
spin_lock_irqsave(&global_cpu_snapshot_lock, flags);

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

this_cpu = raw_smp_processor_id();

Expand All @@ -272,7 +278,7 @@ void arch_trigger_all_cpu_backtrace(void)
smp_fetch_global_regs();

for_each_online_cpu(cpu) {
struct global_reg_snapshot *gp = &global_reg_snapshot[cpu];
struct global_reg_snapshot *gp = &global_cpu_snapshot[cpu].reg;

__global_reg_poll(gp);

Expand All @@ -295,9 +301,9 @@ void arch_trigger_all_cpu_backtrace(void)
}
}

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

spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
}

#ifdef CONFIG_MAGIC_SYSRQ
Expand All @@ -309,16 +315,90 @@ static void sysrq_handle_globreg(int key)

static struct sysrq_key_op sparc_globalreg_op = {
.handler = sysrq_handle_globreg,
.help_msg = "Globalregs",
.help_msg = "global-regs(Y)",
.action_msg = "Show Global CPU Regs",
};

static int __init sparc_globreg_init(void)
static void __global_pmu_self(int this_cpu)
{
struct global_pmu_snapshot *pp;
int i, num;

pp = &global_cpu_snapshot[this_cpu].pmu;

num = 1;
if (tlb_type == hypervisor &&
sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
num = 4;

for (i = 0; i < num; i++) {
pp->pcr[i] = pcr_ops->read_pcr(i);
pp->pic[i] = pcr_ops->read_pic(i);
}
}

static void __global_pmu_poll(struct global_pmu_snapshot *pp)
{
int limit = 0;

while (!pp->pcr[0] && ++limit < 100) {
barrier();
udelay(1);
}
}

static void pmu_snapshot_all_cpus(void)
{
return register_sysrq_key('y', &sparc_globalreg_op);
unsigned long flags;
int this_cpu, cpu;

spin_lock_irqsave(&global_cpu_snapshot_lock, flags);

memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));

this_cpu = raw_smp_processor_id();

__global_pmu_self(this_cpu);

smp_fetch_global_pmu();

for_each_online_cpu(cpu) {
struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu;

__global_pmu_poll(pp);

printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n",
(cpu == this_cpu ? '*' : ' '), cpu,
pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
}

memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));

spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
}

static void sysrq_handle_globpmu(int key)
{
pmu_snapshot_all_cpus();
}

static struct sysrq_key_op sparc_globalpmu_op = {
.handler = sysrq_handle_globpmu,
.help_msg = "global-pmu(X)",
.action_msg = "Show Global PMU Regs",
};

static int __init sparc_sysrq_init(void)
{
int ret = register_sysrq_key('y', &sparc_globalreg_op);

if (!ret)
ret = register_sysrq_key('x', &sparc_globalpmu_op);
return ret;
}

core_initcall(sparc_globreg_init);
core_initcall(sparc_sysrq_init);

#endif

Expand Down
11 changes: 11 additions & 0 deletions trunk/arch/sparc/kernel/smp_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,8 @@ 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_fetch_glob_regs;
extern unsigned long xcall_fetch_glob_pmu;
extern unsigned long xcall_fetch_glob_pmu_n4;
extern unsigned long xcall_receive_signal;
extern unsigned long xcall_new_mmu_context_version;
#ifdef CONFIG_KGDB
Expand Down Expand Up @@ -1000,6 +1002,15 @@ void smp_fetch_global_regs(void)
smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0);
}

void smp_fetch_global_pmu(void)
{
if (tlb_type == hypervisor &&
sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
smp_cross_call(&xcall_fetch_glob_pmu_n4, 0, 0, 0);
else
smp_cross_call(&xcall_fetch_glob_pmu, 0, 0, 0);
}

/* 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
Loading

0 comments on commit 39fbe4e

Please sign in to comment.