powerpc: Merge xmon
The merged version follows the ppc64 version pretty closely mostly, and in fact ARCH=ppc64 now uses the arch/powerpc/xmon version. The main difference for ppc64 is that the 'p' command to call show_state (which was always pretty dodgy) has been replaced by the ppc32 'p' command, which calls a given procedure (so in fact the old 'p' command behaviour can be achieved with 'p $show_state'). Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Родитель
c032524f0d
Коммит
f78541dcec
|
@ -131,7 +131,7 @@ core-y += arch/powerpc/kernel/ \
|
|||
arch/powerpc/sysdev/ \
|
||||
arch/powerpc/platforms/
|
||||
core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
|
||||
#core-$(CONFIG_XMON) += arch/powerpc/xmon/
|
||||
core-$(CONFIG_XMON) += arch/powerpc/xmon/
|
||||
core-$(CONFIG_APUS) += arch/ppc/amiga/
|
||||
drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
|
||||
drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
|
||||
|
|
|
@ -271,6 +271,9 @@ __secondary_hold_acknowledge:
|
|||
li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
|
||||
MTMSRD(r10); /* (except for mach check in rtas) */ \
|
||||
stw r0,GPR0(r11); \
|
||||
lis r10,0x7265; /* put exception frame marker */ \
|
||||
addi r10,r10,0x6773; \
|
||||
stw r10,8(r11); \
|
||||
SAVE_4GPRS(3, r11); \
|
||||
SAVE_2GPRS(7, r11)
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <asm/cputable.h>
|
||||
#include <asm/btext.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/xmon.h>
|
||||
|
||||
#ifdef CONFIG_8xx
|
||||
#include <asm/commproc.h>
|
||||
|
@ -238,10 +237,6 @@ EXPORT_SYMBOL(console_drivers);
|
|||
EXPORT_SYMBOL(cacheable_memcpy);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XMON
|
||||
EXPORT_SYMBOL(xmon);
|
||||
EXPORT_SYMBOL(xmon_printf);
|
||||
#endif
|
||||
EXPORT_SYMBOL(__up);
|
||||
EXPORT_SYMBOL(__down);
|
||||
EXPORT_SYMBOL(__down_interruptible);
|
||||
|
|
|
@ -302,8 +302,10 @@ void __init setup_arch(char **cmdline_p)
|
|||
|
||||
#ifdef CONFIG_XMON
|
||||
xmon_map_scc();
|
||||
if (strstr(cmd_line, "xmon"))
|
||||
xmon(NULL);
|
||||
if (strstr(cmd_line, "xmon")) {
|
||||
xmon_init(1);
|
||||
debugger(NULL);
|
||||
}
|
||||
#endif /* CONFIG_XMON */
|
||||
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include <asm/iSeries/ItLpNaca.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/systemcfg.h>
|
||||
#include <asm/xmon.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
|
|
|
@ -11,6 +11,8 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
|
|||
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
|
||||
memcpy_64.o usercopy_64.o mem_64.o
|
||||
obj-$(CONFIG_PPC_ISERIES) += e2a.o
|
||||
obj-$(CONFIG_XMON) += sstep.o
|
||||
|
||||
ifeq ($(CONFIG_PPC64),y)
|
||||
obj-$(CONFIG_SMP) += locks.o
|
||||
obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# Makefile for xmon
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
EXTRA_CFLAGS += -mno-minimal-toc
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_8xx) += start_8xx.o
|
||||
obj-$(CONFIG_6xx) += start_32.o
|
||||
obj-$(CONFIG_4xx) += start_32.o
|
||||
obj-$(CONFIG_PPC64) += start_64.o
|
||||
obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* NOTE: assert(sizeof(buf) > 23 * sizeof(long))
|
||||
*/
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
_GLOBAL(xmon_setjmp)
|
||||
mflr r0
|
||||
STL r0,0(r3)
|
||||
STL r1,SZL(r3)
|
||||
STL r2,2*SZL(r3)
|
||||
mfcr r0
|
||||
STL r0,3*SZL(r3)
|
||||
STL r13,4*SZL(r3)
|
||||
STL r14,5*SZL(r3)
|
||||
STL r15,6*SZL(r3)
|
||||
STL r16,7*SZL(r3)
|
||||
STL r17,8*SZL(r3)
|
||||
STL r18,9*SZL(r3)
|
||||
STL r19,10*SZL(r3)
|
||||
STL r20,11*SZL(r3)
|
||||
STL r21,12*SZL(r3)
|
||||
STL r22,13*SZL(r3)
|
||||
STL r23,14*SZL(r3)
|
||||
STL r24,15*SZL(r3)
|
||||
STL r25,16*SZL(r3)
|
||||
STL r26,17*SZL(r3)
|
||||
STL r27,18*SZL(r3)
|
||||
STL r28,19*SZL(r3)
|
||||
STL r29,20*SZL(r3)
|
||||
STL r30,21*SZL(r3)
|
||||
STL r31,22*SZL(r3)
|
||||
li r3,0
|
||||
blr
|
||||
|
||||
_GLOBAL(xmon_longjmp)
|
||||
CMPI r4,0
|
||||
bne 1f
|
||||
li r4,1
|
||||
1: LDL r13,4*SZL(r3)
|
||||
LDL r14,5*SZL(r3)
|
||||
LDL r15,6*SZL(r3)
|
||||
LDL r16,7*SZL(r3)
|
||||
LDL r17,8*SZL(r3)
|
||||
LDL r18,9*SZL(r3)
|
||||
LDL r19,10*SZL(r3)
|
||||
LDL r20,11*SZL(r3)
|
||||
LDL r21,12*SZL(r3)
|
||||
LDL r22,13*SZL(r3)
|
||||
LDL r23,14*SZL(r3)
|
||||
LDL r24,15*SZL(r3)
|
||||
LDL r25,16*SZL(r3)
|
||||
LDL r26,17*SZL(r3)
|
||||
LDL r27,18*SZL(r3)
|
||||
LDL r28,19*SZL(r3)
|
||||
LDL r29,20*SZL(r3)
|
||||
LDL r30,21*SZL(r3)
|
||||
LDL r31,22*SZL(r3)
|
||||
LDL r0,3*SZL(r3)
|
||||
mtcrf 0x38,r0
|
||||
LDL r0,0(r3)
|
||||
LDL r1,SZL(r3)
|
||||
LDL r2,2*SZL(r3)
|
||||
mtlr r0
|
||||
mr r3,r4
|
||||
blr
|
||||
|
||||
/*
|
||||
* Grab the register values as they are now.
|
||||
* This won't do a particularily good job because we really
|
||||
* want our caller's caller's registers, and our caller has
|
||||
* already executed its prologue.
|
||||
* ToDo: We could reach back into the caller's save area to do
|
||||
* a better job of representing the caller's state (note that
|
||||
* that will be different for 32-bit and 64-bit, because of the
|
||||
* different ABIs, though).
|
||||
*/
|
||||
_GLOBAL(xmon_save_regs)
|
||||
STL r0,0*SZL(r3)
|
||||
STL r2,2*SZL(r3)
|
||||
STL r3,3*SZL(r3)
|
||||
STL r4,4*SZL(r3)
|
||||
STL r5,5*SZL(r3)
|
||||
STL r6,6*SZL(r3)
|
||||
STL r7,7*SZL(r3)
|
||||
STL r8,8*SZL(r3)
|
||||
STL r9,9*SZL(r3)
|
||||
STL r10,10*SZL(r3)
|
||||
STL r11,11*SZL(r3)
|
||||
STL r12,12*SZL(r3)
|
||||
STL r13,13*SZL(r3)
|
||||
STL r14,14*SZL(r3)
|
||||
STL r15,15*SZL(r3)
|
||||
STL r16,16*SZL(r3)
|
||||
STL r17,17*SZL(r3)
|
||||
STL r18,18*SZL(r3)
|
||||
STL r19,19*SZL(r3)
|
||||
STL r20,20*SZL(r3)
|
||||
STL r21,21*SZL(r3)
|
||||
STL r22,22*SZL(r3)
|
||||
STL r23,23*SZL(r3)
|
||||
STL r24,24*SZL(r3)
|
||||
STL r25,25*SZL(r3)
|
||||
STL r26,26*SZL(r3)
|
||||
STL r27,27*SZL(r3)
|
||||
STL r28,28*SZL(r3)
|
||||
STL r29,29*SZL(r3)
|
||||
STL r30,30*SZL(r3)
|
||||
STL r31,31*SZL(r3)
|
||||
/* go up one stack frame for SP */
|
||||
LDL r4,0(r1)
|
||||
STL r4,1*SZL(r3)
|
||||
/* get caller's LR */
|
||||
LDL r0,LRSAVE(r4)
|
||||
STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
|
||||
STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
|
||||
mfmsr r0
|
||||
STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
|
||||
mfctr r0
|
||||
STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
|
||||
mfxer r0
|
||||
STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
|
||||
mfcr r0
|
||||
STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
|
||||
li r0,0
|
||||
STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
|
||||
blr
|
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <linux/adb.h>
|
||||
#include <linux/pmu.h>
|
||||
#include <linux/cuda.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/xmon.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/bootx.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/btext.h>
|
||||
|
||||
static volatile unsigned char __iomem *sccc, *sccd;
|
||||
unsigned int TXRDY, RXRDY, DLAB;
|
||||
static int xmon_expect(const char *str, unsigned int timeout);
|
||||
|
||||
static int use_serial;
|
||||
static int use_screen;
|
||||
static int via_modem;
|
||||
static int xmon_use_sccb;
|
||||
static struct device_node *channel_node;
|
||||
|
||||
#define TB_SPEED 25000000
|
||||
|
||||
static inline unsigned int readtb(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
asm volatile("mftb %0" : "=r" (ret) :);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void buf_access(void)
|
||||
{
|
||||
if (DLAB)
|
||||
sccd[3] &= ~DLAB; /* reset DLAB */
|
||||
}
|
||||
|
||||
extern int adb_init(void);
|
||||
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
/*
|
||||
* This looks in the "ranges" property for the primary PCI host bridge
|
||||
* to find the physical address of the start of PCI/ISA I/O space.
|
||||
* It is basically a cut-down version of pci_process_bridge_OF_ranges.
|
||||
*/
|
||||
static unsigned long chrp_find_phys_io_base(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
unsigned int *ranges;
|
||||
unsigned long base = CHRP_ISA_IO_BASE;
|
||||
int rlen = 0;
|
||||
int np;
|
||||
|
||||
node = find_devices("isa");
|
||||
if (node != NULL) {
|
||||
node = node->parent;
|
||||
if (node == NULL || node->type == NULL
|
||||
|| strcmp(node->type, "pci") != 0)
|
||||
node = NULL;
|
||||
}
|
||||
if (node == NULL)
|
||||
node = find_devices("pci");
|
||||
if (node == NULL)
|
||||
return base;
|
||||
|
||||
ranges = (unsigned int *) get_property(node, "ranges", &rlen);
|
||||
np = prom_n_addr_cells(node) + 5;
|
||||
while ((rlen -= np * sizeof(unsigned int)) >= 0) {
|
||||
if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
|
||||
/* I/O space starting at 0, grab the phys base */
|
||||
base = ranges[np - 3];
|
||||
break;
|
||||
}
|
||||
ranges += np;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
#endif /* CONFIG_PPC_CHRP */
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static void sysrq_handle_xmon(int key, struct pt_regs *regs,
|
||||
struct tty_struct *tty)
|
||||
{
|
||||
xmon(regs);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_xmon_op =
|
||||
{
|
||||
.handler = sysrq_handle_xmon,
|
||||
.help_msg = "Xmon",
|
||||
.action_msg = "Entering xmon",
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
xmon_map_scc(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
volatile unsigned char __iomem *base;
|
||||
|
||||
if (_machine == _MACH_Pmac) {
|
||||
struct device_node *np;
|
||||
unsigned long addr;
|
||||
#ifdef CONFIG_BOOTX_TEXT
|
||||
if (!use_screen && !use_serial
|
||||
&& !machine_is_compatible("iMac")) {
|
||||
/* see if there is a keyboard in the device tree
|
||||
with a parent of type "adb" */
|
||||
for (np = find_devices("keyboard"); np; np = np->next)
|
||||
if (np->parent && np->parent->type
|
||||
&& strcmp(np->parent->type, "adb") == 0)
|
||||
break;
|
||||
|
||||
/* needs to be hacked if xmon_printk is to be used
|
||||
from within find_via_pmu() */
|
||||
#ifdef CONFIG_ADB_PMU
|
||||
if (np != NULL && boot_text_mapped && find_via_pmu())
|
||||
use_screen = 1;
|
||||
#endif
|
||||
#ifdef CONFIG_ADB_CUDA
|
||||
if (np != NULL && boot_text_mapped && find_via_cuda())
|
||||
use_screen = 1;
|
||||
#endif
|
||||
}
|
||||
if (!use_screen && (np = find_devices("escc")) != NULL) {
|
||||
/*
|
||||
* look for the device node for the serial port
|
||||
* we're using and see if it says it has a modem
|
||||
*/
|
||||
char *name = xmon_use_sccb? "ch-b": "ch-a";
|
||||
char *slots;
|
||||
int l;
|
||||
|
||||
np = np->child;
|
||||
while (np != NULL && strcmp(np->name, name) != 0)
|
||||
np = np->sibling;
|
||||
if (np != NULL) {
|
||||
/* XXX should parse this properly */
|
||||
channel_node = np;
|
||||
slots = get_property(np, "slot-names", &l);
|
||||
if (slots != NULL && l >= 10
|
||||
&& strcmp(slots+4, "Modem") == 0)
|
||||
via_modem = 1;
|
||||
}
|
||||
}
|
||||
btext_drawstring("xmon uses ");
|
||||
if (use_screen)
|
||||
btext_drawstring("screen and keyboard\n");
|
||||
else {
|
||||
if (via_modem)
|
||||
btext_drawstring("modem on ");
|
||||
btext_drawstring(xmon_use_sccb? "printer": "modem");
|
||||
btext_drawstring(" port\n");
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOOTX_TEXT */
|
||||
|
||||
#ifdef CHRP_ESCC
|
||||
addr = 0xc1013020;
|
||||
#else
|
||||
addr = 0xf3013020;
|
||||
#endif
|
||||
TXRDY = 4;
|
||||
RXRDY = 1;
|
||||
|
||||
np = find_devices("mac-io");
|
||||
if (np && np->n_addrs)
|
||||
addr = np->addrs[0].address + 0x13020;
|
||||
base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
|
||||
sccc = base + (addr & ~PAGE_MASK);
|
||||
sccd = sccc + 0x10;
|
||||
|
||||
} else {
|
||||
base = (volatile unsigned char *) isa_io_base;
|
||||
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
if (_machine == _MACH_chrp)
|
||||
base = (volatile unsigned char __iomem *)
|
||||
ioremap(chrp_find_phys_io_base(), 0x1000);
|
||||
#endif
|
||||
|
||||
sccc = base + 0x3fd;
|
||||
sccd = base + 0x3f8;
|
||||
if (xmon_use_sccb) {
|
||||
sccc -= 0x100;
|
||||
sccd -= 0x100;
|
||||
}
|
||||
TXRDY = 0x20;
|
||||
RXRDY = 1;
|
||||
DLAB = 0x80;
|
||||
}
|
||||
#elif defined(CONFIG_GEMINI)
|
||||
/* should already be mapped by the kernel boot */
|
||||
sccc = (volatile unsigned char __iomem *) 0xffeffb0d;
|
||||
sccd = (volatile unsigned char __iomem *) 0xffeffb08;
|
||||
TXRDY = 0x20;
|
||||
RXRDY = 1;
|
||||
DLAB = 0x80;
|
||||
#elif defined(CONFIG_405GP)
|
||||
sccc = (volatile unsigned char __iomem *)0xef600305;
|
||||
sccd = (volatile unsigned char __iomem *)0xef600300;
|
||||
TXRDY = 0x20;
|
||||
RXRDY = 1;
|
||||
DLAB = 0x80;
|
||||
#endif /* platform */
|
||||
|
||||
register_sysrq_key('x', &sysrq_xmon_op);
|
||||
}
|
||||
|
||||
static int scc_initialized = 0;
|
||||
|
||||
void xmon_init_scc(void);
|
||||
extern void cuda_poll(void);
|
||||
|
||||
static inline void do_poll_adb(void)
|
||||
{
|
||||
#ifdef CONFIG_ADB_PMU
|
||||
if (sys_ctrler == SYS_CTRLER_PMU)
|
||||
pmu_poll_adb();
|
||||
#endif /* CONFIG_ADB_PMU */
|
||||
#ifdef CONFIG_ADB_CUDA
|
||||
if (sys_ctrler == SYS_CTRLER_CUDA)
|
||||
cuda_poll();
|
||||
#endif /* CONFIG_ADB_CUDA */
|
||||
}
|
||||
|
||||
int
|
||||
xmon_write(void *handle, void *ptr, int nb)
|
||||
{
|
||||
char *p = ptr;
|
||||
int i, c, ct;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static unsigned long xmon_write_lock;
|
||||
int lock_wait = 1000000;
|
||||
int locked;
|
||||
|
||||
while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
|
||||
if (--lock_wait == 0)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTX_TEXT
|
||||
if (use_screen) {
|
||||
/* write it on the screen */
|
||||
for (i = 0; i < nb; ++i)
|
||||
btext_drawchar(*p++);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
if (!scc_initialized)
|
||||
xmon_init_scc();
|
||||
ct = 0;
|
||||
for (i = 0; i < nb; ++i) {
|
||||
while ((*sccc & TXRDY) == 0)
|
||||
do_poll_adb();
|
||||
c = p[i];
|
||||
if (c == '\n' && !ct) {
|
||||
c = '\r';
|
||||
ct = 1;
|
||||
--i;
|
||||
} else {
|
||||
ct = 0;
|
||||
}
|
||||
buf_access();
|
||||
*sccd = c;
|
||||
eieio();
|
||||
}
|
||||
|
||||
out:
|
||||
#ifdef CONFIG_SMP
|
||||
if (!locked)
|
||||
clear_bit(0, &xmon_write_lock);
|
||||
#endif
|
||||
return nb;
|
||||
}
|
||||
|
||||
int xmon_wants_key;
|
||||
int xmon_adb_keycode;
|
||||
|
||||
#ifdef CONFIG_BOOTX_TEXT
|
||||
static int xmon_adb_shiftstate;
|
||||
|
||||
static unsigned char xmon_keytab[128] =
|
||||
"asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
|
||||
"yt123465=97-80]o" /* 0x10 - 0x1f */
|
||||
"u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
|
||||
"\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
|
||||
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
|
||||
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
|
||||
|
||||
static unsigned char xmon_shift_keytab[128] =
|
||||
"ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
|
||||
"YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
|
||||
"U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
|
||||
"\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
|
||||
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
|
||||
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
|
||||
|
||||
static int
|
||||
xmon_get_adb_key(void)
|
||||
{
|
||||
int k, t, on;
|
||||
|
||||
xmon_wants_key = 1;
|
||||
for (;;) {
|
||||
xmon_adb_keycode = -1;
|
||||
t = 0;
|
||||
on = 0;
|
||||
do {
|
||||
if (--t < 0) {
|
||||
on = 1 - on;
|
||||
btext_drawchar(on? 0xdb: 0x20);
|
||||
btext_drawchar('\b');
|
||||
t = 200000;
|
||||
}
|
||||
do_poll_adb();
|
||||
} while (xmon_adb_keycode == -1);
|
||||
k = xmon_adb_keycode;
|
||||
if (on)
|
||||
btext_drawstring(" \b");
|
||||
|
||||
/* test for shift keys */
|
||||
if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
|
||||
xmon_adb_shiftstate = (k & 0x80) == 0;
|
||||
continue;
|
||||
}
|
||||
if (k >= 0x80)
|
||||
continue; /* ignore up transitions */
|
||||
k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
|
||||
if (k != 0)
|
||||
break;
|
||||
}
|
||||
xmon_wants_key = 0;
|
||||
return k;
|
||||
}
|
||||
#endif /* CONFIG_BOOTX_TEXT */
|
||||
|
||||
int
|
||||
xmon_read(void *handle, void *ptr, int nb)
|
||||
{
|
||||
char *p = ptr;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_BOOTX_TEXT
|
||||
if (use_screen) {
|
||||
for (i = 0; i < nb; ++i)
|
||||
*p++ = xmon_get_adb_key();
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
if (!scc_initialized)
|
||||
xmon_init_scc();
|
||||
for (i = 0; i < nb; ++i) {
|
||||
while ((*sccc & RXRDY) == 0)
|
||||
do_poll_adb();
|
||||
buf_access();
|
||||
*p++ = *sccd;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_read_poll(void)
|
||||
{
|
||||
if ((*sccc & RXRDY) == 0) {
|
||||
do_poll_adb();
|
||||
return -1;
|
||||
}
|
||||
buf_access();
|
||||
return *sccd;
|
||||
}
|
||||
|
||||
static unsigned char scc_inittab[] = {
|
||||
13, 0, /* set baud rate divisor */
|
||||
12, 1,
|
||||
14, 1, /* baud rate gen enable, src=rtxc */
|
||||
11, 0x50, /* clocks = br gen */
|
||||
5, 0xea, /* tx 8 bits, assert DTR & RTS */
|
||||
4, 0x46, /* x16 clock, 1 stop */
|
||||
3, 0xc1, /* rx enable, 8 bits */
|
||||
};
|
||||
|
||||
void
|
||||
xmon_init_scc(void)
|
||||
{
|
||||
if ( _machine == _MACH_chrp )
|
||||
{
|
||||
sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
|
||||
sccd[0] = 12; eieio(); /* DLL = 9600 baud */
|
||||
sccd[1] = 0; eieio();
|
||||
sccd[2] = 0; eieio(); /* FCR = 0 */
|
||||
sccd[3] = 3; eieio(); /* LCR = 8N1 */
|
||||
sccd[1] = 0; eieio(); /* IER = 0 */
|
||||
}
|
||||
else if ( _machine == _MACH_Pmac )
|
||||
{
|
||||
int i, x;
|
||||
|
||||
if (channel_node != 0)
|
||||
pmac_call_feature(
|
||||
PMAC_FTR_SCC_ENABLE,
|
||||
channel_node,
|
||||
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
|
||||
printk(KERN_INFO "Serial port locked ON by debugger !\n");
|
||||
if (via_modem && channel_node != 0) {
|
||||
unsigned int t0;
|
||||
|
||||
pmac_call_feature(
|
||||
PMAC_FTR_MODEM_ENABLE,
|
||||
channel_node, 0, 1);
|
||||
printk(KERN_INFO "Modem powered up by debugger !\n");
|
||||
t0 = readtb();
|
||||
while (readtb() - t0 < 3*TB_SPEED)
|
||||
eieio();
|
||||
}
|
||||
/* use the B channel if requested */
|
||||
if (xmon_use_sccb) {
|
||||
sccc = (volatile unsigned char *)
|
||||
((unsigned long)sccc & ~0x20);
|
||||
sccd = sccc + 0x10;
|
||||
}
|
||||
for (i = 20000; i != 0; --i) {
|
||||
x = *sccc; eieio();
|
||||
}
|
||||
*sccc = 9; eieio(); /* reset A or B side */
|
||||
*sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
|
||||
for (i = 0; i < sizeof(scc_inittab); ++i) {
|
||||
*sccc = scc_inittab[i];
|
||||
eieio();
|
||||
}
|
||||
}
|
||||
scc_initialized = 1;
|
||||
if (via_modem) {
|
||||
for (;;) {
|
||||
xmon_write(NULL, "ATE1V1\r", 7);
|
||||
if (xmon_expect("OK", 5)) {
|
||||
xmon_write(NULL, "ATA\r", 4);
|
||||
if (xmon_expect("CONNECT", 40))
|
||||
break;
|
||||
}
|
||||
xmon_write(NULL, "+++", 3);
|
||||
xmon_expect("OK", 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *xmon_stdin;
|
||||
void *xmon_stdout;
|
||||
void *xmon_stderr;
|
||||
|
||||
int xmon_putc(int c, void *f)
|
||||
{
|
||||
char ch = c;
|
||||
|
||||
if (c == '\n')
|
||||
xmon_putc('\r', f);
|
||||
return xmon_write(f, &ch, 1) == 1? c: -1;
|
||||
}
|
||||
|
||||
int xmon_putchar(int c)
|
||||
{
|
||||
return xmon_putc(c, xmon_stdout);
|
||||
}
|
||||
|
||||
int xmon_fputs(char *str, void *f)
|
||||
{
|
||||
int n = strlen(str);
|
||||
|
||||
return xmon_write(f, str, n) == n? 0: -1;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_readchar(void)
|
||||
{
|
||||
char ch;
|
||||
|
||||
for (;;) {
|
||||
switch (xmon_read(xmon_stdin, &ch, 1)) {
|
||||
case 1:
|
||||
return ch;
|
||||
case -1:
|
||||
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char line[256];
|
||||
static char *lineptr;
|
||||
static int lineleft;
|
||||
|
||||
int xmon_expect(const char *str, unsigned int timeout)
|
||||
{
|
||||
int c;
|
||||
unsigned int t0;
|
||||
|
||||
timeout *= TB_SPEED;
|
||||
t0 = readtb();
|
||||
do {
|
||||
lineptr = line;
|
||||
for (;;) {
|
||||
c = xmon_read_poll();
|
||||
if (c == -1) {
|
||||
if (readtb() - t0 > timeout)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
|
||||
*lineptr++ = c;
|
||||
}
|
||||
*lineptr = 0;
|
||||
} while (strstr(line, str) == NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_getchar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (lineleft == 0) {
|
||||
lineptr = line;
|
||||
for (;;) {
|
||||
c = xmon_readchar();
|
||||
if (c == -1 || c == 4)
|
||||
break;
|
||||
if (c == '\r' || c == '\n') {
|
||||
*lineptr++ = '\n';
|
||||
xmon_putchar('\n');
|
||||
break;
|
||||
}
|
||||
switch (c) {
|
||||
case 0177:
|
||||
case '\b':
|
||||
if (lineptr > line) {
|
||||
xmon_putchar('\b');
|
||||
xmon_putchar(' ');
|
||||
xmon_putchar('\b');
|
||||
--lineptr;
|
||||
}
|
||||
break;
|
||||
case 'U' & 0x1F:
|
||||
while (lineptr > line) {
|
||||
xmon_putchar('\b');
|
||||
xmon_putchar(' ');
|
||||
xmon_putchar('\b');
|
||||
--lineptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lineptr >= &line[sizeof(line) - 1])
|
||||
xmon_putchar('\a');
|
||||
else {
|
||||
xmon_putchar(c);
|
||||
*lineptr++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineleft = lineptr - line;
|
||||
lineptr = line;
|
||||
}
|
||||
if (lineleft == 0)
|
||||
return -1;
|
||||
--lineleft;
|
||||
return *lineptr++;
|
||||
}
|
||||
|
||||
char *
|
||||
xmon_fgets(char *str, int nb, void *f)
|
||||
{
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
for (p = str; p < str + nb - 1; ) {
|
||||
c = xmon_getchar();
|
||||
if (c == -1) {
|
||||
if (p == str)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
xmon_enter(void)
|
||||
{
|
||||
#ifdef CONFIG_ADB_PMU
|
||||
if (_machine == _MACH_Pmac) {
|
||||
pmu_suspend();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
xmon_leave(void)
|
||||
{
|
||||
#ifdef CONFIG_ADB_PMU
|
||||
if (_machine == _MACH_Pmac) {
|
||||
pmu_resume();
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
* Copyright (C) 2000 Dan Malek.
|
||||
* Quick hack of Paul's code to make XMON work on 8xx processors. Lots
|
||||
* of assumptions, like the SMC1 is used, it has been initialized by the
|
||||
* loader at some point, and we can just stuff and suck bytes.
|
||||
* We rely upon the 8xx uart driver to support us, as the interface
|
||||
* changes between boot up and operational phases of the kernel.
|
||||
*/
|
||||
#include <linux/string.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/8xx_immap.h>
|
||||
#include <asm/mpc8xx.h>
|
||||
#include <asm/commproc.h>
|
||||
|
||||
extern void xmon_printf(const char *fmt, ...);
|
||||
extern int xmon_8xx_write(char *str, int nb);
|
||||
extern int xmon_8xx_read_poll(void);
|
||||
extern int xmon_8xx_read_char(void);
|
||||
void prom_drawhex(uint);
|
||||
void prom_drawstring(const char *str);
|
||||
|
||||
static int use_screen = 1; /* default */
|
||||
|
||||
#define TB_SPEED 25000000
|
||||
|
||||
static inline unsigned int readtb(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
asm volatile("mftb %0" : "=r" (ret) :);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void buf_access(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
xmon_map_scc(void)
|
||||
{
|
||||
|
||||
cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
|
||||
use_screen = 0;
|
||||
|
||||
prom_drawstring("xmon uses serial port\n");
|
||||
}
|
||||
|
||||
static int scc_initialized = 0;
|
||||
|
||||
void xmon_init_scc(void);
|
||||
|
||||
int
|
||||
xmon_write(void *handle, void *ptr, int nb)
|
||||
{
|
||||
char *p = ptr;
|
||||
int i, c, ct;
|
||||
|
||||
if (!scc_initialized)
|
||||
xmon_init_scc();
|
||||
|
||||
return(xmon_8xx_write(ptr, nb));
|
||||
}
|
||||
|
||||
int xmon_wants_key;
|
||||
|
||||
int
|
||||
xmon_read(void *handle, void *ptr, int nb)
|
||||
{
|
||||
char *p = ptr;
|
||||
int i;
|
||||
|
||||
if (!scc_initialized)
|
||||
xmon_init_scc();
|
||||
|
||||
for (i = 0; i < nb; ++i) {
|
||||
*p++ = xmon_8xx_read_char();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_read_poll(void)
|
||||
{
|
||||
return(xmon_8xx_read_poll());
|
||||
}
|
||||
|
||||
void
|
||||
xmon_init_scc()
|
||||
{
|
||||
scc_initialized = 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern int (*prom_entry)(void *);
|
||||
|
||||
int
|
||||
xmon_exit(void)
|
||||
{
|
||||
struct prom_args {
|
||||
char *service;
|
||||
} args;
|
||||
|
||||
for (;;) {
|
||||
args.service = "exit";
|
||||
(*prom_entry)(&args);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void *xmon_stdin;
|
||||
void *xmon_stdout;
|
||||
void *xmon_stderr;
|
||||
|
||||
void
|
||||
xmon_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
xmon_putc(int c, void *f)
|
||||
{
|
||||
char ch = c;
|
||||
|
||||
if (c == '\n')
|
||||
xmon_putc('\r', f);
|
||||
return xmon_write(f, &ch, 1) == 1? c: -1;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_putchar(int c)
|
||||
{
|
||||
return xmon_putc(c, xmon_stdout);
|
||||
}
|
||||
|
||||
int
|
||||
xmon_fputs(char *str, void *f)
|
||||
{
|
||||
int n = strlen(str);
|
||||
|
||||
return xmon_write(f, str, n) == n? 0: -1;
|
||||
}
|
||||
|
||||
int
|
||||
xmon_readchar(void)
|
||||
{
|
||||
char ch;
|
||||
|
||||
for (;;) {
|
||||
switch (xmon_read(xmon_stdin, &ch, 1)) {
|
||||
case 1:
|
||||
return ch;
|
||||
case -1:
|
||||
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char line[256];
|
||||
static char *lineptr;
|
||||
static int lineleft;
|
||||
|
||||
#if 0
|
||||
int xmon_expect(const char *str, unsigned int timeout)
|
||||
{
|
||||
int c;
|
||||
unsigned int t0;
|
||||
|
||||
timeout *= TB_SPEED;
|
||||
t0 = readtb();
|
||||
do {
|
||||
lineptr = line;
|
||||
for (;;) {
|
||||
c = xmon_read_poll();
|
||||
if (c == -1) {
|
||||
if (readtb() - t0 > timeout)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
|
||||
*lineptr++ = c;
|
||||
}
|
||||
*lineptr = 0;
|
||||
} while (strstr(line, str) == NULL);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
xmon_getchar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (lineleft == 0) {
|
||||
lineptr = line;
|
||||
for (;;) {
|
||||
c = xmon_readchar();
|
||||
if (c == -1 || c == 4)
|
||||
break;
|
||||
if (c == '\r' || c == '\n') {
|
||||
*lineptr++ = '\n';
|
||||
xmon_putchar('\n');
|
||||
break;
|
||||
}
|
||||
switch (c) {
|
||||
case 0177:
|
||||
case '\b':
|
||||
if (lineptr > line) {
|
||||
xmon_putchar('\b');
|
||||
xmon_putchar(' ');
|
||||
xmon_putchar('\b');
|
||||
--lineptr;
|
||||
}
|
||||
break;
|
||||
case 'U' & 0x1F:
|
||||
while (lineptr > line) {
|
||||
xmon_putchar('\b');
|
||||
xmon_putchar(' ');
|
||||
xmon_putchar('\b');
|
||||
--lineptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lineptr >= &line[sizeof(line) - 1])
|
||||
xmon_putchar('\a');
|
||||
else {
|
||||
xmon_putchar(c);
|
||||
*lineptr++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineleft = lineptr - line;
|
||||
lineptr = line;
|
||||
}
|
||||
if (lineleft == 0)
|
||||
return -1;
|
||||
--lineleft;
|
||||
return *lineptr++;
|
||||
}
|
||||
|
||||
char *
|
||||
xmon_fgets(char *str, int nb, void *f)
|
||||
{
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
for (p = str; p < str + nb - 1; ) {
|
||||
c = xmon_getchar();
|
||||
if (c == -1) {
|
||||
if (p == str)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
prom_drawhex(uint val)
|
||||
{
|
||||
unsigned char buf[10];
|
||||
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--)
|
||||
{
|
||||
buf[i] = "0123456789abcdef"[val & 0x0f];
|
||||
val >>= 4;
|
||||
}
|
||||
buf[8] = '\0';
|
||||
xmon_fputs(buf, xmon_stdout);
|
||||
}
|
||||
|
||||
void
|
||||
prom_drawstring(const char *str)
|
||||
{
|
||||
xmon_fputs(str, xmon_stdout);
|
||||
}
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#include <stdarg.h>
|
||||
#include "nonstdio.h"
|
||||
|
||||
extern int xmon_write(void *, void *, int);
|
||||
|
||||
void
|
||||
xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
||||
void xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
||||
{
|
||||
static char xmon_buf[2048];
|
||||
int n;
|
||||
|
@ -33,8 +33,7 @@ xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
|||
xmon_write(f, xmon_buf, n);
|
||||
}
|
||||
|
||||
void
|
||||
xmon_printf(const char *fmt, ...)
|
||||
void xmon_printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
@ -42,9 +41,9 @@ xmon_printf(const char *fmt, ...)
|
|||
xmon_vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
EXPORT_SYMBOL(xmon_printf);
|
||||
|
||||
void
|
||||
xmon_fprintf(void *f, const char *fmt, ...)
|
||||
void xmon_fprintf(void *f, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
@ -17,25 +17,31 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/string.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/xmon.h>
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
#include <asm/backlight.h>
|
||||
#endif
|
||||
#include <asm/processor.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/ppcdebug.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/sstep.h>
|
||||
#include <asm/bug.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/paca.h>
|
||||
#endif
|
||||
|
||||
#include "nonstdio.h"
|
||||
#include "privinst.h"
|
||||
|
||||
#define scanhex xmon_scanhex
|
||||
#define skipbl xmon_skipbl
|
||||
|
@ -58,7 +64,7 @@ static unsigned long ncsum = 4096;
|
|||
static int termch;
|
||||
static char tmpstr[128];
|
||||
|
||||
#define JMP_BUF_LEN (184/sizeof(long))
|
||||
#define JMP_BUF_LEN 23
|
||||
static long bus_error_jmp[JMP_BUF_LEN];
|
||||
static int catch_memory_errors;
|
||||
static long *xmon_fault_jmp[NR_CPUS];
|
||||
|
@ -130,23 +136,36 @@ static void cacheflush(void);
|
|||
static int cpu_cmd(void);
|
||||
static void csum(void);
|
||||
static void bootcmds(void);
|
||||
static void proccall(void);
|
||||
void dump_segments(void);
|
||||
static void symbol_lookup(void);
|
||||
static void xmon_print_symbol(unsigned long address, const char *mid,
|
||||
const char *after);
|
||||
static const char *getvecname(unsigned long vec);
|
||||
|
||||
static void debug_trace(void);
|
||||
|
||||
extern int print_insn_powerpc(unsigned long, unsigned long, int);
|
||||
extern void printf(const char *fmt, ...);
|
||||
extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
|
||||
extern int xmon_putc(int c, void *f);
|
||||
extern int putchar(int ch);
|
||||
|
||||
extern void xmon_enter(void);
|
||||
extern void xmon_leave(void);
|
||||
|
||||
extern int xmon_read_poll(void);
|
||||
extern int setjmp(long *);
|
||||
extern void longjmp(long *, int);
|
||||
extern unsigned long _ASR;
|
||||
extern long setjmp(long *);
|
||||
extern void longjmp(long *, long);
|
||||
extern void xmon_save_regs(struct pt_regs *);
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define REG "%.16lx"
|
||||
#define REGS_PER_LINE 4
|
||||
#define LAST_VOLATILE 13
|
||||
#else
|
||||
#define REG "%.8lx"
|
||||
#define REGS_PER_LINE 8
|
||||
#define LAST_VOLATILE 12
|
||||
#endif
|
||||
|
||||
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
|
||||
|
||||
|
@ -186,47 +205,46 @@ Commands:\n\
|
|||
ml locate a block of memory\n\
|
||||
mz zero a block of memory\n\
|
||||
mi show information about memory allocation\n\
|
||||
p show the task list\n\
|
||||
p call a procedure\n\
|
||||
r print registers\n\
|
||||
s single step\n\
|
||||
S print special registers\n\
|
||||
t print backtrace\n\
|
||||
T Enable/Disable PPCDBG flags\n\
|
||||
x exit monitor and recover\n\
|
||||
X exit monitor and dont recover\n\
|
||||
u dump segment table or SLB\n\
|
||||
? help\n"
|
||||
"\
|
||||
zr reboot\n\
|
||||
X exit monitor and dont recover\n"
|
||||
#ifdef CONFIG_PPC64
|
||||
" u dump segment table or SLB\n"
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_STD_MMU_32
|
||||
" u dump segment registers\n"
|
||||
#endif
|
||||
" ? help\n"
|
||||
" zr reboot\n\
|
||||
zh halt\n"
|
||||
;
|
||||
|
||||
static struct pt_regs *xmon_regs;
|
||||
|
||||
extern inline void sync(void)
|
||||
static inline void sync(void)
|
||||
{
|
||||
asm volatile("sync; isync");
|
||||
}
|
||||
|
||||
/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
|
||||
A PPC stack frame looks like this:
|
||||
static inline void store_inst(void *p)
|
||||
{
|
||||
asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
|
||||
}
|
||||
|
||||
High Address
|
||||
Back Chain
|
||||
FP reg save area
|
||||
GP reg save area
|
||||
Local var space
|
||||
Parameter save area (SP+48)
|
||||
TOC save area (SP+40)
|
||||
link editor doubleword (SP+32)
|
||||
compiler doubleword (SP+24)
|
||||
LR save (SP+16)
|
||||
CR save (SP+8)
|
||||
Back Chain (SP+0)
|
||||
static inline void cflush(void *p)
|
||||
{
|
||||
asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
|
||||
}
|
||||
|
||||
Note that the LR (ret addr) may not be saved in the current frame if
|
||||
no functions have been called from the current function.
|
||||
*/
|
||||
static inline void cinval(void *p)
|
||||
{
|
||||
asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable surveillance (the service processor watchdog function)
|
||||
|
@ -310,8 +328,8 @@ int xmon_core(struct pt_regs *regs, int fromipi)
|
|||
unsigned long timeout;
|
||||
#endif
|
||||
|
||||
msr = get_msr();
|
||||
set_msrd(msr & ~MSR_EE); /* disable interrupts */
|
||||
msr = mfmsr();
|
||||
mtmsr(msr & ~MSR_EE); /* disable interrupts */
|
||||
|
||||
bp = in_breakpoint_table(regs->nip, &offset);
|
||||
if (bp != NULL) {
|
||||
|
@ -487,7 +505,7 @@ int xmon_core(struct pt_regs *regs, int fromipi)
|
|||
|
||||
insert_cpu_bpts();
|
||||
|
||||
set_msrd(msr); /* restore interrupt enable */
|
||||
mtmsr(msr); /* restore interrupt enable */
|
||||
|
||||
return cmd != 'X';
|
||||
}
|
||||
|
@ -497,56 +515,23 @@ int xmon(struct pt_regs *excp)
|
|||
struct pt_regs regs;
|
||||
|
||||
if (excp == NULL) {
|
||||
/* Ok, grab regs as they are now.
|
||||
This won't do a particularily good job because the
|
||||
prologue has already been executed.
|
||||
ToDo: We could reach back into the callers save
|
||||
area to do a better job of representing the
|
||||
caller's state.
|
||||
*/
|
||||
asm volatile ("std 0,0(%0)\n\
|
||||
std 1,8(%0)\n\
|
||||
std 2,16(%0)\n\
|
||||
std 3,24(%0)\n\
|
||||
std 4,32(%0)\n\
|
||||
std 5,40(%0)\n\
|
||||
std 6,48(%0)\n\
|
||||
std 7,56(%0)\n\
|
||||
std 8,64(%0)\n\
|
||||
std 9,72(%0)\n\
|
||||
std 10,80(%0)\n\
|
||||
std 11,88(%0)\n\
|
||||
std 12,96(%0)\n\
|
||||
std 13,104(%0)\n\
|
||||
std 14,112(%0)\n\
|
||||
std 15,120(%0)\n\
|
||||
std 16,128(%0)\n\
|
||||
std 17,136(%0)\n\
|
||||
std 18,144(%0)\n\
|
||||
std 19,152(%0)\n\
|
||||
std 20,160(%0)\n\
|
||||
std 21,168(%0)\n\
|
||||
std 22,176(%0)\n\
|
||||
std 23,184(%0)\n\
|
||||
std 24,192(%0)\n\
|
||||
std 25,200(%0)\n\
|
||||
std 26,208(%0)\n\
|
||||
std 27,216(%0)\n\
|
||||
std 28,224(%0)\n\
|
||||
std 29,232(%0)\n\
|
||||
std 30,240(%0)\n\
|
||||
std 31,248(%0)" : : "b" (®s));
|
||||
|
||||
regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
|
||||
regs.msr = get_msr();
|
||||
regs.ctr = get_ctr();
|
||||
regs.xer = get_xer();
|
||||
regs.ccr = get_cr();
|
||||
regs.trap = 0;
|
||||
xmon_save_regs(®s);
|
||||
excp = ®s;
|
||||
}
|
||||
return xmon_core(excp, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(xmon);
|
||||
|
||||
irqreturn_t
|
||||
xmon_irq(int irq, void *d, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
printf("Keyboard interrupt\n");
|
||||
xmon(regs);
|
||||
local_irq_restore(flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int xmon_bpt(struct pt_regs *regs)
|
||||
{
|
||||
|
@ -718,7 +703,7 @@ static void insert_cpu_bpts(void)
|
|||
if (dabr.enabled)
|
||||
set_dabr(dabr.address | (dabr.enabled & 7));
|
||||
if (iabr && cpu_has_feature(CPU_FTR_IABR))
|
||||
set_iabr(iabr->address
|
||||
mtspr(SPRN_IABR, iabr->address
|
||||
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
|
||||
}
|
||||
|
||||
|
@ -746,7 +731,7 @@ static void remove_cpu_bpts(void)
|
|||
{
|
||||
set_dabr(0);
|
||||
if (cpu_has_feature(CPU_FTR_IABR))
|
||||
set_iabr(0);
|
||||
mtspr(SPRN_IABR, 0);
|
||||
}
|
||||
|
||||
/* Command interpreting routine */
|
||||
|
@ -830,9 +815,6 @@ cmds(struct pt_regs *excp)
|
|||
case '?':
|
||||
printf(help_string);
|
||||
break;
|
||||
case 'p':
|
||||
show_state();
|
||||
break;
|
||||
case 'b':
|
||||
bpt_cmds();
|
||||
break;
|
||||
|
@ -846,12 +828,14 @@ cmds(struct pt_regs *excp)
|
|||
case 'z':
|
||||
bootcmds();
|
||||
break;
|
||||
case 'T':
|
||||
debug_trace();
|
||||
case 'p':
|
||||
proccall();
|
||||
break;
|
||||
#ifdef CONFIG_PPC_STD_MMU
|
||||
case 'u':
|
||||
dump_segments();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("Unrecognized command: ");
|
||||
do {
|
||||
|
@ -1070,6 +1054,7 @@ bpt_cmds(void)
|
|||
|
||||
cmd = inchar();
|
||||
switch (cmd) {
|
||||
#ifndef CONFIG_8xx
|
||||
case 'd': /* bd - hardware data breakpoint */
|
||||
mode = 7;
|
||||
cmd = inchar();
|
||||
|
@ -1111,6 +1096,7 @@ bpt_cmds(void)
|
|||
iabr = bp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'c':
|
||||
if (!scanhex(&a)) {
|
||||
|
@ -1152,7 +1138,7 @@ bpt_cmds(void)
|
|||
/* print all breakpoints */
|
||||
printf(" type address\n");
|
||||
if (dabr.enabled) {
|
||||
printf(" data %.16lx [", dabr.address);
|
||||
printf(" data "REG" [", dabr.address);
|
||||
if (dabr.enabled & 1)
|
||||
printf("r");
|
||||
if (dabr.enabled & 2)
|
||||
|
@ -1231,6 +1217,18 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
|
|||
|
||||
static int xmon_depth_to_print = 64;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define LRSAVE_OFFSET 0x10
|
||||
#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
|
||||
#define MARKER_OFFSET 0x60
|
||||
#define REGS_OFFSET 0x70
|
||||
#else
|
||||
#define LRSAVE_OFFSET 4
|
||||
#define REG_FRAME_MARKER 0x72656773
|
||||
#define MARKER_OFFSET 8
|
||||
#define REGS_OFFSET 16
|
||||
#endif
|
||||
|
||||
static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
||||
unsigned long pc)
|
||||
{
|
||||
|
@ -1247,7 +1245,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!mread(sp + 16, &ip, sizeof(unsigned long))
|
||||
if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
|
||||
|| !mread(sp, &newsp, sizeof(unsigned long))) {
|
||||
printf("Couldn't read stack frame at %lx\n", sp);
|
||||
break;
|
||||
|
@ -1266,7 +1264,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
|||
get_function_bounds(pc, &fnstart, &fnend);
|
||||
nextip = 0;
|
||||
if (newsp > sp)
|
||||
mread(newsp + 16, &nextip,
|
||||
mread(newsp + LRSAVE_OFFSET, &nextip,
|
||||
sizeof(unsigned long));
|
||||
if (lr == ip) {
|
||||
if (lr < PAGE_OFFSET
|
||||
|
@ -1280,24 +1278,24 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
|||
xmon_print_symbol(lr, " ", "\n");
|
||||
}
|
||||
if (printip) {
|
||||
printf("[%.16lx] ", sp);
|
||||
printf("["REG"] ", sp);
|
||||
xmon_print_symbol(ip, " ", " (unreliable)\n");
|
||||
}
|
||||
pc = lr = 0;
|
||||
|
||||
} else {
|
||||
printf("[%.16lx] ", sp);
|
||||
printf("["REG"] ", sp);
|
||||
xmon_print_symbol(ip, " ", "\n");
|
||||
}
|
||||
|
||||
/* Look for "regshere" marker to see if this is
|
||||
an exception frame. */
|
||||
if (mread(sp + 0x60, &marker, sizeof(unsigned long))
|
||||
&& marker == 0x7265677368657265ul) {
|
||||
if (mread(sp + 0x70, ®s, sizeof(regs))
|
||||
if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
|
||||
&& marker == REG_FRAME_MARKER) {
|
||||
if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
|
||||
!= sizeof(regs)) {
|
||||
printf("Couldn't read registers at %lx\n",
|
||||
sp + 0x70);
|
||||
sp + REGS_OFFSET);
|
||||
break;
|
||||
}
|
||||
printf("--- Exception: %lx %s at ", regs.trap,
|
||||
|
@ -1371,7 +1369,9 @@ void excprint(struct pt_regs *fp)
|
|||
}
|
||||
|
||||
printf(" current = 0x%lx\n", current);
|
||||
#ifdef CONFIG_PPC64
|
||||
printf(" paca = 0x%lx\n", get_paca());
|
||||
#endif
|
||||
if (current) {
|
||||
printf(" pid = %ld, comm = %s\n",
|
||||
current->pid, current->comm);
|
||||
|
@ -1383,7 +1383,7 @@ void excprint(struct pt_regs *fp)
|
|||
|
||||
void prregs(struct pt_regs *fp)
|
||||
{
|
||||
int n;
|
||||
int n, trap;
|
||||
unsigned long base;
|
||||
struct pt_regs regs;
|
||||
|
||||
|
@ -1396,7 +1396,7 @@ void prregs(struct pt_regs *fp)
|
|||
__delay(200);
|
||||
} else {
|
||||
catch_memory_errors = 0;
|
||||
printf("*** Error reading registers from %.16lx\n",
|
||||
printf("*** Error reading registers from "REG"\n",
|
||||
base);
|
||||
return;
|
||||
}
|
||||
|
@ -1404,22 +1404,36 @@ void prregs(struct pt_regs *fp)
|
|||
fp = ®s;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (FULL_REGS(fp)) {
|
||||
for (n = 0; n < 16; ++n)
|
||||
printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
|
||||
printf("R%.2ld = "REG" R%.2ld = "REG"\n",
|
||||
n, fp->gpr[n], n+16, fp->gpr[n+16]);
|
||||
} else {
|
||||
for (n = 0; n < 7; ++n)
|
||||
printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
|
||||
printf("R%.2ld = "REG" R%.2ld = "REG"\n",
|
||||
n, fp->gpr[n], n+7, fp->gpr[n+7]);
|
||||
}
|
||||
#else
|
||||
for (n = 0; n < 32; ++n) {
|
||||
printf("R%.2d = %.8x%s", n, fp->gpr[n],
|
||||
(n & 3) == 3? "\n": " ");
|
||||
if (n == 12 && !FULL_REGS(fp)) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("pc = ");
|
||||
xmon_print_symbol(fp->nip, " ", "\n");
|
||||
printf("lr = ");
|
||||
xmon_print_symbol(fp->link, " ", "\n");
|
||||
printf("msr = %.16lx cr = %.8lx\n", fp->msr, fp->ccr);
|
||||
printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
|
||||
printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
|
||||
printf("ctr = "REG" xer = "REG" trap = %4lx\n",
|
||||
fp->ctr, fp->xer, fp->trap);
|
||||
trap = TRAP(fp);
|
||||
if (trap == 0x300 || trap == 0x380 || trap == 0x600)
|
||||
printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
|
||||
}
|
||||
|
||||
void cacheflush(void)
|
||||
|
@ -1519,8 +1533,7 @@ static unsigned long regno;
|
|||
extern char exc_prolog;
|
||||
extern char dec_exc;
|
||||
|
||||
void
|
||||
super_regs(void)
|
||||
void super_regs(void)
|
||||
{
|
||||
int cmd;
|
||||
unsigned long val;
|
||||
|
@ -1536,12 +1549,14 @@ super_regs(void)
|
|||
asm("mr %0,1" : "=r" (sp) :);
|
||||
asm("mr %0,2" : "=r" (toc) :);
|
||||
|
||||
printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
|
||||
printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
|
||||
printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
|
||||
printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
|
||||
printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
|
||||
printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
|
||||
printf("msr = "REG" sprg0= "REG"\n",
|
||||
mfmsr(), mfspr(SPRN_SPRG0));
|
||||
printf("pvr = "REG" sprg1= "REG"\n",
|
||||
mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
|
||||
printf("dec = "REG" sprg2= "REG"\n",
|
||||
mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
|
||||
printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
|
||||
printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
// Dump out relevant Paca data areas.
|
||||
printf("Paca: \n");
|
||||
|
@ -1578,11 +1593,6 @@ super_regs(void)
|
|||
case 'r':
|
||||
printf("spr %lx = %lx\n", regno, read_spr(regno));
|
||||
break;
|
||||
case 'm':
|
||||
val = get_msr();
|
||||
scanhex(&val);
|
||||
set_msrd(val);
|
||||
break;
|
||||
}
|
||||
scannl();
|
||||
}
|
||||
|
@ -1604,13 +1614,13 @@ mread(unsigned long adrs, void *buf, int size)
|
|||
q = (char *)buf;
|
||||
switch (size) {
|
||||
case 2:
|
||||
*(short *)q = *(short *)p;
|
||||
*(u16 *)q = *(u16 *)p;
|
||||
break;
|
||||
case 4:
|
||||
*(int *)q = *(int *)p;
|
||||
*(u32 *)q = *(u32 *)p;
|
||||
break;
|
||||
case 8:
|
||||
*(long *)q = *(long *)p;
|
||||
*(u64 *)q = *(u64 *)p;
|
||||
break;
|
||||
default:
|
||||
for( ; n < size; ++n) {
|
||||
|
@ -1641,13 +1651,13 @@ mwrite(unsigned long adrs, void *buf, int size)
|
|||
q = (char *) buf;
|
||||
switch (size) {
|
||||
case 2:
|
||||
*(short *)p = *(short *)q;
|
||||
*(u16 *)p = *(u16 *)q;
|
||||
break;
|
||||
case 4:
|
||||
*(int *)p = *(int *)q;
|
||||
*(u32 *)p = *(u32 *)q;
|
||||
break;
|
||||
case 8:
|
||||
*(long *)p = *(long *)q;
|
||||
*(u64 *)p = *(u64 *)q;
|
||||
break;
|
||||
default:
|
||||
for ( ; n < size; ++n) {
|
||||
|
@ -1667,11 +1677,12 @@ mwrite(unsigned long adrs, void *buf, int size)
|
|||
}
|
||||
|
||||
static int fault_type;
|
||||
static int fault_except;
|
||||
static char *fault_chars[] = { "--", "**", "##" };
|
||||
|
||||
static int
|
||||
handle_fault(struct pt_regs *regs)
|
||||
static int handle_fault(struct pt_regs *regs)
|
||||
{
|
||||
fault_except = TRAP(regs);
|
||||
switch (TRAP(regs)) {
|
||||
case 0x200:
|
||||
fault_type = 0;
|
||||
|
@ -1960,7 +1971,7 @@ prdump(unsigned long adrs, long ndump)
|
|||
unsigned char temp[16];
|
||||
|
||||
for (n = ndump; n > 0;) {
|
||||
printf("%.16lx", adrs);
|
||||
printf(REG, adrs);
|
||||
putchar(' ');
|
||||
r = n < 16? n: 16;
|
||||
nr = mread(adrs, temp, r);
|
||||
|
@ -2008,7 +2019,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
|
|||
if (nr == 0) {
|
||||
if (praddr) {
|
||||
const char *x = fault_chars[fault_type];
|
||||
printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
|
||||
printf(REG" %s%s%s%s\n", adr, x, x, x, x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2023,7 +2034,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
|
|||
dotted = 0;
|
||||
last_inst = inst;
|
||||
if (praddr)
|
||||
printf("%.16lx %.8x", adr, inst);
|
||||
printf(REG" %.8x", adr, inst);
|
||||
printf("\t");
|
||||
print_insn_powerpc(inst, adr, 0); /* always returns 4 */
|
||||
printf("\n");
|
||||
|
@ -2152,6 +2163,42 @@ memzcan(void)
|
|||
printf("%.8x\n", a - mskip);
|
||||
}
|
||||
|
||||
void proccall(void)
|
||||
{
|
||||
unsigned long args[8];
|
||||
unsigned long ret;
|
||||
int i;
|
||||
typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long);
|
||||
callfunc_t func;
|
||||
|
||||
if (!scanhex(&adrs))
|
||||
return;
|
||||
if (termch != '\n')
|
||||
termch = 0;
|
||||
for (i = 0; i < 8; ++i)
|
||||
args[i] = 0;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (!scanhex(&args[i]) || termch == '\n')
|
||||
break;
|
||||
termch = 0;
|
||||
}
|
||||
func = (callfunc_t) adrs;
|
||||
ret = 0;
|
||||
if (setjmp(bus_error_jmp) == 0) {
|
||||
catch_memory_errors = 1;
|
||||
sync();
|
||||
ret = func(args[0], args[1], args[2], args[3],
|
||||
args[4], args[5], args[6], args[7]);
|
||||
sync();
|
||||
printf("return value is %x\n", ret);
|
||||
} else {
|
||||
printf("*** %x exception occurred\n", fault_except);
|
||||
}
|
||||
catch_memory_errors = 0;
|
||||
}
|
||||
|
||||
/* Input scanning routines */
|
||||
int
|
||||
skipbl(void)
|
||||
|
@ -2174,7 +2221,12 @@ static char *regnames[N_PTREGS] = {
|
|||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
||||
"pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "softe",
|
||||
"pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
|
||||
#ifdef CONFIG_PPC64
|
||||
"softe",
|
||||
#else
|
||||
"mq",
|
||||
#endif
|
||||
"trap", "dar", "dsisr", "res"
|
||||
};
|
||||
|
||||
|
@ -2280,8 +2332,7 @@ scannl(void)
|
|||
c = inchar();
|
||||
}
|
||||
|
||||
int
|
||||
hexdigit(int c)
|
||||
int hexdigit(int c)
|
||||
{
|
||||
if( '0' <= c && c <= '9' )
|
||||
return c - '0';
|
||||
|
@ -2378,7 +2429,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
|
|||
const char *name = NULL;
|
||||
unsigned long offset, size;
|
||||
|
||||
printf("%.16lx", address);
|
||||
printf(REG, address);
|
||||
if (setjmp(bus_error_jmp) == 0) {
|
||||
catch_memory_errors = 1;
|
||||
sync();
|
||||
|
@ -2399,55 +2450,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
|
|||
printf("%s", after);
|
||||
}
|
||||
|
||||
static void debug_trace(void)
|
||||
{
|
||||
unsigned long val, cmd, on;
|
||||
|
||||
cmd = skipbl();
|
||||
if (cmd == '\n') {
|
||||
/* show current state */
|
||||
unsigned long i;
|
||||
printf("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
|
||||
for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
|
||||
on = PPCDBG_BITVAL(i) & ppc64_debug_switch;
|
||||
printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
|
||||
if (((i+1) % 3) == 0)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
while (cmd != '\n') {
|
||||
on = 1; /* default if no sign given */
|
||||
while (cmd == '+' || cmd == '-') {
|
||||
on = (cmd == '+');
|
||||
cmd = inchar();
|
||||
if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */
|
||||
ppc64_debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
|
||||
printf("Setting all values to %s...\n", on ? "on" : "off");
|
||||
if (cmd == '\n') return;
|
||||
else cmd = skipbl();
|
||||
}
|
||||
else
|
||||
termch = cmd;
|
||||
}
|
||||
termch = cmd; /* not +/- ... let scanhex see it */
|
||||
scanhex((void *)&val);
|
||||
if (val >= 64) {
|
||||
printf("Value %x out of range:\n", val);
|
||||
return;
|
||||
}
|
||||
if (on) {
|
||||
ppc64_debug_switch |= PPCDBG_BITVAL(val);
|
||||
printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
|
||||
} else {
|
||||
ppc64_debug_switch &= ~PPCDBG_BITVAL(val);
|
||||
printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
|
||||
}
|
||||
cmd = skipbl();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static void dump_slb(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -2484,6 +2487,27 @@ static void dump_stab(void)
|
|||
}
|
||||
}
|
||||
|
||||
void dump_segments(void)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FTR_SLB))
|
||||
dump_slb();
|
||||
else
|
||||
dump_stab();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_STD_MMU_32
|
||||
void dump_segments(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("sr0-15 =");
|
||||
for (i = 0; i < 16; ++i)
|
||||
printf(" %x", mfsrin(i));
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void xmon_init(int enable)
|
||||
{
|
||||
if (enable) {
|
||||
|
@ -2504,11 +2528,3 @@ void xmon_init(int enable)
|
|||
__debugger_fault_handler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dump_segments(void)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FTR_SLB))
|
||||
dump_slb();
|
||||
else
|
||||
dump_stab();
|
||||
}
|
|
@ -89,7 +89,7 @@ core-y += arch/powerpc/mm/
|
|||
core-y += arch/powerpc/sysdev/
|
||||
core-y += arch/powerpc/platforms/
|
||||
core-y += arch/powerpc/lib/
|
||||
core-$(CONFIG_XMON) += arch/ppc64/xmon/
|
||||
core-$(CONFIG_XMON) += arch/powerpc/xmon/
|
||||
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
||||
|
||||
boot := arch/ppc64/boot
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
# Makefile for xmon
|
||||
|
||||
EXTRA_CFLAGS += -mno-minimal-toc
|
||||
|
||||
obj-y := start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* NOTE: assert(sizeof(buf) > 184)
|
||||
*/
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
_GLOBAL(xmon_setjmp)
|
||||
mflr r0
|
||||
std r0,0(r3)
|
||||
std r1,8(r3)
|
||||
std r2,16(r3)
|
||||
mfcr r0
|
||||
std r0,24(r3)
|
||||
std r13,32(r3)
|
||||
std r14,40(r3)
|
||||
std r15,48(r3)
|
||||
std r16,56(r3)
|
||||
std r17,64(r3)
|
||||
std r18,72(r3)
|
||||
std r19,80(r3)
|
||||
std r20,88(r3)
|
||||
std r21,96(r3)
|
||||
std r22,104(r3)
|
||||
std r23,112(r3)
|
||||
std r24,120(r3)
|
||||
std r25,128(r3)
|
||||
std r26,136(r3)
|
||||
std r27,144(r3)
|
||||
std r28,152(r3)
|
||||
std r29,160(r3)
|
||||
std r30,168(r3)
|
||||
std r31,176(r3)
|
||||
li r3,0
|
||||
blr
|
||||
|
||||
_GLOBAL(xmon_longjmp)
|
||||
cmpdi r4,0
|
||||
bne 1f
|
||||
li r4,1
|
||||
1: ld r13,32(r3)
|
||||
ld r14,40(r3)
|
||||
ld r15,48(r3)
|
||||
ld r16,56(r3)
|
||||
ld r17,64(r3)
|
||||
ld r18,72(r3)
|
||||
ld r19,80(r3)
|
||||
ld r20,88(r3)
|
||||
ld r21,96(r3)
|
||||
ld r22,104(r3)
|
||||
ld r23,112(r3)
|
||||
ld r24,120(r3)
|
||||
ld r25,128(r3)
|
||||
ld r26,136(r3)
|
||||
ld r27,144(r3)
|
||||
ld r28,152(r3)
|
||||
ld r29,160(r3)
|
||||
ld r30,168(r3)
|
||||
ld r31,176(r3)
|
||||
ld r0,24(r3)
|
||||
mtcrf 56,r0
|
||||
ld r0,0(r3)
|
||||
ld r1,8(r3)
|
||||
ld r2,16(r3)
|
||||
mtlr r0
|
||||
mr r3,r4
|
||||
blr
|
|
@ -188,6 +188,10 @@ n:
|
|||
#define LDL ld
|
||||
#define STL std
|
||||
#define CMPI cmpdi
|
||||
#define SZL 8
|
||||
|
||||
/* offsets for stack frame layout */
|
||||
#define LRSAVE 16
|
||||
|
||||
#else /* 32-bit */
|
||||
#define LOADADDR(rn,name) \
|
||||
|
@ -203,6 +207,10 @@ n:
|
|||
#define LDL lwz
|
||||
#define STL stw
|
||||
#define CMPI cmpwi
|
||||
#define SZL 4
|
||||
|
||||
/* offsets for stack frame layout */
|
||||
#define LRSAVE 4
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@
|
|||
#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
|
||||
: : "r" (v))
|
||||
#define mtmsrd(v) __mtmsrd((v), 0)
|
||||
#define mtmsr(v) mtmsrd(v)
|
||||
#else
|
||||
#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
struct pt_regs;
|
||||
|
||||
extern void xmon(struct pt_regs *excp);
|
||||
extern int xmon(struct pt_regs *excp);
|
||||
extern void xmon_printf(const char *fmt, ...);
|
||||
extern void xmon_init(int);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче