Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: kgdb: kgdboc console poll hooks for mpsc uart kgdb: kgdboc console poll hooks for cpm uart kgdb, powerpc: arch specific powerpc kgdb support kgdb: support for ARCH=arm kgdb: remove unused HAVE_ARCH_KGDB_SHADOW_INFO config variable
This commit is contained in:
commit
0f6e38a638
@ -12,6 +12,7 @@ config ARM
|
|||||||
select RTC_LIB
|
select RTC_LIB
|
||||||
select SYS_SUPPORTS_APM_EMULATION
|
select SYS_SUPPORTS_APM_EMULATION
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_KPROBES if (!XIP_KERNEL)
|
select HAVE_KPROBES if (!XIP_KERNEL)
|
||||||
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
||||||
select HAVE_FTRACE if (!XIP_KERNEL)
|
select HAVE_FTRACE if (!XIP_KERNEL)
|
||||||
|
@ -28,6 +28,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
|
|||||||
obj-$(CONFIG_ATAGS_PROC) += atags.o
|
obj-$(CONFIG_ATAGS_PROC) += atags.o
|
||||||
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
|
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
|
||||||
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
|
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
|
||||||
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
|
|
||||||
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
||||||
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
|
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
|
||||||
|
201
arch/arm/kernel/kgdb.c
Normal file
201
arch/arm/kernel/kgdb.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* arch/arm/kernel/kgdb.c
|
||||||
|
*
|
||||||
|
* ARM KGDB support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002-2004 MontaVista Software, Inc
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc.
|
||||||
|
*
|
||||||
|
* Authors: George Davis <davis_g@mvista.com>
|
||||||
|
* Deepak Saxena <dsaxena@plexity.net>
|
||||||
|
*/
|
||||||
|
#include <linux/kgdb.h>
|
||||||
|
#include <asm/traps.h>
|
||||||
|
|
||||||
|
/* Make a local copy of the registers passed into the handler (bletch) */
|
||||||
|
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
|
||||||
|
{
|
||||||
|
int regno;
|
||||||
|
|
||||||
|
/* Initialize all to zero. */
|
||||||
|
for (regno = 0; regno < GDB_MAX_REGS; regno++)
|
||||||
|
gdb_regs[regno] = 0;
|
||||||
|
|
||||||
|
gdb_regs[_R0] = kernel_regs->ARM_r0;
|
||||||
|
gdb_regs[_R1] = kernel_regs->ARM_r1;
|
||||||
|
gdb_regs[_R2] = kernel_regs->ARM_r2;
|
||||||
|
gdb_regs[_R3] = kernel_regs->ARM_r3;
|
||||||
|
gdb_regs[_R4] = kernel_regs->ARM_r4;
|
||||||
|
gdb_regs[_R5] = kernel_regs->ARM_r5;
|
||||||
|
gdb_regs[_R6] = kernel_regs->ARM_r6;
|
||||||
|
gdb_regs[_R7] = kernel_regs->ARM_r7;
|
||||||
|
gdb_regs[_R8] = kernel_regs->ARM_r8;
|
||||||
|
gdb_regs[_R9] = kernel_regs->ARM_r9;
|
||||||
|
gdb_regs[_R10] = kernel_regs->ARM_r10;
|
||||||
|
gdb_regs[_FP] = kernel_regs->ARM_fp;
|
||||||
|
gdb_regs[_IP] = kernel_regs->ARM_ip;
|
||||||
|
gdb_regs[_SPT] = kernel_regs->ARM_sp;
|
||||||
|
gdb_regs[_LR] = kernel_regs->ARM_lr;
|
||||||
|
gdb_regs[_PC] = kernel_regs->ARM_pc;
|
||||||
|
gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
|
||||||
|
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
|
||||||
|
{
|
||||||
|
kernel_regs->ARM_r0 = gdb_regs[_R0];
|
||||||
|
kernel_regs->ARM_r1 = gdb_regs[_R1];
|
||||||
|
kernel_regs->ARM_r2 = gdb_regs[_R2];
|
||||||
|
kernel_regs->ARM_r3 = gdb_regs[_R3];
|
||||||
|
kernel_regs->ARM_r4 = gdb_regs[_R4];
|
||||||
|
kernel_regs->ARM_r5 = gdb_regs[_R5];
|
||||||
|
kernel_regs->ARM_r6 = gdb_regs[_R6];
|
||||||
|
kernel_regs->ARM_r7 = gdb_regs[_R7];
|
||||||
|
kernel_regs->ARM_r8 = gdb_regs[_R8];
|
||||||
|
kernel_regs->ARM_r9 = gdb_regs[_R9];
|
||||||
|
kernel_regs->ARM_r10 = gdb_regs[_R10];
|
||||||
|
kernel_regs->ARM_fp = gdb_regs[_FP];
|
||||||
|
kernel_regs->ARM_ip = gdb_regs[_IP];
|
||||||
|
kernel_regs->ARM_sp = gdb_regs[_SPT];
|
||||||
|
kernel_regs->ARM_lr = gdb_regs[_LR];
|
||||||
|
kernel_regs->ARM_pc = gdb_regs[_PC];
|
||||||
|
kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
|
||||||
|
{
|
||||||
|
struct pt_regs *thread_regs;
|
||||||
|
int regno;
|
||||||
|
|
||||||
|
/* Just making sure... */
|
||||||
|
if (task == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initialize to zero */
|
||||||
|
for (regno = 0; regno < GDB_MAX_REGS; regno++)
|
||||||
|
gdb_regs[regno] = 0;
|
||||||
|
|
||||||
|
/* Otherwise, we have only some registers from switch_to() */
|
||||||
|
thread_regs = task_pt_regs(task);
|
||||||
|
gdb_regs[_R0] = thread_regs->ARM_r0;
|
||||||
|
gdb_regs[_R1] = thread_regs->ARM_r1;
|
||||||
|
gdb_regs[_R2] = thread_regs->ARM_r2;
|
||||||
|
gdb_regs[_R3] = thread_regs->ARM_r3;
|
||||||
|
gdb_regs[_R4] = thread_regs->ARM_r4;
|
||||||
|
gdb_regs[_R5] = thread_regs->ARM_r5;
|
||||||
|
gdb_regs[_R6] = thread_regs->ARM_r6;
|
||||||
|
gdb_regs[_R7] = thread_regs->ARM_r7;
|
||||||
|
gdb_regs[_R8] = thread_regs->ARM_r8;
|
||||||
|
gdb_regs[_R9] = thread_regs->ARM_r9;
|
||||||
|
gdb_regs[_R10] = thread_regs->ARM_r10;
|
||||||
|
gdb_regs[_FP] = thread_regs->ARM_fp;
|
||||||
|
gdb_regs[_IP] = thread_regs->ARM_ip;
|
||||||
|
gdb_regs[_SPT] = thread_regs->ARM_sp;
|
||||||
|
gdb_regs[_LR] = thread_regs->ARM_lr;
|
||||||
|
gdb_regs[_PC] = thread_regs->ARM_pc;
|
||||||
|
gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compiled_break;
|
||||||
|
|
||||||
|
int kgdb_arch_handle_exception(int exception_vector, int signo,
|
||||||
|
int err_code, char *remcom_in_buffer,
|
||||||
|
char *remcom_out_buffer,
|
||||||
|
struct pt_regs *linux_regs)
|
||||||
|
{
|
||||||
|
unsigned long addr;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
switch (remcom_in_buffer[0]) {
|
||||||
|
case 'D':
|
||||||
|
case 'k':
|
||||||
|
case 'c':
|
||||||
|
kgdb_contthread = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to read optional parameter, pc unchanged if no parm.
|
||||||
|
* If this was a compiled breakpoint, we need to move
|
||||||
|
* to the next instruction or we will just breakpoint
|
||||||
|
* over and over again.
|
||||||
|
*/
|
||||||
|
ptr = &remcom_in_buffer[1];
|
||||||
|
if (kgdb_hex2long(&ptr, &addr))
|
||||||
|
linux_regs->ARM_pc = addr;
|
||||||
|
else if (compiled_break == 1)
|
||||||
|
linux_regs->ARM_pc += 4;
|
||||||
|
|
||||||
|
compiled_break = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||||
|
{
|
||||||
|
kgdb_handle_exception(1, SIGTRAP, 0, regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||||
|
{
|
||||||
|
compiled_break = 1;
|
||||||
|
kgdb_handle_exception(1, SIGTRAP, 0, regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct undef_hook kgdb_brkpt_hook = {
|
||||||
|
.instr_mask = 0xffffffff,
|
||||||
|
.instr_val = KGDB_BREAKINST,
|
||||||
|
.fn = kgdb_brk_fn
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct undef_hook kgdb_compiled_brkpt_hook = {
|
||||||
|
.instr_mask = 0xffffffff,
|
||||||
|
.instr_val = KGDB_COMPILED_BREAK,
|
||||||
|
.fn = kgdb_compiled_brk_fn
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kgdb_arch_init - Perform any architecture specific initalization.
|
||||||
|
*
|
||||||
|
* This function will handle the initalization of any architecture
|
||||||
|
* specific callbacks.
|
||||||
|
*/
|
||||||
|
int kgdb_arch_init(void)
|
||||||
|
{
|
||||||
|
register_undef_hook(&kgdb_brkpt_hook);
|
||||||
|
register_undef_hook(&kgdb_compiled_brkpt_hook);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kgdb_arch_exit - Perform any architecture specific uninitalization.
|
||||||
|
*
|
||||||
|
* This function will handle the uninitalization of any architecture
|
||||||
|
* specific callbacks, for dynamic registration and unregistration.
|
||||||
|
*/
|
||||||
|
void kgdb_arch_exit(void)
|
||||||
|
{
|
||||||
|
unregister_undef_hook(&kgdb_brkpt_hook);
|
||||||
|
unregister_undef_hook(&kgdb_compiled_brkpt_hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register our undef instruction hooks with ARM undef core.
|
||||||
|
* We regsiter a hook specifically looking for the KGB break inst
|
||||||
|
* and we handle the normal undef case within the do_undefinstr
|
||||||
|
* handler.
|
||||||
|
*/
|
||||||
|
struct kgdb_arch arch_kgdb_ops = {
|
||||||
|
#ifndef __ARMEB__
|
||||||
|
.gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
|
||||||
|
#else /* ! __ARMEB__ */
|
||||||
|
.gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
|
||||||
|
#endif
|
||||||
|
};
|
@ -36,6 +36,7 @@
|
|||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
|
#include <asm/traps.h>
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "atags.h"
|
#include "atags.h"
|
||||||
@ -853,6 +854,7 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
conswitchp = &dummy_con;
|
conswitchp = &dummy_con;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
early_trap_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -707,6 +707,11 @@ void abort(void)
|
|||||||
EXPORT_SYMBOL(abort);
|
EXPORT_SYMBOL(abort);
|
||||||
|
|
||||||
void __init trap_init(void)
|
void __init trap_init(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init early_trap_init(void)
|
||||||
{
|
{
|
||||||
unsigned long vectors = CONFIG_VECTORS_BASE;
|
unsigned long vectors = CONFIG_VECTORS_BASE;
|
||||||
extern char __stubs_start[], __stubs_end[];
|
extern char __stubs_start[], __stubs_end[];
|
||||||
|
@ -112,6 +112,7 @@ config PPC
|
|||||||
select HAVE_FTRACE
|
select HAVE_FTRACE
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_LMB
|
select HAVE_LMB
|
||||||
select HAVE_DMA_ATTRS if PPC64
|
select HAVE_DMA_ATTRS if PPC64
|
||||||
|
@ -41,22 +41,6 @@ config HCALL_STATS
|
|||||||
This option will add a small amount of overhead to all hypervisor
|
This option will add a small amount of overhead to all hypervisor
|
||||||
calls.
|
calls.
|
||||||
|
|
||||||
config DEBUGGER
|
|
||||||
bool "Enable debugger hooks"
|
|
||||||
depends on DEBUG_KERNEL
|
|
||||||
help
|
|
||||||
Include in-kernel hooks for kernel debuggers. Unless you are
|
|
||||||
intending to debug the kernel, say N here.
|
|
||||||
|
|
||||||
config KGDB
|
|
||||||
bool "Include kgdb kernel debugger"
|
|
||||||
depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
|
|
||||||
select DEBUG_INFO
|
|
||||||
help
|
|
||||||
Include in-kernel hooks for kgdb, the Linux kernel source level
|
|
||||||
debugger. See <http://kgdb.sourceforge.net/> for more information.
|
|
||||||
Unless you are intending to debug the kernel, say N here.
|
|
||||||
|
|
||||||
config CODE_PATCHING_SELFTEST
|
config CODE_PATCHING_SELFTEST
|
||||||
bool "Run self-tests of the code-patching code."
|
bool "Run self-tests of the code-patching code."
|
||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL
|
||||||
@ -67,36 +51,9 @@ config FTR_FIXUP_SELFTEST
|
|||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL
|
||||||
default n
|
default n
|
||||||
|
|
||||||
choice
|
|
||||||
prompt "Serial Port"
|
|
||||||
depends on KGDB
|
|
||||||
default KGDB_TTYS1
|
|
||||||
|
|
||||||
config KGDB_TTYS0
|
|
||||||
bool "ttyS0"
|
|
||||||
|
|
||||||
config KGDB_TTYS1
|
|
||||||
bool "ttyS1"
|
|
||||||
|
|
||||||
config KGDB_TTYS2
|
|
||||||
bool "ttyS2"
|
|
||||||
|
|
||||||
config KGDB_TTYS3
|
|
||||||
bool "ttyS3"
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
config KGDB_CONSOLE
|
|
||||||
bool "Enable serial console thru kgdb port"
|
|
||||||
depends on KGDB && 8xx || CPM2
|
|
||||||
help
|
|
||||||
If you enable this, all serial console messages will be sent
|
|
||||||
over the gdb stub.
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
config XMON
|
config XMON
|
||||||
bool "Include xmon kernel debugger"
|
bool "Include xmon kernel debugger"
|
||||||
depends on DEBUGGER
|
depends on DEBUG_KERNEL
|
||||||
help
|
help
|
||||||
Include in-kernel hooks for the xmon kernel monitor/debugger.
|
Include in-kernel hooks for the xmon kernel monitor/debugger.
|
||||||
Unless you are intending to debug the kernel, say N here.
|
Unless you are intending to debug the kernel, say N here.
|
||||||
@ -126,6 +83,11 @@ config XMON_DISASSEMBLY
|
|||||||
to say Y here, unless you're building for a memory-constrained
|
to say Y here, unless you're building for a memory-constrained
|
||||||
system.
|
system.
|
||||||
|
|
||||||
|
config DEBUGGER
|
||||||
|
bool
|
||||||
|
depends on KGDB || XMON
|
||||||
|
default y
|
||||||
|
|
||||||
config IRQSTACKS
|
config IRQSTACKS
|
||||||
bool "Use separate kernel stacks when processing interrupts"
|
bool "Use separate kernel stacks when processing interrupts"
|
||||||
help
|
help
|
||||||
|
@ -74,6 +74,7 @@ obj-y += time.o prom.o traps.o setup-common.o \
|
|||||||
misc_$(CONFIG_WORD_SIZE).o
|
misc_$(CONFIG_WORD_SIZE).o
|
||||||
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
|
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
|
||||||
obj-$(CONFIG_PPC64) += dma_64.o iommu.o
|
obj-$(CONFIG_PPC64) += dma_64.o iommu.o
|
||||||
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
|
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
|
||||||
obj-$(CONFIG_MODULES) += ppc_ksyms.o
|
obj-$(CONFIG_MODULES) += ppc_ksyms.o
|
||||||
obj-$(CONFIG_BOOTX_TEXT) += btext.o
|
obj-$(CONFIG_BOOTX_TEXT) += btext.o
|
||||||
|
410
arch/powerpc/kernel/kgdb.c
Normal file
410
arch/powerpc/kernel/kgdb.c
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
/*
|
||||||
|
* PowerPC backend to the KGDB stub.
|
||||||
|
*
|
||||||
|
* 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
|
||||||
|
* Copyright (C) 2003 Timesys Corporation.
|
||||||
|
* Copyright (C) 2004-2006 MontaVista Software, Inc.
|
||||||
|
* PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
|
||||||
|
* PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
|
||||||
|
* Sergei Shtylyov <sshtylyov@ru.mvista.com>
|
||||||
|
* Copyright (C) 2007-2008 Wind River Systems, Inc.
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public License
|
||||||
|
* version 2. This program as licensed "as is" without any warranty of any
|
||||||
|
* kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kgdb.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <asm/current.h>
|
||||||
|
#include <asm/processor.h>
|
||||||
|
#include <asm/machdep.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This table contains the mapping between PowerPC hardware trap types, and
|
||||||
|
* signals, which are primarily what GDB understands. GDB and the kernel
|
||||||
|
* don't always agree on values, so we use constants taken from gdb-6.2.
|
||||||
|
*/
|
||||||
|
static struct hard_trap_info
|
||||||
|
{
|
||||||
|
unsigned int tt; /* Trap type code for powerpc */
|
||||||
|
unsigned char signo; /* Signal that we map this trap into */
|
||||||
|
} hard_trap_info[] = {
|
||||||
|
{ 0x0100, 0x02 /* SIGINT */ }, /* system reset */
|
||||||
|
{ 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
|
||||||
|
{ 0x0300, 0x0b /* SIGSEGV */ }, /* data access */
|
||||||
|
{ 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */
|
||||||
|
{ 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */
|
||||||
|
{ 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
|
||||||
|
{ 0x0700, 0x05 /* SIGTRAP */ }, /* program check */
|
||||||
|
{ 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */
|
||||||
|
{ 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
|
||||||
|
{ 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */
|
||||||
|
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
|
||||||
|
{ 0x2002, 0x05 /* SIGTRAP */ }, /* debug */
|
||||||
|
#if defined(CONFIG_FSL_BOOKE)
|
||||||
|
{ 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */
|
||||||
|
{ 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */
|
||||||
|
{ 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */
|
||||||
|
{ 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */
|
||||||
|
{ 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */
|
||||||
|
{ 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */
|
||||||
|
{ 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */
|
||||||
|
{ 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */
|
||||||
|
{ 0x3200, 0x02 /* SIGINT */ }, /* watchdog */
|
||||||
|
#else /* ! CONFIG_FSL_BOOKE */
|
||||||
|
{ 0x1000, 0x0e /* SIGALRM */ }, /* prog interval timer */
|
||||||
|
{ 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */
|
||||||
|
{ 0x1020, 0x02 /* SIGINT */ }, /* watchdog */
|
||||||
|
{ 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */
|
||||||
|
{ 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */
|
||||||
|
#endif
|
||||||
|
#else /* ! (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) */
|
||||||
|
{ 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */
|
||||||
|
#if defined(CONFIG_8xx)
|
||||||
|
{ 0x1000, 0x04 /* SIGILL */ }, /* software emulation */
|
||||||
|
#else /* ! CONFIG_8xx */
|
||||||
|
{ 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */
|
||||||
|
{ 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */
|
||||||
|
{ 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
|
||||||
|
#if defined(CONFIG_PPC64)
|
||||||
|
{ 0x1200, 0x05 /* SIGILL */ }, /* system error */
|
||||||
|
{ 0x1500, 0x04 /* SIGILL */ }, /* soft patch */
|
||||||
|
{ 0x1600, 0x04 /* SIGILL */ }, /* maintenance */
|
||||||
|
{ 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */
|
||||||
|
{ 0x1800, 0x04 /* SIGILL */ }, /* thermal */
|
||||||
|
#else /* ! CONFIG_PPC64 */
|
||||||
|
{ 0x1400, 0x02 /* SIGINT */ }, /* SMI */
|
||||||
|
{ 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */
|
||||||
|
{ 0x1700, 0x04 /* SIGILL */ }, /* TAU */
|
||||||
|
{ 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
{ 0x0000, 0x00 } /* Must be last */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int computeSignal(unsigned int tt)
|
||||||
|
{
|
||||||
|
struct hard_trap_info *ht;
|
||||||
|
|
||||||
|
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
|
||||||
|
if (ht->tt == tt)
|
||||||
|
return ht->signo;
|
||||||
|
|
||||||
|
return SIGHUP; /* default for things we don't know about */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_call_nmi_hook(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
kgdb_nmicallback(raw_smp_processor_id(), regs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
void kgdb_roundup_cpus(unsigned long flags)
|
||||||
|
{
|
||||||
|
smp_send_debugger_break(MSG_ALL_BUT_SELF);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* KGDB functions to use existing PowerPC64 hooks. */
|
||||||
|
static int kgdb_debugger(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_handle_breakpoint(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (user_mode(regs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
|
||||||
|
regs->nip += 4;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_singlestep(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct thread_info *thread_info, *exception_thread_info;
|
||||||
|
|
||||||
|
if (user_mode(regs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Book E and perhaps other processsors, singlestep is handled on
|
||||||
|
* the critical exception stack. This causes current_thread_info()
|
||||||
|
* to fail, since it it locates the thread_info by masking off
|
||||||
|
* the low bits of the current stack pointer. We work around
|
||||||
|
* this issue by copying the thread_info from the kernel stack
|
||||||
|
* before calling kgdb_handle_exception, and copying it back
|
||||||
|
* afterwards. On most processors the copy is avoided since
|
||||||
|
* exception_thread_info == thread_info.
|
||||||
|
*/
|
||||||
|
thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
|
||||||
|
exception_thread_info = current_thread_info();
|
||||||
|
|
||||||
|
if (thread_info != exception_thread_info)
|
||||||
|
memcpy(exception_thread_info, thread_info, sizeof *thread_info);
|
||||||
|
|
||||||
|
kgdb_handle_exception(0, SIGTRAP, 0, regs);
|
||||||
|
|
||||||
|
if (thread_info != exception_thread_info)
|
||||||
|
memcpy(thread_info, exception_thread_info, sizeof *thread_info);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_iabr_match(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (user_mode(regs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kgdb_dabr_match(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (user_mode(regs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PACK64(ptr, src) do { *(ptr++) = (src); } while (0)
|
||||||
|
|
||||||
|
#define PACK32(ptr, src) do { \
|
||||||
|
u32 *ptr32; \
|
||||||
|
ptr32 = (u32 *)ptr; \
|
||||||
|
*(ptr32++) = (src); \
|
||||||
|
ptr = (unsigned long *)ptr32; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
unsigned long *ptr = gdb_regs;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
memset(gdb_regs, 0, NUMREGBYTES);
|
||||||
|
|
||||||
|
for (reg = 0; reg < 32; reg++)
|
||||||
|
PACK64(ptr, regs->gpr[reg]);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FSL_BOOKE
|
||||||
|
#ifdef CONFIG_SPE
|
||||||
|
for (reg = 0; reg < 32; reg++)
|
||||||
|
PACK64(ptr, current->thread.evr[reg]);
|
||||||
|
#else
|
||||||
|
ptr += 32;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/* fp registers not used by kernel, leave zero */
|
||||||
|
ptr += 32 * 8 / sizeof(long);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PACK64(ptr, regs->nip);
|
||||||
|
PACK64(ptr, regs->msr);
|
||||||
|
PACK32(ptr, regs->ccr);
|
||||||
|
PACK64(ptr, regs->link);
|
||||||
|
PACK64(ptr, regs->ctr);
|
||||||
|
PACK32(ptr, regs->xer);
|
||||||
|
|
||||||
|
BUG_ON((unsigned long)ptr >
|
||||||
|
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
||||||
|
{
|
||||||
|
struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
|
||||||
|
STACK_FRAME_OVERHEAD);
|
||||||
|
unsigned long *ptr = gdb_regs;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
memset(gdb_regs, 0, NUMREGBYTES);
|
||||||
|
|
||||||
|
/* Regs GPR0-2 */
|
||||||
|
for (reg = 0; reg < 3; reg++)
|
||||||
|
PACK64(ptr, regs->gpr[reg]);
|
||||||
|
|
||||||
|
/* Regs GPR3-13 are caller saved, not in regs->gpr[] */
|
||||||
|
ptr += 11;
|
||||||
|
|
||||||
|
/* Regs GPR14-31 */
|
||||||
|
for (reg = 14; reg < 32; reg++)
|
||||||
|
PACK64(ptr, regs->gpr[reg]);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FSL_BOOKE
|
||||||
|
#ifdef CONFIG_SPE
|
||||||
|
for (reg = 0; reg < 32; reg++)
|
||||||
|
PACK64(ptr, p->thread.evr[reg]);
|
||||||
|
#else
|
||||||
|
ptr += 32;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/* fp registers not used by kernel, leave zero */
|
||||||
|
ptr += 32 * 8 / sizeof(long);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PACK64(ptr, regs->nip);
|
||||||
|
PACK64(ptr, regs->msr);
|
||||||
|
PACK32(ptr, regs->ccr);
|
||||||
|
PACK64(ptr, regs->link);
|
||||||
|
PACK64(ptr, regs->ctr);
|
||||||
|
PACK32(ptr, regs->xer);
|
||||||
|
|
||||||
|
BUG_ON((unsigned long)ptr >
|
||||||
|
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
|
||||||
|
|
||||||
|
#define UNPACK32(dest, ptr) do { \
|
||||||
|
u32 *ptr32; \
|
||||||
|
ptr32 = (u32 *)ptr; \
|
||||||
|
dest = *(ptr32++); \
|
||||||
|
ptr = (unsigned long *)ptr32; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
unsigned long *ptr = gdb_regs;
|
||||||
|
int reg;
|
||||||
|
#ifdef CONFIG_SPE
|
||||||
|
union {
|
||||||
|
u32 v32[2];
|
||||||
|
u64 v64;
|
||||||
|
} acc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (reg = 0; reg < 32; reg++)
|
||||||
|
UNPACK64(regs->gpr[reg], ptr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FSL_BOOKE
|
||||||
|
#ifdef CONFIG_SPE
|
||||||
|
for (reg = 0; reg < 32; reg++)
|
||||||
|
UNPACK64(current->thread.evr[reg], ptr);
|
||||||
|
#else
|
||||||
|
ptr += 32;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/* fp registers not used by kernel, leave zero */
|
||||||
|
ptr += 32 * 8 / sizeof(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UNPACK64(regs->nip, ptr);
|
||||||
|
UNPACK64(regs->msr, ptr);
|
||||||
|
UNPACK32(regs->ccr, ptr);
|
||||||
|
UNPACK64(regs->link, ptr);
|
||||||
|
UNPACK64(regs->ctr, ptr);
|
||||||
|
UNPACK32(regs->xer, ptr);
|
||||||
|
|
||||||
|
BUG_ON((unsigned long)ptr >
|
||||||
|
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function does PowerPC specific procesing for interfacing to gdb.
|
||||||
|
*/
|
||||||
|
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
|
||||||
|
char *remcom_in_buffer, char *remcom_out_buffer,
|
||||||
|
struct pt_regs *linux_regs)
|
||||||
|
{
|
||||||
|
char *ptr = &remcom_in_buffer[1];
|
||||||
|
unsigned long addr;
|
||||||
|
|
||||||
|
switch (remcom_in_buffer[0]) {
|
||||||
|
/*
|
||||||
|
* sAA..AA Step one instruction from AA..AA
|
||||||
|
* This will return an error to gdb ..
|
||||||
|
*/
|
||||||
|
case 's':
|
||||||
|
case 'c':
|
||||||
|
/* handle the optional parameter */
|
||||||
|
if (kgdb_hex2long(&ptr, &addr))
|
||||||
|
linux_regs->nip = addr;
|
||||||
|
|
||||||
|
atomic_set(&kgdb_cpu_doing_single_step, -1);
|
||||||
|
/* set the trace bit if we're stepping */
|
||||||
|
if (remcom_in_buffer[0] == 's') {
|
||||||
|
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
|
||||||
|
mtspr(SPRN_DBCR0,
|
||||||
|
mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
|
||||||
|
linux_regs->msr |= MSR_DE;
|
||||||
|
#else
|
||||||
|
linux_regs->msr |= MSR_SE;
|
||||||
|
#endif
|
||||||
|
kgdb_single_step = 1;
|
||||||
|
if (kgdb_contthread)
|
||||||
|
atomic_set(&kgdb_cpu_doing_single_step,
|
||||||
|
raw_smp_processor_id());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global data
|
||||||
|
*/
|
||||||
|
struct kgdb_arch arch_kgdb_ops = {
|
||||||
|
.gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int kgdb_not_implemented(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *old__debugger_ipi;
|
||||||
|
static void *old__debugger;
|
||||||
|
static void *old__debugger_bpt;
|
||||||
|
static void *old__debugger_sstep;
|
||||||
|
static void *old__debugger_iabr_match;
|
||||||
|
static void *old__debugger_dabr_match;
|
||||||
|
static void *old__debugger_fault_handler;
|
||||||
|
|
||||||
|
int kgdb_arch_init(void)
|
||||||
|
{
|
||||||
|
old__debugger_ipi = __debugger_ipi;
|
||||||
|
old__debugger = __debugger;
|
||||||
|
old__debugger_bpt = __debugger_bpt;
|
||||||
|
old__debugger_sstep = __debugger_sstep;
|
||||||
|
old__debugger_iabr_match = __debugger_iabr_match;
|
||||||
|
old__debugger_dabr_match = __debugger_dabr_match;
|
||||||
|
old__debugger_fault_handler = __debugger_fault_handler;
|
||||||
|
|
||||||
|
__debugger_ipi = kgdb_call_nmi_hook;
|
||||||
|
__debugger = kgdb_debugger;
|
||||||
|
__debugger_bpt = kgdb_handle_breakpoint;
|
||||||
|
__debugger_sstep = kgdb_singlestep;
|
||||||
|
__debugger_iabr_match = kgdb_iabr_match;
|
||||||
|
__debugger_dabr_match = kgdb_dabr_match;
|
||||||
|
__debugger_fault_handler = kgdb_not_implemented;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kgdb_arch_exit(void)
|
||||||
|
{
|
||||||
|
__debugger_ipi = old__debugger_ipi;
|
||||||
|
__debugger = old__debugger;
|
||||||
|
__debugger_bpt = old__debugger_bpt;
|
||||||
|
__debugger_sstep = old__debugger_sstep;
|
||||||
|
__debugger_iabr_match = old__debugger_iabr_match;
|
||||||
|
__debugger_dabr_match = old__debugger_dabr_match;
|
||||||
|
__debugger_fault_handler = old__debugger_fault_handler;
|
||||||
|
}
|
@ -43,10 +43,6 @@
|
|||||||
|
|
||||||
#define DBG(fmt...)
|
#define DBG(fmt...)
|
||||||
|
|
||||||
#if defined CONFIG_KGDB
|
|
||||||
#include <asm/kgdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void bootx_init(unsigned long r4, unsigned long phys);
|
extern void bootx_init(unsigned long r4, unsigned long phys);
|
||||||
|
|
||||||
int boot_cpuid;
|
int boot_cpuid;
|
||||||
@ -302,18 +298,6 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
|
|
||||||
xmon_setup();
|
xmon_setup();
|
||||||
|
|
||||||
#if defined(CONFIG_KGDB)
|
|
||||||
if (ppc_md.kgdb_map_scc)
|
|
||||||
ppc_md.kgdb_map_scc();
|
|
||||||
set_debug_traps();
|
|
||||||
if (strstr(cmd_line, "gdb")) {
|
|
||||||
if (ppc_md.progress)
|
|
||||||
ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
|
|
||||||
printk("kgdb breakpoint activated\n");
|
|
||||||
breakpoint();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set cache line size based on type of cpu as a default.
|
* Set cache line size based on type of cpu as a default.
|
||||||
* Systems with OF can look in the properties on the cpu node(s)
|
* Systems with OF can look in the properties on the cpu node(s)
|
||||||
|
@ -97,8 +97,6 @@ extern struct machdep_calls pmac_md;
|
|||||||
int sccdbg;
|
int sccdbg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void zs_kgdb_hook(int tty_num);
|
|
||||||
|
|
||||||
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
|
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
|
||||||
EXPORT_SYMBOL(sys_ctrler);
|
EXPORT_SYMBOL(sys_ctrler);
|
||||||
|
|
||||||
@ -329,10 +327,6 @@ static void __init pmac_setup_arch(void)
|
|||||||
l2cr_init();
|
l2cr_init();
|
||||||
#endif /* CONFIG_PPC32 */
|
#endif /* CONFIG_PPC32 */
|
||||||
|
|
||||||
#ifdef CONFIG_KGDB
|
|
||||||
zs_kgdb_hook(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
find_via_cuda();
|
find_via_cuda();
|
||||||
find_via_pmu();
|
find_via_pmu();
|
||||||
smu_init();
|
smu_init();
|
||||||
|
@ -201,6 +201,10 @@ static void cpm_uart_int_tx(struct uart_port *port)
|
|||||||
cpm_uart_tx_pump(port);
|
cpm_uart_tx_pump(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static int serial_polled;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receive characters
|
* Receive characters
|
||||||
*/
|
*/
|
||||||
@ -222,6 +226,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
|||||||
*/
|
*/
|
||||||
bdp = pinfo->rx_cur;
|
bdp = pinfo->rx_cur;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
if (unlikely(serial_polled)) {
|
||||||
|
serial_polled = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* get status */
|
/* get status */
|
||||||
status = in_be16(&bdp->cbd_sc);
|
status = in_be16(&bdp->cbd_sc);
|
||||||
/* If this one is empty, return happy */
|
/* If this one is empty, return happy */
|
||||||
@ -253,7 +263,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
|||||||
goto handle_error;
|
goto handle_error;
|
||||||
if (uart_handle_sysrq_char(port, ch))
|
if (uart_handle_sysrq_char(port, ch))
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
if (unlikely(serial_polled)) {
|
||||||
|
serial_polled = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
error_return:
|
error_return:
|
||||||
tty_insert_flip_char(tty, ch, flg);
|
tty_insert_flip_char(tty, ch, flg);
|
||||||
|
|
||||||
@ -865,6 +880,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
|
|||||||
cpm_uart_request_port(port);
|
cpm_uart_request_port(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
/* Serial polling routines for writing and reading from the uart while
|
||||||
|
* in an interrupt or debug context.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GDB_BUF_SIZE 512 /* power of 2, please */
|
||||||
|
|
||||||
|
static char poll_buf[GDB_BUF_SIZE];
|
||||||
|
static char *pollp;
|
||||||
|
static int poll_chars;
|
||||||
|
|
||||||
|
static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
|
||||||
|
{
|
||||||
|
u_char c, *cp;
|
||||||
|
volatile cbd_t *bdp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Get the address of the host memory buffer.
|
||||||
|
*/
|
||||||
|
bdp = pinfo->rx_cur;
|
||||||
|
while (bdp->cbd_sc & BD_SC_EMPTY)
|
||||||
|
;
|
||||||
|
|
||||||
|
/* If the buffer address is in the CPM DPRAM, don't
|
||||||
|
* convert it.
|
||||||
|
*/
|
||||||
|
cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||||
|
|
||||||
|
if (obuf) {
|
||||||
|
i = c = bdp->cbd_datlen;
|
||||||
|
while (i-- > 0)
|
||||||
|
*obuf++ = *cp++;
|
||||||
|
} else
|
||||||
|
c = *cp;
|
||||||
|
bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
|
||||||
|
bdp->cbd_sc |= BD_SC_EMPTY;
|
||||||
|
|
||||||
|
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||||
|
bdp = pinfo->rx_bd_base;
|
||||||
|
else
|
||||||
|
bdp++;
|
||||||
|
pinfo->rx_cur = (cbd_t *)bdp;
|
||||||
|
|
||||||
|
return (int)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm_get_poll_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||||
|
|
||||||
|
if (!serial_polled) {
|
||||||
|
serial_polled = 1;
|
||||||
|
poll_chars = 0;
|
||||||
|
}
|
||||||
|
if (poll_chars <= 0) {
|
||||||
|
poll_chars = poll_wait_key(poll_buf, pinfo);
|
||||||
|
pollp = poll_buf;
|
||||||
|
}
|
||||||
|
poll_chars--;
|
||||||
|
return *pollp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm_put_poll_char(struct uart_port *port,
|
||||||
|
unsigned char c)
|
||||||
|
{
|
||||||
|
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||||
|
static char ch[2];
|
||||||
|
|
||||||
|
ch[0] = (char)c;
|
||||||
|
cpm_uart_early_write(pinfo->port.line, ch, 1);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CONSOLE_POLL */
|
||||||
|
|
||||||
static struct uart_ops cpm_uart_pops = {
|
static struct uart_ops cpm_uart_pops = {
|
||||||
.tx_empty = cpm_uart_tx_empty,
|
.tx_empty = cpm_uart_tx_empty,
|
||||||
.set_mctrl = cpm_uart_set_mctrl,
|
.set_mctrl = cpm_uart_set_mctrl,
|
||||||
@ -882,6 +971,10 @@ static struct uart_ops cpm_uart_pops = {
|
|||||||
.request_port = cpm_uart_request_port,
|
.request_port = cpm_uart_request_port,
|
||||||
.config_port = cpm_uart_config_port,
|
.config_port = cpm_uart_config_port,
|
||||||
.verify_port = cpm_uart_verify_port,
|
.verify_port = cpm_uart_verify_port,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_get_char = cpm_get_poll_char,
|
||||||
|
.poll_put_char = cpm_put_poll_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uart_cpm_port cpm_uart_ports[UART_NR];
|
struct uart_cpm_port cpm_uart_ports[UART_NR];
|
||||||
|
@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static int serial_polled;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
|
|||||||
while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
|
while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
|
||||||
& SDMA_DESC_CMDSTAT_O)) {
|
& SDMA_DESC_CMDSTAT_O)) {
|
||||||
bytes_in = be16_to_cpu(rxre->bytecnt);
|
bytes_in = be16_to_cpu(rxre->bytecnt);
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
if (unlikely(serial_polled)) {
|
||||||
|
serial_polled = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Following use of tty struct directly is deprecated */
|
/* Following use of tty struct directly is deprecated */
|
||||||
if (unlikely(tty_buffer_request_room(tty, bytes_in)
|
if (unlikely(tty_buffer_request_room(tty, bytes_in)
|
||||||
< bytes_in)) {
|
< bytes_in)) {
|
||||||
@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
|
|||||||
if (uart_handle_sysrq_char(&pi->port, *bp)) {
|
if (uart_handle_sysrq_char(&pi->port, *bp)) {
|
||||||
bp++;
|
bp++;
|
||||||
bytes_in--;
|
bytes_in--;
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
if (unlikely(serial_polled)) {
|
||||||
|
serial_polled = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
goto next_frame;
|
goto next_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
/* Serial polling routines for writing and reading from the uart while
|
||||||
|
* in an interrupt or debug context.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char poll_buf[2048];
|
||||||
|
static int poll_ptr;
|
||||||
|
static int poll_cnt;
|
||||||
|
static void mpsc_put_poll_char(struct uart_port *port,
|
||||||
|
unsigned char c);
|
||||||
|
|
||||||
|
static int mpsc_get_poll_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
|
||||||
|
struct mpsc_rx_desc *rxre;
|
||||||
|
u32 cmdstat, bytes_in, i;
|
||||||
|
u8 *bp;
|
||||||
|
|
||||||
|
if (!serial_polled)
|
||||||
|
serial_polled = 1;
|
||||||
|
|
||||||
|
pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
|
||||||
|
|
||||||
|
if (poll_cnt) {
|
||||||
|
poll_cnt--;
|
||||||
|
return poll_buf[poll_ptr++];
|
||||||
|
}
|
||||||
|
poll_ptr = 0;
|
||||||
|
poll_cnt = 0;
|
||||||
|
|
||||||
|
while (poll_cnt == 0) {
|
||||||
|
rxre = (struct mpsc_rx_desc *)(pi->rxr +
|
||||||
|
(pi->rxr_posn*MPSC_RXRE_SIZE));
|
||||||
|
dma_cache_sync(pi->port.dev, (void *)rxre,
|
||||||
|
MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
|
||||||
|
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
|
||||||
|
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
|
||||||
|
invalidate_dcache_range((ulong)rxre,
|
||||||
|
(ulong)rxre + MPSC_RXRE_SIZE);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Loop through Rx descriptors handling ones that have
|
||||||
|
* been completed.
|
||||||
|
*/
|
||||||
|
while (poll_cnt == 0 &&
|
||||||
|
!((cmdstat = be32_to_cpu(rxre->cmdstat)) &
|
||||||
|
SDMA_DESC_CMDSTAT_O)){
|
||||||
|
bytes_in = be16_to_cpu(rxre->bytecnt);
|
||||||
|
bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
|
||||||
|
dma_cache_sync(pi->port.dev, (void *) bp,
|
||||||
|
MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
|
||||||
|
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
|
||||||
|
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
|
||||||
|
invalidate_dcache_range((ulong)bp,
|
||||||
|
(ulong)bp + MPSC_RXBE_SIZE);
|
||||||
|
#endif
|
||||||
|
if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
|
||||||
|
SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
|
||||||
|
!(cmdstat & pi->port.ignore_status_mask)) {
|
||||||
|
poll_buf[poll_cnt] = *bp;
|
||||||
|
poll_cnt++;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < bytes_in; i++) {
|
||||||
|
poll_buf[poll_cnt] = *bp++;
|
||||||
|
poll_cnt++;
|
||||||
|
}
|
||||||
|
pi->port.icount.rx += bytes_in;
|
||||||
|
}
|
||||||
|
rxre->bytecnt = cpu_to_be16(0);
|
||||||
|
wmb();
|
||||||
|
rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
|
||||||
|
SDMA_DESC_CMDSTAT_EI |
|
||||||
|
SDMA_DESC_CMDSTAT_F |
|
||||||
|
SDMA_DESC_CMDSTAT_L);
|
||||||
|
wmb();
|
||||||
|
dma_cache_sync(pi->port.dev, (void *)rxre,
|
||||||
|
MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
|
||||||
|
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
|
||||||
|
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
|
||||||
|
flush_dcache_range((ulong)rxre,
|
||||||
|
(ulong)rxre + MPSC_RXRE_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Advance to next descriptor */
|
||||||
|
pi->rxr_posn = (pi->rxr_posn + 1) &
|
||||||
|
(MPSC_RXR_ENTRIES - 1);
|
||||||
|
rxre = (struct mpsc_rx_desc *)(pi->rxr +
|
||||||
|
(pi->rxr_posn * MPSC_RXRE_SIZE));
|
||||||
|
dma_cache_sync(pi->port.dev, (void *)rxre,
|
||||||
|
MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
|
||||||
|
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
|
||||||
|
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
|
||||||
|
invalidate_dcache_range((ulong)rxre,
|
||||||
|
(ulong)rxre + MPSC_RXRE_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart rx engine, if its stopped */
|
||||||
|
if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
|
||||||
|
mpsc_start_rx(pi);
|
||||||
|
}
|
||||||
|
if (poll_cnt) {
|
||||||
|
poll_cnt--;
|
||||||
|
return poll_buf[poll_ptr++];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void mpsc_put_poll_char(struct uart_port *port,
|
||||||
|
unsigned char c)
|
||||||
|
{
|
||||||
|
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
data = readl(pi->mpsc_base + MPSC_MPCR);
|
||||||
|
writeb(c, pi->mpsc_base + MPSC_CHR_1);
|
||||||
|
mb();
|
||||||
|
data = readl(pi->mpsc_base + MPSC_CHR_2);
|
||||||
|
data |= MPSC_CHR_2_TTCS;
|
||||||
|
writel(data, pi->mpsc_base + MPSC_CHR_2);
|
||||||
|
mb();
|
||||||
|
|
||||||
|
while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct uart_ops mpsc_pops = {
|
static struct uart_ops mpsc_pops = {
|
||||||
.tx_empty = mpsc_tx_empty,
|
.tx_empty = mpsc_tx_empty,
|
||||||
@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = {
|
|||||||
.request_port = mpsc_request_port,
|
.request_port = mpsc_request_port,
|
||||||
.config_port = mpsc_config_port,
|
.config_port = mpsc_config_port,
|
||||||
.verify_port = mpsc_verify_port,
|
.verify_port = mpsc_verify_port,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_get_char = mpsc_get_poll_char,
|
||||||
|
.poll_put_char = mpsc_put_poll_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
104
include/asm-arm/kgdb.h
Normal file
104
include/asm-arm/kgdb.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* ARM KGDB support
|
||||||
|
*
|
||||||
|
* Author: Deepak Saxena <dsaxena@mvista.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 MontaVista Software Inc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARM_KGDB_H__
|
||||||
|
#define __ARM_KGDB_H__
|
||||||
|
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDB assumes that we're a user process being debugged, so
|
||||||
|
* it will send us an SWI command to write into memory as the
|
||||||
|
* debug trap. When an SWI occurs, the next instruction addr is
|
||||||
|
* placed into R14_svc before jumping to the vector trap.
|
||||||
|
* This doesn't work for kernel debugging as we are already in SVC
|
||||||
|
* we would loose the kernel's LR, which is a bad thing. This
|
||||||
|
* is bad thing.
|
||||||
|
*
|
||||||
|
* By doing this as an undefined instruction trap, we force a mode
|
||||||
|
* switch from SVC to UND mode, allowing us to save full kernel state.
|
||||||
|
*
|
||||||
|
* We also define a KGDB_COMPILED_BREAK which can be used to compile
|
||||||
|
* in breakpoints. This is important for things like sysrq-G and for
|
||||||
|
* the initial breakpoint from trap_init().
|
||||||
|
*
|
||||||
|
* Note to ARM HW designers: Add real trap support like SH && PPC to
|
||||||
|
* make our lives much much simpler. :)
|
||||||
|
*/
|
||||||
|
#define BREAK_INSTR_SIZE 4
|
||||||
|
#define GDB_BREAKINST 0xef9f0001
|
||||||
|
#define KGDB_BREAKINST 0xe7ffdefe
|
||||||
|
#define KGDB_COMPILED_BREAK 0xe7ffdeff
|
||||||
|
#define CACHE_FLUSH_IS_SAFE 1
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
static inline void arch_kgdb_breakpoint(void)
|
||||||
|
{
|
||||||
|
asm(".word 0xe7ffdeff");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void kgdb_handle_bus_error(void);
|
||||||
|
extern int kgdb_fault_expected;
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From Kevin Hilman:
|
||||||
|
*
|
||||||
|
* gdb is expecting the following registers layout.
|
||||||
|
*
|
||||||
|
* r0-r15: 1 long word each
|
||||||
|
* f0-f7: unused, 3 long words each !!
|
||||||
|
* fps: unused, 1 long word
|
||||||
|
* cpsr: 1 long word
|
||||||
|
*
|
||||||
|
* Even though f0-f7 and fps are not used, they need to be
|
||||||
|
* present in the registers sent for correct processing in
|
||||||
|
* the host-side gdb.
|
||||||
|
*
|
||||||
|
* In particular, it is crucial that CPSR is in the right place,
|
||||||
|
* otherwise gdb will not be able to correctly interpret stepping over
|
||||||
|
* conditional branches.
|
||||||
|
*/
|
||||||
|
#define _GP_REGS 16
|
||||||
|
#define _FP_REGS 8
|
||||||
|
#define _EXTRA_REGS 2
|
||||||
|
#define GDB_MAX_REGS (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
|
||||||
|
|
||||||
|
#define KGDB_MAX_NO_CPUS 1
|
||||||
|
#define BUFMAX 400
|
||||||
|
#define NUMREGBYTES (GDB_MAX_REGS << 2)
|
||||||
|
#define NUMCRITREGBYTES (32 << 2)
|
||||||
|
|
||||||
|
#define _R0 0
|
||||||
|
#define _R1 1
|
||||||
|
#define _R2 2
|
||||||
|
#define _R3 3
|
||||||
|
#define _R4 4
|
||||||
|
#define _R5 5
|
||||||
|
#define _R6 6
|
||||||
|
#define _R7 7
|
||||||
|
#define _R8 8
|
||||||
|
#define _R9 9
|
||||||
|
#define _R10 10
|
||||||
|
#define _FP 11
|
||||||
|
#define _IP 12
|
||||||
|
#define _SPT 13
|
||||||
|
#define _LR 14
|
||||||
|
#define _PC 15
|
||||||
|
#define _CPSR (GDB_MAX_REGS - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* So that we can denote the end of a frame for tracing,
|
||||||
|
* in the simple case:
|
||||||
|
*/
|
||||||
|
#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC, _SPT, func)
|
||||||
|
|
||||||
|
#endif /* __ASM_KGDB_H__ */
|
@ -24,4 +24,6 @@ static inline int in_exception_text(unsigned long ptr)
|
|||||||
ptr < (unsigned long)&__exception_text_end;
|
ptr < (unsigned long)&__exception_text_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void __init early_trap_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,57 +1,65 @@
|
|||||||
/*
|
/*
|
||||||
* kgdb.h: Defines and declarations for serial line source level
|
* include/asm-powerpc/kgdb.h
|
||||||
* remote debugging of the Linux kernel using gdb.
|
|
||||||
*
|
*
|
||||||
|
* The PowerPC (32/64) specific defines / externs for KGDB. Based on
|
||||||
|
* the previous 32bit and 64bit specific files, which had the following
|
||||||
|
* copyrights:
|
||||||
|
*
|
||||||
|
* PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
|
||||||
|
* PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
|
||||||
|
* PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
|
||||||
* PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
|
* PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||||
|
* Author: Tom Rini <trini@kernel.crashing.org>
|
||||||
|
*
|
||||||
|
* 2006 (c) MontaVista Software, Inc. This file is licensed under
|
||||||
|
* the terms of the GNU General Public License version 2. This program
|
||||||
|
* is licensed "as is" without any warranty of any kind, whether express
|
||||||
|
* or implied.
|
||||||
*/
|
*/
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#ifndef _PPC_KGDB_H
|
#ifndef __POWERPC_KGDB_H__
|
||||||
#define _PPC_KGDB_H
|
#define __POWERPC_KGDB_H__
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
/* Things specific to the gen550 backend. */
|
#define BREAK_INSTR_SIZE 4
|
||||||
struct uart_port;
|
#define BUFMAX ((NUMREGBYTES * 2) + 512)
|
||||||
|
#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
|
||||||
extern void gen550_progress(char *, unsigned short);
|
static inline void arch_kgdb_breakpoint(void)
|
||||||
extern void gen550_kgdb_map_scc(void);
|
{
|
||||||
extern void gen550_init(int, struct uart_port *);
|
asm(".long 0x7d821008"); /* twge r2, r2 */
|
||||||
|
}
|
||||||
/* Things specific to the pmac backend. */
|
#define CACHE_FLUSH_IS_SAFE 1
|
||||||
extern void zs_kgdb_hook(int tty_num);
|
|
||||||
|
|
||||||
/* To init the kgdb engine. (called by serial hook)*/
|
|
||||||
extern void set_debug_traps(void);
|
|
||||||
|
|
||||||
/* To enter the debugger explicitly. */
|
|
||||||
extern void breakpoint(void);
|
|
||||||
|
|
||||||
/* For taking exceptions
|
|
||||||
* these are defined in traps.c
|
|
||||||
*/
|
|
||||||
extern int (*debugger)(struct pt_regs *regs);
|
|
||||||
extern int (*debugger_bpt)(struct pt_regs *regs);
|
|
||||||
extern int (*debugger_sstep)(struct pt_regs *regs);
|
|
||||||
extern int (*debugger_iabr_match)(struct pt_regs *regs);
|
|
||||||
extern int (*debugger_dabr_match)(struct pt_regs *regs);
|
|
||||||
extern void (*debugger_fault_handler)(struct pt_regs *regs);
|
|
||||||
|
|
||||||
/* What we bring to the party */
|
|
||||||
int kgdb_bpt(struct pt_regs *regs);
|
|
||||||
int kgdb_sstep(struct pt_regs *regs);
|
|
||||||
void kgdb(struct pt_regs *regs);
|
|
||||||
int kgdb_iabr_match(struct pt_regs *regs);
|
|
||||||
int kgdb_dabr_match(struct pt_regs *regs);
|
|
||||||
|
|
||||||
|
/* The number bytes of registers we have to save depends on a few
|
||||||
|
* things. For 64bit we default to not including vector registers and
|
||||||
|
* vector state registers. */
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
/*
|
/*
|
||||||
* external low-level support routines (ie macserial.c)
|
* 64 bit (8 byte) registers:
|
||||||
|
* 32 gpr, 32 fpr, nip, msr, link, ctr
|
||||||
|
* 32 bit (4 byte) registers:
|
||||||
|
* ccr, xer, fpscr
|
||||||
*/
|
*/
|
||||||
extern void kgdb_interruptible(int); /* control interrupts from serial */
|
#define NUMREGBYTES ((68 * 8) + (3 * 4))
|
||||||
extern void putDebugChar(char); /* write a single character */
|
#define NUMCRITREGBYTES 184
|
||||||
extern char getDebugChar(void); /* read and return a single char */
|
#else /* CONFIG_PPC32 */
|
||||||
|
/* On non-E500 family PPC32 we determine the size by picking the last
|
||||||
|
* register we need, but on E500 we skip sections so we list what we
|
||||||
|
* need to store, and add it up. */
|
||||||
|
#ifndef CONFIG_E500
|
||||||
|
#define MAXREG (PT_FPSCR+1)
|
||||||
|
#else
|
||||||
|
/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
|
||||||
|
#define MAXREG ((32*2)+6+2+1)
|
||||||
|
#endif
|
||||||
|
#define NUMREGBYTES (MAXREG * sizeof(int))
|
||||||
|
/* CR/LR, R1, R2, R13-R31 inclusive. */
|
||||||
|
#define NUMCRITREGBYTES (23 * sizeof(int))
|
||||||
|
#endif /* 32/64 */
|
||||||
#endif /* !(__ASSEMBLY__) */
|
#endif /* !(__ASSEMBLY__) */
|
||||||
#endif /* !(_PPC_KGDB_H) */
|
#endif /* !__POWERPC_KGDB_H__ */
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
|
|
||||||
config HAVE_ARCH_KGDB_SHADOW_INFO
|
|
||||||
bool
|
|
||||||
|
|
||||||
config HAVE_ARCH_KGDB
|
config HAVE_ARCH_KGDB
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user