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