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/sysdev/ \
|
||||||
arch/powerpc/platforms/
|
arch/powerpc/platforms/
|
||||||
core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
|
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/
|
core-$(CONFIG_APUS) += arch/ppc/amiga/
|
||||||
drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
|
drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
|
||||||
drivers-$(CONFIG_4xx) += arch/ppc/4xx_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 */ \
|
li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
|
||||||
MTMSRD(r10); /* (except for mach check in rtas) */ \
|
MTMSRD(r10); /* (except for mach check in rtas) */ \
|
||||||
stw r0,GPR0(r11); \
|
stw r0,GPR0(r11); \
|
||||||
|
lis r10,0x7265; /* put exception frame marker */ \
|
||||||
|
addi r10,r10,0x6773; \
|
||||||
|
stw r10,8(r11); \
|
||||||
SAVE_4GPRS(3, r11); \
|
SAVE_4GPRS(3, r11); \
|
||||||
SAVE_2GPRS(7, r11)
|
SAVE_2GPRS(7, r11)
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include <asm/cputable.h>
|
#include <asm/cputable.h>
|
||||||
#include <asm/btext.h>
|
#include <asm/btext.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
#include <asm/xmon.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_8xx
|
#ifdef CONFIG_8xx
|
||||||
#include <asm/commproc.h>
|
#include <asm/commproc.h>
|
||||||
|
@ -238,10 +237,6 @@ EXPORT_SYMBOL(console_drivers);
|
||||||
EXPORT_SYMBOL(cacheable_memcpy);
|
EXPORT_SYMBOL(cacheable_memcpy);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_XMON
|
|
||||||
EXPORT_SYMBOL(xmon);
|
|
||||||
EXPORT_SYMBOL(xmon_printf);
|
|
||||||
#endif
|
|
||||||
EXPORT_SYMBOL(__up);
|
EXPORT_SYMBOL(__up);
|
||||||
EXPORT_SYMBOL(__down);
|
EXPORT_SYMBOL(__down);
|
||||||
EXPORT_SYMBOL(__down_interruptible);
|
EXPORT_SYMBOL(__down_interruptible);
|
||||||
|
|
|
@ -302,8 +302,10 @@ void __init setup_arch(char **cmdline_p)
|
||||||
|
|
||||||
#ifdef CONFIG_XMON
|
#ifdef CONFIG_XMON
|
||||||
xmon_map_scc();
|
xmon_map_scc();
|
||||||
if (strstr(cmd_line, "xmon"))
|
if (strstr(cmd_line, "xmon")) {
|
||||||
xmon(NULL);
|
xmon_init(1);
|
||||||
|
debugger(NULL);
|
||||||
|
}
|
||||||
#endif /* CONFIG_XMON */
|
#endif /* CONFIG_XMON */
|
||||||
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
|
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#include <asm/iSeries/ItLpNaca.h>
|
#include <asm/iSeries/ItLpNaca.h>
|
||||||
#include <asm/firmware.h>
|
#include <asm/firmware.h>
|
||||||
#include <asm/systemcfg.h>
|
#include <asm/systemcfg.h>
|
||||||
|
#include <asm/xmon.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DBG(fmt...) udbg_printf(fmt)
|
#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 \
|
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
|
||||||
memcpy_64.o usercopy_64.o mem_64.o
|
memcpy_64.o usercopy_64.o mem_64.o
|
||||||
obj-$(CONFIG_PPC_ISERIES) += e2a.o
|
obj-$(CONFIG_PPC_ISERIES) += e2a.o
|
||||||
|
obj-$(CONFIG_XMON) += sstep.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_PPC64),y)
|
ifeq ($(CONFIG_PPC64),y)
|
||||||
obj-$(CONFIG_SMP) += locks.o
|
obj-$(CONFIG_SMP) += locks.o
|
||||||
obj-$(CONFIG_DEBUG_KERNEL) += sstep.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/kernel.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "nonstdio.h"
|
#include "nonstdio.h"
|
||||||
|
|
||||||
extern int xmon_write(void *, void *, int);
|
extern int xmon_write(void *, void *, int);
|
||||||
|
|
||||||
void
|
void xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
||||||
xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
|
||||||
{
|
{
|
||||||
static char xmon_buf[2048];
|
static char xmon_buf[2048];
|
||||||
int n;
|
int n;
|
||||||
|
@ -33,8 +33,7 @@ xmon_vfprintf(void *f, const char *fmt, va_list ap)
|
||||||
xmon_write(f, xmon_buf, n);
|
xmon_write(f, xmon_buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void xmon_printf(const char *fmt, ...)
|
||||||
xmon_printf(const char *fmt, ...)
|
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
@ -42,9 +41,9 @@ xmon_printf(const char *fmt, ...)
|
||||||
xmon_vfprintf(stdout, fmt, ap);
|
xmon_vfprintf(stdout, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(xmon_printf);
|
||||||
|
|
||||||
void
|
void xmon_fprintf(void *f, const char *fmt, ...)
|
||||||
xmon_fprintf(void *f, const char *fmt, ...)
|
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
|
@ -17,25 +17,31 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/string.h>
|
#include <asm/string.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
|
#include <asm/xmon.h>
|
||||||
|
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||||
|
#include <asm/backlight.h>
|
||||||
|
#endif
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/paca.h>
|
|
||||||
#include <asm/ppcdebug.h>
|
|
||||||
#include <asm/cputable.h>
|
#include <asm/cputable.h>
|
||||||
#include <asm/rtas.h>
|
#include <asm/rtas.h>
|
||||||
#include <asm/sstep.h>
|
#include <asm/sstep.h>
|
||||||
#include <asm/bug.h>
|
#include <asm/bug.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
#include <asm/hvcall.h>
|
#include <asm/hvcall.h>
|
||||||
|
#include <asm/paca.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "nonstdio.h"
|
#include "nonstdio.h"
|
||||||
#include "privinst.h"
|
|
||||||
|
|
||||||
#define scanhex xmon_scanhex
|
#define scanhex xmon_scanhex
|
||||||
#define skipbl xmon_skipbl
|
#define skipbl xmon_skipbl
|
||||||
|
@ -58,7 +64,7 @@ static unsigned long ncsum = 4096;
|
||||||
static int termch;
|
static int termch;
|
||||||
static char tmpstr[128];
|
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 long bus_error_jmp[JMP_BUF_LEN];
|
||||||
static int catch_memory_errors;
|
static int catch_memory_errors;
|
||||||
static long *xmon_fault_jmp[NR_CPUS];
|
static long *xmon_fault_jmp[NR_CPUS];
|
||||||
|
@ -130,23 +136,36 @@ static void cacheflush(void);
|
||||||
static int cpu_cmd(void);
|
static int cpu_cmd(void);
|
||||||
static void csum(void);
|
static void csum(void);
|
||||||
static void bootcmds(void);
|
static void bootcmds(void);
|
||||||
|
static void proccall(void);
|
||||||
void dump_segments(void);
|
void dump_segments(void);
|
||||||
static void symbol_lookup(void);
|
static void symbol_lookup(void);
|
||||||
static void xmon_print_symbol(unsigned long address, const char *mid,
|
static void xmon_print_symbol(unsigned long address, const char *mid,
|
||||||
const char *after);
|
const char *after);
|
||||||
static const char *getvecname(unsigned long vec);
|
static const char *getvecname(unsigned long vec);
|
||||||
|
|
||||||
static void debug_trace(void);
|
|
||||||
|
|
||||||
extern int print_insn_powerpc(unsigned long, unsigned long, int);
|
extern int print_insn_powerpc(unsigned long, unsigned long, int);
|
||||||
extern void printf(const char *fmt, ...);
|
extern void printf(const char *fmt, ...);
|
||||||
extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
|
extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
|
||||||
extern int xmon_putc(int c, void *f);
|
extern int xmon_putc(int c, void *f);
|
||||||
extern int putchar(int ch);
|
extern int putchar(int ch);
|
||||||
|
|
||||||
|
extern void xmon_enter(void);
|
||||||
|
extern void xmon_leave(void);
|
||||||
|
|
||||||
extern int xmon_read_poll(void);
|
extern int xmon_read_poll(void);
|
||||||
extern int setjmp(long *);
|
extern long setjmp(long *);
|
||||||
extern void longjmp(long *, int);
|
extern void longjmp(long *, long);
|
||||||
extern unsigned long _ASR;
|
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])
|
#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\
|
ml locate a block of memory\n\
|
||||||
mz zero a block of memory\n\
|
mz zero a block of memory\n\
|
||||||
mi show information about memory allocation\n\
|
mi show information about memory allocation\n\
|
||||||
p show the task list\n\
|
p call a procedure\n\
|
||||||
r print registers\n\
|
r print registers\n\
|
||||||
s single step\n\
|
s single step\n\
|
||||||
S print special registers\n\
|
S print special registers\n\
|
||||||
t print backtrace\n\
|
t print backtrace\n\
|
||||||
T Enable/Disable PPCDBG flags\n\
|
T Enable/Disable PPCDBG flags\n\
|
||||||
x exit monitor and recover\n\
|
x exit monitor and recover\n\
|
||||||
X exit monitor and dont recover\n\
|
X exit monitor and dont recover\n"
|
||||||
u dump segment table or SLB\n\
|
#ifdef CONFIG_PPC64
|
||||||
? help\n"
|
" u dump segment table or SLB\n"
|
||||||
"\
|
#endif
|
||||||
zr reboot\n\
|
#ifdef CONFIG_PPC_STD_MMU_32
|
||||||
|
" u dump segment registers\n"
|
||||||
|
#endif
|
||||||
|
" ? help\n"
|
||||||
|
" zr reboot\n\
|
||||||
zh halt\n"
|
zh halt\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static struct pt_regs *xmon_regs;
|
static struct pt_regs *xmon_regs;
|
||||||
|
|
||||||
extern inline void sync(void)
|
static inline void sync(void)
|
||||||
{
|
{
|
||||||
asm volatile("sync; isync");
|
asm volatile("sync; isync");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
|
static inline void store_inst(void *p)
|
||||||
A PPC stack frame looks like this:
|
{
|
||||||
|
asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
|
||||||
|
}
|
||||||
|
|
||||||
High Address
|
static inline void cflush(void *p)
|
||||||
Back Chain
|
{
|
||||||
FP reg save area
|
asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
|
||||||
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)
|
|
||||||
|
|
||||||
Note that the LR (ret addr) may not be saved in the current frame if
|
static inline void cinval(void *p)
|
||||||
no functions have been called from the current function.
|
{
|
||||||
*/
|
asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable surveillance (the service processor watchdog function)
|
* Disable surveillance (the service processor watchdog function)
|
||||||
|
@ -310,8 +328,8 @@ int xmon_core(struct pt_regs *regs, int fromipi)
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
msr = get_msr();
|
msr = mfmsr();
|
||||||
set_msrd(msr & ~MSR_EE); /* disable interrupts */
|
mtmsr(msr & ~MSR_EE); /* disable interrupts */
|
||||||
|
|
||||||
bp = in_breakpoint_table(regs->nip, &offset);
|
bp = in_breakpoint_table(regs->nip, &offset);
|
||||||
if (bp != NULL) {
|
if (bp != NULL) {
|
||||||
|
@ -487,7 +505,7 @@ int xmon_core(struct pt_regs *regs, int fromipi)
|
||||||
|
|
||||||
insert_cpu_bpts();
|
insert_cpu_bpts();
|
||||||
|
|
||||||
set_msrd(msr); /* restore interrupt enable */
|
mtmsr(msr); /* restore interrupt enable */
|
||||||
|
|
||||||
return cmd != 'X';
|
return cmd != 'X';
|
||||||
}
|
}
|
||||||
|
@ -497,56 +515,23 @@ int xmon(struct pt_regs *excp)
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
|
|
||||||
if (excp == NULL) {
|
if (excp == NULL) {
|
||||||
/* Ok, grab regs as they are now.
|
xmon_save_regs(®s);
|
||||||
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;
|
|
||||||
excp = ®s;
|
excp = ®s;
|
||||||
}
|
}
|
||||||
return xmon_core(excp, 0);
|
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)
|
int xmon_bpt(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +703,7 @@ static void insert_cpu_bpts(void)
|
||||||
if (dabr.enabled)
|
if (dabr.enabled)
|
||||||
set_dabr(dabr.address | (dabr.enabled & 7));
|
set_dabr(dabr.address | (dabr.enabled & 7));
|
||||||
if (iabr && cpu_has_feature(CPU_FTR_IABR))
|
if (iabr && cpu_has_feature(CPU_FTR_IABR))
|
||||||
set_iabr(iabr->address
|
mtspr(SPRN_IABR, iabr->address
|
||||||
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
|
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,7 +731,7 @@ static void remove_cpu_bpts(void)
|
||||||
{
|
{
|
||||||
set_dabr(0);
|
set_dabr(0);
|
||||||
if (cpu_has_feature(CPU_FTR_IABR))
|
if (cpu_has_feature(CPU_FTR_IABR))
|
||||||
set_iabr(0);
|
mtspr(SPRN_IABR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Command interpreting routine */
|
/* Command interpreting routine */
|
||||||
|
@ -830,9 +815,6 @@ cmds(struct pt_regs *excp)
|
||||||
case '?':
|
case '?':
|
||||||
printf(help_string);
|
printf(help_string);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
|
||||||
show_state();
|
|
||||||
break;
|
|
||||||
case 'b':
|
case 'b':
|
||||||
bpt_cmds();
|
bpt_cmds();
|
||||||
break;
|
break;
|
||||||
|
@ -846,12 +828,14 @@ cmds(struct pt_regs *excp)
|
||||||
case 'z':
|
case 'z':
|
||||||
bootcmds();
|
bootcmds();
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'p':
|
||||||
debug_trace();
|
proccall();
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_PPC_STD_MMU
|
||||||
case 'u':
|
case 'u':
|
||||||
dump_segments();
|
dump_segments();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
printf("Unrecognized command: ");
|
printf("Unrecognized command: ");
|
||||||
do {
|
do {
|
||||||
|
@ -1070,6 +1054,7 @@ bpt_cmds(void)
|
||||||
|
|
||||||
cmd = inchar();
|
cmd = inchar();
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
#ifndef CONFIG_8xx
|
||||||
case 'd': /* bd - hardware data breakpoint */
|
case 'd': /* bd - hardware data breakpoint */
|
||||||
mode = 7;
|
mode = 7;
|
||||||
cmd = inchar();
|
cmd = inchar();
|
||||||
|
@ -1111,6 +1096,7 @@ bpt_cmds(void)
|
||||||
iabr = bp;
|
iabr = bp;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (!scanhex(&a)) {
|
if (!scanhex(&a)) {
|
||||||
|
@ -1152,7 +1138,7 @@ bpt_cmds(void)
|
||||||
/* print all breakpoints */
|
/* print all breakpoints */
|
||||||
printf(" type address\n");
|
printf(" type address\n");
|
||||||
if (dabr.enabled) {
|
if (dabr.enabled) {
|
||||||
printf(" data %.16lx [", dabr.address);
|
printf(" data "REG" [", dabr.address);
|
||||||
if (dabr.enabled & 1)
|
if (dabr.enabled & 1)
|
||||||
printf("r");
|
printf("r");
|
||||||
if (dabr.enabled & 2)
|
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;
|
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,
|
static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
||||||
unsigned long pc)
|
unsigned long pc)
|
||||||
{
|
{
|
||||||
|
@ -1247,7 +1245,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mread(sp + 16, &ip, sizeof(unsigned long))
|
if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
|
||||||
|| !mread(sp, &newsp, sizeof(unsigned long))) {
|
|| !mread(sp, &newsp, sizeof(unsigned long))) {
|
||||||
printf("Couldn't read stack frame at %lx\n", sp);
|
printf("Couldn't read stack frame at %lx\n", sp);
|
||||||
break;
|
break;
|
||||||
|
@ -1266,7 +1264,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
||||||
get_function_bounds(pc, &fnstart, &fnend);
|
get_function_bounds(pc, &fnstart, &fnend);
|
||||||
nextip = 0;
|
nextip = 0;
|
||||||
if (newsp > sp)
|
if (newsp > sp)
|
||||||
mread(newsp + 16, &nextip,
|
mread(newsp + LRSAVE_OFFSET, &nextip,
|
||||||
sizeof(unsigned long));
|
sizeof(unsigned long));
|
||||||
if (lr == ip) {
|
if (lr == ip) {
|
||||||
if (lr < PAGE_OFFSET
|
if (lr < PAGE_OFFSET
|
||||||
|
@ -1280,24 +1278,24 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
|
||||||
xmon_print_symbol(lr, " ", "\n");
|
xmon_print_symbol(lr, " ", "\n");
|
||||||
}
|
}
|
||||||
if (printip) {
|
if (printip) {
|
||||||
printf("[%.16lx] ", sp);
|
printf("["REG"] ", sp);
|
||||||
xmon_print_symbol(ip, " ", " (unreliable)\n");
|
xmon_print_symbol(ip, " ", " (unreliable)\n");
|
||||||
}
|
}
|
||||||
pc = lr = 0;
|
pc = lr = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
printf("[%.16lx] ", sp);
|
printf("["REG"] ", sp);
|
||||||
xmon_print_symbol(ip, " ", "\n");
|
xmon_print_symbol(ip, " ", "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for "regshere" marker to see if this is
|
/* Look for "regshere" marker to see if this is
|
||||||
an exception frame. */
|
an exception frame. */
|
||||||
if (mread(sp + 0x60, &marker, sizeof(unsigned long))
|
if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
|
||||||
&& marker == 0x7265677368657265ul) {
|
&& marker == REG_FRAME_MARKER) {
|
||||||
if (mread(sp + 0x70, ®s, sizeof(regs))
|
if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
|
||||||
!= sizeof(regs)) {
|
!= sizeof(regs)) {
|
||||||
printf("Couldn't read registers at %lx\n",
|
printf("Couldn't read registers at %lx\n",
|
||||||
sp + 0x70);
|
sp + REGS_OFFSET);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("--- Exception: %lx %s at ", regs.trap,
|
printf("--- Exception: %lx %s at ", regs.trap,
|
||||||
|
@ -1371,7 +1369,9 @@ void excprint(struct pt_regs *fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" current = 0x%lx\n", current);
|
printf(" current = 0x%lx\n", current);
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
printf(" paca = 0x%lx\n", get_paca());
|
printf(" paca = 0x%lx\n", get_paca());
|
||||||
|
#endif
|
||||||
if (current) {
|
if (current) {
|
||||||
printf(" pid = %ld, comm = %s\n",
|
printf(" pid = %ld, comm = %s\n",
|
||||||
current->pid, current->comm);
|
current->pid, current->comm);
|
||||||
|
@ -1383,7 +1383,7 @@ void excprint(struct pt_regs *fp)
|
||||||
|
|
||||||
void prregs(struct pt_regs *fp)
|
void prregs(struct pt_regs *fp)
|
||||||
{
|
{
|
||||||
int n;
|
int n, trap;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
|
|
||||||
|
@ -1396,7 +1396,7 @@ void prregs(struct pt_regs *fp)
|
||||||
__delay(200);
|
__delay(200);
|
||||||
} else {
|
} else {
|
||||||
catch_memory_errors = 0;
|
catch_memory_errors = 0;
|
||||||
printf("*** Error reading registers from %.16lx\n",
|
printf("*** Error reading registers from "REG"\n",
|
||||||
base);
|
base);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1404,22 +1404,36 @@ void prregs(struct pt_regs *fp)
|
||||||
fp = ®s;
|
fp = ®s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
if (FULL_REGS(fp)) {
|
if (FULL_REGS(fp)) {
|
||||||
for (n = 0; n < 16; ++n)
|
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]);
|
n, fp->gpr[n], n+16, fp->gpr[n+16]);
|
||||||
} else {
|
} else {
|
||||||
for (n = 0; n < 7; ++n)
|
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]);
|
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 = ");
|
printf("pc = ");
|
||||||
xmon_print_symbol(fp->nip, " ", "\n");
|
xmon_print_symbol(fp->nip, " ", "\n");
|
||||||
printf("lr = ");
|
printf("lr = ");
|
||||||
xmon_print_symbol(fp->link, " ", "\n");
|
xmon_print_symbol(fp->link, " ", "\n");
|
||||||
printf("msr = %.16lx cr = %.8lx\n", fp->msr, fp->ccr);
|
printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
|
||||||
printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
|
printf("ctr = "REG" xer = "REG" trap = %4lx\n",
|
||||||
fp->ctr, fp->xer, fp->trap);
|
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)
|
void cacheflush(void)
|
||||||
|
@ -1519,8 +1533,7 @@ static unsigned long regno;
|
||||||
extern char exc_prolog;
|
extern char exc_prolog;
|
||||||
extern char dec_exc;
|
extern char dec_exc;
|
||||||
|
|
||||||
void
|
void super_regs(void)
|
||||||
super_regs(void)
|
|
||||||
{
|
{
|
||||||
int cmd;
|
int cmd;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
@ -1536,12 +1549,14 @@ super_regs(void)
|
||||||
asm("mr %0,1" : "=r" (sp) :);
|
asm("mr %0,1" : "=r" (sp) :);
|
||||||
asm("mr %0,2" : "=r" (toc) :);
|
asm("mr %0,2" : "=r" (toc) :);
|
||||||
|
|
||||||
printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
|
printf("msr = "REG" sprg0= "REG"\n",
|
||||||
printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
|
mfmsr(), mfspr(SPRN_SPRG0));
|
||||||
printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
|
printf("pvr = "REG" sprg1= "REG"\n",
|
||||||
printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
|
mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
|
||||||
printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
|
printf("dec = "REG" sprg2= "REG"\n",
|
||||||
printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
|
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
|
#ifdef CONFIG_PPC_ISERIES
|
||||||
// Dump out relevant Paca data areas.
|
// Dump out relevant Paca data areas.
|
||||||
printf("Paca: \n");
|
printf("Paca: \n");
|
||||||
|
@ -1578,11 +1593,6 @@ super_regs(void)
|
||||||
case 'r':
|
case 'r':
|
||||||
printf("spr %lx = %lx\n", regno, read_spr(regno));
|
printf("spr %lx = %lx\n", regno, read_spr(regno));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
|
||||||
val = get_msr();
|
|
||||||
scanhex(&val);
|
|
||||||
set_msrd(val);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
scannl();
|
scannl();
|
||||||
}
|
}
|
||||||
|
@ -1604,13 +1614,13 @@ mread(unsigned long adrs, void *buf, int size)
|
||||||
q = (char *)buf;
|
q = (char *)buf;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 2:
|
case 2:
|
||||||
*(short *)q = *(short *)p;
|
*(u16 *)q = *(u16 *)p;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
*(int *)q = *(int *)p;
|
*(u32 *)q = *(u32 *)p;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
*(long *)q = *(long *)p;
|
*(u64 *)q = *(u64 *)p;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for( ; n < size; ++n) {
|
for( ; n < size; ++n) {
|
||||||
|
@ -1641,13 +1651,13 @@ mwrite(unsigned long adrs, void *buf, int size)
|
||||||
q = (char *) buf;
|
q = (char *) buf;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 2:
|
case 2:
|
||||||
*(short *)p = *(short *)q;
|
*(u16 *)p = *(u16 *)q;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
*(int *)p = *(int *)q;
|
*(u32 *)p = *(u32 *)q;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
*(long *)p = *(long *)q;
|
*(u64 *)p = *(u64 *)q;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for ( ; n < size; ++n) {
|
for ( ; n < size; ++n) {
|
||||||
|
@ -1667,11 +1677,12 @@ mwrite(unsigned long adrs, void *buf, int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fault_type;
|
static int fault_type;
|
||||||
|
static int fault_except;
|
||||||
static char *fault_chars[] = { "--", "**", "##" };
|
static char *fault_chars[] = { "--", "**", "##" };
|
||||||
|
|
||||||
static int
|
static int handle_fault(struct pt_regs *regs)
|
||||||
handle_fault(struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
|
fault_except = TRAP(regs);
|
||||||
switch (TRAP(regs)) {
|
switch (TRAP(regs)) {
|
||||||
case 0x200:
|
case 0x200:
|
||||||
fault_type = 0;
|
fault_type = 0;
|
||||||
|
@ -1960,7 +1971,7 @@ prdump(unsigned long adrs, long ndump)
|
||||||
unsigned char temp[16];
|
unsigned char temp[16];
|
||||||
|
|
||||||
for (n = ndump; n > 0;) {
|
for (n = ndump; n > 0;) {
|
||||||
printf("%.16lx", adrs);
|
printf(REG, adrs);
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
r = n < 16? n: 16;
|
r = n < 16? n: 16;
|
||||||
nr = mread(adrs, temp, r);
|
nr = mread(adrs, temp, r);
|
||||||
|
@ -2008,7 +2019,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
|
||||||
if (nr == 0) {
|
if (nr == 0) {
|
||||||
if (praddr) {
|
if (praddr) {
|
||||||
const char *x = fault_chars[fault_type];
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2023,7 +2034,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
|
||||||
dotted = 0;
|
dotted = 0;
|
||||||
last_inst = inst;
|
last_inst = inst;
|
||||||
if (praddr)
|
if (praddr)
|
||||||
printf("%.16lx %.8x", adr, inst);
|
printf(REG" %.8x", adr, inst);
|
||||||
printf("\t");
|
printf("\t");
|
||||||
print_insn_powerpc(inst, adr, 0); /* always returns 4 */
|
print_insn_powerpc(inst, adr, 0); /* always returns 4 */
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -2152,6 +2163,42 @@ memzcan(void)
|
||||||
printf("%.8x\n", a - mskip);
|
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 */
|
/* Input scanning routines */
|
||||||
int
|
int
|
||||||
skipbl(void)
|
skipbl(void)
|
||||||
|
@ -2174,7 +2221,12 @@ static char *regnames[N_PTREGS] = {
|
||||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
"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"
|
"trap", "dar", "dsisr", "res"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2280,8 +2332,7 @@ scannl(void)
|
||||||
c = inchar();
|
c = inchar();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int hexdigit(int c)
|
||||||
hexdigit(int c)
|
|
||||||
{
|
{
|
||||||
if( '0' <= c && c <= '9' )
|
if( '0' <= c && c <= '9' )
|
||||||
return c - '0';
|
return c - '0';
|
||||||
|
@ -2378,7 +2429,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
unsigned long offset, size;
|
unsigned long offset, size;
|
||||||
|
|
||||||
printf("%.16lx", address);
|
printf(REG, address);
|
||||||
if (setjmp(bus_error_jmp) == 0) {
|
if (setjmp(bus_error_jmp) == 0) {
|
||||||
catch_memory_errors = 1;
|
catch_memory_errors = 1;
|
||||||
sync();
|
sync();
|
||||||
|
@ -2399,55 +2450,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
|
||||||
printf("%s", after);
|
printf("%s", after);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_trace(void)
|
#ifdef CONFIG_PPC64
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_slb(void)
|
static void dump_slb(void)
|
||||||
{
|
{
|
||||||
int i;
|
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)
|
void xmon_init(int enable)
|
||||||
{
|
{
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
@ -2504,11 +2528,3 @@ void xmon_init(int enable)
|
||||||
__debugger_fault_handler = NULL;
|
__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/sysdev/
|
||||||
core-y += arch/powerpc/platforms/
|
core-y += arch/powerpc/platforms/
|
||||||
core-y += arch/powerpc/lib/
|
core-y += arch/powerpc/lib/
|
||||||
core-$(CONFIG_XMON) += arch/ppc64/xmon/
|
core-$(CONFIG_XMON) += arch/powerpc/xmon/
|
||||||
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
||||||
|
|
||||||
boot := arch/ppc64/boot
|
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 LDL ld
|
||||||
#define STL std
|
#define STL std
|
||||||
#define CMPI cmpdi
|
#define CMPI cmpdi
|
||||||
|
#define SZL 8
|
||||||
|
|
||||||
|
/* offsets for stack frame layout */
|
||||||
|
#define LRSAVE 16
|
||||||
|
|
||||||
#else /* 32-bit */
|
#else /* 32-bit */
|
||||||
#define LOADADDR(rn,name) \
|
#define LOADADDR(rn,name) \
|
||||||
|
@ -203,6 +207,10 @@ n:
|
||||||
#define LDL lwz
|
#define LDL lwz
|
||||||
#define STL stw
|
#define STL stw
|
||||||
#define CMPI cmpwi
|
#define CMPI cmpwi
|
||||||
|
#define SZL 4
|
||||||
|
|
||||||
|
/* offsets for stack frame layout */
|
||||||
|
#define LRSAVE 4
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -546,6 +546,7 @@
|
||||||
#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
|
#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
|
||||||
: : "r" (v))
|
: : "r" (v))
|
||||||
#define mtmsrd(v) __mtmsrd((v), 0)
|
#define mtmsrd(v) __mtmsrd((v), 0)
|
||||||
|
#define mtmsr(v) mtmsrd(v)
|
||||||
#else
|
#else
|
||||||
#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
|
#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
struct pt_regs;
|
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_printf(const char *fmt, ...);
|
||||||
extern void xmon_init(int);
|
extern void xmon_init(int);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче