Linux Audio

Check our new training course

Loading...
   1/*
   2 * Routines providing a simple monitor for use on the PowerMac.
   3 *
   4 * Copyright (C) 1996-2005 Paul Mackerras.
   5 * Copyright (C) 2001 PPC64 Team, IBM Corp
   6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13#include <linux/errno.h>
  14#include <linux/sched.h>
  15#include <linux/smp.h>
  16#include <linux/mm.h>
  17#include <linux/reboot.h>
  18#include <linux/delay.h>
  19#include <linux/kallsyms.h>
  20#include <linux/cpumask.h>
  21#include <linux/export.h>
  22#include <linux/sysrq.h>
  23#include <linux/interrupt.h>
  24#include <linux/irq.h>
  25#include <linux/bug.h>
  26
  27#include <asm/ptrace.h>
  28#include <asm/string.h>
  29#include <asm/prom.h>
  30#include <asm/machdep.h>
  31#include <asm/xmon.h>
  32#include <asm/processor.h>
  33#include <asm/pgtable.h>
  34#include <asm/mmu.h>
  35#include <asm/mmu_context.h>
  36#include <asm/cputable.h>
  37#include <asm/rtas.h>
  38#include <asm/sstep.h>
  39#include <asm/irq_regs.h>
  40#include <asm/spu.h>
  41#include <asm/spu_priv1.h>
  42#include <asm/setjmp.h>
  43#include <asm/reg.h>
  44#include <asm/debug.h>
  45
  46#ifdef CONFIG_PPC64
  47#include <asm/hvcall.h>
  48#include <asm/paca.h>
  49#endif
  50
  51#include "nonstdio.h"
  52#include "dis-asm.h"
  53
  54#define scanhex	xmon_scanhex
  55#define skipbl	xmon_skipbl
  56
  57#ifdef CONFIG_SMP
  58static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
  59static unsigned long xmon_taken = 1;
  60static int xmon_owner;
  61static int xmon_gate;
  62#endif /* CONFIG_SMP */
  63
  64static unsigned long in_xmon __read_mostly = 0;
  65
  66static unsigned long adrs;
  67static int size = 1;
  68#define MAX_DUMP (128 * 1024)
  69static unsigned long ndump = 64;
  70static unsigned long nidump = 16;
  71static unsigned long ncsum = 4096;
  72static int termch;
  73static char tmpstr[128];
  74
  75static long bus_error_jmp[JMP_BUF_LEN];
  76static int catch_memory_errors;
  77static long *xmon_fault_jmp[NR_CPUS];
  78
  79/* Breakpoint stuff */
  80struct bpt {
  81	unsigned long	address;
  82	unsigned int	instr[2];
  83	atomic_t	ref_count;
  84	int		enabled;
  85	unsigned long	pad;
  86};
  87
  88/* Bits in bpt.enabled */
  89#define BP_IABR_TE	1		/* IABR translation enabled */
  90#define BP_IABR		2
  91#define BP_TRAP		8
  92#define BP_DABR		0x10
  93
  94#define NBPTS	256
  95static struct bpt bpts[NBPTS];
  96static struct bpt dabr;
  97static struct bpt *iabr;
  98static unsigned bpinstr = 0x7fe00008;	/* trap */
  99
 100#define BP_NUM(bp)	((bp) - bpts + 1)
 101
 102/* Prototypes */
 103static int cmds(struct pt_regs *);
 104static int mread(unsigned long, void *, int);
 105static int mwrite(unsigned long, void *, int);
 106static int handle_fault(struct pt_regs *);
 107static void byterev(unsigned char *, int);
 108static void memex(void);
 109static int bsesc(void);
 110static void dump(void);
 111static void prdump(unsigned long, long);
 112static int ppc_inst_dump(unsigned long, long, int);
 113static void dump_log_buf(void);
 114static void backtrace(struct pt_regs *);
 115static void excprint(struct pt_regs *);
 116static void prregs(struct pt_regs *);
 117static void memops(int);
 118static void memlocate(void);
 119static void memzcan(void);
 120static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
 121int skipbl(void);
 122int scanhex(unsigned long *valp);
 123static void scannl(void);
 124static int hexdigit(int);
 125void getstring(char *, int);
 126static void flush_input(void);
 127static int inchar(void);
 128static void take_input(char *);
 129static unsigned long read_spr(int);
 130static void write_spr(int, unsigned long);
 131static void super_regs(void);
 132static void remove_bpts(void);
 133static void insert_bpts(void);
 134static void remove_cpu_bpts(void);
 135static void insert_cpu_bpts(void);
 136static struct bpt *at_breakpoint(unsigned long pc);
 137static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
 138static int  do_step(struct pt_regs *);
 139static void bpt_cmds(void);
 140static void cacheflush(void);
 141static int  cpu_cmd(void);
 142static void csum(void);
 143static void bootcmds(void);
 144static void proccall(void);
 145void dump_segments(void);
 146static void symbol_lookup(void);
 147static void xmon_show_stack(unsigned long sp, unsigned long lr,
 148			    unsigned long pc);
 149static void xmon_print_symbol(unsigned long address, const char *mid,
 150			      const char *after);
 151static const char *getvecname(unsigned long vec);
 152
 153static int do_spu_cmd(void);
 154
 155#ifdef CONFIG_44x
 156static void dump_tlb_44x(void);
 157#endif
 158#ifdef CONFIG_PPC_BOOK3E
 159static void dump_tlb_book3e(void);
 160#endif
 161
 162static int xmon_no_auto_backtrace;
 163
 164extern void xmon_enter(void);
 165extern void xmon_leave(void);
 166
 167#ifdef CONFIG_PPC64
 168#define REG		"%.16lx"
 169#define REGS_PER_LINE	4
 170#define LAST_VOLATILE	13
 171#else
 172#define REG		"%.8lx"
 173#define REGS_PER_LINE	8
 174#define LAST_VOLATILE	12
 175#endif
 176
 177#define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
 178
 179#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
 180			 || ('a' <= (c) && (c) <= 'f') \
 181			 || ('A' <= (c) && (c) <= 'F'))
 182#define isalnum(c)	(('0' <= (c) && (c) <= '9') \
 183			 || ('a' <= (c) && (c) <= 'z') \
 184			 || ('A' <= (c) && (c) <= 'Z'))
 185#define isspace(c)	(c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
 186
 187static char *help_string = "\
 188Commands:\n\
 189  b	show breakpoints\n\
 190  bd	set data breakpoint\n\
 191  bi	set instruction breakpoint\n\
 192  bc	clear breakpoint\n"
 193#ifdef CONFIG_SMP
 194  "\
 195  c	print cpus stopped in xmon\n\
 196  c#	try to switch to cpu number h (in hex)\n"
 197#endif
 198  "\
 199  C	checksum\n\
 200  d	dump bytes\n\
 201  di	dump instructions\n\
 202  df	dump float values\n\
 203  dd	dump double values\n\
 204  dl    dump the kernel log buffer\n\
 205  dr	dump stream of raw bytes\n\
 206  e	print exception information\n\
 207  f	flush cache\n\
 208  la	lookup symbol+offset of specified address\n\
 209  ls	lookup address of specified symbol\n\
 210  m	examine/change memory\n\
 211  mm	move a block of memory\n\
 212  ms	set a block of memory\n\
 213  md	compare two blocks of memory\n\
 214  ml	locate a block of memory\n\
 215  mz	zero a block of memory\n\
 216  mi	show information about memory allocation\n\
 217  p 	call a procedure\n\
 218  r	print registers\n\
 219  s	single step\n"
 220#ifdef CONFIG_SPU_BASE
 221"  ss	stop execution on all spus\n\
 222  sr	restore execution on stopped spus\n\
 223  sf  #	dump spu fields for spu # (in hex)\n\
 224  sd  #	dump spu local store for spu # (in hex)\n\
 225  sdi #	disassemble spu local store for spu # (in hex)\n"
 226#endif
 227"  S	print special registers\n\
 228  t	print backtrace\n\
 229  x	exit monitor and recover\n\
 230  X	exit monitor and dont recover\n"
 231#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
 232"  u	dump segment table or SLB\n"
 233#elif defined(CONFIG_PPC_STD_MMU_32)
 234"  u	dump segment registers\n"
 235#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
 236"  u	dump TLB\n"
 237#endif
 238"  ?	help\n"
 239"  zr	reboot\n\
 240  zh	halt\n"
 241;
 242
 243static struct pt_regs *xmon_regs;
 244
 245static inline void sync(void)
 246{
 247	asm volatile("sync; isync");
 248}
 249
 250static inline void store_inst(void *p)
 251{
 252	asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
 253}
 254
 255static inline void cflush(void *p)
 256{
 257	asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
 258}
 259
 260static inline void cinval(void *p)
 261{
 262	asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
 263}
 264
 265/*
 266 * Disable surveillance (the service processor watchdog function)
 267 * while we are in xmon.
 268 * XXX we should re-enable it when we leave. :)
 269 */
 270#define SURVEILLANCE_TOKEN	9000
 271
 272static inline void disable_surveillance(void)
 273{
 274#ifdef CONFIG_PPC_PSERIES
 275	/* Since this can't be a module, args should end up below 4GB. */
 276	static struct rtas_args args;
 277
 278	/*
 279	 * At this point we have got all the cpus we can into
 280	 * xmon, so there is hopefully no other cpu calling RTAS
 281	 * at the moment, even though we don't take rtas.lock.
 282	 * If we did try to take rtas.lock there would be a
 283	 * real possibility of deadlock.
 284	 */
 285	args.token = rtas_token("set-indicator");
 286	if (args.token == RTAS_UNKNOWN_SERVICE)
 287		return;
 288	args.nargs = 3;
 289	args.nret = 1;
 290	args.rets = &args.args[3];
 291	args.args[0] = SURVEILLANCE_TOKEN;
 292	args.args[1] = 0;
 293	args.args[2] = 0;
 294	enter_rtas(__pa(&args));
 295#endif /* CONFIG_PPC_PSERIES */
 296}
 297
 298#ifdef CONFIG_SMP
 299static int xmon_speaker;
 300
 301static void get_output_lock(void)
 302{
 303	int me = smp_processor_id() + 0x100;
 304	int last_speaker = 0, prev;
 305	long timeout;
 306
 307	if (xmon_speaker == me)
 308		return;
 309	for (;;) {
 310		if (xmon_speaker == 0) {
 311			last_speaker = cmpxchg(&xmon_speaker, 0, me);
 312			if (last_speaker == 0)
 313				return;
 314		}
 315		timeout = 10000000;
 316		while (xmon_speaker == last_speaker) {
 317			if (--timeout > 0)
 318				continue;
 319			/* hostile takeover */
 320			prev = cmpxchg(&xmon_speaker, last_speaker, me);
 321			if (prev == last_speaker)
 322				return;
 323			break;
 324		}
 325	}
 326}
 327
 328static void release_output_lock(void)
 329{
 330	xmon_speaker = 0;
 331}
 332
 333int cpus_are_in_xmon(void)
 334{
 335	return !cpumask_empty(&cpus_in_xmon);
 336}
 337#endif
 338
 339static inline int unrecoverable_excp(struct pt_regs *regs)
 340{
 341#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
 342	/* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
 343	return 0;
 344#else
 345	return ((regs->msr & MSR_RI) == 0);
 346#endif
 347}
 348
 349static int xmon_core(struct pt_regs *regs, int fromipi)
 350{
 351	int cmd = 0;
 352	struct bpt *bp;
 353	long recurse_jmp[JMP_BUF_LEN];
 354	unsigned long offset;
 355	unsigned long flags;
 356#ifdef CONFIG_SMP
 357	int cpu;
 358	int secondary;
 359	unsigned long timeout;
 360#endif
 361
 362	local_irq_save(flags);
 363
 364	bp = in_breakpoint_table(regs->nip, &offset);
 365	if (bp != NULL) {
 366		regs->nip = bp->address + offset;
 367		atomic_dec(&bp->ref_count);
 368	}
 369
 370	remove_cpu_bpts();
 371
 372#ifdef CONFIG_SMP
 373	cpu = smp_processor_id();
 374	if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 375		get_output_lock();
 376		excprint(regs);
 377		printf("cpu 0x%x: Exception %lx %s in xmon, "
 378		       "returning to main loop\n",
 379		       cpu, regs->trap, getvecname(TRAP(regs)));
 380		release_output_lock();
 381		longjmp(xmon_fault_jmp[cpu], 1);
 382	}
 383
 384	if (setjmp(recurse_jmp) != 0) {
 385		if (!in_xmon || !xmon_gate) {
 386			get_output_lock();
 387			printf("xmon: WARNING: bad recursive fault "
 388			       "on cpu 0x%x\n", cpu);
 389			release_output_lock();
 390			goto waiting;
 391		}
 392		secondary = !(xmon_taken && cpu == xmon_owner);
 393		goto cmdloop;
 394	}
 395
 396	xmon_fault_jmp[cpu] = recurse_jmp;
 397	cpumask_set_cpu(cpu, &cpus_in_xmon);
 398
 399	bp = NULL;
 400	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
 401		bp = at_breakpoint(regs->nip);
 402	if (bp || unrecoverable_excp(regs))
 403		fromipi = 0;
 404
 405	if (!fromipi) {
 406		get_output_lock();
 407		excprint(regs);
 408		if (bp) {
 409			printf("cpu 0x%x stopped at breakpoint 0x%x (",
 410			       cpu, BP_NUM(bp));
 411			xmon_print_symbol(regs->nip, " ", ")\n");
 412		}
 413		if (unrecoverable_excp(regs))
 414			printf("WARNING: exception is not recoverable, "
 415			       "can't continue\n");
 416		release_output_lock();
 417	}
 418
 419 waiting:
 420	secondary = 1;
 421	while (secondary && !xmon_gate) {
 422		if (in_xmon == 0) {
 423			if (fromipi)
 424				goto leave;
 425			secondary = test_and_set_bit(0, &in_xmon);
 426		}
 427		barrier();
 428	}
 429
 430	if (!secondary && !xmon_gate) {
 431		/* we are the first cpu to come in */
 432		/* interrupt other cpu(s) */
 433		int ncpus = num_online_cpus();
 434
 435		xmon_owner = cpu;
 436		mb();
 437		if (ncpus > 1) {
 438			smp_send_debugger_break();
 439			/* wait for other cpus to come in */
 440			for (timeout = 100000000; timeout != 0; --timeout) {
 441				if (cpumask_weight(&cpus_in_xmon) >= ncpus)
 442					break;
 443				barrier();
 444			}
 445		}
 446		remove_bpts();
 447		disable_surveillance();
 448		/* for breakpoint or single step, print the current instr. */
 449		if (bp || TRAP(regs) == 0xd00)
 450			ppc_inst_dump(regs->nip, 1, 0);
 451		printf("enter ? for help\n");
 452		mb();
 453		xmon_gate = 1;
 454		barrier();
 455	}
 456
 457 cmdloop:
 458	while (in_xmon) {
 459		if (secondary) {
 460			if (cpu == xmon_owner) {
 461				if (!test_and_set_bit(0, &xmon_taken)) {
 462					secondary = 0;
 463					continue;
 464				}
 465				/* missed it */
 466				while (cpu == xmon_owner)
 467					barrier();
 468			}
 469			barrier();
 470		} else {
 471			cmd = cmds(regs);
 472			if (cmd != 0) {
 473				/* exiting xmon */
 474				insert_bpts();
 475				xmon_gate = 0;
 476				wmb();
 477				in_xmon = 0;
 478				break;
 479			}
 480			/* have switched to some other cpu */
 481			secondary = 1;
 482		}
 483	}
 484 leave:
 485	cpumask_clear_cpu(cpu, &cpus_in_xmon);
 486	xmon_fault_jmp[cpu] = NULL;
 487#else
 488	/* UP is simple... */
 489	if (in_xmon) {
 490		printf("Exception %lx %s in xmon, returning to main loop\n",
 491		       regs->trap, getvecname(TRAP(regs)));
 492		longjmp(xmon_fault_jmp[0], 1);
 493	}
 494	if (setjmp(recurse_jmp) == 0) {
 495		xmon_fault_jmp[0] = recurse_jmp;
 496		in_xmon = 1;
 497
 498		excprint(regs);
 499		bp = at_breakpoint(regs->nip);
 500		if (bp) {
 501			printf("Stopped at breakpoint %x (", BP_NUM(bp));
 502			xmon_print_symbol(regs->nip, " ", ")\n");
 503		}
 504		if (unrecoverable_excp(regs))
 505			printf("WARNING: exception is not recoverable, "
 506			       "can't continue\n");
 507		remove_bpts();
 508		disable_surveillance();
 509		/* for breakpoint or single step, print the current instr. */
 510		if (bp || TRAP(regs) == 0xd00)
 511			ppc_inst_dump(regs->nip, 1, 0);
 512		printf("enter ? for help\n");
 513	}
 514
 515	cmd = cmds(regs);
 516
 517	insert_bpts();
 518	in_xmon = 0;
 519#endif
 520
 521#ifdef CONFIG_BOOKE
 522	if (regs->msr & MSR_DE) {
 523		bp = at_breakpoint(regs->nip);
 524		if (bp != NULL) {
 525			regs->nip = (unsigned long) &bp->instr[0];
 526			atomic_inc(&bp->ref_count);
 527		}
 528	}
 529#else
 530	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
 531		bp = at_breakpoint(regs->nip);
 532		if (bp != NULL) {
 533			int stepped = emulate_step(regs, bp->instr[0]);
 534			if (stepped == 0) {
 535				regs->nip = (unsigned long) &bp->instr[0];
 536				atomic_inc(&bp->ref_count);
 537			} else if (stepped < 0) {
 538				printf("Couldn't single-step %s instruction\n",
 539				    (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
 540			}
 541		}
 542	}
 543#endif
 544	insert_cpu_bpts();
 545
 546	local_irq_restore(flags);
 547
 548	return cmd != 'X' && cmd != EOF;
 549}
 550
 551int xmon(struct pt_regs *excp)
 552{
 553	struct pt_regs regs;
 554
 555	if (excp == NULL) {
 556		ppc_save_regs(&regs);
 557		excp = &regs;
 558	}
 559
 560	return xmon_core(excp, 0);
 561}
 562EXPORT_SYMBOL(xmon);
 563
 564irqreturn_t xmon_irq(int irq, void *d)
 565{
 566	unsigned long flags;
 567	local_irq_save(flags);
 568	printf("Keyboard interrupt\n");
 569	xmon(get_irq_regs());
 570	local_irq_restore(flags);
 571	return IRQ_HANDLED;
 572}
 573
 574static int xmon_bpt(struct pt_regs *regs)
 575{
 576	struct bpt *bp;
 577	unsigned long offset;
 578
 579	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
 580		return 0;
 581
 582	/* Are we at the trap at bp->instr[1] for some bp? */
 583	bp = in_breakpoint_table(regs->nip, &offset);
 584	if (bp != NULL && offset == 4) {
 585		regs->nip = bp->address + 4;
 586		atomic_dec(&bp->ref_count);
 587		return 1;
 588	}
 589
 590	/* Are we at a breakpoint? */
 591	bp = at_breakpoint(regs->nip);
 592	if (!bp)
 593		return 0;
 594
 595	xmon_core(regs, 0);
 596
 597	return 1;
 598}
 599
 600static int xmon_sstep(struct pt_regs *regs)
 601{
 602	if (user_mode(regs))
 603		return 0;
 604	xmon_core(regs, 0);
 605	return 1;
 606}
 607
 608static int xmon_dabr_match(struct pt_regs *regs)
 609{
 610	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
 611		return 0;
 612	if (dabr.enabled == 0)
 613		return 0;
 614	xmon_core(regs, 0);
 615	return 1;
 616}
 617
 618static int xmon_iabr_match(struct pt_regs *regs)
 619{
 620	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
 621		return 0;
 622	if (iabr == NULL)
 623		return 0;
 624	xmon_core(regs, 0);
 625	return 1;
 626}
 627
 628static int xmon_ipi(struct pt_regs *regs)
 629{
 630#ifdef CONFIG_SMP
 631	if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
 632		xmon_core(regs, 1);
 633#endif
 634	return 0;
 635}
 636
 637static int xmon_fault_handler(struct pt_regs *regs)
 638{
 639	struct bpt *bp;
 640	unsigned long offset;
 641
 642	if (in_xmon && catch_memory_errors)
 643		handle_fault(regs);	/* doesn't return */
 644
 645	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
 646		bp = in_breakpoint_table(regs->nip, &offset);
 647		if (bp != NULL) {
 648			regs->nip = bp->address + offset;
 649			atomic_dec(&bp->ref_count);
 650		}
 651	}
 652
 653	return 0;
 654}
 655
 656static struct bpt *at_breakpoint(unsigned long pc)
 657{
 658	int i;
 659	struct bpt *bp;
 660
 661	bp = bpts;
 662	for (i = 0; i < NBPTS; ++i, ++bp)
 663		if (bp->enabled && pc == bp->address)
 664			return bp;
 665	return NULL;
 666}
 667
 668static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
 669{
 670	unsigned long off;
 671
 672	off = nip - (unsigned long) bpts;
 673	if (off >= sizeof(bpts))
 674		return NULL;
 675	off %= sizeof(struct bpt);
 676	if (off != offsetof(struct bpt, instr[0])
 677	    && off != offsetof(struct bpt, instr[1]))
 678		return NULL;
 679	*offp = off - offsetof(struct bpt, instr[0]);
 680	return (struct bpt *) (nip - off);
 681}
 682
 683static struct bpt *new_breakpoint(unsigned long a)
 684{
 685	struct bpt *bp;
 686
 687	a &= ~3UL;
 688	bp = at_breakpoint(a);
 689	if (bp)
 690		return bp;
 691
 692	for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
 693		if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
 694			bp->address = a;
 695			bp->instr[1] = bpinstr;
 696			store_inst(&bp->instr[1]);
 697			return bp;
 698		}
 699	}
 700
 701	printf("Sorry, no free breakpoints.  Please clear one first.\n");
 702	return NULL;
 703}
 704
 705static void insert_bpts(void)
 706{
 707	int i;
 708	struct bpt *bp;
 709
 710	bp = bpts;
 711	for (i = 0; i < NBPTS; ++i, ++bp) {
 712		if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
 713			continue;
 714		if (mread(bp->address, &bp->instr[0], 4) != 4) {
 715			printf("Couldn't read instruction at %lx, "
 716			       "disabling breakpoint there\n", bp->address);
 717			bp->enabled = 0;
 718			continue;
 719		}
 720		if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
 721			printf("Breakpoint at %lx is on an mtmsrd or rfid "
 722			       "instruction, disabling it\n", bp->address);
 723			bp->enabled = 0;
 724			continue;
 725		}
 726		store_inst(&bp->instr[0]);
 727		if (bp->enabled & BP_IABR)
 728			continue;
 729		if (mwrite(bp->address, &bpinstr, 4) != 4) {
 730			printf("Couldn't write instruction at %lx, "
 731			       "disabling breakpoint there\n", bp->address);
 732			bp->enabled &= ~BP_TRAP;
 733			continue;
 734		}
 735		store_inst((void *)bp->address);
 736	}
 737}
 738
 739static void insert_cpu_bpts(void)
 740{
 741	if (dabr.enabled)
 742		set_dabr(dabr.address | (dabr.enabled & 7));
 743	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 744		mtspr(SPRN_IABR, iabr->address
 745			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
 746}
 747
 748static void remove_bpts(void)
 749{
 750	int i;
 751	struct bpt *bp;
 752	unsigned instr;
 753
 754	bp = bpts;
 755	for (i = 0; i < NBPTS; ++i, ++bp) {
 756		if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
 757			continue;
 758		if (mread(bp->address, &instr, 4) == 4
 759		    && instr == bpinstr
 760		    && mwrite(bp->address, &bp->instr, 4) != 4)
 761			printf("Couldn't remove breakpoint at %lx\n",
 762			       bp->address);
 763		else
 764			store_inst((void *)bp->address);
 765	}
 766}
 767
 768static void remove_cpu_bpts(void)
 769{
 770	set_dabr(0);
 771	if (cpu_has_feature(CPU_FTR_IABR))
 772		mtspr(SPRN_IABR, 0);
 773}
 774
 775/* Command interpreting routine */
 776static char *last_cmd;
 777
 778static int
 779cmds(struct pt_regs *excp)
 780{
 781	int cmd = 0;
 782
 783	last_cmd = NULL;
 784	xmon_regs = excp;
 785
 786	if (!xmon_no_auto_backtrace) {
 787		xmon_no_auto_backtrace = 1;
 788		xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
 789	}
 790
 791	for(;;) {
 792#ifdef CONFIG_SMP
 793		printf("%x:", smp_processor_id());
 794#endif /* CONFIG_SMP */
 795		printf("mon> ");
 796		flush_input();
 797		termch = 0;
 798		cmd = skipbl();
 799		if( cmd == '\n' ) {
 800			if (last_cmd == NULL)
 801				continue;
 802			take_input(last_cmd);
 803			last_cmd = NULL;
 804			cmd = inchar();
 805		}
 806		switch (cmd) {
 807		case 'm':
 808			cmd = inchar();
 809			switch (cmd) {
 810			case 'm':
 811			case 's':
 812			case 'd':
 813				memops(cmd);
 814				break;
 815			case 'l':
 816				memlocate();
 817				break;
 818			case 'z':
 819				memzcan();
 820				break;
 821			case 'i':
 822				show_mem(0);
 823				break;
 824			default:
 825				termch = cmd;
 826				memex();
 827			}
 828			break;
 829		case 'd':
 830			dump();
 831			break;
 832		case 'l':
 833			symbol_lookup();
 834			break;
 835		case 'r':
 836			prregs(excp);	/* print regs */
 837			break;
 838		case 'e':
 839			excprint(excp);
 840			break;
 841		case 'S':
 842			super_regs();
 843			break;
 844		case 't':
 845			backtrace(excp);
 846			break;
 847		case 'f':
 848			cacheflush();
 849			break;
 850		case 's':
 851			if (do_spu_cmd() == 0)
 852				break;
 853			if (do_step(excp))
 854				return cmd;
 855			break;
 856		case 'x':
 857		case 'X':
 858			return cmd;
 859		case EOF:
 860			printf(" <no input ...>\n");
 861			mdelay(2000);
 862			return cmd;
 863		case '?':
 864			xmon_puts(help_string);
 865			break;
 866		case 'b':
 867			bpt_cmds();
 868			break;
 869		case 'C':
 870			csum();
 871			break;
 872		case 'c':
 873			if (cpu_cmd())
 874				return 0;
 875			break;
 876		case 'z':
 877			bootcmds();
 878			break;
 879		case 'p':
 880			proccall();
 881			break;
 882#ifdef CONFIG_PPC_STD_MMU
 883		case 'u':
 884			dump_segments();
 885			break;
 886#elif defined(CONFIG_4xx)
 887		case 'u':
 888			dump_tlb_44x();
 889			break;
 890#elif defined(CONFIG_PPC_BOOK3E)
 891		case 'u':
 892			dump_tlb_book3e();
 893			break;
 894#endif
 895		default:
 896			printf("Unrecognized command: ");
 897		        do {
 898				if (' ' < cmd && cmd <= '~')
 899					putchar(cmd);
 900				else
 901					printf("\\x%x", cmd);
 902				cmd = inchar();
 903		        } while (cmd != '\n'); 
 904			printf(" (type ? for help)\n");
 905			break;
 906		}
 907	}
 908}
 909
 910#ifdef CONFIG_BOOKE
 911static int do_step(struct pt_regs *regs)
 912{
 913	regs->msr |= MSR_DE;
 914	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
 915	return 1;
 916}
 917#else
 918/*
 919 * Step a single instruction.
 920 * Some instructions we emulate, others we execute with MSR_SE set.
 921 */
 922static int do_step(struct pt_regs *regs)
 923{
 924	unsigned int instr;
 925	int stepped;
 926
 927	/* check we are in 64-bit kernel mode, translation enabled */
 928	if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
 929		if (mread(regs->nip, &instr, 4) == 4) {
 930			stepped = emulate_step(regs, instr);
 931			if (stepped < 0) {
 932				printf("Couldn't single-step %s instruction\n",
 933				       (IS_RFID(instr)? "rfid": "mtmsrd"));
 934				return 0;
 935			}
 936			if (stepped > 0) {
 937				regs->trap = 0xd00 | (regs->trap & 1);
 938				printf("stepped to ");
 939				xmon_print_symbol(regs->nip, " ", "\n");
 940				ppc_inst_dump(regs->nip, 1, 0);
 941				return 0;
 942			}
 943		}
 944	}
 945	regs->msr |= MSR_SE;
 946	return 1;
 947}
 948#endif
 949
 950static void bootcmds(void)
 951{
 952	int cmd;
 953
 954	cmd = inchar();
 955	if (cmd == 'r')
 956		ppc_md.restart(NULL);
 957	else if (cmd == 'h')
 958		ppc_md.halt();
 959	else if (cmd == 'p')
 960		ppc_md.power_off();
 961}
 962
 963static int cpu_cmd(void)
 964{
 965#ifdef CONFIG_SMP
 966	unsigned long cpu;
 967	int timeout;
 968	int count;
 969
 970	if (!scanhex(&cpu)) {
 971		/* print cpus waiting or in xmon */
 972		printf("cpus stopped:");
 973		count = 0;
 974		for_each_possible_cpu(cpu) {
 975			if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 976				if (count == 0)
 977					printf(" %x", cpu);
 978				++count;
 979			} else {
 980				if (count > 1)
 981					printf("-%x", cpu - 1);
 982				count = 0;
 983			}
 984		}
 985		if (count > 1)
 986			printf("-%x", NR_CPUS - 1);
 987		printf("\n");
 988		return 0;
 989	}
 990	/* try to switch to cpu specified */
 991	if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 992		printf("cpu 0x%x isn't in xmon\n", cpu);
 993		return 0;
 994	}
 995	xmon_taken = 0;
 996	mb();
 997	xmon_owner = cpu;
 998	timeout = 10000000;
 999	while (!xmon_taken) {
1000		if (--timeout == 0) {
1001			if (test_and_set_bit(0, &xmon_taken))
1002				break;
1003			/* take control back */
1004			mb();
1005			xmon_owner = smp_processor_id();
1006			printf("cpu %u didn't take control\n", cpu);
1007			return 0;
1008		}
1009		barrier();
1010	}
1011	return 1;
1012#else
1013	return 0;
1014#endif /* CONFIG_SMP */
1015}
1016
1017static unsigned short fcstab[256] = {
1018	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1019	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1020	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1021	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1022	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1023	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1024	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1025	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1026	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1027	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1028	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1029	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1030	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1031	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1032	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1033	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1034	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1035	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1036	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1037	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1038	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1039	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1040	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1041	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1042	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1043	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1044	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1045	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1046	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1047	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1048	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1049	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1050};
1051
1052#define FCS(fcs, c)	(((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1053
1054static void
1055csum(void)
1056{
1057	unsigned int i;
1058	unsigned short fcs;
1059	unsigned char v;
1060
1061	if (!scanhex(&adrs))
1062		return;
1063	if (!scanhex(&ncsum))
1064		return;
1065	fcs = 0xffff;
1066	for (i = 0; i < ncsum; ++i) {
1067		if (mread(adrs+i, &v, 1) == 0) {
1068			printf("csum stopped at %x\n", adrs+i);
1069			break;
1070		}
1071		fcs = FCS(fcs, v);
1072	}
1073	printf("%x\n", fcs);
1074}
1075
1076/*
1077 * Check if this is a suitable place to put a breakpoint.
1078 */
1079static long check_bp_loc(unsigned long addr)
1080{
1081	unsigned int instr;
1082
1083	addr &= ~3;
1084	if (!is_kernel_addr(addr)) {
1085		printf("Breakpoints may only be placed at kernel addresses\n");
1086		return 0;
1087	}
1088	if (!mread(addr, &instr, sizeof(instr))) {
1089		printf("Can't read instruction at address %lx\n", addr);
1090		return 0;
1091	}
1092	if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1093		printf("Breakpoints may not be placed on mtmsrd or rfid "
1094		       "instructions\n");
1095		return 0;
1096	}
1097	return 1;
1098}
1099
1100static char *breakpoint_help_string = 
1101    "Breakpoint command usage:\n"
1102    "b                show breakpoints\n"
1103    "b <addr> [cnt]   set breakpoint at given instr addr\n"
1104    "bc               clear all breakpoints\n"
1105    "bc <n/addr>      clear breakpoint number n or at addr\n"
1106    "bi <addr> [cnt]  set hardware instr breakpoint (POWER3/RS64 only)\n"
1107    "bd <addr> [cnt]  set hardware data breakpoint\n"
1108    "";
1109
1110static void
1111bpt_cmds(void)
1112{
1113	int cmd;
1114	unsigned long a;
1115	int mode, i;
1116	struct bpt *bp;
1117	const char badaddr[] = "Only kernel addresses are permitted "
1118		"for breakpoints\n";
1119
1120	cmd = inchar();
1121	switch (cmd) {
1122#ifndef CONFIG_8xx
1123	case 'd':	/* bd - hardware data breakpoint */
1124		mode = 7;
1125		cmd = inchar();
1126		if (cmd == 'r')
1127			mode = 5;
1128		else if (cmd == 'w')
1129			mode = 6;
1130		else
1131			termch = cmd;
1132		dabr.address = 0;
1133		dabr.enabled = 0;
1134		if (scanhex(&dabr.address)) {
1135			if (!is_kernel_addr(dabr.address)) {
1136				printf(badaddr);
1137				break;
1138			}
1139			dabr.address &= ~7;
1140			dabr.enabled = mode | BP_DABR;
1141		}
1142		break;
1143
1144	case 'i':	/* bi - hardware instr breakpoint */
1145		if (!cpu_has_feature(CPU_FTR_IABR)) {
1146			printf("Hardware instruction breakpoint "
1147			       "not supported on this cpu\n");
1148			break;
1149		}
1150		if (iabr) {
1151			iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1152			iabr = NULL;
1153		}
1154		if (!scanhex(&a))
1155			break;
1156		if (!check_bp_loc(a))
1157			break;
1158		bp = new_breakpoint(a);
1159		if (bp != NULL) {
1160			bp->enabled |= BP_IABR | BP_IABR_TE;
1161			iabr = bp;
1162		}
1163		break;
1164#endif
1165
1166	case 'c':
1167		if (!scanhex(&a)) {
1168			/* clear all breakpoints */
1169			for (i = 0; i < NBPTS; ++i)
1170				bpts[i].enabled = 0;
1171			iabr = NULL;
1172			dabr.enabled = 0;
1173			printf("All breakpoints cleared\n");
1174			break;
1175		}
1176
1177		if (a <= NBPTS && a >= 1) {
1178			/* assume a breakpoint number */
1179			bp = &bpts[a-1];	/* bp nums are 1 based */
1180		} else {
1181			/* assume a breakpoint address */
1182			bp = at_breakpoint(a);
1183			if (bp == NULL) {
1184				printf("No breakpoint at %x\n", a);
1185				break;
1186			}
1187		}
1188
1189		printf("Cleared breakpoint %x (", BP_NUM(bp));
1190		xmon_print_symbol(bp->address, " ", ")\n");
1191		bp->enabled = 0;
1192		break;
1193
1194	default:
1195		termch = cmd;
1196	        cmd = skipbl();
1197		if (cmd == '?') {
1198			printf(breakpoint_help_string);
1199			break;
1200		}
1201		termch = cmd;
1202		if (!scanhex(&a)) {
1203			/* print all breakpoints */
1204			printf("   type            address\n");
1205			if (dabr.enabled) {
1206				printf("   data   "REG"  [", dabr.address);
1207				if (dabr.enabled & 1)
1208					printf("r");
1209				if (dabr.enabled & 2)
1210					printf("w");
1211				printf("]\n");
1212			}
1213			for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1214				if (!bp->enabled)
1215					continue;
1216				printf("%2x %s   ", BP_NUM(bp),
1217				    (bp->enabled & BP_IABR)? "inst": "trap");
1218				xmon_print_symbol(bp->address, "  ", "\n");
1219			}
1220			break;
1221		}
1222
1223		if (!check_bp_loc(a))
1224			break;
1225		bp = new_breakpoint(a);
1226		if (bp != NULL)
1227			bp->enabled |= BP_TRAP;
1228		break;
1229	}
1230}
1231
1232/* Very cheap human name for vector lookup. */
1233static
1234const char *getvecname(unsigned long vec)
1235{
1236	char *ret;
1237
1238	switch (vec) {
1239	case 0x100:	ret = "(System Reset)"; break;
1240	case 0x200:	ret = "(Machine Check)"; break;
1241	case 0x300:	ret = "(Data Access)"; break;
1242	case 0x380:	ret = "(Data SLB Access)"; break;
1243	case 0x400:	ret = "(Instruction Access)"; break;
1244	case 0x480:	ret = "(Instruction SLB Access)"; break;
1245	case 0x500:	ret = "(Hardware Interrupt)"; break;
1246	case 0x600:	ret = "(Alignment)"; break;
1247	case 0x700:	ret = "(Program Check)"; break;
1248	case 0x800:	ret = "(FPU Unavailable)"; break;
1249	case 0x900:	ret = "(Decrementer)"; break;
1250	case 0xc00:	ret = "(System Call)"; break;
1251	case 0xd00:	ret = "(Single Step)"; break;
1252	case 0xf00:	ret = "(Performance Monitor)"; break;
1253	case 0xf20:	ret = "(Altivec Unavailable)"; break;
1254	case 0x1300:	ret = "(Instruction Breakpoint)"; break;
1255	default: ret = "";
1256	}
1257	return ret;
1258}
1259
1260static void get_function_bounds(unsigned long pc, unsigned long *startp,
1261				unsigned long *endp)
1262{
1263	unsigned long size, offset;
1264	const char *name;
1265
1266	*startp = *endp = 0;
1267	if (pc == 0)
1268		return;
1269	if (setjmp(bus_error_jmp) == 0) {
1270		catch_memory_errors = 1;
1271		sync();
1272		name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1273		if (name != NULL) {
1274			*startp = pc - offset;
1275			*endp = pc - offset + size;
1276		}
1277		sync();
1278	}
1279	catch_memory_errors = 0;
1280}
1281
1282static int xmon_depth_to_print = 64;
1283
1284#define LRSAVE_OFFSET		(STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1285#define MARKER_OFFSET		(STACK_FRAME_MARKER * sizeof(unsigned long))
1286
1287#ifdef __powerpc64__
1288#define REGS_OFFSET		0x70
1289#else
1290#define REGS_OFFSET		16
1291#endif
1292
1293static void xmon_show_stack(unsigned long sp, unsigned long lr,
1294			    unsigned long pc)
1295{
1296	unsigned long ip;
1297	unsigned long newsp;
1298	unsigned long marker;
1299	int count = 0;
1300	struct pt_regs regs;
1301
1302	do {
1303		if (sp < PAGE_OFFSET) {
1304			if (sp != 0)
1305				printf("SP (%lx) is in userspace\n", sp);
1306			break;
1307		}
1308
1309		if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1310		    || !mread(sp, &newsp, sizeof(unsigned long))) {
1311			printf("Couldn't read stack frame at %lx\n", sp);
1312			break;
1313		}
1314
1315		/*
1316		 * For the first stack frame, try to work out if
1317		 * LR and/or the saved LR value in the bottommost
1318		 * stack frame are valid.
1319		 */
1320		if ((pc | lr) != 0) {
1321			unsigned long fnstart, fnend;
1322			unsigned long nextip;
1323			int printip = 1;
1324
1325			get_function_bounds(pc, &fnstart, &fnend);
1326			nextip = 0;
1327			if (newsp > sp)
1328				mread(newsp + LRSAVE_OFFSET, &nextip,
1329				      sizeof(unsigned long));
1330			if (lr == ip) {
1331				if (lr < PAGE_OFFSET
1332				    || (fnstart <= lr && lr < fnend))
1333					printip = 0;
1334			} else if (lr == nextip) {
1335				printip = 0;
1336			} else if (lr >= PAGE_OFFSET
1337				   && !(fnstart <= lr && lr < fnend)) {
1338				printf("[link register   ] ");
1339				xmon_print_symbol(lr, " ", "\n");
1340			}
1341			if (printip) {
1342				printf("["REG"] ", sp);
1343				xmon_print_symbol(ip, " ", " (unreliable)\n");
1344			}
1345			pc = lr = 0;
1346
1347		} else {
1348			printf("["REG"] ", sp);
1349			xmon_print_symbol(ip, " ", "\n");
1350		}
1351
1352		/* Look for "regshere" marker to see if this is
1353		   an exception frame. */
1354		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1355		    && marker == STACK_FRAME_REGS_MARKER) {
1356			if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1357			    != sizeof(regs)) {
1358				printf("Couldn't read registers at %lx\n",
1359				       sp + REGS_OFFSET);
1360				break;
1361			}
1362                        printf("--- Exception: %lx %s at ", regs.trap,
1363			       getvecname(TRAP(&regs)));
1364			pc = regs.nip;
1365			lr = regs.link;
1366			xmon_print_symbol(pc, " ", "\n");
1367		}
1368
1369		if (newsp == 0)
1370			break;
1371
1372		sp = newsp;
1373	} while (count++ < xmon_depth_to_print);
1374}
1375
1376static void backtrace(struct pt_regs *excp)
1377{
1378	unsigned long sp;
1379
1380	if (scanhex(&sp))
1381		xmon_show_stack(sp, 0, 0);
1382	else
1383		xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1384	scannl();
1385}
1386
1387static void print_bug_trap(struct pt_regs *regs)
1388{
1389#ifdef CONFIG_BUG
1390	const struct bug_entry *bug;
1391	unsigned long addr;
1392
1393	if (regs->msr & MSR_PR)
1394		return;		/* not in kernel */
1395	addr = regs->nip;	/* address of trap instruction */
1396	if (addr < PAGE_OFFSET)
1397		return;
1398	bug = find_bug(regs->nip);
1399	if (bug == NULL)
1400		return;
1401	if (is_warning_bug(bug))
1402		return;
1403
1404#ifdef CONFIG_DEBUG_BUGVERBOSE
1405	printf("kernel BUG at %s:%u!\n",
1406	       bug->file, bug->line);
1407#else
1408	printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1409#endif
1410#endif /* CONFIG_BUG */
1411}
1412
1413static void excprint(struct pt_regs *fp)
1414{
1415	unsigned long trap;
1416
1417#ifdef CONFIG_SMP
1418	printf("cpu 0x%x: ", smp_processor_id());
1419#endif /* CONFIG_SMP */
1420
1421	trap = TRAP(fp);
1422	printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1423	printf("    pc: ");
1424	xmon_print_symbol(fp->nip, ": ", "\n");
1425
1426	printf("    lr: ", fp->link);
1427	xmon_print_symbol(fp->link, ": ", "\n");
1428
1429	printf("    sp: %lx\n", fp->gpr[1]);
1430	printf("   msr: %lx\n", fp->msr);
1431
1432	if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1433		printf("   dar: %lx\n", fp->dar);
1434		if (trap != 0x380)
1435			printf(" dsisr: %lx\n", fp->dsisr);
1436	}
1437
1438	printf("  current = 0x%lx\n", current);
1439#ifdef CONFIG_PPC64
1440	printf("  paca    = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1441	       local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1442#endif
1443	if (current) {
1444		printf("    pid   = %ld, comm = %s\n",
1445		       current->pid, current->comm);
1446	}
1447
1448	if (trap == 0x700)
1449		print_bug_trap(fp);
1450}
1451
1452static void prregs(struct pt_regs *fp)
1453{
1454	int n, trap;
1455	unsigned long base;
1456	struct pt_regs regs;
1457
1458	if (scanhex(&base)) {
1459		if (setjmp(bus_error_jmp) == 0) {
1460			catch_memory_errors = 1;
1461			sync();
1462			regs = *(struct pt_regs *)base;
1463			sync();
1464			__delay(200);
1465		} else {
1466			catch_memory_errors = 0;
1467			printf("*** Error reading registers from "REG"\n",
1468			       base);
1469			return;
1470		}
1471		catch_memory_errors = 0;
1472		fp = &regs;
1473	}
1474
1475#ifdef CONFIG_PPC64
1476	if (FULL_REGS(fp)) {
1477		for (n = 0; n < 16; ++n)
1478			printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1479			       n, fp->gpr[n], n+16, fp->gpr[n+16]);
1480	} else {
1481		for (n = 0; n < 7; ++n)
1482			printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1483			       n, fp->gpr[n], n+7, fp->gpr[n+7]);
1484	}
1485#else
1486	for (n = 0; n < 32; ++n) {
1487		printf("R%.2d = %.8x%s", n, fp->gpr[n],
1488		       (n & 3) == 3? "\n": "   ");
1489		if (n == 12 && !FULL_REGS(fp)) {
1490			printf("\n");
1491			break;
1492		}
1493	}
1494#endif
1495	printf("pc  = ");
1496	xmon_print_symbol(fp->nip, " ", "\n");
1497	if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1498		printf("cfar= ");
1499		xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1500	}
1501	printf("lr  = ");
1502	xmon_print_symbol(fp->link, " ", "\n");
1503	printf("msr = "REG"   cr  = %.8lx\n", fp->msr, fp->ccr);
1504	printf("ctr = "REG"   xer = "REG"   trap = %4lx\n",
1505	       fp->ctr, fp->xer, fp->trap);
1506	trap = TRAP(fp);
1507	if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1508		printf("dar = "REG"   dsisr = %.8lx\n", fp->dar, fp->dsisr);
1509}
1510
1511static void cacheflush(void)
1512{
1513	int cmd;
1514	unsigned long nflush;
1515
1516	cmd = inchar();
1517	if (cmd != 'i')
1518		termch = cmd;
1519	scanhex((void *)&adrs);
1520	if (termch != '\n')
1521		termch = 0;
1522	nflush = 1;
1523	scanhex(&nflush);
1524	nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1525	if (setjmp(bus_error_jmp) == 0) {
1526		catch_memory_errors = 1;
1527		sync();
1528
1529		if (cmd != 'i') {
1530			for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1531				cflush((void *) adrs);
1532		} else {
1533			for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1534				cinval((void *) adrs);
1535		}
1536		sync();
1537		/* wait a little while to see if we get a machine check */
1538		__delay(200);
1539	}
1540	catch_memory_errors = 0;
1541}
1542
1543static unsigned long
1544read_spr(int n)
1545{
1546	unsigned int instrs[2];
1547	unsigned long (*code)(void);
1548	unsigned long ret = -1UL;
1549#ifdef CONFIG_PPC64
1550	unsigned long opd[3];
1551
1552	opd[0] = (unsigned long)instrs;
1553	opd[1] = 0;
1554	opd[2] = 0;
1555	code = (unsigned long (*)(void)) opd;
1556#else
1557	code = (unsigned long (*)(void)) instrs;
1558#endif
1559
1560	/* mfspr r3,n; blr */
1561	instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1562	instrs[1] = 0x4e800020;
1563	store_inst(instrs);
1564	store_inst(instrs+1);
1565
1566	if (setjmp(bus_error_jmp) == 0) {
1567		catch_memory_errors = 1;
1568		sync();
1569
1570		ret = code();
1571
1572		sync();
1573		/* wait a little while to see if we get a machine check */
1574		__delay(200);
1575		n = size;
1576	}
1577
1578	return ret;
1579}
1580
1581static void
1582write_spr(int n, unsigned long val)
1583{
1584	unsigned int instrs[2];
1585	unsigned long (*code)(unsigned long);
1586#ifdef CONFIG_PPC64
1587	unsigned long opd[3];
1588
1589	opd[0] = (unsigned long)instrs;
1590	opd[1] = 0;
1591	opd[2] = 0;
1592	code = (unsigned long (*)(unsigned long)) opd;
1593#else
1594	code = (unsigned long (*)(unsigned long)) instrs;
1595#endif
1596
1597	instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1598	instrs[1] = 0x4e800020;
1599	store_inst(instrs);
1600	store_inst(instrs+1);
1601
1602	if (setjmp(bus_error_jmp) == 0) {
1603		catch_memory_errors = 1;
1604		sync();
1605
1606		code(val);
1607
1608		sync();
1609		/* wait a little while to see if we get a machine check */
1610		__delay(200);
1611		n = size;
1612	}
1613}
1614
1615static unsigned long regno;
1616extern char exc_prolog;
1617extern char dec_exc;
1618
1619static void super_regs(void)
1620{
1621	int cmd;
1622	unsigned long val;
1623
1624	cmd = skipbl();
1625	if (cmd == '\n') {
1626	        unsigned long sp, toc;
1627		asm("mr %0,1" : "=r" (sp) :);
1628		asm("mr %0,2" : "=r" (toc) :);
1629
1630		printf("msr  = "REG"  sprg0= "REG"\n",
1631		       mfmsr(), mfspr(SPRN_SPRG0));
1632		printf("pvr  = "REG"  sprg1= "REG"\n",
1633		       mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
1634		printf("dec  = "REG"  sprg2= "REG"\n",
1635		       mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1636		printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1637		printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
1638
1639		return;
1640	}
1641
1642	scanhex(&regno);
1643	switch (cmd) {
1644	case 'w':
1645		val = read_spr(regno);
1646		scanhex(&val);
1647		write_spr(regno, val);
1648		/* fall through */
1649	case 'r':
1650		printf("spr %lx = %lx\n", regno, read_spr(regno));
1651		break;
1652	}
1653	scannl();
1654}
1655
1656/*
1657 * Stuff for reading and writing memory safely
1658 */
1659static int
1660mread(unsigned long adrs, void *buf, int size)
1661{
1662	volatile int n;
1663	char *p, *q;
1664
1665	n = 0;
1666	if (setjmp(bus_error_jmp) == 0) {
1667		catch_memory_errors = 1;
1668		sync();
1669		p = (char *)adrs;
1670		q = (char *)buf;
1671		switch (size) {
1672		case 2:
1673			*(u16 *)q = *(u16 *)p;
1674			break;
1675		case 4:
1676			*(u32 *)q = *(u32 *)p;
1677			break;
1678		case 8:
1679			*(u64 *)q = *(u64 *)p;
1680			break;
1681		default:
1682			for( ; n < size; ++n) {
1683				*q++ = *p++;
1684				sync();
1685			}
1686		}
1687		sync();
1688		/* wait a little while to see if we get a machine check */
1689		__delay(200);
1690		n = size;
1691	}
1692	catch_memory_errors = 0;
1693	return n;
1694}
1695
1696static int
1697mwrite(unsigned long adrs, void *buf, int size)
1698{
1699	volatile int n;
1700	char *p, *q;
1701
1702	n = 0;
1703	if (setjmp(bus_error_jmp) == 0) {
1704		catch_memory_errors = 1;
1705		sync();
1706		p = (char *) adrs;
1707		q = (char *) buf;
1708		switch (size) {
1709		case 2:
1710			*(u16 *)p = *(u16 *)q;
1711			break;
1712		case 4:
1713			*(u32 *)p = *(u32 *)q;
1714			break;
1715		case 8:
1716			*(u64 *)p = *(u64 *)q;
1717			break;
1718		default:
1719			for ( ; n < size; ++n) {
1720				*p++ = *q++;
1721				sync();
1722			}
1723		}
1724		sync();
1725		/* wait a little while to see if we get a machine check */
1726		__delay(200);
1727		n = size;
1728	} else {
1729		printf("*** Error writing address %x\n", adrs + n);
1730	}
1731	catch_memory_errors = 0;
1732	return n;
1733}
1734
1735static int fault_type;
1736static int fault_except;
1737static char *fault_chars[] = { "--", "**", "##" };
1738
1739static int handle_fault(struct pt_regs *regs)
1740{
1741	fault_except = TRAP(regs);
1742	switch (TRAP(regs)) {
1743	case 0x200:
1744		fault_type = 0;
1745		break;
1746	case 0x300:
1747	case 0x380:
1748		fault_type = 1;
1749		break;
1750	default:
1751		fault_type = 2;
1752	}
1753
1754	longjmp(bus_error_jmp, 1);
1755
1756	return 0;
1757}
1758
1759#define SWAP(a, b, t)	((t) = (a), (a) = (b), (b) = (t))
1760
1761static void
1762byterev(unsigned char *val, int size)
1763{
1764	int t;
1765	
1766	switch (size) {
1767	case 2:
1768		SWAP(val[0], val[1], t);
1769		break;
1770	case 4:
1771		SWAP(val[0], val[3], t);
1772		SWAP(val[1], val[2], t);
1773		break;
1774	case 8: /* is there really any use for this? */
1775		SWAP(val[0], val[7], t);
1776		SWAP(val[1], val[6], t);
1777		SWAP(val[2], val[5], t);
1778		SWAP(val[3], val[4], t);
1779		break;
1780	}
1781}
1782
1783static int brev;
1784static int mnoread;
1785
1786static char *memex_help_string = 
1787    "Memory examine command usage:\n"
1788    "m [addr] [flags] examine/change memory\n"
1789    "  addr is optional.  will start where left off.\n"
1790    "  flags may include chars from this set:\n"
1791    "    b   modify by bytes (default)\n"
1792    "    w   modify by words (2 byte)\n"
1793    "    l   modify by longs (4 byte)\n"
1794    "    d   modify by doubleword (8 byte)\n"
1795    "    r   toggle reverse byte order mode\n"
1796    "    n   do not read memory (for i/o spaces)\n"
1797    "    .   ok to read (default)\n"
1798    "NOTE: flags are saved as defaults\n"
1799    "";
1800
1801static char *memex_subcmd_help_string = 
1802    "Memory examine subcommands:\n"
1803    "  hexval   write this val to current location\n"
1804    "  'string' write chars from string to this location\n"
1805    "  '        increment address\n"
1806    "  ^        decrement address\n"
1807    "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1808    "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1809    "  `        clear no-read flag\n"
1810    "  ;        stay at this addr\n"
1811    "  v        change to byte mode\n"
1812    "  w        change to word (2 byte) mode\n"
1813    "  l        change to long (4 byte) mode\n"
1814    "  u        change to doubleword (8 byte) mode\n"
1815    "  m addr   change current addr\n"
1816    "  n        toggle no-read flag\n"
1817    "  r        toggle byte reverse flag\n"
1818    "  < count  back up count bytes\n"
1819    "  > count  skip forward count bytes\n"
1820    "  x        exit this mode\n"
1821    "";
1822
1823static void
1824memex(void)
1825{
1826	int cmd, inc, i, nslash;
1827	unsigned long n;
1828	unsigned char val[16];
1829
1830	scanhex((void *)&adrs);
1831	cmd = skipbl();
1832	if (cmd == '?') {
1833		printf(memex_help_string);
1834		return;
1835	} else {
1836		termch = cmd;
1837	}
1838	last_cmd = "m\n";
1839	while ((cmd = skipbl()) != '\n') {
1840		switch( cmd ){
1841		case 'b':	size = 1;	break;
1842		case 'w':	size = 2;	break;
1843		case 'l':	size = 4;	break;
1844		case 'd':	size = 8;	break;
1845		case 'r': 	brev = !brev;	break;
1846		case 'n':	mnoread = 1;	break;
1847		case '.':	mnoread = 0;	break;
1848		}
1849	}
1850	if( size <= 0 )
1851		size = 1;
1852	else if( size > 8 )
1853		size = 8;
1854	for(;;){
1855		if (!mnoread)
1856			n = mread(adrs, val, size);
1857		printf(REG"%c", adrs, brev? 'r': ' ');
1858		if (!mnoread) {
1859			if (brev)
1860				byterev(val, size);
1861			putchar(' ');
1862			for (i = 0; i < n; ++i)
1863				printf("%.2x", val[i]);
1864			for (; i < size; ++i)
1865				printf("%s", fault_chars[fault_type]);
1866		}
1867		putchar(' ');
1868		inc = size;
1869		nslash = 0;
1870		for(;;){
1871			if( scanhex(&n) ){
1872				for (i = 0; i < size; ++i)
1873					val[i] = n >> (i * 8);
1874				if (!brev)
1875					byterev(val, size);
1876				mwrite(adrs, val, size);
1877				inc = size;
1878			}
1879			cmd = skipbl();
1880			if (cmd == '\n')
1881				break;
1882			inc = 0;
1883			switch (cmd) {
1884			case '\'':
1885				for(;;){
1886					n = inchar();
1887					if( n == '\\' )
1888						n = bsesc();
1889					else if( n == '\'' )
1890						break;
1891					for (i = 0; i < size; ++i)
1892						val[i] = n >> (i * 8);
1893					if (!brev)
1894						byterev(val, size);
1895					mwrite(adrs, val, size);
1896					adrs += size;
1897				}
1898				adrs -= size;
1899				inc = size;
1900				break;
1901			case ',':
1902				adrs += size;
1903				break;
1904			case '.':
1905				mnoread = 0;
1906				break;
1907			case ';':
1908				break;
1909			case 'x':
1910			case EOF:
1911				scannl();
1912				return;
1913			case 'b':
1914			case 'v':
1915				size = 1;
1916				break;
1917			case 'w':
1918				size = 2;
1919				break;
1920			case 'l':
1921				size = 4;
1922				break;
1923			case 'u':
1924				size = 8;
1925				break;
1926			case '^':
1927				adrs -= size;
1928				break;
1929				break;
1930			case '/':
1931				if (nslash > 0)
1932					adrs -= 1 << nslash;
1933				else
1934					nslash = 0;
1935				nslash += 4;
1936				adrs += 1 << nslash;
1937				break;
1938			case '\\':
1939				if (nslash < 0)
1940					adrs += 1 << -nslash;
1941				else
1942					nslash = 0;
1943				nslash -= 4;
1944				adrs -= 1 << -nslash;
1945				break;
1946			case 'm':
1947				scanhex((void *)&adrs);
1948				break;
1949			case 'n':
1950				mnoread = 1;
1951				break;
1952			case 'r':
1953				brev = !brev;
1954				break;
1955			case '<':
1956				n = size;
1957				scanhex(&n);
1958				adrs -= n;
1959				break;
1960			case '>':
1961				n = size;
1962				scanhex(&n);
1963				adrs += n;
1964				break;
1965			case '?':
1966				printf(memex_subcmd_help_string);
1967				break;
1968			}
1969		}
1970		adrs += inc;
1971	}
1972}
1973
1974static int
1975bsesc(void)
1976{
1977	int c;
1978
1979	c = inchar();
1980	switch( c ){
1981	case 'n':	c = '\n';	break;
1982	case 'r':	c = '\r';	break;
1983	case 'b':	c = '\b';	break;
1984	case 't':	c = '\t';	break;
1985	}
1986	return c;
1987}
1988
1989static void xmon_rawdump (unsigned long adrs, long ndump)
1990{
1991	long n, m, r, nr;
1992	unsigned char temp[16];
1993
1994	for (n = ndump; n > 0;) {
1995		r = n < 16? n: 16;
1996		nr = mread(adrs, temp, r);
1997		adrs += nr;
1998		for (m = 0; m < r; ++m) {
1999			if (m < nr)
2000				printf("%.2x", temp[m]);
2001			else
2002				printf("%s", fault_chars[fault_type]);
2003		}
2004		n -= r;
2005		if (nr < r)
2006			break;
2007	}
2008	printf("\n");
2009}
2010
2011#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
2012			 || ('a' <= (c) && (c) <= 'f') \
2013			 || ('A' <= (c) && (c) <= 'F'))
2014static void
2015dump(void)
2016{
2017	int c;
2018
2019	c = inchar();
2020	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2021		termch = c;
2022	scanhex((void *)&adrs);
2023	if (termch != '\n')
2024		termch = 0;
2025	if (c == 'i') {
2026		scanhex(&nidump);
2027		if (nidump == 0)
2028			nidump = 16;
2029		else if (nidump > MAX_DUMP)
2030			nidump = MAX_DUMP;
2031		adrs += ppc_inst_dump(adrs, nidump, 1);
2032		last_cmd = "di\n";
2033	} else if (c == 'l') {
2034		dump_log_buf();
2035	} else if (c == 'r') {
2036		scanhex(&ndump);
2037		if (ndump == 0)
2038			ndump = 64;
2039		xmon_rawdump(adrs, ndump);
2040		adrs += ndump;
2041		last_cmd = "dr\n";
2042	} else {
2043		scanhex(&ndump);
2044		if (ndump == 0)
2045			ndump = 64;
2046		else if (ndump > MAX_DUMP)
2047			ndump = MAX_DUMP;
2048		prdump(adrs, ndump);
2049		adrs += ndump;
2050		last_cmd = "d\n";
2051	}
2052}
2053
2054static void
2055prdump(unsigned long adrs, long ndump)
2056{
2057	long n, m, c, r, nr;
2058	unsigned char temp[16];
2059
2060	for (n = ndump; n > 0;) {
2061		printf(REG, adrs);
2062		putchar(' ');
2063		r = n < 16? n: 16;
2064		nr = mread(adrs, temp, r);
2065		adrs += nr;
2066		for (m = 0; m < r; ++m) {
2067		        if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2068				putchar(' ');
2069			if (m < nr)
2070				printf("%.2x", temp[m]);
2071			else
2072				printf("%s", fault_chars[fault_type]);
2073		}
2074		for (; m < 16; ++m) {
2075		        if ((m & (sizeof(long) - 1)) == 0)
2076				putchar(' ');
2077			printf("  ");
2078		}
2079		printf("  |");
2080		for (m = 0; m < r; ++m) {
2081			if (m < nr) {
2082				c = temp[m];
2083				putchar(' ' <= c && c <= '~'? c: '.');
2084			} else
2085				putchar(' ');
2086		}
2087		n -= r;
2088		for (; m < 16; ++m)
2089			putchar(' ');
2090		printf("|\n");
2091		if (nr < r)
2092			break;
2093	}
2094}
2095
2096typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2097
2098static int
2099generic_inst_dump(unsigned long adr, long count, int praddr,
2100			instruction_dump_func dump_func)
2101{
2102	int nr, dotted;
2103	unsigned long first_adr;
2104	unsigned long inst, last_inst = 0;
2105	unsigned char val[4];
2106
2107	dotted = 0;
2108	for (first_adr = adr; count > 0; --count, adr += 4) {
2109		nr = mread(adr, val, 4);
2110		if (nr == 0) {
2111			if (praddr) {
2112				const char *x = fault_chars[fault_type];
2113				printf(REG"  %s%s%s%s\n", adr, x, x, x, x);
2114			}
2115			break;
2116		}
2117		inst = GETWORD(val);
2118		if (adr > first_adr && inst == last_inst) {
2119			if (!dotted) {
2120				printf(" ...\n");
2121				dotted = 1;
2122			}
2123			continue;
2124		}
2125		dotted = 0;
2126		last_inst = inst;
2127		if (praddr)
2128			printf(REG"  %.8x", adr, inst);
2129		printf("\t");
2130		dump_func(inst, adr);
2131		printf("\n");
2132	}
2133	return adr - first_adr;
2134}
2135
2136static int
2137ppc_inst_dump(unsigned long adr, long count, int praddr)
2138{
2139	return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2140}
2141
2142void
2143print_address(unsigned long addr)
2144{
2145	xmon_print_symbol(addr, "\t# ", "");
2146}
2147
2148void
2149dump_log_buf(void)
2150{
2151        const unsigned long size = 128;
2152        unsigned long end, addr;
2153        unsigned char buf[size + 1];
2154
2155        addr = 0;
2156        buf[size] = '\0';
2157
2158        if (setjmp(bus_error_jmp) != 0) {
2159                printf("Unable to lookup symbol __log_buf!\n");
2160                return;
2161        }
2162
2163        catch_memory_errors = 1;
2164        sync();
2165        addr = kallsyms_lookup_name("__log_buf");
2166
2167        if (! addr)
2168                printf("Symbol __log_buf not found!\n");
2169        else {
2170                end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
2171                while (addr < end) {
2172                        if (! mread(addr, buf, size)) {
2173                                printf("Can't read memory at address 0x%lx\n", addr);
2174                                break;
2175                        }
2176
2177                        printf("%s", buf);
2178
2179                        if (strlen(buf) < size)
2180                                break;
2181
2182                        addr += size;
2183                }
2184        }
2185
2186        sync();
2187        /* wait a little while to see if we get a machine check */
2188        __delay(200);
2189        catch_memory_errors = 0;
2190}
2191
2192/*
2193 * Memory operations - move, set, print differences
2194 */
2195static unsigned long mdest;		/* destination address */
2196static unsigned long msrc;		/* source address */
2197static unsigned long mval;		/* byte value to set memory to */
2198static unsigned long mcount;		/* # bytes to affect */
2199static unsigned long mdiffs;		/* max # differences to print */
2200
2201static void
2202memops(int cmd)
2203{
2204	scanhex((void *)&mdest);
2205	if( termch != '\n' )
2206		termch = 0;
2207	scanhex((void *)(cmd == 's'? &mval: &msrc));
2208	if( termch != '\n' )
2209		termch = 0;
2210	scanhex((void *)&mcount);
2211	switch( cmd ){
2212	case 'm':
2213		memmove((void *)mdest, (void *)msrc, mcount);
2214		break;
2215	case 's':
2216		memset((void *)mdest, mval, mcount);
2217		break;
2218	case 'd':
2219		if( termch != '\n' )
2220			termch = 0;
2221		scanhex((void *)&mdiffs);
2222		memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2223		break;
2224	}
2225}
2226
2227static void
2228memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2229{
2230	unsigned n, prt;
2231
2232	prt = 0;
2233	for( n = nb; n > 0; --n )
2234		if( *p1++ != *p2++ )
2235			if( ++prt <= maxpr )
2236				printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2237					p1[-1], p2 - 1, p2[-1]);
2238	if( prt > maxpr )
2239		printf("Total of %d differences\n", prt);
2240}
2241
2242static unsigned mend;
2243static unsigned mask;
2244
2245static void
2246memlocate(void)
2247{
2248	unsigned a, n;
2249	unsigned char val[4];
2250
2251	last_cmd = "ml";
2252	scanhex((void *)&mdest);
2253	if (termch != '\n') {
2254		termch = 0;
2255		scanhex((void *)&mend);
2256		if (termch != '\n') {
2257			termch = 0;
2258			scanhex((void *)&mval);
2259			mask = ~0;
2260			if (termch != '\n') termch = 0;
2261			scanhex((void *)&mask);
2262		}
2263	}
2264	n = 0;
2265	for (a = mdest; a < mend; a += 4) {
2266		if (mread(a, val, 4) == 4
2267			&& ((GETWORD(val) ^ mval) & mask) == 0) {
2268			printf("%.16x:  %.16x\n", a, GETWORD(val));
2269			if (++n >= 10)
2270				break;
2271		}
2272	}
2273}
2274
2275static unsigned long mskip = 0x1000;
2276static unsigned long mlim = 0xffffffff;
2277
2278static void
2279memzcan(void)
2280{
2281	unsigned char v;
2282	unsigned a;
2283	int ok, ook;
2284
2285	scanhex(&mdest);
2286	if (termch != '\n') termch = 0;
2287	scanhex(&mskip);
2288	if (termch != '\n') termch = 0;
2289	scanhex(&mlim);
2290	ook = 0;
2291	for (a = mdest; a < mlim; a += mskip) {
2292		ok = mread(a, &v, 1);
2293		if (ok && !ook) {
2294			printf("%.8x .. ", a);
2295		} else if (!ok && ook)
2296			printf("%.8x\n", a - mskip);
2297		ook = ok;
2298		if (a + mskip < a)
2299			break;
2300	}
2301	if (ook)
2302		printf("%.8x\n", a - mskip);
2303}
2304
2305static void proccall(void)
2306{
2307	unsigned long args[8];
2308	unsigned long ret;
2309	int i;
2310	typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2311			unsigned long, unsigned long, unsigned long,
2312			unsigned long, unsigned long, unsigned long);
2313	callfunc_t func;
2314
2315	if (!scanhex(&adrs))
2316		return;
2317	if (termch != '\n')
2318		termch = 0;
2319	for (i = 0; i < 8; ++i)
2320		args[i] = 0;
2321	for (i = 0; i < 8; ++i) {
2322		if (!scanhex(&args[i]) || termch == '\n')
2323			break;
2324		termch = 0;
2325	}
2326	func = (callfunc_t) adrs;
2327	ret = 0;
2328	if (setjmp(bus_error_jmp) == 0) {
2329		catch_memory_errors = 1;
2330		sync();
2331		ret = func(args[0], args[1], args[2], args[3],
2332			   args[4], args[5], args[6], args[7]);
2333		sync();
2334		printf("return value is %x\n", ret);
2335	} else {
2336		printf("*** %x exception occurred\n", fault_except);
2337	}
2338	catch_memory_errors = 0;
2339}
2340
2341/* Input scanning routines */
2342int
2343skipbl(void)
2344{
2345	int c;
2346
2347	if( termch != 0 ){
2348		c = termch;
2349		termch = 0;
2350	} else
2351		c = inchar();
2352	while( c == ' ' || c == '\t' )
2353		c = inchar();
2354	return c;
2355}
2356
2357#define N_PTREGS	44
2358static char *regnames[N_PTREGS] = {
2359	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2360	"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2361	"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2362	"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2363	"pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2364#ifdef CONFIG_PPC64
2365	"softe",
2366#else
2367	"mq",
2368#endif
2369	"trap", "dar", "dsisr", "res"
2370};
2371
2372int
2373scanhex(unsigned long *vp)
2374{
2375	int c, d;
2376	unsigned long v;
2377
2378	c = skipbl();
2379	if (c == '%') {
2380		/* parse register name */
2381		char regname[8];
2382		int i;
2383
2384		for (i = 0; i < sizeof(regname) - 1; ++i) {
2385			c = inchar();
2386			if (!isalnum(c)) {
2387				termch = c;
2388				break;
2389			}
2390			regname[i] = c;
2391		}
2392		regname[i] = 0;
2393		for (i = 0; i < N_PTREGS; ++i) {
2394			if (strcmp(regnames[i], regname) == 0) {
2395				if (xmon_regs == NULL) {
2396					printf("regs not available\n");
2397					return 0;
2398				}
2399				*vp = ((unsigned long *)xmon_regs)[i];
2400				return 1;
2401			}
2402		}
2403		printf("invalid register name '%%%s'\n", regname);
2404		return 0;
2405	}
2406
2407	/* skip leading "0x" if any */
2408
2409	if (c == '0') {
2410		c = inchar();
2411		if (c == 'x') {
2412			c = inchar();
2413		} else {
2414			d = hexdigit(c);
2415			if (d == EOF) {
2416				termch = c;
2417				*vp = 0;
2418				return 1;
2419			}
2420		}
2421	} else if (c == '$') {
2422		int i;
2423		for (i=0; i<63; i++) {
2424			c = inchar();
2425			if (isspace(c)) {
2426				termch = c;
2427				break;
2428			}
2429			tmpstr[i] = c;
2430		}
2431		tmpstr[i++] = 0;
2432		*vp = 0;
2433		if (setjmp(bus_error_jmp) == 0) {
2434			catch_memory_errors = 1;
2435			sync();
2436			*vp = kallsyms_lookup_name(tmpstr);
2437			sync();
2438		}
2439		catch_memory_errors = 0;
2440		if (!(*vp)) {
2441			printf("unknown symbol '%s'\n", tmpstr);
2442			return 0;
2443		}
2444		return 1;
2445	}
2446
2447	d = hexdigit(c);
2448	if (d == EOF) {
2449		termch = c;
2450		return 0;
2451	}
2452	v = 0;
2453	do {
2454		v = (v << 4) + d;
2455		c = inchar();
2456		d = hexdigit(c);
2457	} while (d != EOF);
2458	termch = c;
2459	*vp = v;
2460	return 1;
2461}
2462
2463static void
2464scannl(void)
2465{
2466	int c;
2467
2468	c = termch;
2469	termch = 0;
2470	while( c != '\n' )
2471		c = inchar();
2472}
2473
2474static int hexdigit(int c)
2475{
2476	if( '0' <= c && c <= '9' )
2477		return c - '0';
2478	if( 'A' <= c && c <= 'F' )
2479		return c - ('A' - 10);
2480	if( 'a' <= c && c <= 'f' )
2481		return c - ('a' - 10);
2482	return EOF;
2483}
2484
2485void
2486getstring(char *s, int size)
2487{
2488	int c;
2489
2490	c = skipbl();
2491	do {
2492		if( size > 1 ){
2493			*s++ = c;
2494			--size;
2495		}
2496		c = inchar();
2497	} while( c != ' ' && c != '\t' && c != '\n' );
2498	termch = c;
2499	*s = 0;
2500}
2501
2502static char line[256];
2503static char *lineptr;
2504
2505static void
2506flush_input(void)
2507{
2508	lineptr = NULL;
2509}
2510
2511static int
2512inchar(void)
2513{
2514	if (lineptr == NULL || *lineptr == 0) {
2515		if (xmon_gets(line, sizeof(line)) == NULL) {
2516			lineptr = NULL;
2517			return EOF;
2518		}
2519		lineptr = line;
2520	}
2521	return *lineptr++;
2522}
2523
2524static void
2525take_input(char *str)
2526{
2527	lineptr = str;
2528}
2529
2530
2531static void
2532symbol_lookup(void)
2533{
2534	int type = inchar();
2535	unsigned long addr;
2536	static char tmp[64];
2537
2538	switch (type) {
2539	case 'a':
2540		if (scanhex(&addr))
2541			xmon_print_symbol(addr, ": ", "\n");
2542		termch = 0;
2543		break;
2544	case 's':
2545		getstring(tmp, 64);
2546		if (setjmp(bus_error_jmp) == 0) {
2547			catch_memory_errors = 1;
2548			sync();
2549			addr = kallsyms_lookup_name(tmp);
2550			if (addr)
2551				printf("%s: %lx\n", tmp, addr);
2552			else
2553				printf("Symbol '%s' not found.\n", tmp);
2554			sync();
2555		}
2556		catch_memory_errors = 0;
2557		termch = 0;
2558		break;
2559	}
2560}
2561
2562
2563/* Print an address in numeric and symbolic form (if possible) */
2564static void xmon_print_symbol(unsigned long address, const char *mid,
2565			      const char *after)
2566{
2567	char *modname;
2568	const char *name = NULL;
2569	unsigned long offset, size;
2570
2571	printf(REG, address);
2572	if (setjmp(bus_error_jmp) == 0) {
2573		catch_memory_errors = 1;
2574		sync();
2575		name = kallsyms_lookup(address, &size, &offset, &modname,
2576				       tmpstr);
2577		sync();
2578		/* wait a little while to see if we get a machine check */
2579		__delay(200);
2580	}
2581
2582	catch_memory_errors = 0;
2583
2584	if (name) {
2585		printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2586		if (modname)
2587			printf(" [%s]", modname);
2588	}
2589	printf("%s", after);
2590}
2591
2592#ifdef CONFIG_PPC_BOOK3S_64
2593static void dump_slb(void)
2594{
2595	int i;
2596	unsigned long esid,vsid,valid;
2597	unsigned long llp;
2598
2599	printf("SLB contents of cpu %x\n", smp_processor_id());
2600
2601	for (i = 0; i < mmu_slb_size; i++) {
2602		asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
2603		asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
2604		valid = (esid & SLB_ESID_V);
2605		if (valid | esid | vsid) {
2606			printf("%02d %016lx %016lx", i, esid, vsid);
2607			if (valid) {
2608				llp = vsid & SLB_VSID_LLP;
2609				if (vsid & SLB_VSID_B_1T) {
2610					printf("  1T  ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2611						GET_ESID_1T(esid),
2612						(vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2613						llp);
2614				} else {
2615					printf(" 256M ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2616						GET_ESID(esid),
2617						(vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2618						llp);
2619				}
2620			} else
2621				printf("\n");
2622		}
2623	}
2624}
2625
2626static void dump_stab(void)
2627{
2628	int i;
2629	unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
2630
2631	printf("Segment table contents of cpu %x\n", smp_processor_id());
2632
2633	for (i = 0; i < PAGE_SIZE/16; i++) {
2634		unsigned long a, b;
2635
2636		a = *tmp++;
2637		b = *tmp++;
2638
2639		if (a || b) {
2640			printf("%03d %016lx ", i, a);
2641			printf("%016lx\n", b);
2642		}
2643	}
2644}
2645
2646void dump_segments(void)
2647{
2648	if (mmu_has_feature(MMU_FTR_SLB))
2649		dump_slb();
2650	else
2651		dump_stab();
2652}
2653#endif
2654
2655#ifdef CONFIG_PPC_STD_MMU_32
2656void dump_segments(void)
2657{
2658	int i;
2659
2660	printf("sr0-15 =");
2661	for (i = 0; i < 16; ++i)
2662		printf(" %x", mfsrin(i));
2663	printf("\n");
2664}
2665#endif
2666
2667#ifdef CONFIG_44x
2668static void dump_tlb_44x(void)
2669{
2670	int i;
2671
2672	for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2673		unsigned long w0,w1,w2;
2674		asm volatile("tlbre  %0,%1,0" : "=r" (w0) : "r" (i));
2675		asm volatile("tlbre  %0,%1,1" : "=r" (w1) : "r" (i));
2676		asm volatile("tlbre  %0,%1,2" : "=r" (w2) : "r" (i));
2677		printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2678		if (w0 & PPC44x_TLB_VALID) {
2679			printf("V %08x -> %01x%08x %c%c%c%c%c",
2680			       w0 & PPC44x_TLB_EPN_MASK,
2681			       w1 & PPC44x_TLB_ERPN_MASK,
2682			       w1 & PPC44x_TLB_RPN_MASK,
2683			       (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2684			       (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2685			       (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2686			       (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2687			       (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2688		}
2689		printf("\n");
2690	}
2691}
2692#endif /* CONFIG_44x */
2693
2694#ifdef CONFIG_PPC_BOOK3E
2695static void dump_tlb_book3e(void)
2696{
2697	u32 mmucfg, pidmask, lpidmask;
2698	u64 ramask;
2699	int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2700	int mmu_version;
2701	static const char *pgsz_names[] = {
2702		"  1K",
2703		"  2K",
2704		"  4K",
2705		"  8K",
2706		" 16K",
2707		" 32K",
2708		" 64K",
2709		"128K",
2710		"256K",
2711		"512K",
2712		"  1M",
2713		"  2M",
2714		"  4M",
2715		"  8M",
2716		" 16M",
2717		" 32M",
2718		" 64M",
2719		"128M",
2720		"256M",
2721		"512M",
2722		"  1G",
2723		"  2G",
2724		"  4G",
2725		"  8G",
2726		" 16G",
2727		" 32G",
2728		" 64G",
2729		"128G",
2730		"256G",
2731		"512G",
2732		"  1T",
2733		"  2T",
2734	};
2735
2736	/* Gather some infos about the MMU */
2737	mmucfg = mfspr(SPRN_MMUCFG);
2738	mmu_version = (mmucfg & 3) + 1;
2739	ntlbs = ((mmucfg >> 2) & 3) + 1;
2740	pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2741	lpidsz = (mmucfg >> 24) & 0xf;
2742	rasz = (mmucfg >> 16) & 0x7f;
2743	if ((mmu_version > 1) && (mmucfg & 0x10000))
2744		lrat = 1;
2745	printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2746	       mmu_version, ntlbs, pidsz, lpidsz, rasz);
2747	pidmask = (1ul << pidsz) - 1;
2748	lpidmask = (1ul << lpidsz) - 1;
2749	ramask = (1ull << rasz) - 1;
2750
2751	for (tlb = 0; tlb < ntlbs; tlb++) {
2752		u32 tlbcfg;
2753		int nent, assoc, new_cc = 1;
2754		printf("TLB %d:\n------\n", tlb);
2755		switch(tlb) {
2756		case 0:
2757			tlbcfg = mfspr(SPRN_TLB0CFG);
2758			break;
2759		case 1:
2760			tlbcfg = mfspr(SPRN_TLB1CFG);
2761			break;
2762		case 2:
2763			tlbcfg = mfspr(SPRN_TLB2CFG);
2764			break;
2765		case 3:
2766			tlbcfg = mfspr(SPRN_TLB3CFG);
2767			break;
2768		default:
2769			printf("Unsupported TLB number !\n");
2770			continue;
2771		}
2772		nent = tlbcfg & 0xfff;
2773		assoc = (tlbcfg >> 24) & 0xff;
2774		for (i = 0; i < nent; i++) {
2775			u32 mas0 = MAS0_TLBSEL(tlb);
2776			u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2777			u64 mas2 = 0;
2778			u64 mas7_mas3;
2779			int esel = i, cc = i;
2780
2781			if (assoc != 0) {
2782				cc = i / assoc;
2783				esel = i % assoc;
2784				mas2 = cc * 0x1000;
2785			}
2786
2787			mas0 |= MAS0_ESEL(esel);
2788			mtspr(SPRN_MAS0, mas0);
2789			mtspr(SPRN_MAS1, mas1);
2790			mtspr(SPRN_MAS2, mas2);
2791			asm volatile("tlbre  0,0,0" : : : "memory");
2792			mas1 = mfspr(SPRN_MAS1);
2793			mas2 = mfspr(SPRN_MAS2);
2794			mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2795			if (assoc && (i % assoc) == 0)
2796				new_cc = 1;
2797			if (!(mas1 & MAS1_VALID))
2798				continue;
2799			if (assoc == 0)
2800				printf("%04x- ", i);
2801			else if (new_cc)
2802				printf("%04x-%c", cc, 'A' + esel);
2803			else
2804				printf("    |%c", 'A' + esel);
2805			new_cc = 0;
2806			printf(" %016llx %04x %s %c%c AS%c",
2807			       mas2 & ~0x3ffull,
2808			       (mas1 >> 16) & 0x3fff,
2809			       pgsz_names[(mas1 >> 7) & 0x1f],
2810			       mas1 & MAS1_IND ? 'I' : ' ',
2811			       mas1 & MAS1_IPROT ? 'P' : ' ',
2812			       mas1 & MAS1_TS ? '1' : '0');
2813			printf(" %c%c%c%c%c%c%c",
2814			       mas2 & MAS2_X0 ? 'a' : ' ',
2815			       mas2 & MAS2_X1 ? 'v' : ' ',
2816			       mas2 & MAS2_W  ? 'w' : ' ',
2817			       mas2 & MAS2_I  ? 'i' : ' ',
2818			       mas2 & MAS2_M  ? 'm' : ' ',
2819			       mas2 & MAS2_G  ? 'g' : ' ',
2820			       mas2 & MAS2_E  ? 'e' : ' ');
2821			printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2822			if (mas1 & MAS1_IND)
2823				printf(" %s\n",
2824				       pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2825			else
2826				printf(" U%c%c%c S%c%c%c\n",
2827				       mas7_mas3 & MAS3_UX ? 'x' : ' ',
2828				       mas7_mas3 & MAS3_UW ? 'w' : ' ',
2829				       mas7_mas3 & MAS3_UR ? 'r' : ' ',
2830				       mas7_mas3 & MAS3_SX ? 'x' : ' ',
2831				       mas7_mas3 & MAS3_SW ? 'w' : ' ',
2832				       mas7_mas3 & MAS3_SR ? 'r' : ' ');
2833		}
2834	}
2835}
2836#endif /* CONFIG_PPC_BOOK3E */
2837
2838static void xmon_init(int enable)
2839{
2840	if (enable) {
2841		__debugger = xmon;
2842		__debugger_ipi = xmon_ipi;
2843		__debugger_bpt = xmon_bpt;
2844		__debugger_sstep = xmon_sstep;
2845		__debugger_iabr_match = xmon_iabr_match;
2846		__debugger_dabr_match = xmon_dabr_match;
2847		__debugger_fault_handler = xmon_fault_handler;
2848	} else {
2849		__debugger = NULL;
2850		__debugger_ipi = NULL;
2851		__debugger_bpt = NULL;
2852		__debugger_sstep = NULL;
2853		__debugger_iabr_match = NULL;
2854		__debugger_dabr_match = NULL;
2855		__debugger_fault_handler = NULL;
2856	}
2857	xmon_map_scc();
2858}
2859
2860#ifdef CONFIG_MAGIC_SYSRQ
2861static void sysrq_handle_xmon(int key)
2862{
2863	/* ensure xmon is enabled */
2864	xmon_init(1);
2865	debugger(get_irq_regs());
2866}
2867
2868static struct sysrq_key_op sysrq_xmon_op = {
2869	.handler =	sysrq_handle_xmon,
2870	.help_msg =	"Xmon",
2871	.action_msg =	"Entering xmon",
2872};
2873
2874static int __init setup_xmon_sysrq(void)
2875{
2876	register_sysrq_key('x', &sysrq_xmon_op);
2877	return 0;
2878}
2879__initcall(setup_xmon_sysrq);
2880#endif /* CONFIG_MAGIC_SYSRQ */
2881
2882static int __initdata xmon_early, xmon_off;
2883
2884static int __init early_parse_xmon(char *p)
2885{
2886	if (!p || strncmp(p, "early", 5) == 0) {
2887		/* just "xmon" is equivalent to "xmon=early" */
2888		xmon_init(1);
2889		xmon_early = 1;
2890	} else if (strncmp(p, "on", 2) == 0)
2891		xmon_init(1);
2892	else if (strncmp(p, "off", 3) == 0)
2893		xmon_off = 1;
2894	else if (strncmp(p, "nobt", 4) == 0)
2895		xmon_no_auto_backtrace = 1;
2896	else
2897		return 1;
2898
2899	return 0;
2900}
2901early_param("xmon", early_parse_xmon);
2902
2903void __init xmon_setup(void)
2904{
2905#ifdef CONFIG_XMON_DEFAULT
2906	if (!xmon_off)
2907		xmon_init(1);
2908#endif
2909	if (xmon_early)
2910		debugger(NULL);
2911}
2912
2913#ifdef CONFIG_SPU_BASE
2914
2915struct spu_info {
2916	struct spu *spu;
2917	u64 saved_mfc_sr1_RW;
2918	u32 saved_spu_runcntl_RW;
2919	unsigned long dump_addr;
2920	u8 stopped_ok;
2921};
2922
2923#define XMON_NUM_SPUS	16	/* Enough for current hardware */
2924
2925static struct spu_info spu_info[XMON_NUM_SPUS];
2926
2927void xmon_register_spus(struct list_head *list)
2928{
2929	struct spu *spu;
2930
2931	list_for_each_entry(spu, list, full_list) {
2932		if (spu->number >= XMON_NUM_SPUS) {
2933			WARN_ON(1);
2934			continue;
2935		}
2936
2937		spu_info[spu->number].spu = spu;
2938		spu_info[spu->number].stopped_ok = 0;
2939		spu_info[spu->number].dump_addr = (unsigned long)
2940				spu_info[spu->number].spu->local_store;
2941	}
2942}
2943
2944static void stop_spus(void)
2945{
2946	struct spu *spu;
2947	int i;
2948	u64 tmp;
2949
2950	for (i = 0; i < XMON_NUM_SPUS; i++) {
2951		if (!spu_info[i].spu)
2952			continue;
2953
2954		if (setjmp(bus_error_jmp) == 0) {
2955			catch_memory_errors = 1;
2956			sync();
2957
2958			spu = spu_info[i].spu;
2959
2960			spu_info[i].saved_spu_runcntl_RW =
2961				in_be32(&spu->problem->spu_runcntl_RW);
2962
2963			tmp = spu_mfc_sr1_get(spu);
2964			spu_info[i].saved_mfc_sr1_RW = tmp;
2965
2966			tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2967			spu_mfc_sr1_set(spu, tmp);
2968
2969			sync();
2970			__delay(200);
2971
2972			spu_info[i].stopped_ok = 1;
2973
2974			printf("Stopped spu %.2d (was %s)\n", i,
2975					spu_info[i].saved_spu_runcntl_RW ?
2976					"running" : "stopped");
2977		} else {
2978			catch_memory_errors = 0;
2979			printf("*** Error stopping spu %.2d\n", i);
2980		}
2981		catch_memory_errors = 0;
2982	}
2983}
2984
2985static void restart_spus(void)
2986{
2987	struct spu *spu;
2988	int i;
2989
2990	for (i = 0; i < XMON_NUM_SPUS; i++) {
2991		if (!spu_info[i].spu)
2992			continue;
2993
2994		if (!spu_info[i].stopped_ok) {
2995			printf("*** Error, spu %d was not successfully stopped"
2996					", not restarting\n", i);
2997			continue;
2998		}
2999
3000		if (setjmp(bus_error_jmp) == 0) {
3001			catch_memory_errors = 1;
3002			sync();
3003
3004			spu = spu_info[i].spu;
3005			spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3006			out_be32(&spu->problem->spu_runcntl_RW,
3007					spu_info[i].saved_spu_runcntl_RW);
3008
3009			sync();
3010			__delay(200);
3011
3012			printf("Restarted spu %.2d\n", i);
3013		} else {
3014			catch_memory_errors = 0;
3015			printf("*** Error restarting spu %.2d\n", i);
3016		}
3017		catch_memory_errors = 0;
3018	}
3019}
3020
3021#define DUMP_WIDTH	23
3022#define DUMP_VALUE(format, field, value)				\
3023do {									\
3024	if (setjmp(bus_error_jmp) == 0) {				\
3025		catch_memory_errors = 1;				\
3026		sync();							\
3027		printf("  %-*s = "format"\n", DUMP_WIDTH,		\
3028				#field, value);				\
3029		sync();							\
3030		__delay(200);						\
3031	} else {							\
3032		catch_memory_errors = 0;				\
3033		printf("  %-*s = *** Error reading field.\n",		\
3034					DUMP_WIDTH, #field);		\
3035	}								\
3036	catch_memory_errors = 0;					\
3037} while (0)
3038
3039#define DUMP_FIELD(obj, format, field)	\
3040	DUMP_VALUE(format, field, obj->field)
3041
3042static void dump_spu_fields(struct spu *spu)
3043{
3044	printf("Dumping spu fields at address %p:\n", spu);
3045
3046	DUMP_FIELD(spu, "0x%x", number);
3047	DUMP_FIELD(spu, "%s", name);
3048	DUMP_FIELD(spu, "0x%lx", local_store_phys);
3049	DUMP_FIELD(spu, "0x%p", local_store);
3050	DUMP_FIELD(spu, "0x%lx", ls_size);
3051	DUMP_FIELD(spu, "0x%x", node);
3052	DUMP_FIELD(spu, "0x%lx", flags);
3053	DUMP_FIELD(spu, "%d", class_0_pending);
3054	DUMP_FIELD(spu, "0x%lx", class_0_dar);
3055	DUMP_FIELD(spu, "0x%lx", class_1_dar);
3056	DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3057	DUMP_FIELD(spu, "0x%lx", irqs[0]);
3058	DUMP_FIELD(spu, "0x%lx", irqs[1]);
3059	DUMP_FIELD(spu, "0x%lx", irqs[2]);
3060	DUMP_FIELD(spu, "0x%x", slb_replace);
3061	DUMP_FIELD(spu, "%d", pid);
3062	DUMP_FIELD(spu, "0x%p", mm);
3063	DUMP_FIELD(spu, "0x%p", ctx);
3064	DUMP_FIELD(spu, "0x%p", rq);
3065	DUMP_FIELD(spu, "0x%p", timestamp);
3066	DUMP_FIELD(spu, "0x%lx", problem_phys);
3067	DUMP_FIELD(spu, "0x%p", problem);
3068	DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3069			in_be32(&spu->problem->spu_runcntl_RW));
3070	DUMP_VALUE("0x%x", problem->spu_status_R,
3071			in_be32(&spu->problem->spu_status_R));
3072	DUMP_VALUE("0x%x", problem->spu_npc_RW,
3073			in_be32(&spu->problem->spu_npc_RW));
3074	DUMP_FIELD(spu, "0x%p", priv2);
3075	DUMP_FIELD(spu, "0x%p", pdata);
3076}
3077
3078int
3079spu_inst_dump(unsigned long adr, long count, int praddr)
3080{
3081	return generic_inst_dump(adr, count, praddr, print_insn_spu);
3082}
3083
3084static void dump_spu_ls(unsigned long num, int subcmd)
3085{
3086	unsigned long offset, addr, ls_addr;
3087
3088	if (setjmp(bus_error_jmp) == 0) {
3089		catch_memory_errors = 1;
3090		sync();
3091		ls_addr = (unsigned long)spu_info[num].spu->local_store;
3092		sync();
3093		__delay(200);
3094	} else {
3095		catch_memory_errors = 0;
3096		printf("*** Error: accessing spu info for spu %d\n", num);
3097		return;
3098	}
3099	catch_memory_errors = 0;
3100
3101	if (scanhex(&offset))
3102		addr = ls_addr + offset;
3103	else
3104		addr = spu_info[num].dump_addr;
3105
3106	if (addr >= ls_addr + LS_SIZE) {
3107		printf("*** Error: address outside of local store\n");
3108		return;
3109	}
3110
3111	switch (subcmd) {
3112	case 'i':
3113		addr += spu_inst_dump(addr, 16, 1);
3114		last_cmd = "sdi\n";
3115		break;
3116	default:
3117		prdump(addr, 64);
3118		addr += 64;
3119		last_cmd = "sd\n";
3120		break;
3121	}
3122
3123	spu_info[num].dump_addr = addr;
3124}
3125
3126static int do_spu_cmd(void)
3127{
3128	static unsigned long num = 0;
3129	int cmd, subcmd = 0;
3130
3131	cmd = inchar();
3132	switch (cmd) {
3133	case 's':
3134		stop_spus();
3135		break;
3136	case 'r':
3137		restart_spus();
3138		break;
3139	case 'd':
3140		subcmd = inchar();
3141		if (isxdigit(subcmd) || subcmd == '\n')
3142			termch = subcmd;
3143	case 'f':
3144		scanhex(&num);
3145		if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3146			printf("*** Error: invalid spu number\n");
3147			return 0;
3148		}
3149
3150		switch (cmd) {
3151		case 'f':
3152			dump_spu_fields(spu_info[num].spu);
3153			break;
3154		default:
3155			dump_spu_ls(num, subcmd);
3156			break;
3157		}
3158
3159		break;
3160	default:
3161		return -1;
3162	}
3163
3164	return 0;
3165}
3166#else /* ! CONFIG_SPU_BASE */
3167static int do_spu_cmd(void)
3168{
3169	return -1;
3170}
3171#endif