Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-block.git] / arch / powerpc / xmon / xmon.c
CommitLineData
1da177e4
LT
1/*
2 * Routines providing a simple monitor for use on the PowerMac.
3 *
fca5dcd4 4 * Copyright (C) 1996-2005 Paul Mackerras.
1da177e4
LT
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
1da177e4
LT
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/smp.h>
14#include <linux/mm.h>
15#include <linux/reboot.h>
16#include <linux/delay.h>
17#include <linux/kallsyms.h>
18#include <linux/cpumask.h>
f78541dc 19#include <linux/module.h>
fca5dcd4 20#include <linux/sysrq.h>
4694ca02 21#include <linux/interrupt.h>
1da177e4
LT
22
23#include <asm/ptrace.h>
24#include <asm/string.h>
25#include <asm/prom.h>
26#include <asm/machdep.h>
f78541dc 27#include <asm/xmon.h>
1da177e4
LT
28#include <asm/processor.h>
29#include <asm/pgtable.h>
30#include <asm/mmu.h>
31#include <asm/mmu_context.h>
1da177e4
LT
32#include <asm/cputable.h>
33#include <asm/rtas.h>
34#include <asm/sstep.h>
35#include <asm/bug.h>
f78541dc
PM
36
37#ifdef CONFIG_PPC64
1da177e4 38#include <asm/hvcall.h>
f78541dc
PM
39#include <asm/paca.h>
40#endif
1da177e4
LT
41
42#include "nonstdio.h"
1da177e4
LT
43
44#define scanhex xmon_scanhex
45#define skipbl xmon_skipbl
46
47#ifdef CONFIG_SMP
48cpumask_t cpus_in_xmon = CPU_MASK_NONE;
49static unsigned long xmon_taken = 1;
50static int xmon_owner;
51static int xmon_gate;
52#endif /* CONFIG_SMP */
53
54static unsigned long in_xmon = 0;
55
56static unsigned long adrs;
57static int size = 1;
58#define MAX_DUMP (128 * 1024)
59static unsigned long ndump = 64;
60static unsigned long nidump = 16;
61static unsigned long ncsum = 4096;
62static int termch;
63static char tmpstr[128];
64
f78541dc 65#define JMP_BUF_LEN 23
1da177e4
LT
66static long bus_error_jmp[JMP_BUF_LEN];
67static int catch_memory_errors;
68static long *xmon_fault_jmp[NR_CPUS];
69#define setjmp xmon_setjmp
70#define longjmp xmon_longjmp
71
72/* Breakpoint stuff */
73struct bpt {
74 unsigned long address;
75 unsigned int instr[2];
76 atomic_t ref_count;
77 int enabled;
78 unsigned long pad;
79};
80
81/* Bits in bpt.enabled */
82#define BP_IABR_TE 1 /* IABR translation enabled */
83#define BP_IABR 2
84#define BP_TRAP 8
85#define BP_DABR 0x10
86
87#define NBPTS 256
88static struct bpt bpts[NBPTS];
89static struct bpt dabr;
90static struct bpt *iabr;
91static unsigned bpinstr = 0x7fe00008; /* trap */
92
93#define BP_NUM(bp) ((bp) - bpts + 1)
94
95/* Prototypes */
96static int cmds(struct pt_regs *);
97static int mread(unsigned long, void *, int);
98static int mwrite(unsigned long, void *, int);
99static int handle_fault(struct pt_regs *);
100static void byterev(unsigned char *, int);
101static void memex(void);
102static int bsesc(void);
103static void dump(void);
104static void prdump(unsigned long, long);
105static int ppc_inst_dump(unsigned long, long, int);
106void print_address(unsigned long);
107static void backtrace(struct pt_regs *);
108static void excprint(struct pt_regs *);
109static void prregs(struct pt_regs *);
110static void memops(int);
111static void memlocate(void);
112static void memzcan(void);
113static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
114int skipbl(void);
115int scanhex(unsigned long *valp);
116static void scannl(void);
117static int hexdigit(int);
118void getstring(char *, int);
119static void flush_input(void);
120static int inchar(void);
121static void take_input(char *);
122static unsigned long read_spr(int);
123static void write_spr(int, unsigned long);
124static void super_regs(void);
125static void remove_bpts(void);
126static void insert_bpts(void);
127static void remove_cpu_bpts(void);
128static void insert_cpu_bpts(void);
129static struct bpt *at_breakpoint(unsigned long pc);
130static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
131static int do_step(struct pt_regs *);
132static void bpt_cmds(void);
133static void cacheflush(void);
134static int cpu_cmd(void);
135static void csum(void);
136static void bootcmds(void);
f78541dc 137static void proccall(void);
1da177e4
LT
138void dump_segments(void);
139static void symbol_lookup(void);
140static void xmon_print_symbol(unsigned long address, const char *mid,
141 const char *after);
142static const char *getvecname(unsigned long vec);
143
1da177e4 144extern int print_insn_powerpc(unsigned long, unsigned long, int);
f78541dc
PM
145
146extern void xmon_enter(void);
147extern void xmon_leave(void);
148
f78541dc
PM
149extern long setjmp(long *);
150extern void longjmp(long *, long);
151extern void xmon_save_regs(struct pt_regs *);
152
153#ifdef CONFIG_PPC64
154#define REG "%.16lx"
155#define REGS_PER_LINE 4
156#define LAST_VOLATILE 13
157#else
158#define REG "%.8lx"
159#define REGS_PER_LINE 8
160#define LAST_VOLATILE 12
161#endif
1da177e4
LT
162
163#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
164
165#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
166 || ('a' <= (c) && (c) <= 'f') \
167 || ('A' <= (c) && (c) <= 'F'))
168#define isalnum(c) (('0' <= (c) && (c) <= '9') \
169 || ('a' <= (c) && (c) <= 'z') \
170 || ('A' <= (c) && (c) <= 'Z'))
171#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
172
173static char *help_string = "\
174Commands:\n\
175 b show breakpoints\n\
176 bd set data breakpoint\n\
177 bi set instruction breakpoint\n\
178 bc clear breakpoint\n"
179#ifdef CONFIG_SMP
180 "\
181 c print cpus stopped in xmon\n\
182 c# try to switch to cpu number h (in hex)\n"
183#endif
184 "\
185 C checksum\n\
186 d dump bytes\n\
187 di dump instructions\n\
188 df dump float values\n\
189 dd dump double values\n\
7e5b5938 190 dr dump stream of raw bytes\n\
1da177e4
LT
191 e print exception information\n\
192 f flush cache\n\
193 la lookup symbol+offset of specified address\n\
194 ls lookup address of specified symbol\n\
195 m examine/change memory\n\
196 mm move a block of memory\n\
197 ms set a block of memory\n\
198 md compare two blocks of memory\n\
199 ml locate a block of memory\n\
200 mz zero a block of memory\n\
201 mi show information about memory allocation\n\
f78541dc 202 p call a procedure\n\
1da177e4
LT
203 r print registers\n\
204 s single step\n\
205 S print special registers\n\
206 t print backtrace\n\
1da177e4 207 x exit monitor and recover\n\
f78541dc
PM
208 X exit monitor and dont recover\n"
209#ifdef CONFIG_PPC64
210" u dump segment table or SLB\n"
211#endif
212#ifdef CONFIG_PPC_STD_MMU_32
213" u dump segment registers\n"
214#endif
215" ? help\n"
216" zr reboot\n\
1da177e4
LT
217 zh halt\n"
218;
219
220static struct pt_regs *xmon_regs;
221
f78541dc 222static inline void sync(void)
1da177e4
LT
223{
224 asm volatile("sync; isync");
225}
226
f78541dc
PM
227static inline void store_inst(void *p)
228{
229 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
230}
231
232static inline void cflush(void *p)
233{
234 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
235}
236
237static inline void cinval(void *p)
238{
239 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
240}
1da177e4
LT
241
242/*
243 * Disable surveillance (the service processor watchdog function)
244 * while we are in xmon.
245 * XXX we should re-enable it when we leave. :)
246 */
247#define SURVEILLANCE_TOKEN 9000
248
249static inline void disable_surveillance(void)
250{
251#ifdef CONFIG_PPC_PSERIES
252 /* Since this can't be a module, args should end up below 4GB. */
253 static struct rtas_args args;
254
255 /*
256 * At this point we have got all the cpus we can into
257 * xmon, so there is hopefully no other cpu calling RTAS
258 * at the moment, even though we don't take rtas.lock.
259 * If we did try to take rtas.lock there would be a
260 * real possibility of deadlock.
261 */
262 args.token = rtas_token("set-indicator");
263 if (args.token == RTAS_UNKNOWN_SERVICE)
264 return;
265 args.nargs = 3;
266 args.nret = 1;
267 args.rets = &args.args[3];
268 args.args[0] = SURVEILLANCE_TOKEN;
269 args.args[1] = 0;
270 args.args[2] = 0;
271 enter_rtas(__pa(&args));
272#endif /* CONFIG_PPC_PSERIES */
273}
274
275#ifdef CONFIG_SMP
276static int xmon_speaker;
277
278static void get_output_lock(void)
279{
280 int me = smp_processor_id() + 0x100;
281 int last_speaker = 0, prev;
282 long timeout;
283
284 if (xmon_speaker == me)
285 return;
286 for (;;) {
287 if (xmon_speaker == 0) {
288 last_speaker = cmpxchg(&xmon_speaker, 0, me);
289 if (last_speaker == 0)
290 return;
291 }
292 timeout = 10000000;
293 while (xmon_speaker == last_speaker) {
294 if (--timeout > 0)
295 continue;
296 /* hostile takeover */
297 prev = cmpxchg(&xmon_speaker, last_speaker, me);
298 if (prev == last_speaker)
299 return;
300 break;
301 }
302 }
303}
304
305static void release_output_lock(void)
306{
307 xmon_speaker = 0;
308}
309#endif
310
b0da9856 311static int xmon_core(struct pt_regs *regs, int fromipi)
1da177e4
LT
312{
313 int cmd = 0;
314 unsigned long msr;
315 struct bpt *bp;
316 long recurse_jmp[JMP_BUF_LEN];
317 unsigned long offset;
318#ifdef CONFIG_SMP
319 int cpu;
320 int secondary;
321 unsigned long timeout;
322#endif
323
f78541dc
PM
324 msr = mfmsr();
325 mtmsr(msr & ~MSR_EE); /* disable interrupts */
1da177e4
LT
326
327 bp = in_breakpoint_table(regs->nip, &offset);
328 if (bp != NULL) {
329 regs->nip = bp->address + offset;
330 atomic_dec(&bp->ref_count);
331 }
332
333 remove_cpu_bpts();
334
335#ifdef CONFIG_SMP
336 cpu = smp_processor_id();
337 if (cpu_isset(cpu, cpus_in_xmon)) {
338 get_output_lock();
339 excprint(regs);
340 printf("cpu 0x%x: Exception %lx %s in xmon, "
341 "returning to main loop\n",
342 cpu, regs->trap, getvecname(TRAP(regs)));
5cb4cc0d 343 release_output_lock();
1da177e4
LT
344 longjmp(xmon_fault_jmp[cpu], 1);
345 }
346
347 if (setjmp(recurse_jmp) != 0) {
348 if (!in_xmon || !xmon_gate) {
5cb4cc0d 349 get_output_lock();
1da177e4
LT
350 printf("xmon: WARNING: bad recursive fault "
351 "on cpu 0x%x\n", cpu);
5cb4cc0d 352 release_output_lock();
1da177e4
LT
353 goto waiting;
354 }
355 secondary = !(xmon_taken && cpu == xmon_owner);
356 goto cmdloop;
357 }
358
359 xmon_fault_jmp[cpu] = recurse_jmp;
360 cpu_set(cpu, cpus_in_xmon);
361
362 bp = NULL;
363 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
364 bp = at_breakpoint(regs->nip);
365 if (bp || (regs->msr & MSR_RI) == 0)
366 fromipi = 0;
367
368 if (!fromipi) {
369 get_output_lock();
370 excprint(regs);
371 if (bp) {
372 printf("cpu 0x%x stopped at breakpoint 0x%x (",
373 cpu, BP_NUM(bp));
374 xmon_print_symbol(regs->nip, " ", ")\n");
375 }
376 if ((regs->msr & MSR_RI) == 0)
377 printf("WARNING: exception is not recoverable, "
378 "can't continue\n");
379 release_output_lock();
380 }
381
382 waiting:
383 secondary = 1;
384 while (secondary && !xmon_gate) {
385 if (in_xmon == 0) {
386 if (fromipi)
387 goto leave;
388 secondary = test_and_set_bit(0, &in_xmon);
389 }
390 barrier();
391 }
392
393 if (!secondary && !xmon_gate) {
394 /* we are the first cpu to come in */
395 /* interrupt other cpu(s) */
396 int ncpus = num_online_cpus();
397
398 xmon_owner = cpu;
399 mb();
400 if (ncpus > 1) {
401 smp_send_debugger_break(MSG_ALL_BUT_SELF);
402 /* wait for other cpus to come in */
403 for (timeout = 100000000; timeout != 0; --timeout) {
404 if (cpus_weight(cpus_in_xmon) >= ncpus)
405 break;
406 barrier();
407 }
408 }
409 remove_bpts();
410 disable_surveillance();
411 /* for breakpoint or single step, print the current instr. */
412 if (bp || TRAP(regs) == 0xd00)
413 ppc_inst_dump(regs->nip, 1, 0);
414 printf("enter ? for help\n");
415 mb();
416 xmon_gate = 1;
417 barrier();
418 }
419
420 cmdloop:
421 while (in_xmon) {
422 if (secondary) {
423 if (cpu == xmon_owner) {
424 if (!test_and_set_bit(0, &xmon_taken)) {
425 secondary = 0;
426 continue;
427 }
428 /* missed it */
429 while (cpu == xmon_owner)
430 barrier();
431 }
432 barrier();
433 } else {
434 cmd = cmds(regs);
435 if (cmd != 0) {
436 /* exiting xmon */
437 insert_bpts();
438 xmon_gate = 0;
439 wmb();
440 in_xmon = 0;
441 break;
442 }
443 /* have switched to some other cpu */
444 secondary = 1;
445 }
446 }
447 leave:
448 cpu_clear(cpu, cpus_in_xmon);
449 xmon_fault_jmp[cpu] = NULL;
1da177e4
LT
450#else
451 /* UP is simple... */
452 if (in_xmon) {
453 printf("Exception %lx %s in xmon, returning to main loop\n",
454 regs->trap, getvecname(TRAP(regs)));
455 longjmp(xmon_fault_jmp[0], 1);
456 }
457 if (setjmp(recurse_jmp) == 0) {
458 xmon_fault_jmp[0] = recurse_jmp;
459 in_xmon = 1;
460
461 excprint(regs);
462 bp = at_breakpoint(regs->nip);
463 if (bp) {
464 printf("Stopped at breakpoint %x (", BP_NUM(bp));
465 xmon_print_symbol(regs->nip, " ", ")\n");
466 }
467 if ((regs->msr & MSR_RI) == 0)
468 printf("WARNING: exception is not recoverable, "
469 "can't continue\n");
470 remove_bpts();
471 disable_surveillance();
472 /* for breakpoint or single step, print the current instr. */
473 if (bp || TRAP(regs) == 0xd00)
474 ppc_inst_dump(regs->nip, 1, 0);
475 printf("enter ? for help\n");
476 }
477
478 cmd = cmds(regs);
479
480 insert_bpts();
481 in_xmon = 0;
482#endif
483
484 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
485 bp = at_breakpoint(regs->nip);
486 if (bp != NULL) {
487 int stepped = emulate_step(regs, bp->instr[0]);
488 if (stepped == 0) {
489 regs->nip = (unsigned long) &bp->instr[0];
490 atomic_inc(&bp->ref_count);
491 } else if (stepped < 0) {
492 printf("Couldn't single-step %s instruction\n",
493 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
494 }
495 }
496 }
497
498 insert_cpu_bpts();
499
f78541dc 500 mtmsr(msr); /* restore interrupt enable */
1da177e4
LT
501
502 return cmd != 'X';
503}
504
505int xmon(struct pt_regs *excp)
506{
507 struct pt_regs regs;
508
509 if (excp == NULL) {
f78541dc 510 xmon_save_regs(&regs);
1da177e4
LT
511 excp = &regs;
512 }
513 return xmon_core(excp, 0);
514}
f78541dc
PM
515EXPORT_SYMBOL(xmon);
516
517irqreturn_t
518xmon_irq(int irq, void *d, struct pt_regs *regs)
519{
520 unsigned long flags;
521 local_irq_save(flags);
522 printf("Keyboard interrupt\n");
523 xmon(regs);
524 local_irq_restore(flags);
525 return IRQ_HANDLED;
526}
1da177e4 527
b0da9856 528static int xmon_bpt(struct pt_regs *regs)
1da177e4
LT
529{
530 struct bpt *bp;
531 unsigned long offset;
532
533 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
534 return 0;
535
536 /* Are we at the trap at bp->instr[1] for some bp? */
537 bp = in_breakpoint_table(regs->nip, &offset);
538 if (bp != NULL && offset == 4) {
539 regs->nip = bp->address + 4;
540 atomic_dec(&bp->ref_count);
541 return 1;
542 }
543
544 /* Are we at a breakpoint? */
545 bp = at_breakpoint(regs->nip);
546 if (!bp)
547 return 0;
548
549 xmon_core(regs, 0);
550
551 return 1;
552}
553
b0da9856 554static int xmon_sstep(struct pt_regs *regs)
1da177e4
LT
555{
556 if (user_mode(regs))
557 return 0;
558 xmon_core(regs, 0);
559 return 1;
560}
561
b0da9856 562static int xmon_dabr_match(struct pt_regs *regs)
1da177e4
LT
563{
564 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
565 return 0;
fd9648df
AB
566 if (dabr.enabled == 0)
567 return 0;
1da177e4
LT
568 xmon_core(regs, 0);
569 return 1;
570}
571
b0da9856 572static int xmon_iabr_match(struct pt_regs *regs)
1da177e4
LT
573{
574 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
575 return 0;
576 if (iabr == 0)
577 return 0;
578 xmon_core(regs, 0);
579 return 1;
580}
581
b0da9856 582static int xmon_ipi(struct pt_regs *regs)
1da177e4
LT
583{
584#ifdef CONFIG_SMP
585 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
586 xmon_core(regs, 1);
587#endif
588 return 0;
589}
590
b0da9856 591static int xmon_fault_handler(struct pt_regs *regs)
1da177e4
LT
592{
593 struct bpt *bp;
594 unsigned long offset;
595
596 if (in_xmon && catch_memory_errors)
597 handle_fault(regs); /* doesn't return */
598
599 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
600 bp = in_breakpoint_table(regs->nip, &offset);
601 if (bp != NULL) {
602 regs->nip = bp->address + offset;
603 atomic_dec(&bp->ref_count);
604 }
605 }
606
607 return 0;
608}
609
1da177e4
LT
610static struct bpt *at_breakpoint(unsigned long pc)
611{
612 int i;
613 struct bpt *bp;
614
615 bp = bpts;
616 for (i = 0; i < NBPTS; ++i, ++bp)
617 if (bp->enabled && pc == bp->address)
618 return bp;
619 return NULL;
620}
621
622static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
623{
624 unsigned long off;
625
626 off = nip - (unsigned long) bpts;
627 if (off >= sizeof(bpts))
628 return NULL;
629 off %= sizeof(struct bpt);
630 if (off != offsetof(struct bpt, instr[0])
631 && off != offsetof(struct bpt, instr[1]))
632 return NULL;
633 *offp = off - offsetof(struct bpt, instr[0]);
634 return (struct bpt *) (nip - off);
635}
636
637static struct bpt *new_breakpoint(unsigned long a)
638{
639 struct bpt *bp;
640
641 a &= ~3UL;
642 bp = at_breakpoint(a);
643 if (bp)
644 return bp;
645
646 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
647 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
648 bp->address = a;
649 bp->instr[1] = bpinstr;
650 store_inst(&bp->instr[1]);
651 return bp;
652 }
653 }
654
655 printf("Sorry, no free breakpoints. Please clear one first.\n");
656 return NULL;
657}
658
659static void insert_bpts(void)
660{
661 int i;
662 struct bpt *bp;
663
664 bp = bpts;
665 for (i = 0; i < NBPTS; ++i, ++bp) {
666 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
667 continue;
668 if (mread(bp->address, &bp->instr[0], 4) != 4) {
669 printf("Couldn't read instruction at %lx, "
670 "disabling breakpoint there\n", bp->address);
671 bp->enabled = 0;
672 continue;
673 }
674 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
675 printf("Breakpoint at %lx is on an mtmsrd or rfid "
676 "instruction, disabling it\n", bp->address);
677 bp->enabled = 0;
678 continue;
679 }
680 store_inst(&bp->instr[0]);
681 if (bp->enabled & BP_IABR)
682 continue;
683 if (mwrite(bp->address, &bpinstr, 4) != 4) {
684 printf("Couldn't write instruction at %lx, "
685 "disabling breakpoint there\n", bp->address);
686 bp->enabled &= ~BP_TRAP;
687 continue;
688 }
689 store_inst((void *)bp->address);
690 }
691}
692
693static void insert_cpu_bpts(void)
694{
695 if (dabr.enabled)
fd9648df 696 set_dabr(dabr.address | (dabr.enabled & 7));
1da177e4 697 if (iabr && cpu_has_feature(CPU_FTR_IABR))
f78541dc 698 mtspr(SPRN_IABR, iabr->address
1da177e4
LT
699 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
700}
701
702static void remove_bpts(void)
703{
704 int i;
705 struct bpt *bp;
706 unsigned instr;
707
708 bp = bpts;
709 for (i = 0; i < NBPTS; ++i, ++bp) {
710 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
711 continue;
712 if (mread(bp->address, &instr, 4) == 4
713 && instr == bpinstr
714 && mwrite(bp->address, &bp->instr, 4) != 4)
715 printf("Couldn't remove breakpoint at %lx\n",
716 bp->address);
717 else
718 store_inst((void *)bp->address);
719 }
720}
721
722static void remove_cpu_bpts(void)
723{
fd9648df 724 set_dabr(0);
1da177e4 725 if (cpu_has_feature(CPU_FTR_IABR))
f78541dc 726 mtspr(SPRN_IABR, 0);
1da177e4
LT
727}
728
729/* Command interpreting routine */
730static char *last_cmd;
731
732static int
733cmds(struct pt_regs *excp)
734{
735 int cmd = 0;
736
737 last_cmd = NULL;
738 xmon_regs = excp;
739 for(;;) {
740#ifdef CONFIG_SMP
741 printf("%x:", smp_processor_id());
742#endif /* CONFIG_SMP */
743 printf("mon> ");
1da177e4
LT
744 flush_input();
745 termch = 0;
746 cmd = skipbl();
747 if( cmd == '\n' ) {
748 if (last_cmd == NULL)
749 continue;
750 take_input(last_cmd);
751 last_cmd = NULL;
752 cmd = inchar();
753 }
754 switch (cmd) {
755 case 'm':
756 cmd = inchar();
757 switch (cmd) {
758 case 'm':
759 case 's':
760 case 'd':
761 memops(cmd);
762 break;
763 case 'l':
764 memlocate();
765 break;
766 case 'z':
767 memzcan();
768 break;
769 case 'i':
770 show_mem();
771 break;
772 default:
773 termch = cmd;
774 memex();
775 }
776 break;
777 case 'd':
778 dump();
779 break;
780 case 'l':
781 symbol_lookup();
782 break;
783 case 'r':
784 prregs(excp); /* print regs */
785 break;
786 case 'e':
787 excprint(excp);
788 break;
789 case 'S':
790 super_regs();
791 break;
792 case 't':
793 backtrace(excp);
794 break;
795 case 'f':
796 cacheflush();
797 break;
798 case 's':
799 if (do_step(excp))
800 return cmd;
801 break;
802 case 'x':
803 case 'X':
bb6b9b28 804 return cmd;
1da177e4 805 case EOF:
bb6b9b28
BH
806 printf(" <no input ...>\n");
807 mdelay(2000);
1da177e4
LT
808 return cmd;
809 case '?':
810 printf(help_string);
811 break;
1da177e4
LT
812 case 'b':
813 bpt_cmds();
814 break;
815 case 'C':
816 csum();
817 break;
818 case 'c':
819 if (cpu_cmd())
820 return 0;
821 break;
822 case 'z':
823 bootcmds();
824 break;
f78541dc
PM
825 case 'p':
826 proccall();
1da177e4 827 break;
f78541dc 828#ifdef CONFIG_PPC_STD_MMU
1da177e4
LT
829 case 'u':
830 dump_segments();
831 break;
f78541dc 832#endif
1da177e4
LT
833 default:
834 printf("Unrecognized command: ");
835 do {
836 if (' ' < cmd && cmd <= '~')
837 putchar(cmd);
838 else
839 printf("\\x%x", cmd);
840 cmd = inchar();
841 } while (cmd != '\n');
842 printf(" (type ? for help)\n");
843 break;
844 }
845 }
846}
847
848/*
849 * Step a single instruction.
850 * Some instructions we emulate, others we execute with MSR_SE set.
851 */
852static int do_step(struct pt_regs *regs)
853{
854 unsigned int instr;
855 int stepped;
856
857 /* check we are in 64-bit kernel mode, translation enabled */
858 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
859 if (mread(regs->nip, &instr, 4) == 4) {
860 stepped = emulate_step(regs, instr);
861 if (stepped < 0) {
862 printf("Couldn't single-step %s instruction\n",
863 (IS_RFID(instr)? "rfid": "mtmsrd"));
864 return 0;
865 }
866 if (stepped > 0) {
867 regs->trap = 0xd00 | (regs->trap & 1);
868 printf("stepped to ");
869 xmon_print_symbol(regs->nip, " ", "\n");
870 ppc_inst_dump(regs->nip, 1, 0);
871 return 0;
872 }
873 }
874 }
875 regs->msr |= MSR_SE;
876 return 1;
877}
878
879static void bootcmds(void)
880{
881 int cmd;
882
883 cmd = inchar();
884 if (cmd == 'r')
885 ppc_md.restart(NULL);
886 else if (cmd == 'h')
887 ppc_md.halt();
888 else if (cmd == 'p')
889 ppc_md.power_off();
890}
891
892static int cpu_cmd(void)
893{
894#ifdef CONFIG_SMP
895 unsigned long cpu;
896 int timeout;
897 int count;
898
899 if (!scanhex(&cpu)) {
900 /* print cpus waiting or in xmon */
901 printf("cpus stopped:");
902 count = 0;
903 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
904 if (cpu_isset(cpu, cpus_in_xmon)) {
905 if (count == 0)
906 printf(" %x", cpu);
907 ++count;
908 } else {
909 if (count > 1)
910 printf("-%x", cpu - 1);
911 count = 0;
912 }
913 }
914 if (count > 1)
915 printf("-%x", NR_CPUS - 1);
916 printf("\n");
917 return 0;
918 }
919 /* try to switch to cpu specified */
920 if (!cpu_isset(cpu, cpus_in_xmon)) {
921 printf("cpu 0x%x isn't in xmon\n", cpu);
922 return 0;
923 }
924 xmon_taken = 0;
925 mb();
926 xmon_owner = cpu;
927 timeout = 10000000;
928 while (!xmon_taken) {
929 if (--timeout == 0) {
930 if (test_and_set_bit(0, &xmon_taken))
931 break;
932 /* take control back */
933 mb();
934 xmon_owner = smp_processor_id();
935 printf("cpu %u didn't take control\n", cpu);
936 return 0;
937 }
938 barrier();
939 }
940 return 1;
941#else
942 return 0;
943#endif /* CONFIG_SMP */
944}
945
946static unsigned short fcstab[256] = {
947 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
948 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
949 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
950 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
951 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
952 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
953 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
954 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
955 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
956 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
957 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
958 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
959 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
960 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
961 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
962 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
963 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
964 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
965 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
966 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
967 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
968 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
969 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
970 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
971 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
972 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
973 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
974 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
975 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
976 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
977 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
978 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
979};
980
981#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
982
983static void
984csum(void)
985{
986 unsigned int i;
987 unsigned short fcs;
988 unsigned char v;
989
990 if (!scanhex(&adrs))
991 return;
992 if (!scanhex(&ncsum))
993 return;
994 fcs = 0xffff;
995 for (i = 0; i < ncsum; ++i) {
996 if (mread(adrs+i, &v, 1) == 0) {
997 printf("csum stopped at %x\n", adrs+i);
998 break;
999 }
1000 fcs = FCS(fcs, v);
1001 }
1002 printf("%x\n", fcs);
1003}
1004
1005/*
1006 * Check if this is a suitable place to put a breakpoint.
1007 */
1008static long check_bp_loc(unsigned long addr)
1009{
1010 unsigned int instr;
1011
1012 addr &= ~3;
51fae6de 1013 if (!is_kernel_addr(addr)) {
1da177e4
LT
1014 printf("Breakpoints may only be placed at kernel addresses\n");
1015 return 0;
1016 }
1017 if (!mread(addr, &instr, sizeof(instr))) {
1018 printf("Can't read instruction at address %lx\n", addr);
1019 return 0;
1020 }
1021 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1022 printf("Breakpoints may not be placed on mtmsrd or rfid "
1023 "instructions\n");
1024 return 0;
1025 }
1026 return 1;
1027}
1028
1029static char *breakpoint_help_string =
1030 "Breakpoint command usage:\n"
1031 "b show breakpoints\n"
1032 "b <addr> [cnt] set breakpoint at given instr addr\n"
1033 "bc clear all breakpoints\n"
1034 "bc <n/addr> clear breakpoint number n or at addr\n"
1035 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1036 "bd <addr> [cnt] set hardware data breakpoint\n"
1037 "";
1038
1039static void
1040bpt_cmds(void)
1041{
1042 int cmd;
1043 unsigned long a;
1044 int mode, i;
1045 struct bpt *bp;
1046 const char badaddr[] = "Only kernel addresses are permitted "
1047 "for breakpoints\n";
1048
1049 cmd = inchar();
1050 switch (cmd) {
f78541dc 1051#ifndef CONFIG_8xx
1da177e4
LT
1052 case 'd': /* bd - hardware data breakpoint */
1053 mode = 7;
1054 cmd = inchar();
1055 if (cmd == 'r')
1056 mode = 5;
1057 else if (cmd == 'w')
1058 mode = 6;
1059 else
1060 termch = cmd;
1061 dabr.address = 0;
1062 dabr.enabled = 0;
1063 if (scanhex(&dabr.address)) {
51fae6de 1064 if (!is_kernel_addr(dabr.address)) {
1da177e4
LT
1065 printf(badaddr);
1066 break;
1067 }
1068 dabr.address &= ~7;
1069 dabr.enabled = mode | BP_DABR;
1070 }
1071 break;
1072
1073 case 'i': /* bi - hardware instr breakpoint */
1074 if (!cpu_has_feature(CPU_FTR_IABR)) {
1075 printf("Hardware instruction breakpoint "
1076 "not supported on this cpu\n");
1077 break;
1078 }
1079 if (iabr) {
1080 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1081 iabr = NULL;
1082 }
1083 if (!scanhex(&a))
1084 break;
1085 if (!check_bp_loc(a))
1086 break;
1087 bp = new_breakpoint(a);
1088 if (bp != NULL) {
1089 bp->enabled |= BP_IABR | BP_IABR_TE;
1090 iabr = bp;
1091 }
1092 break;
f78541dc 1093#endif
1da177e4
LT
1094
1095 case 'c':
1096 if (!scanhex(&a)) {
1097 /* clear all breakpoints */
1098 for (i = 0; i < NBPTS; ++i)
1099 bpts[i].enabled = 0;
1100 iabr = NULL;
1101 dabr.enabled = 0;
1102 printf("All breakpoints cleared\n");
1103 break;
1104 }
1105
1106 if (a <= NBPTS && a >= 1) {
1107 /* assume a breakpoint number */
1108 bp = &bpts[a-1]; /* bp nums are 1 based */
1109 } else {
1110 /* assume a breakpoint address */
1111 bp = at_breakpoint(a);
1112 if (bp == 0) {
1113 printf("No breakpoint at %x\n", a);
1114 break;
1115 }
1116 }
1117
1118 printf("Cleared breakpoint %x (", BP_NUM(bp));
1119 xmon_print_symbol(bp->address, " ", ")\n");
1120 bp->enabled = 0;
1121 break;
1122
1123 default:
1124 termch = cmd;
1125 cmd = skipbl();
1126 if (cmd == '?') {
1127 printf(breakpoint_help_string);
1128 break;
1129 }
1130 termch = cmd;
1131 if (!scanhex(&a)) {
1132 /* print all breakpoints */
1133 printf(" type address\n");
1134 if (dabr.enabled) {
f78541dc 1135 printf(" data "REG" [", dabr.address);
1da177e4
LT
1136 if (dabr.enabled & 1)
1137 printf("r");
1138 if (dabr.enabled & 2)
1139 printf("w");
1140 printf("]\n");
1141 }
1142 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1143 if (!bp->enabled)
1144 continue;
1145 printf("%2x %s ", BP_NUM(bp),
1146 (bp->enabled & BP_IABR)? "inst": "trap");
1147 xmon_print_symbol(bp->address, " ", "\n");
1148 }
1149 break;
1150 }
1151
1152 if (!check_bp_loc(a))
1153 break;
1154 bp = new_breakpoint(a);
1155 if (bp != NULL)
1156 bp->enabled |= BP_TRAP;
1157 break;
1158 }
1159}
1160
1161/* Very cheap human name for vector lookup. */
1162static
1163const char *getvecname(unsigned long vec)
1164{
1165 char *ret;
1166
1167 switch (vec) {
1168 case 0x100: ret = "(System Reset)"; break;
1169 case 0x200: ret = "(Machine Check)"; break;
1170 case 0x300: ret = "(Data Access)"; break;
1171 case 0x380: ret = "(Data SLB Access)"; break;
1172 case 0x400: ret = "(Instruction Access)"; break;
1173 case 0x480: ret = "(Instruction SLB Access)"; break;
1174 case 0x500: ret = "(Hardware Interrupt)"; break;
1175 case 0x600: ret = "(Alignment)"; break;
1176 case 0x700: ret = "(Program Check)"; break;
1177 case 0x800: ret = "(FPU Unavailable)"; break;
1178 case 0x900: ret = "(Decrementer)"; break;
1179 case 0xc00: ret = "(System Call)"; break;
1180 case 0xd00: ret = "(Single Step)"; break;
1181 case 0xf00: ret = "(Performance Monitor)"; break;
1182 case 0xf20: ret = "(Altivec Unavailable)"; break;
1183 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1184 default: ret = "";
1185 }
1186 return ret;
1187}
1188
1189static void get_function_bounds(unsigned long pc, unsigned long *startp,
1190 unsigned long *endp)
1191{
1192 unsigned long size, offset;
1193 const char *name;
1194 char *modname;
1195
1196 *startp = *endp = 0;
1197 if (pc == 0)
1198 return;
1199 if (setjmp(bus_error_jmp) == 0) {
1200 catch_memory_errors = 1;
1201 sync();
1202 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1203 if (name != NULL) {
1204 *startp = pc - offset;
1205 *endp = pc - offset + size;
1206 }
1207 sync();
1208 }
1209 catch_memory_errors = 0;
1210}
1211
1212static int xmon_depth_to_print = 64;
1213
f78541dc
PM
1214#ifdef CONFIG_PPC64
1215#define LRSAVE_OFFSET 0x10
1216#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1217#define MARKER_OFFSET 0x60
1218#define REGS_OFFSET 0x70
1219#else
1220#define LRSAVE_OFFSET 4
1221#define REG_FRAME_MARKER 0x72656773
1222#define MARKER_OFFSET 8
1223#define REGS_OFFSET 16
1224#endif
1225
1da177e4
LT
1226static void xmon_show_stack(unsigned long sp, unsigned long lr,
1227 unsigned long pc)
1228{
1229 unsigned long ip;
1230 unsigned long newsp;
1231 unsigned long marker;
1232 int count = 0;
1233 struct pt_regs regs;
1234
1235 do {
1236 if (sp < PAGE_OFFSET) {
1237 if (sp != 0)
1238 printf("SP (%lx) is in userspace\n", sp);
1239 break;
1240 }
1241
f78541dc 1242 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1da177e4
LT
1243 || !mread(sp, &newsp, sizeof(unsigned long))) {
1244 printf("Couldn't read stack frame at %lx\n", sp);
1245 break;
1246 }
1247
1248 /*
1249 * For the first stack frame, try to work out if
1250 * LR and/or the saved LR value in the bottommost
1251 * stack frame are valid.
1252 */
1253 if ((pc | lr) != 0) {
1254 unsigned long fnstart, fnend;
1255 unsigned long nextip;
1256 int printip = 1;
1257
1258 get_function_bounds(pc, &fnstart, &fnend);
1259 nextip = 0;
1260 if (newsp > sp)
f78541dc 1261 mread(newsp + LRSAVE_OFFSET, &nextip,
1da177e4
LT
1262 sizeof(unsigned long));
1263 if (lr == ip) {
1264 if (lr < PAGE_OFFSET
1265 || (fnstart <= lr && lr < fnend))
1266 printip = 0;
1267 } else if (lr == nextip) {
1268 printip = 0;
1269 } else if (lr >= PAGE_OFFSET
1270 && !(fnstart <= lr && lr < fnend)) {
1271 printf("[link register ] ");
1272 xmon_print_symbol(lr, " ", "\n");
1273 }
1274 if (printip) {
f78541dc 1275 printf("["REG"] ", sp);
1da177e4
LT
1276 xmon_print_symbol(ip, " ", " (unreliable)\n");
1277 }
1278 pc = lr = 0;
1279
1280 } else {
f78541dc 1281 printf("["REG"] ", sp);
1da177e4
LT
1282 xmon_print_symbol(ip, " ", "\n");
1283 }
1284
1285 /* Look for "regshere" marker to see if this is
1286 an exception frame. */
f78541dc
PM
1287 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1288 && marker == REG_FRAME_MARKER) {
1289 if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1da177e4
LT
1290 != sizeof(regs)) {
1291 printf("Couldn't read registers at %lx\n",
f78541dc 1292 sp + REGS_OFFSET);
1da177e4
LT
1293 break;
1294 }
1295 printf("--- Exception: %lx %s at ", regs.trap,
1296 getvecname(TRAP(&regs)));
1297 pc = regs.nip;
1298 lr = regs.link;
1299 xmon_print_symbol(pc, " ", "\n");
1300 }
1301
1302 if (newsp == 0)
1303 break;
1304
1305 sp = newsp;
1306 } while (count++ < xmon_depth_to_print);
1307}
1308
1309static void backtrace(struct pt_regs *excp)
1310{
1311 unsigned long sp;
1312
1313 if (scanhex(&sp))
1314 xmon_show_stack(sp, 0, 0);
1315 else
1316 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1317 scannl();
1318}
1319
1320static void print_bug_trap(struct pt_regs *regs)
1321{
1322 struct bug_entry *bug;
1323 unsigned long addr;
1324
1325 if (regs->msr & MSR_PR)
1326 return; /* not in kernel */
1327 addr = regs->nip; /* address of trap instruction */
1328 if (addr < PAGE_OFFSET)
1329 return;
1330 bug = find_bug(regs->nip);
1331 if (bug == NULL)
1332 return;
1333 if (bug->line & BUG_WARNING_TRAP)
1334 return;
1335
1336 printf("kernel BUG in %s at %s:%d!\n",
1337 bug->function, bug->file, (unsigned int)bug->line);
1338}
1339
1340void excprint(struct pt_regs *fp)
1341{
1342 unsigned long trap;
1343
1344#ifdef CONFIG_SMP
1345 printf("cpu 0x%x: ", smp_processor_id());
1346#endif /* CONFIG_SMP */
1347
1348 trap = TRAP(fp);
1349 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1350 printf(" pc: ");
1351 xmon_print_symbol(fp->nip, ": ", "\n");
1352
1353 printf(" lr: ", fp->link);
1354 xmon_print_symbol(fp->link, ": ", "\n");
1355
1356 printf(" sp: %lx\n", fp->gpr[1]);
1357 printf(" msr: %lx\n", fp->msr);
1358
1359 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1360 printf(" dar: %lx\n", fp->dar);
1361 if (trap != 0x380)
1362 printf(" dsisr: %lx\n", fp->dsisr);
1363 }
1364
1365 printf(" current = 0x%lx\n", current);
f78541dc 1366#ifdef CONFIG_PPC64
1da177e4 1367 printf(" paca = 0x%lx\n", get_paca());
f78541dc 1368#endif
1da177e4
LT
1369 if (current) {
1370 printf(" pid = %ld, comm = %s\n",
1371 current->pid, current->comm);
1372 }
1373
1374 if (trap == 0x700)
1375 print_bug_trap(fp);
1376}
1377
1378void prregs(struct pt_regs *fp)
1379{
f78541dc 1380 int n, trap;
1da177e4
LT
1381 unsigned long base;
1382 struct pt_regs regs;
1383
1384 if (scanhex(&base)) {
1385 if (setjmp(bus_error_jmp) == 0) {
1386 catch_memory_errors = 1;
1387 sync();
1388 regs = *(struct pt_regs *)base;
1389 sync();
1390 __delay(200);
1391 } else {
1392 catch_memory_errors = 0;
f78541dc 1393 printf("*** Error reading registers from "REG"\n",
1da177e4
LT
1394 base);
1395 return;
1396 }
1397 catch_memory_errors = 0;
1398 fp = &regs;
1399 }
1400
f78541dc 1401#ifdef CONFIG_PPC64
1da177e4
LT
1402 if (FULL_REGS(fp)) {
1403 for (n = 0; n < 16; ++n)
f78541dc 1404 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1405 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1406 } else {
1407 for (n = 0; n < 7; ++n)
f78541dc 1408 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1409 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1410 }
f78541dc
PM
1411#else
1412 for (n = 0; n < 32; ++n) {
1413 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1414 (n & 3) == 3? "\n": " ");
1415 if (n == 12 && !FULL_REGS(fp)) {
1416 printf("\n");
1417 break;
1418 }
1419 }
1420#endif
1da177e4
LT
1421 printf("pc = ");
1422 xmon_print_symbol(fp->nip, " ", "\n");
1423 printf("lr = ");
1424 xmon_print_symbol(fp->link, " ", "\n");
f78541dc
PM
1425 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1426 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1da177e4 1427 fp->ctr, fp->xer, fp->trap);
f78541dc
PM
1428 trap = TRAP(fp);
1429 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1430 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1da177e4
LT
1431}
1432
1433void cacheflush(void)
1434{
1435 int cmd;
1436 unsigned long nflush;
1437
1438 cmd = inchar();
1439 if (cmd != 'i')
1440 termch = cmd;
1441 scanhex((void *)&adrs);
1442 if (termch != '\n')
1443 termch = 0;
1444 nflush = 1;
1445 scanhex(&nflush);
1446 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1447 if (setjmp(bus_error_jmp) == 0) {
1448 catch_memory_errors = 1;
1449 sync();
1450
1451 if (cmd != 'i') {
1452 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1453 cflush((void *) adrs);
1454 } else {
1455 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1456 cinval((void *) adrs);
1457 }
1458 sync();
1459 /* wait a little while to see if we get a machine check */
1460 __delay(200);
1461 }
1462 catch_memory_errors = 0;
1463}
1464
1465unsigned long
1466read_spr(int n)
1467{
1468 unsigned int instrs[2];
1469 unsigned long (*code)(void);
1da177e4 1470 unsigned long ret = -1UL;
548ccebc
PM
1471#ifdef CONFIG_PPC64
1472 unsigned long opd[3];
1da177e4 1473
1da177e4
LT
1474 opd[0] = (unsigned long)instrs;
1475 opd[1] = 0;
1476 opd[2] = 0;
548ccebc
PM
1477 code = (unsigned long (*)(void)) opd;
1478#else
1479 code = (unsigned long (*)(void)) instrs;
1480#endif
1481
1482 /* mfspr r3,n; blr */
1483 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1484 instrs[1] = 0x4e800020;
1da177e4
LT
1485 store_inst(instrs);
1486 store_inst(instrs+1);
1da177e4
LT
1487
1488 if (setjmp(bus_error_jmp) == 0) {
1489 catch_memory_errors = 1;
1490 sync();
1491
1492 ret = code();
1493
1494 sync();
1495 /* wait a little while to see if we get a machine check */
1496 __delay(200);
1497 n = size;
1498 }
1499
1500 return ret;
1501}
1502
1503void
1504write_spr(int n, unsigned long val)
1505{
1506 unsigned int instrs[2];
1507 unsigned long (*code)(unsigned long);
548ccebc 1508#ifdef CONFIG_PPC64
1da177e4
LT
1509 unsigned long opd[3];
1510
1da177e4
LT
1511 opd[0] = (unsigned long)instrs;
1512 opd[1] = 0;
1513 opd[2] = 0;
548ccebc
PM
1514 code = (unsigned long (*)(unsigned long)) opd;
1515#else
1516 code = (unsigned long (*)(unsigned long)) instrs;
1517#endif
1518
1519 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1520 instrs[1] = 0x4e800020;
1da177e4
LT
1521 store_inst(instrs);
1522 store_inst(instrs+1);
1da177e4
LT
1523
1524 if (setjmp(bus_error_jmp) == 0) {
1525 catch_memory_errors = 1;
1526 sync();
1527
1528 code(val);
1529
1530 sync();
1531 /* wait a little while to see if we get a machine check */
1532 __delay(200);
1533 n = size;
1534 }
1535}
1536
1537static unsigned long regno;
1538extern char exc_prolog;
1539extern char dec_exc;
1540
f78541dc 1541void super_regs(void)
1da177e4
LT
1542{
1543 int cmd;
1544 unsigned long val;
1545#ifdef CONFIG_PPC_ISERIES
1546 struct paca_struct *ptrPaca = NULL;
1547 struct lppaca *ptrLpPaca = NULL;
1548 struct ItLpRegSave *ptrLpRegSave = NULL;
1549#endif
1550
1551 cmd = skipbl();
1552 if (cmd == '\n') {
1553 unsigned long sp, toc;
1554 asm("mr %0,1" : "=r" (sp) :);
1555 asm("mr %0,2" : "=r" (toc) :);
1556
f78541dc
PM
1557 printf("msr = "REG" sprg0= "REG"\n",
1558 mfmsr(), mfspr(SPRN_SPRG0));
1559 printf("pvr = "REG" sprg1= "REG"\n",
1560 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1561 printf("dec = "REG" sprg2= "REG"\n",
1562 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1563 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1564 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1da177e4
LT
1565#ifdef CONFIG_PPC_ISERIES
1566 // Dump out relevant Paca data areas.
1567 printf("Paca: \n");
1568 ptrPaca = get_paca();
1569
1570 printf(" Local Processor Control Area (LpPaca): \n");
1571 ptrLpPaca = ptrPaca->lppaca_ptr;
1572 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1573 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1574 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1575 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1576 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1577
1578 printf(" Local Processor Register Save Area (LpRegSave): \n");
1579 ptrLpRegSave = ptrPaca->reg_save_ptr;
1580 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1581 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1582 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1583 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1584 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1585 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1586#endif
1587
1588 return;
1589 }
1590
1591 scanhex(&regno);
1592 switch (cmd) {
1593 case 'w':
1594 val = read_spr(regno);
1595 scanhex(&val);
1596 write_spr(regno, val);
1597 /* fall through */
1598 case 'r':
1599 printf("spr %lx = %lx\n", regno, read_spr(regno));
1600 break;
1da177e4
LT
1601 }
1602 scannl();
1603}
1604
1605/*
1606 * Stuff for reading and writing memory safely
1607 */
1608int
1609mread(unsigned long adrs, void *buf, int size)
1610{
1611 volatile int n;
1612 char *p, *q;
1613
1614 n = 0;
1615 if (setjmp(bus_error_jmp) == 0) {
1616 catch_memory_errors = 1;
1617 sync();
1618 p = (char *)adrs;
1619 q = (char *)buf;
1620 switch (size) {
1621 case 2:
f78541dc 1622 *(u16 *)q = *(u16 *)p;
1da177e4
LT
1623 break;
1624 case 4:
f78541dc 1625 *(u32 *)q = *(u32 *)p;
1da177e4
LT
1626 break;
1627 case 8:
f78541dc 1628 *(u64 *)q = *(u64 *)p;
1da177e4
LT
1629 break;
1630 default:
1631 for( ; n < size; ++n) {
1632 *q++ = *p++;
1633 sync();
1634 }
1635 }
1636 sync();
1637 /* wait a little while to see if we get a machine check */
1638 __delay(200);
1639 n = size;
1640 }
1641 catch_memory_errors = 0;
1642 return n;
1643}
1644
1645int
1646mwrite(unsigned long adrs, void *buf, int size)
1647{
1648 volatile int n;
1649 char *p, *q;
1650
1651 n = 0;
1652 if (setjmp(bus_error_jmp) == 0) {
1653 catch_memory_errors = 1;
1654 sync();
1655 p = (char *) adrs;
1656 q = (char *) buf;
1657 switch (size) {
1658 case 2:
f78541dc 1659 *(u16 *)p = *(u16 *)q;
1da177e4
LT
1660 break;
1661 case 4:
f78541dc 1662 *(u32 *)p = *(u32 *)q;
1da177e4
LT
1663 break;
1664 case 8:
f78541dc 1665 *(u64 *)p = *(u64 *)q;
1da177e4
LT
1666 break;
1667 default:
1668 for ( ; n < size; ++n) {
1669 *p++ = *q++;
1670 sync();
1671 }
1672 }
1673 sync();
1674 /* wait a little while to see if we get a machine check */
1675 __delay(200);
1676 n = size;
1677 } else {
1678 printf("*** Error writing address %x\n", adrs + n);
1679 }
1680 catch_memory_errors = 0;
1681 return n;
1682}
1683
1684static int fault_type;
f78541dc 1685static int fault_except;
1da177e4
LT
1686static char *fault_chars[] = { "--", "**", "##" };
1687
f78541dc 1688static int handle_fault(struct pt_regs *regs)
1da177e4 1689{
f78541dc 1690 fault_except = TRAP(regs);
1da177e4
LT
1691 switch (TRAP(regs)) {
1692 case 0x200:
1693 fault_type = 0;
1694 break;
1695 case 0x300:
1696 case 0x380:
1697 fault_type = 1;
1698 break;
1699 default:
1700 fault_type = 2;
1701 }
1702
1703 longjmp(bus_error_jmp, 1);
1704
1705 return 0;
1706}
1707
1708#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1709
1710void
1711byterev(unsigned char *val, int size)
1712{
1713 int t;
1714
1715 switch (size) {
1716 case 2:
1717 SWAP(val[0], val[1], t);
1718 break;
1719 case 4:
1720 SWAP(val[0], val[3], t);
1721 SWAP(val[1], val[2], t);
1722 break;
1723 case 8: /* is there really any use for this? */
1724 SWAP(val[0], val[7], t);
1725 SWAP(val[1], val[6], t);
1726 SWAP(val[2], val[5], t);
1727 SWAP(val[3], val[4], t);
1728 break;
1729 }
1730}
1731
1732static int brev;
1733static int mnoread;
1734
1735static char *memex_help_string =
1736 "Memory examine command usage:\n"
1737 "m [addr] [flags] examine/change memory\n"
1738 " addr is optional. will start where left off.\n"
1739 " flags may include chars from this set:\n"
1740 " b modify by bytes (default)\n"
1741 " w modify by words (2 byte)\n"
1742 " l modify by longs (4 byte)\n"
1743 " d modify by doubleword (8 byte)\n"
1744 " r toggle reverse byte order mode\n"
1745 " n do not read memory (for i/o spaces)\n"
1746 " . ok to read (default)\n"
1747 "NOTE: flags are saved as defaults\n"
1748 "";
1749
1750static char *memex_subcmd_help_string =
1751 "Memory examine subcommands:\n"
1752 " hexval write this val to current location\n"
1753 " 'string' write chars from string to this location\n"
1754 " ' increment address\n"
1755 " ^ decrement address\n"
1756 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1757 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1758 " ` clear no-read flag\n"
1759 " ; stay at this addr\n"
1760 " v change to byte mode\n"
1761 " w change to word (2 byte) mode\n"
1762 " l change to long (4 byte) mode\n"
1763 " u change to doubleword (8 byte) mode\n"
1764 " m addr change current addr\n"
1765 " n toggle no-read flag\n"
1766 " r toggle byte reverse flag\n"
1767 " < count back up count bytes\n"
1768 " > count skip forward count bytes\n"
1769 " x exit this mode\n"
1770 "";
1771
1772void
1773memex(void)
1774{
1775 int cmd, inc, i, nslash;
1776 unsigned long n;
1777 unsigned char val[16];
1778
1779 scanhex((void *)&adrs);
1780 cmd = skipbl();
1781 if (cmd == '?') {
1782 printf(memex_help_string);
1783 return;
1784 } else {
1785 termch = cmd;
1786 }
1787 last_cmd = "m\n";
1788 while ((cmd = skipbl()) != '\n') {
1789 switch( cmd ){
1790 case 'b': size = 1; break;
1791 case 'w': size = 2; break;
1792 case 'l': size = 4; break;
1793 case 'd': size = 8; break;
1794 case 'r': brev = !brev; break;
1795 case 'n': mnoread = 1; break;
1796 case '.': mnoread = 0; break;
1797 }
1798 }
1799 if( size <= 0 )
1800 size = 1;
1801 else if( size > 8 )
1802 size = 8;
1803 for(;;){
1804 if (!mnoread)
1805 n = mread(adrs, val, size);
e1449ed9 1806 printf(REG"%c", adrs, brev? 'r': ' ');
1da177e4
LT
1807 if (!mnoread) {
1808 if (brev)
1809 byterev(val, size);
1810 putchar(' ');
1811 for (i = 0; i < n; ++i)
1812 printf("%.2x", val[i]);
1813 for (; i < size; ++i)
1814 printf("%s", fault_chars[fault_type]);
1815 }
1816 putchar(' ');
1817 inc = size;
1818 nslash = 0;
1819 for(;;){
1820 if( scanhex(&n) ){
1821 for (i = 0; i < size; ++i)
1822 val[i] = n >> (i * 8);
1823 if (!brev)
1824 byterev(val, size);
1825 mwrite(adrs, val, size);
1826 inc = size;
1827 }
1828 cmd = skipbl();
1829 if (cmd == '\n')
1830 break;
1831 inc = 0;
1832 switch (cmd) {
1833 case '\'':
1834 for(;;){
1835 n = inchar();
1836 if( n == '\\' )
1837 n = bsesc();
1838 else if( n == '\'' )
1839 break;
1840 for (i = 0; i < size; ++i)
1841 val[i] = n >> (i * 8);
1842 if (!brev)
1843 byterev(val, size);
1844 mwrite(adrs, val, size);
1845 adrs += size;
1846 }
1847 adrs -= size;
1848 inc = size;
1849 break;
1850 case ',':
1851 adrs += size;
1852 break;
1853 case '.':
1854 mnoread = 0;
1855 break;
1856 case ';':
1857 break;
1858 case 'x':
1859 case EOF:
1860 scannl();
1861 return;
1862 case 'b':
1863 case 'v':
1864 size = 1;
1865 break;
1866 case 'w':
1867 size = 2;
1868 break;
1869 case 'l':
1870 size = 4;
1871 break;
1872 case 'u':
1873 size = 8;
1874 break;
1875 case '^':
1876 adrs -= size;
1877 break;
1878 break;
1879 case '/':
1880 if (nslash > 0)
1881 adrs -= 1 << nslash;
1882 else
1883 nslash = 0;
1884 nslash += 4;
1885 adrs += 1 << nslash;
1886 break;
1887 case '\\':
1888 if (nslash < 0)
1889 adrs += 1 << -nslash;
1890 else
1891 nslash = 0;
1892 nslash -= 4;
1893 adrs -= 1 << -nslash;
1894 break;
1895 case 'm':
1896 scanhex((void *)&adrs);
1897 break;
1898 case 'n':
1899 mnoread = 1;
1900 break;
1901 case 'r':
1902 brev = !brev;
1903 break;
1904 case '<':
1905 n = size;
1906 scanhex(&n);
1907 adrs -= n;
1908 break;
1909 case '>':
1910 n = size;
1911 scanhex(&n);
1912 adrs += n;
1913 break;
1914 case '?':
1915 printf(memex_subcmd_help_string);
1916 break;
1917 }
1918 }
1919 adrs += inc;
1920 }
1921}
1922
1923int
1924bsesc(void)
1925{
1926 int c;
1927
1928 c = inchar();
1929 switch( c ){
1930 case 'n': c = '\n'; break;
1931 case 'r': c = '\r'; break;
1932 case 'b': c = '\b'; break;
1933 case 't': c = '\t'; break;
1934 }
1935 return c;
1936}
1937
7e5b5938
OH
1938static void xmon_rawdump (unsigned long adrs, long ndump)
1939{
1940 long n, m, r, nr;
1941 unsigned char temp[16];
1942
1943 for (n = ndump; n > 0;) {
1944 r = n < 16? n: 16;
1945 nr = mread(adrs, temp, r);
1946 adrs += nr;
1947 for (m = 0; m < r; ++m) {
1948 if (m < nr)
1949 printf("%.2x", temp[m]);
1950 else
1951 printf("%s", fault_chars[fault_type]);
1952 }
1953 n -= r;
1954 if (nr < r)
1955 break;
1956 }
1957 printf("\n");
1958}
1959
1da177e4
LT
1960#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1961 || ('a' <= (c) && (c) <= 'f') \
1962 || ('A' <= (c) && (c) <= 'F'))
1963void
1964dump(void)
1965{
1966 int c;
1967
1968 c = inchar();
1969 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1970 termch = c;
1971 scanhex((void *)&adrs);
1972 if (termch != '\n')
1973 termch = 0;
1974 if (c == 'i') {
1975 scanhex(&nidump);
1976 if (nidump == 0)
1977 nidump = 16;
1978 else if (nidump > MAX_DUMP)
1979 nidump = MAX_DUMP;
1980 adrs += ppc_inst_dump(adrs, nidump, 1);
1981 last_cmd = "di\n";
7e5b5938
OH
1982 } else if (c == 'r') {
1983 scanhex(&ndump);
1984 if (ndump == 0)
1985 ndump = 64;
1986 xmon_rawdump(adrs, ndump);
1987 adrs += ndump;
1988 last_cmd = "dr\n";
1da177e4
LT
1989 } else {
1990 scanhex(&ndump);
1991 if (ndump == 0)
1992 ndump = 64;
1993 else if (ndump > MAX_DUMP)
1994 ndump = MAX_DUMP;
1995 prdump(adrs, ndump);
1996 adrs += ndump;
1997 last_cmd = "d\n";
1998 }
1999}
2000
2001void
2002prdump(unsigned long adrs, long ndump)
2003{
2004 long n, m, c, r, nr;
2005 unsigned char temp[16];
2006
2007 for (n = ndump; n > 0;) {
f78541dc 2008 printf(REG, adrs);
1da177e4
LT
2009 putchar(' ');
2010 r = n < 16? n: 16;
2011 nr = mread(adrs, temp, r);
2012 adrs += nr;
2013 for (m = 0; m < r; ++m) {
e1449ed9
PM
2014 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2015 putchar(' ');
1da177e4
LT
2016 if (m < nr)
2017 printf("%.2x", temp[m]);
2018 else
2019 printf("%s", fault_chars[fault_type]);
2020 }
e1449ed9
PM
2021 for (; m < 16; ++m) {
2022 if ((m & (sizeof(long) - 1)) == 0)
2023 putchar(' ');
1da177e4 2024 printf(" ");
e1449ed9 2025 }
1da177e4
LT
2026 printf(" |");
2027 for (m = 0; m < r; ++m) {
2028 if (m < nr) {
2029 c = temp[m];
2030 putchar(' ' <= c && c <= '~'? c: '.');
2031 } else
2032 putchar(' ');
2033 }
2034 n -= r;
2035 for (; m < 16; ++m)
2036 putchar(' ');
2037 printf("|\n");
2038 if (nr < r)
2039 break;
2040 }
2041}
2042
2043int
2044ppc_inst_dump(unsigned long adr, long count, int praddr)
2045{
2046 int nr, dotted;
2047 unsigned long first_adr;
2048 unsigned long inst, last_inst = 0;
2049 unsigned char val[4];
2050
2051 dotted = 0;
2052 for (first_adr = adr; count > 0; --count, adr += 4) {
2053 nr = mread(adr, val, 4);
2054 if (nr == 0) {
2055 if (praddr) {
2056 const char *x = fault_chars[fault_type];
f78541dc 2057 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
1da177e4
LT
2058 }
2059 break;
2060 }
2061 inst = GETWORD(val);
2062 if (adr > first_adr && inst == last_inst) {
2063 if (!dotted) {
2064 printf(" ...\n");
2065 dotted = 1;
2066 }
2067 continue;
2068 }
2069 dotted = 0;
2070 last_inst = inst;
2071 if (praddr)
f78541dc 2072 printf(REG" %.8x", adr, inst);
1da177e4
LT
2073 printf("\t");
2074 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2075 printf("\n");
2076 }
2077 return adr - first_adr;
2078}
2079
2080void
2081print_address(unsigned long addr)
2082{
2083 xmon_print_symbol(addr, "\t# ", "");
2084}
2085
2086
2087/*
2088 * Memory operations - move, set, print differences
2089 */
2090static unsigned long mdest; /* destination address */
2091static unsigned long msrc; /* source address */
2092static unsigned long mval; /* byte value to set memory to */
2093static unsigned long mcount; /* # bytes to affect */
2094static unsigned long mdiffs; /* max # differences to print */
2095
2096void
2097memops(int cmd)
2098{
2099 scanhex((void *)&mdest);
2100 if( termch != '\n' )
2101 termch = 0;
2102 scanhex((void *)(cmd == 's'? &mval: &msrc));
2103 if( termch != '\n' )
2104 termch = 0;
2105 scanhex((void *)&mcount);
2106 switch( cmd ){
2107 case 'm':
2108 memmove((void *)mdest, (void *)msrc, mcount);
2109 break;
2110 case 's':
2111 memset((void *)mdest, mval, mcount);
2112 break;
2113 case 'd':
2114 if( termch != '\n' )
2115 termch = 0;
2116 scanhex((void *)&mdiffs);
2117 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2118 break;
2119 }
2120}
2121
2122void
2123memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2124{
2125 unsigned n, prt;
2126
2127 prt = 0;
2128 for( n = nb; n > 0; --n )
2129 if( *p1++ != *p2++ )
2130 if( ++prt <= maxpr )
2131 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2132 p1[-1], p2 - 1, p2[-1]);
2133 if( prt > maxpr )
2134 printf("Total of %d differences\n", prt);
2135}
2136
2137static unsigned mend;
2138static unsigned mask;
2139
2140void
2141memlocate(void)
2142{
2143 unsigned a, n;
2144 unsigned char val[4];
2145
2146 last_cmd = "ml";
2147 scanhex((void *)&mdest);
2148 if (termch != '\n') {
2149 termch = 0;
2150 scanhex((void *)&mend);
2151 if (termch != '\n') {
2152 termch = 0;
2153 scanhex((void *)&mval);
2154 mask = ~0;
2155 if (termch != '\n') termch = 0;
2156 scanhex((void *)&mask);
2157 }
2158 }
2159 n = 0;
2160 for (a = mdest; a < mend; a += 4) {
2161 if (mread(a, val, 4) == 4
2162 && ((GETWORD(val) ^ mval) & mask) == 0) {
2163 printf("%.16x: %.16x\n", a, GETWORD(val));
2164 if (++n >= 10)
2165 break;
2166 }
2167 }
2168}
2169
2170static unsigned long mskip = 0x1000;
2171static unsigned long mlim = 0xffffffff;
2172
2173void
2174memzcan(void)
2175{
2176 unsigned char v;
2177 unsigned a;
2178 int ok, ook;
2179
2180 scanhex(&mdest);
2181 if (termch != '\n') termch = 0;
2182 scanhex(&mskip);
2183 if (termch != '\n') termch = 0;
2184 scanhex(&mlim);
2185 ook = 0;
2186 for (a = mdest; a < mlim; a += mskip) {
2187 ok = mread(a, &v, 1);
2188 if (ok && !ook) {
2189 printf("%.8x .. ", a);
1da177e4
LT
2190 } else if (!ok && ook)
2191 printf("%.8x\n", a - mskip);
2192 ook = ok;
2193 if (a + mskip < a)
2194 break;
2195 }
2196 if (ook)
2197 printf("%.8x\n", a - mskip);
2198}
2199
f78541dc
PM
2200void proccall(void)
2201{
2202 unsigned long args[8];
2203 unsigned long ret;
2204 int i;
2205 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2206 unsigned long, unsigned long, unsigned long,
2207 unsigned long, unsigned long, unsigned long);
2208 callfunc_t func;
2209
2210 if (!scanhex(&adrs))
2211 return;
2212 if (termch != '\n')
2213 termch = 0;
2214 for (i = 0; i < 8; ++i)
2215 args[i] = 0;
2216 for (i = 0; i < 8; ++i) {
2217 if (!scanhex(&args[i]) || termch == '\n')
2218 break;
2219 termch = 0;
2220 }
2221 func = (callfunc_t) adrs;
2222 ret = 0;
2223 if (setjmp(bus_error_jmp) == 0) {
2224 catch_memory_errors = 1;
2225 sync();
2226 ret = func(args[0], args[1], args[2], args[3],
2227 args[4], args[5], args[6], args[7]);
2228 sync();
2229 printf("return value is %x\n", ret);
2230 } else {
2231 printf("*** %x exception occurred\n", fault_except);
2232 }
2233 catch_memory_errors = 0;
2234}
2235
1da177e4
LT
2236/* Input scanning routines */
2237int
2238skipbl(void)
2239{
2240 int c;
2241
2242 if( termch != 0 ){
2243 c = termch;
2244 termch = 0;
2245 } else
2246 c = inchar();
2247 while( c == ' ' || c == '\t' )
2248 c = inchar();
2249 return c;
2250}
2251
2252#define N_PTREGS 44
2253static char *regnames[N_PTREGS] = {
2254 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2255 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2256 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2257 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
f78541dc
PM
2258 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2259#ifdef CONFIG_PPC64
2260 "softe",
2261#else
2262 "mq",
2263#endif
1da177e4
LT
2264 "trap", "dar", "dsisr", "res"
2265};
2266
2267int
2268scanhex(unsigned long *vp)
2269{
2270 int c, d;
2271 unsigned long v;
2272
2273 c = skipbl();
2274 if (c == '%') {
2275 /* parse register name */
2276 char regname[8];
2277 int i;
2278
2279 for (i = 0; i < sizeof(regname) - 1; ++i) {
2280 c = inchar();
2281 if (!isalnum(c)) {
2282 termch = c;
2283 break;
2284 }
2285 regname[i] = c;
2286 }
2287 regname[i] = 0;
2288 for (i = 0; i < N_PTREGS; ++i) {
2289 if (strcmp(regnames[i], regname) == 0) {
2290 if (xmon_regs == NULL) {
2291 printf("regs not available\n");
2292 return 0;
2293 }
2294 *vp = ((unsigned long *)xmon_regs)[i];
2295 return 1;
2296 }
2297 }
2298 printf("invalid register name '%%%s'\n", regname);
2299 return 0;
2300 }
2301
2302 /* skip leading "0x" if any */
2303
2304 if (c == '0') {
2305 c = inchar();
2306 if (c == 'x') {
2307 c = inchar();
2308 } else {
2309 d = hexdigit(c);
2310 if (d == EOF) {
2311 termch = c;
2312 *vp = 0;
2313 return 1;
2314 }
2315 }
2316 } else if (c == '$') {
2317 int i;
2318 for (i=0; i<63; i++) {
2319 c = inchar();
2320 if (isspace(c)) {
2321 termch = c;
2322 break;
2323 }
2324 tmpstr[i] = c;
2325 }
2326 tmpstr[i++] = 0;
6879dc13
BH
2327 *vp = 0;
2328 if (setjmp(bus_error_jmp) == 0) {
2329 catch_memory_errors = 1;
2330 sync();
2331 *vp = kallsyms_lookup_name(tmpstr);
2332 sync();
2333 }
2334 catch_memory_errors = 0;
1da177e4
LT
2335 if (!(*vp)) {
2336 printf("unknown symbol '%s'\n", tmpstr);
2337 return 0;
2338 }
2339 return 1;
2340 }
2341
2342 d = hexdigit(c);
2343 if (d == EOF) {
2344 termch = c;
2345 return 0;
2346 }
2347 v = 0;
2348 do {
2349 v = (v << 4) + d;
2350 c = inchar();
2351 d = hexdigit(c);
2352 } while (d != EOF);
2353 termch = c;
2354 *vp = v;
2355 return 1;
2356}
2357
2358void
2359scannl(void)
2360{
2361 int c;
2362
2363 c = termch;
2364 termch = 0;
2365 while( c != '\n' )
2366 c = inchar();
2367}
2368
f78541dc 2369int hexdigit(int c)
1da177e4
LT
2370{
2371 if( '0' <= c && c <= '9' )
2372 return c - '0';
2373 if( 'A' <= c && c <= 'F' )
2374 return c - ('A' - 10);
2375 if( 'a' <= c && c <= 'f' )
2376 return c - ('a' - 10);
2377 return EOF;
2378}
2379
2380void
2381getstring(char *s, int size)
2382{
2383 int c;
2384
2385 c = skipbl();
2386 do {
2387 if( size > 1 ){
2388 *s++ = c;
2389 --size;
2390 }
2391 c = inchar();
2392 } while( c != ' ' && c != '\t' && c != '\n' );
2393 termch = c;
2394 *s = 0;
2395}
2396
2397static char line[256];
2398static char *lineptr;
2399
2400void
2401flush_input(void)
2402{
2403 lineptr = NULL;
2404}
2405
2406int
2407inchar(void)
2408{
2409 if (lineptr == NULL || *lineptr == 0) {
fca5dcd4 2410 if (xmon_gets(line, sizeof(line)) == NULL) {
1da177e4
LT
2411 lineptr = NULL;
2412 return EOF;
2413 }
2414 lineptr = line;
2415 }
2416 return *lineptr++;
2417}
2418
2419void
2420take_input(char *str)
2421{
2422 lineptr = str;
2423}
2424
2425
2426static void
2427symbol_lookup(void)
2428{
2429 int type = inchar();
2430 unsigned long addr;
2431 static char tmp[64];
2432
2433 switch (type) {
2434 case 'a':
2435 if (scanhex(&addr))
2436 xmon_print_symbol(addr, ": ", "\n");
2437 termch = 0;
2438 break;
2439 case 's':
2440 getstring(tmp, 64);
2441 if (setjmp(bus_error_jmp) == 0) {
2442 catch_memory_errors = 1;
2443 sync();
2444 addr = kallsyms_lookup_name(tmp);
2445 if (addr)
2446 printf("%s: %lx\n", tmp, addr);
2447 else
2448 printf("Symbol '%s' not found.\n", tmp);
2449 sync();
2450 }
2451 catch_memory_errors = 0;
2452 termch = 0;
2453 break;
2454 }
2455}
2456
2457
2458/* Print an address in numeric and symbolic form (if possible) */
2459static void xmon_print_symbol(unsigned long address, const char *mid,
2460 const char *after)
2461{
2462 char *modname;
2463 const char *name = NULL;
2464 unsigned long offset, size;
2465
f78541dc 2466 printf(REG, address);
1da177e4
LT
2467 if (setjmp(bus_error_jmp) == 0) {
2468 catch_memory_errors = 1;
2469 sync();
2470 name = kallsyms_lookup(address, &size, &offset, &modname,
2471 tmpstr);
2472 sync();
2473 /* wait a little while to see if we get a machine check */
2474 __delay(200);
2475 }
2476
2477 catch_memory_errors = 0;
2478
2479 if (name) {
2480 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2481 if (modname)
2482 printf(" [%s]", modname);
2483 }
2484 printf("%s", after);
2485}
2486
f78541dc 2487#ifdef CONFIG_PPC64
1da177e4
LT
2488static void dump_slb(void)
2489{
2490 int i;
2491 unsigned long tmp;
2492
2493 printf("SLB contents of cpu %x\n", smp_processor_id());
2494
2495 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2496 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2497 printf("%02d %016lx ", i, tmp);
2498
2499 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2500 printf("%016lx\n", tmp);
2501 }
2502}
2503
2504static void dump_stab(void)
2505{
2506 int i;
2507 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2508
2509 printf("Segment table contents of cpu %x\n", smp_processor_id());
2510
2511 for (i = 0; i < PAGE_SIZE/16; i++) {
2512 unsigned long a, b;
2513
2514 a = *tmp++;
2515 b = *tmp++;
2516
2517 if (a || b) {
2518 printf("%03d %016lx ", i, a);
2519 printf("%016lx\n", b);
2520 }
2521 }
2522}
2523
f78541dc
PM
2524void dump_segments(void)
2525{
2526 if (cpu_has_feature(CPU_FTR_SLB))
2527 dump_slb();
2528 else
2529 dump_stab();
2530}
2531#endif
2532
2533#ifdef CONFIG_PPC_STD_MMU_32
2534void dump_segments(void)
2535{
2536 int i;
2537
2538 printf("sr0-15 =");
2539 for (i = 0; i < 16; ++i)
2540 printf(" %x", mfsrin(i));
2541 printf("\n");
2542}
2543#endif
2544
b13cfd17
OH
2545void xmon_init(int enable)
2546{
2547 if (enable) {
2548 __debugger = xmon;
2549 __debugger_ipi = xmon_ipi;
2550 __debugger_bpt = xmon_bpt;
2551 __debugger_sstep = xmon_sstep;
2552 __debugger_iabr_match = xmon_iabr_match;
2553 __debugger_dabr_match = xmon_dabr_match;
2554 __debugger_fault_handler = xmon_fault_handler;
2555 } else {
2556 __debugger = NULL;
2557 __debugger_ipi = NULL;
2558 __debugger_bpt = NULL;
2559 __debugger_sstep = NULL;
2560 __debugger_iabr_match = NULL;
2561 __debugger_dabr_match = NULL;
2562 __debugger_fault_handler = NULL;
2563 }
fca5dcd4 2564 xmon_map_scc();
1da177e4 2565}
fca5dcd4
PM
2566
2567#ifdef CONFIG_MAGIC_SYSRQ
2568static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2569 struct tty_struct *tty)
2570{
2571 /* ensure xmon is enabled */
2572 xmon_init(1);
2573 debugger(pt_regs);
2574}
2575
2576static struct sysrq_key_op sysrq_xmon_op =
2577{
2578 .handler = sysrq_handle_xmon,
2579 .help_msg = "Xmon",
2580 .action_msg = "Entering xmon",
2581};
2582
2583static int __init setup_xmon_sysrq(void)
2584{
2585 register_sysrq_key('x', &sysrq_xmon_op);
2586 return 0;
2587}
2588__initcall(setup_xmon_sysrq);
2589#endif /* CONFIG_MAGIC_SYSRQ */