提交 d9c56619 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc64: Do not clobber %g7 in setcontext() trap.
  sparc64: Kill __show_regs().
  sparc: Add __KERNEL__ ifdef protection to pt_regs helpers.
  sparc64: Kill smp_report_regs().
  sparc64: Kill VERBOSE_SHOWREGS code.
  sparc64: Hook up trigger_all_cpu_backtrace().
  sparc64: Make global reg dumping even more useful.
  sparc: Ignore drivers/video/console/promcon_tbl.c conmakehash generated file
  sparc64: FUTEX_OP_ANDN fix
  sparc: merge of_platform_{32,64}.h
  sparc64: Kill isa_bus_type.
  sparc64: Fix global reg snapshotting on self-cpu.
......@@ -59,7 +59,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
__futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ANDN:
__futex_cas_op("and\t%2, %4, %1", ret, oldval, uaddr, oparg);
__futex_cas_op("andn\t%2, %4, %1", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_XOR:
__futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
......
......@@ -90,4 +90,7 @@ static inline unsigned long get_softint(void)
return retval;
}
void __trigger_all_cpu_backtrace(void);
#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
#endif
#ifndef ___ASM_SPARC_OF_PLATFORM_H
#define ___ASM_SPARC_OF_PLATFORM_H
#if defined(__sparc__) && defined(__arch64__)
#include <asm/of_platform_64.h>
#else
#include <asm/of_platform_32.h>
#endif
/*
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
* <benh@kernel.crashing.org>
* Modified for Sparc by merging parts of asm/of_device.h
* by Stephen Rothwell
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
/* This is just here during the transition */
#include <linux/of_platform.h>
extern struct bus_type ebus_bus_type;
extern struct bus_type sbus_bus_type;
#define of_bus_type of_platform_bus_type /* for compatibility */
#endif
#ifndef _ASM_SPARC_OF_PLATFORM_H
#define _ASM_SPARC_OF_PLATFORM_H
/*
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
* <benh@kernel.crashing.org>
* Modified for Sparc by merging parts of asm/of_device.h
* by Stephen Rothwell
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
/* This is just here during the transition */
#include <linux/of_platform.h>
extern struct bus_type ebus_bus_type;
extern struct bus_type sbus_bus_type;
#define of_bus_type of_platform_bus_type /* for compatibility */
#endif /* _ASM_SPARC_OF_PLATFORM_H */
#ifndef _ASM_SPARC64_OF_PLATFORM_H
#define _ASM_SPARC64_OF_PLATFORM_H
/*
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
* <benh@kernel.crashing.org>
* Modified for Sparc by merging parts of asm/of_device.h
* by Stephen Rothwell
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
/* This is just here during the transition */
#include <linux/of_platform.h>
extern struct bus_type isa_bus_type;
extern struct bus_type ebus_bus_type;
extern struct bus_type sbus_bus_type;
#define of_bus_type of_platform_bus_type /* for compatibility */
#endif /* _ASM_SPARC64_OF_PLATFORM_H */
......@@ -40,16 +40,6 @@ struct pt_regs {
#define UREG_FP UREG_I6
#define UREG_RETPC UREG_I7
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->psr &= ~PSR_SYSCALL);
}
/* A register window */
struct reg_window {
unsigned long locals[8];
......@@ -72,6 +62,16 @@ struct sparc_stackf {
#ifdef __KERNEL__
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->psr &= ~PSR_SYSCALL);
}
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
......
......@@ -37,21 +37,6 @@ struct pt_regs {
unsigned int magic;
};
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
return regs->magic & 0x1ff;
}
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->tstate & TSTATE_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->tstate &= ~TSTATE_SYSCALL);
}
struct pt_regs32 {
unsigned int psr;
unsigned int pc;
......@@ -128,15 +113,30 @@ struct sparc_trapf {
#ifdef __KERNEL__
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
return regs->magic & 0x1ff;
}
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->tstate & TSTATE_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->tstate &= ~TSTATE_SYSCALL);
}
struct global_reg_snapshot {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned long o7;
unsigned long i7;
unsigned long rpc;
struct thread_info *thread;
unsigned long pad1;
unsigned long pad2;
};
#define __ARCH_WANT_COMPAT_SYS_PTRACE
......@@ -154,7 +154,6 @@ extern unsigned long profile_pc(struct pt_regs *);
#define profile_pc(regs) instruction_pointer(regs)
#endif
extern void show_regs(struct pt_regs *);
extern void __show_regs(struct pt_regs *);
#endif
#else /* __ASSEMBLY__ */
......@@ -315,9 +314,9 @@ extern void __show_regs(struct pt_regs *);
#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
#define GR_SNAP_RPC 0x28
#define GR_SNAP_THREAD 0x30
#define GR_SNAP_PAD1 0x38
#endif /* __KERNEL__ */
......
......@@ -56,9 +56,6 @@ struct of_device *of_find_device_by_node(struct device_node *dp)
EXPORT_SYMBOL(of_find_device_by_node);
#ifdef CONFIG_PCI
struct bus_type isa_bus_type;
EXPORT_SYMBOL(isa_bus_type);
struct bus_type ebus_bus_type;
EXPORT_SYMBOL(ebus_bus_type);
#endif
......@@ -841,8 +838,6 @@ static int __init of_bus_driver_init(void)
err = of_bus_type_init(&of_platform_bus_type, "of");
#ifdef CONFIG_PCI
if (!err)
err = of_bus_type_init(&isa_bus_type, "isa");
if (!err)
err = of_bus_type_init(&ebus_bus_type, "ebus");
#endif
......
......@@ -52,8 +52,6 @@
#include <asm/irq_regs.h>
#include <asm/smp.h>
/* #define VERBOSE_SHOWREGS */
static void sparc64_yield(int cpu)
{
if (tlb_type != hypervisor)
......@@ -213,22 +211,8 @@ static void show_regwindow(struct pt_regs *regs)
printk("I7: <%pS>\n", (void *) rwk->ins[7]);
}
#ifdef CONFIG_SMP
static DEFINE_SPINLOCK(regdump_lock);
#endif
void __show_regs(struct pt_regs * regs)
void show_regs(struct pt_regs *regs)
{
#ifdef CONFIG_SMP
unsigned long flags;
/* Protect against xcall ipis which might lead to livelock on the lock */
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate"
: "=r" (flags)
: "i" (PSTATE_IE));
spin_lock(&regdump_lock);
#endif
printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate,
regs->tpc, regs->tnpc, regs->y, print_tainted());
printk("TPC: <%pS>\n", (void *) regs->tpc);
......@@ -246,64 +230,24 @@ void __show_regs(struct pt_regs * regs)
regs->u_regs[15]);
printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
show_regwindow(regs);
#ifdef CONFIG_SMP
spin_unlock(&regdump_lock);
__asm__ __volatile__("wrpr %0, 0, %%pstate"
: : "r" (flags));
#endif
}
#ifdef VERBOSE_SHOWREGS
static void idump_from_user (unsigned int *pc)
{
int i;
int code;
if((((unsigned long) pc) & 3))
return;
pc -= 3;
for(i = -3; i < 6; i++) {
get_user(code, pc);
printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
pc++;
}
printk("\n");
}
#endif
struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
static DEFINE_SPINLOCK(global_reg_snapshot_lock);
void show_regs(struct pt_regs *regs)
static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
{
#ifdef VERBOSE_SHOWREGS
extern long etrap, etraptl1;
#endif
__show_regs(regs);
#if 0
#ifdef CONFIG_SMP
{
extern void smp_report_regs(void);
unsigned long thread_base, fp;
smp_report_regs();
}
#endif
#endif
thread_base = (unsigned long) tp;
fp = (unsigned long) rw;
#ifdef VERBOSE_SHOWREGS
if (regs->tpc >= &etrap && regs->tpc < &etraptl1 &&
regs->u_regs[14] >= (long)current - PAGE_SIZE &&
regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) {
printk ("*********parent**********\n");
__show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF));
idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc);
printk ("*********endpar**********\n");
}
#endif
if (fp < (thread_base + sizeof(struct thread_info)) ||
fp >= (thread_base + THREAD_SIZE))
return false;
return true;
}
#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)
{
......@@ -315,14 +259,22 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];
if (regs->tstate & TSTATE_PRIV) {
struct thread_info *tp = current_thread_info();
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
if (kstack_valid(tp, rw)) {
global_reg_snapshot[this_cpu].i7 = rw->ins[7];
rw = (struct reg_window *)
(rw->ins[6] + STACK_BIAS);
if (kstack_valid(tp, rw))
global_reg_snapshot[this_cpu].rpc = rw->ins[7];
}
} else {
global_reg_snapshot[this_cpu].i7 = 0;
global_reg_snapshot[this_cpu].rpc = 0;
}
global_reg_snapshot[this_cpu].thread = tp;
}
......@@ -341,7 +293,7 @@ static void __global_reg_poll(struct global_reg_snapshot *gp)
}
}
static void sysrq_handle_globreg(int key, struct tty_struct *tty)
void __trigger_all_cpu_backtrace(void)
{
struct thread_info *tp = current_thread_info();
struct pt_regs *regs = get_irq_regs();
......@@ -375,13 +327,14 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty)
((tp && tp->task) ? tp->task->pid : -1));
if (gp->tstate & TSTATE_PRIV) {
printk(" TPC[%pS] O7[%pS] I7[%pS]\n",
printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n",
(void *) gp->tpc,
(void *) gp->o7,
(void *) gp->i7);
(void *) gp->i7,
(void *) gp->rpc);
} else {
printk(" TPC[%lx] O7[%lx] I7[%lx]\n",
gp->tpc, gp->o7, gp->i7);
printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
gp->tpc, gp->o7, gp->i7, gp->rpc);
}
}
......@@ -390,6 +343,13 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty)
spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
}
#ifdef CONFIG_MAGIC_SYSRQ
static void sysrq_handle_globreg(int key, struct tty_struct *tty)
{
__trigger_all_cpu_backtrace();
}
static struct sysrq_key_op sparc_globalreg_op = {
.handler = sysrq_handle_globreg,
.help_msg = "Globalregs",
......
......@@ -2,7 +2,7 @@
* arch/sparc64/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
......@@ -91,7 +91,9 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));
/* Skip %g7 as that's the thread register in userspace. */
err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
......
......@@ -843,7 +843,6 @@ void smp_tsb_sync(struct mm_struct *mm)
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
......@@ -1022,11 +1021,6 @@ void kgdb_roundup_cpus(unsigned long flags)
}
#endif
void smp_report_regs(void)
{
smp_cross_call(&xcall_report_regs, 0, 0, 0);
}
#ifdef CONFIG_MAGIC_SYSRQ
void smp_fetch_global_regs(void)
{
......
......@@ -68,7 +68,6 @@ extern void *__memscan_zero(void *, size_t);
extern void *__memscan_generic(void *, int, size_t);
extern int __memcmp(const void *, const void *, __kernel_size_t);
extern __kernel_size_t strlen(const char *);
extern void show_regs(struct pt_regs *);
extern void syscall_trace(struct pt_regs *, int);
extern void sys_sigsuspend(void);
extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
......
......@@ -1777,7 +1777,7 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
pfx,
ent->err_raddr, ent->err_size, ent->err_cpu);
__show_regs(regs);
show_regs(regs);
if ((cnt = atomic_read(ocnt)) != 0) {
atomic_set(ocnt, 0);
......@@ -2177,7 +2177,6 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
void die_if_kernel(char *str, struct pt_regs *regs)
{
static int die_counter;
extern void smp_report_regs(void);
int count = 0;
/* Amuse the user. */
......@@ -2190,7 +2189,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw");
__show_regs(regs);
show_regs(regs);
add_taint(TAINT_DIE);
if (regs->tstate & TSTATE_PRIV) {
struct reg_window *rw = (struct reg_window *)
......@@ -2215,11 +2214,6 @@ void die_if_kernel(char *str, struct pt_regs *regs)
}
user_instruction_dump ((unsigned int __user *) regs->tpc);
}
#if 0
#ifdef CONFIG_SMP
smp_report_regs();
#endif
#endif
if (regs->tstate & TSTATE_PRIV)
do_exit(SIGKILL);
do_exit(SIGSEGV);
......
......@@ -480,41 +480,6 @@ xcall_sync_tick:
b rtrap_xcall
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
/* NOTE: This is SPECIAL!! We do etrap/rtrap however
* we choose to deal with the "BH's run with
* %pil==15" problem (described in asm/pil.h)
* by just invoking rtrap directly past where
* BH's are checked for.
*
* We do it like this because we do not want %pil==15
* lockups to prevent regs being reported.
*/
.globl xcall_report_regs
xcall_report_regs:
661: rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
.section .sun4v_2insn_patch, "ax"
.word 661b
nop
nop
.previous
rdpr %pil, %g2
wrpr %g0, 15, %pil
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
/* Has to be a non-v9 branch due to the large distance. */
b rtrap_xcall
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
#ifdef CONFIG_MAGIC_SYSRQ
.globl xcall_fetch_glob_regs
xcall_fetch_glob_regs:
......@@ -531,6 +496,13 @@ xcall_fetch_glob_regs:
stx %g7, [%g1 + GR_SNAP_TNPC]
stx %o7, [%g1 + GR_SNAP_O7]
stx %i7, [%g1 + GR_SNAP_I7]
/* Don't try this at home kids... */
rdpr %cwp, %g2
sub %g2, 1, %g7
wrpr %g7, %cwp
mov %i7, %g7
wrpr %g2, %cwp
stx %g7, [%g1 + GR_SNAP_RPC]
sethi %hi(trap_block), %g7
or %g7, %lo(trap_block), %g7
sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2
......
# conmakehash generated file
promcon_tbl.c
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册