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>
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index dedf121..29cda07 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -131,7 +131,7 @@
 				   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/
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 600ea19..b102e3a 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -271,6 +271,9 @@
 	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)
 
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 5f3a12b..8bc5403 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -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(cacheable_memcpy);
 #endif
 
-#ifdef CONFIG_XMON
-EXPORT_SYMBOL(xmon);
-EXPORT_SYMBOL(xmon_printf);
-#endif
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 7c99e6b..9680ae9 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -302,8 +302,10 @@
 
 #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);
 
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 950e6f0..681537f8 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -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)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 0115bf9..e6b2be3 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -11,6 +11,8 @@
 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
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
new file mode 100644
index 0000000..79a784f
--- /dev/null
+++ b/arch/powerpc/xmon/Makefile
@@ -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
diff --git a/arch/ppc64/xmon/ansidecl.h b/arch/powerpc/xmon/ansidecl.h
similarity index 100%
rename from arch/ppc64/xmon/ansidecl.h
rename to arch/powerpc/xmon/ansidecl.h
diff --git a/arch/ppc64/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
similarity index 100%
rename from arch/ppc64/xmon/nonstdio.h
rename to arch/powerpc/xmon/nonstdio.h
diff --git a/arch/ppc64/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
similarity index 100%
rename from arch/ppc64/xmon/ppc-dis.c
rename to arch/powerpc/xmon/ppc-dis.c
diff --git a/arch/ppc64/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c
similarity index 100%
rename from arch/ppc64/xmon/ppc-opc.c
rename to arch/powerpc/xmon/ppc-opc.c
diff --git a/arch/ppc64/xmon/ppc.h b/arch/powerpc/xmon/ppc.h
similarity index 100%
rename from arch/ppc64/xmon/ppc.h
rename to arch/powerpc/xmon/ppc.h
diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S
new file mode 100644
index 0000000..f8e40df
--- /dev/null
+++ b/arch/powerpc/xmon/setjmp.S
@@ -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
diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c
new file mode 100644
index 0000000..69b658c
--- /dev/null
+++ b/arch/powerpc/xmon/start_32.c
@@ -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
+}
diff --git a/arch/ppc64/xmon/start.c b/arch/powerpc/xmon/start_64.c
similarity index 100%
rename from arch/ppc64/xmon/start.c
rename to arch/powerpc/xmon/start_64.c
diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c
new file mode 100644
index 0000000..a48bd59
--- /dev/null
+++ b/arch/powerpc/xmon/start_8xx.c
@@ -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);
+}
diff --git a/arch/ppc64/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c
similarity index 84%
rename from arch/ppc64/xmon/subr_prf.c
rename to arch/powerpc/xmon/subr_prf.c
index 5242bd7..b48738c 100644
--- a/arch/ppc64/xmon/subr_prf.c
+++ b/arch/powerpc/xmon/subr_prf.c
@@ -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_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_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;
 
diff --git a/arch/ppc64/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
similarity index 90%
rename from arch/ppc64/xmon/xmon.c
rename to arch/powerpc/xmon/xmon.c
index 74e63a8..d0623e0 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -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 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 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 @@
   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 @@
 	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 @@
 
 	insert_cpu_bpts();
 
-	set_msrd(msr);		/* restore interrupt enable */
+	mtmsr(msr);		/* restore interrupt enable */
 
 	return cmd != 'X';
 }
@@ -497,56 +515,23 @@
 	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" (&regs));
-
-		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(&regs);
 		excp = &regs;
 	}
 	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 @@
 	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 @@
 {
 	set_dabr(0);
 	if (cpu_has_feature(CPU_FTR_IABR))
-		set_iabr(0);
+		mtspr(SPRN_IABR, 0);
 }
 
 /* Command interpreting routine */
@@ -830,9 +815,6 @@
 		case '?':
 			printf(help_string);
 			break;
-		case 'p':
-			show_state();
-			break;
 		case 'b':
 			bpt_cmds();
 			break;
@@ -846,12 +828,14 @@
 		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 @@
 
 	cmd = inchar();
 	switch (cmd) {
+#ifndef CONFIG_8xx
 	case 'd':	/* bd - hardware data breakpoint */
 		mode = 7;
 		cmd = inchar();
@@ -1111,6 +1096,7 @@
 			iabr = bp;
 		}
 		break;
+#endif
 
 	case 'c':
 		if (!scanhex(&a)) {
@@ -1152,7 +1138,7 @@
 			/* 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 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 @@
 			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 @@
 			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 @@
 				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, &regs, sizeof(regs))
+		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
+		    && marker == REG_FRAME_MARKER) {
+			if (mread(sp + REGS_OFFSET, &regs, 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 @@
 	}
 
 	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 prregs(struct pt_regs *fp)
 {
-	int n;
+	int n, trap;
 	unsigned long base;
 	struct pt_regs regs;
 
@@ -1396,7 +1396,7 @@
 			__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 @@
 		fp = &regs;
 	}
 
+#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 @@
 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 @@
 		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 @@
 	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 @@
 		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 @@
 		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 @@
 }
 
 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 @@
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 	"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 @@
 		c = inchar();
 }
 
-int
-hexdigit(int c)
+int hexdigit(int c)
 {
 	if( '0' <= c && c <= '9' )
 		return c - '0';
@@ -2378,7 +2429,7 @@
 	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 @@
 	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 @@
 	}
 }
 
+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 @@
 		__debugger_fault_handler = NULL;
 	}
 }
-
-void dump_segments(void)
-{
-	if (cpu_has_feature(CPU_FTR_SLB))
-		dump_slb();
-	else
-		dump_stab();
-}
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 2a7af76..743f0db 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -89,7 +89,7 @@
 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
diff --git a/arch/ppc64/xmon/Makefile b/arch/ppc64/xmon/Makefile
deleted file mode 100644
index fb21a70..0000000
--- a/arch/ppc64/xmon/Makefile
+++ /dev/null
@@ -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
diff --git a/arch/ppc64/xmon/setjmp.S b/arch/ppc64/xmon/setjmp.S
deleted file mode 100644
index 30ee643..0000000
--- a/arch/ppc64/xmon/setjmp.S
+++ /dev/null
@@ -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