[PATCH] ppc32: Add support for handling PCI interrupts on MPC834x PCI expansion card
[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>
1da177e4
LT
22
23#include <asm/ptrace.h>
24#include <asm/string.h>
25#include <asm/prom.h>
26#include <asm/machdep.h>
f78541dc
PM
27#include <asm/xmon.h>
28#ifdef CONFIG_PMAC_BACKLIGHT
29#include <asm/backlight.h>
30#endif
1da177e4
LT
31#include <asm/processor.h>
32#include <asm/pgtable.h>
33#include <asm/mmu.h>
34#include <asm/mmu_context.h>
1da177e4
LT
35#include <asm/cputable.h>
36#include <asm/rtas.h>
37#include <asm/sstep.h>
38#include <asm/bug.h>
f78541dc
PM
39
40#ifdef CONFIG_PPC64
1da177e4 41#include <asm/hvcall.h>
f78541dc
PM
42#include <asm/paca.h>
43#endif
1da177e4
LT
44
45#include "nonstdio.h"
1da177e4
LT
46
47#define scanhex xmon_scanhex
48#define skipbl xmon_skipbl
49
50#ifdef CONFIG_SMP
51cpumask_t cpus_in_xmon = CPU_MASK_NONE;
52static unsigned long xmon_taken = 1;
53static int xmon_owner;
54static int xmon_gate;
55#endif /* CONFIG_SMP */
56
57static unsigned long in_xmon = 0;
58
59static unsigned long adrs;
60static int size = 1;
61#define MAX_DUMP (128 * 1024)
62static unsigned long ndump = 64;
63static unsigned long nidump = 16;
64static unsigned long ncsum = 4096;
65static int termch;
66static char tmpstr[128];
67
f78541dc 68#define JMP_BUF_LEN 23
1da177e4
LT
69static long bus_error_jmp[JMP_BUF_LEN];
70static int catch_memory_errors;
71static long *xmon_fault_jmp[NR_CPUS];
72#define setjmp xmon_setjmp
73#define longjmp xmon_longjmp
74
75/* Breakpoint stuff */
76struct bpt {
77 unsigned long address;
78 unsigned int instr[2];
79 atomic_t ref_count;
80 int enabled;
81 unsigned long pad;
82};
83
84/* Bits in bpt.enabled */
85#define BP_IABR_TE 1 /* IABR translation enabled */
86#define BP_IABR 2
87#define BP_TRAP 8
88#define BP_DABR 0x10
89
90#define NBPTS 256
91static struct bpt bpts[NBPTS];
92static struct bpt dabr;
93static struct bpt *iabr;
94static unsigned bpinstr = 0x7fe00008; /* trap */
95
96#define BP_NUM(bp) ((bp) - bpts + 1)
97
98/* Prototypes */
99static int cmds(struct pt_regs *);
100static int mread(unsigned long, void *, int);
101static int mwrite(unsigned long, void *, int);
102static int handle_fault(struct pt_regs *);
103static void byterev(unsigned char *, int);
104static void memex(void);
105static int bsesc(void);
106static void dump(void);
107static void prdump(unsigned long, long);
108static int ppc_inst_dump(unsigned long, long, int);
109void print_address(unsigned long);
110static void backtrace(struct pt_regs *);
111static void excprint(struct pt_regs *);
112static void prregs(struct pt_regs *);
113static void memops(int);
114static void memlocate(void);
115static void memzcan(void);
116static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
117int skipbl(void);
118int scanhex(unsigned long *valp);
119static void scannl(void);
120static int hexdigit(int);
121void getstring(char *, int);
122static void flush_input(void);
123static int inchar(void);
124static void take_input(char *);
125static unsigned long read_spr(int);
126static void write_spr(int, unsigned long);
127static void super_regs(void);
128static void remove_bpts(void);
129static void insert_bpts(void);
130static void remove_cpu_bpts(void);
131static void insert_cpu_bpts(void);
132static struct bpt *at_breakpoint(unsigned long pc);
133static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
134static int do_step(struct pt_regs *);
135static void bpt_cmds(void);
136static void cacheflush(void);
137static int cpu_cmd(void);
138static void csum(void);
139static void bootcmds(void);
f78541dc 140static void proccall(void);
1da177e4
LT
141void dump_segments(void);
142static void symbol_lookup(void);
143static void xmon_print_symbol(unsigned long address, const char *mid,
144 const char *after);
145static const char *getvecname(unsigned long vec);
146
1da177e4 147extern int print_insn_powerpc(unsigned long, unsigned long, int);
f78541dc
PM
148
149extern void xmon_enter(void);
150extern void xmon_leave(void);
151
f78541dc
PM
152extern long setjmp(long *);
153extern void longjmp(long *, long);
154extern void xmon_save_regs(struct pt_regs *);
155
156#ifdef CONFIG_PPC64
157#define REG "%.16lx"
158#define REGS_PER_LINE 4
159#define LAST_VOLATILE 13
160#else
161#define REG "%.8lx"
162#define REGS_PER_LINE 8
163#define LAST_VOLATILE 12
164#endif
1da177e4
LT
165
166#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
167
168#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
169 || ('a' <= (c) && (c) <= 'f') \
170 || ('A' <= (c) && (c) <= 'F'))
171#define isalnum(c) (('0' <= (c) && (c) <= '9') \
172 || ('a' <= (c) && (c) <= 'z') \
173 || ('A' <= (c) && (c) <= 'Z'))
174#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
175
176static char *help_string = "\
177Commands:\n\
178 b show breakpoints\n\
179 bd set data breakpoint\n\
180 bi set instruction breakpoint\n\
181 bc clear breakpoint\n"
182#ifdef CONFIG_SMP
183 "\
184 c print cpus stopped in xmon\n\
185 c# try to switch to cpu number h (in hex)\n"
186#endif
187 "\
188 C checksum\n\
189 d dump bytes\n\
190 di dump instructions\n\
191 df dump float values\n\
192 dd dump double values\n\
193 e print exception information\n\
194 f flush cache\n\
195 la lookup symbol+offset of specified address\n\
196 ls lookup address of specified symbol\n\
197 m examine/change memory\n\
198 mm move a block of memory\n\
199 ms set a block of memory\n\
200 md compare two blocks of memory\n\
201 ml locate a block of memory\n\
202 mz zero a block of memory\n\
203 mi show information about memory allocation\n\
f78541dc 204 p call a procedure\n\
1da177e4
LT
205 r print registers\n\
206 s single step\n\
207 S print special registers\n\
208 t print backtrace\n\
1da177e4 209 x exit monitor and recover\n\
f78541dc
PM
210 X exit monitor and dont recover\n"
211#ifdef CONFIG_PPC64
212" u dump segment table or SLB\n"
213#endif
214#ifdef CONFIG_PPC_STD_MMU_32
215" u dump segment registers\n"
216#endif
217" ? help\n"
218" zr reboot\n\
1da177e4
LT
219 zh halt\n"
220;
221
222static struct pt_regs *xmon_regs;
223
f78541dc 224static inline void sync(void)
1da177e4
LT
225{
226 asm volatile("sync; isync");
227}
228
f78541dc
PM
229static inline void store_inst(void *p)
230{
231 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
232}
233
234static inline void cflush(void *p)
235{
236 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
237}
238
239static inline void cinval(void *p)
240{
241 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
242}
1da177e4
LT
243
244/*
245 * Disable surveillance (the service processor watchdog function)
246 * while we are in xmon.
247 * XXX we should re-enable it when we leave. :)
248 */
249#define SURVEILLANCE_TOKEN 9000
250
251static inline void disable_surveillance(void)
252{
253#ifdef CONFIG_PPC_PSERIES
254 /* Since this can't be a module, args should end up below 4GB. */
255 static struct rtas_args args;
256
257 /*
258 * At this point we have got all the cpus we can into
259 * xmon, so there is hopefully no other cpu calling RTAS
260 * at the moment, even though we don't take rtas.lock.
261 * If we did try to take rtas.lock there would be a
262 * real possibility of deadlock.
263 */
264 args.token = rtas_token("set-indicator");
265 if (args.token == RTAS_UNKNOWN_SERVICE)
266 return;
267 args.nargs = 3;
268 args.nret = 1;
269 args.rets = &args.args[3];
270 args.args[0] = SURVEILLANCE_TOKEN;
271 args.args[1] = 0;
272 args.args[2] = 0;
273 enter_rtas(__pa(&args));
274#endif /* CONFIG_PPC_PSERIES */
275}
276
277#ifdef CONFIG_SMP
278static int xmon_speaker;
279
280static void get_output_lock(void)
281{
282 int me = smp_processor_id() + 0x100;
283 int last_speaker = 0, prev;
284 long timeout;
285
286 if (xmon_speaker == me)
287 return;
288 for (;;) {
289 if (xmon_speaker == 0) {
290 last_speaker = cmpxchg(&xmon_speaker, 0, me);
291 if (last_speaker == 0)
292 return;
293 }
294 timeout = 10000000;
295 while (xmon_speaker == last_speaker) {
296 if (--timeout > 0)
297 continue;
298 /* hostile takeover */
299 prev = cmpxchg(&xmon_speaker, last_speaker, me);
300 if (prev == last_speaker)
301 return;
302 break;
303 }
304 }
305}
306
307static void release_output_lock(void)
308{
309 xmon_speaker = 0;
310}
311#endif
312
313int xmon_core(struct pt_regs *regs, int fromipi)
314{
315 int cmd = 0;
316 unsigned long msr;
317 struct bpt *bp;
318 long recurse_jmp[JMP_BUF_LEN];
319 unsigned long offset;
320#ifdef CONFIG_SMP
321 int cpu;
322 int secondary;
323 unsigned long timeout;
324#endif
325
f78541dc
PM
326 msr = mfmsr();
327 mtmsr(msr & ~MSR_EE); /* disable interrupts */
1da177e4
LT
328
329 bp = in_breakpoint_table(regs->nip, &offset);
330 if (bp != NULL) {
331 regs->nip = bp->address + offset;
332 atomic_dec(&bp->ref_count);
333 }
334
335 remove_cpu_bpts();
336
337#ifdef CONFIG_SMP
338 cpu = smp_processor_id();
339 if (cpu_isset(cpu, cpus_in_xmon)) {
340 get_output_lock();
341 excprint(regs);
342 printf("cpu 0x%x: Exception %lx %s in xmon, "
343 "returning to main loop\n",
344 cpu, regs->trap, getvecname(TRAP(regs)));
5cb4cc0d 345 release_output_lock();
1da177e4
LT
346 longjmp(xmon_fault_jmp[cpu], 1);
347 }
348
349 if (setjmp(recurse_jmp) != 0) {
350 if (!in_xmon || !xmon_gate) {
5cb4cc0d 351 get_output_lock();
1da177e4
LT
352 printf("xmon: WARNING: bad recursive fault "
353 "on cpu 0x%x\n", cpu);
5cb4cc0d 354 release_output_lock();
1da177e4
LT
355 goto waiting;
356 }
357 secondary = !(xmon_taken && cpu == xmon_owner);
358 goto cmdloop;
359 }
360
361 xmon_fault_jmp[cpu] = recurse_jmp;
362 cpu_set(cpu, cpus_in_xmon);
363
364 bp = NULL;
365 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
366 bp = at_breakpoint(regs->nip);
367 if (bp || (regs->msr & MSR_RI) == 0)
368 fromipi = 0;
369
370 if (!fromipi) {
371 get_output_lock();
372 excprint(regs);
373 if (bp) {
374 printf("cpu 0x%x stopped at breakpoint 0x%x (",
375 cpu, BP_NUM(bp));
376 xmon_print_symbol(regs->nip, " ", ")\n");
377 }
378 if ((regs->msr & MSR_RI) == 0)
379 printf("WARNING: exception is not recoverable, "
380 "can't continue\n");
381 release_output_lock();
382 }
383
384 waiting:
385 secondary = 1;
386 while (secondary && !xmon_gate) {
387 if (in_xmon == 0) {
388 if (fromipi)
389 goto leave;
390 secondary = test_and_set_bit(0, &in_xmon);
391 }
392 barrier();
393 }
394
395 if (!secondary && !xmon_gate) {
396 /* we are the first cpu to come in */
397 /* interrupt other cpu(s) */
398 int ncpus = num_online_cpus();
399
400 xmon_owner = cpu;
401 mb();
402 if (ncpus > 1) {
403 smp_send_debugger_break(MSG_ALL_BUT_SELF);
404 /* wait for other cpus to come in */
405 for (timeout = 100000000; timeout != 0; --timeout) {
406 if (cpus_weight(cpus_in_xmon) >= ncpus)
407 break;
408 barrier();
409 }
410 }
411 remove_bpts();
412 disable_surveillance();
413 /* for breakpoint or single step, print the current instr. */
414 if (bp || TRAP(regs) == 0xd00)
415 ppc_inst_dump(regs->nip, 1, 0);
416 printf("enter ? for help\n");
417 mb();
418 xmon_gate = 1;
419 barrier();
420 }
421
422 cmdloop:
423 while (in_xmon) {
424 if (secondary) {
425 if (cpu == xmon_owner) {
426 if (!test_and_set_bit(0, &xmon_taken)) {
427 secondary = 0;
428 continue;
429 }
430 /* missed it */
431 while (cpu == xmon_owner)
432 barrier();
433 }
434 barrier();
435 } else {
436 cmd = cmds(regs);
437 if (cmd != 0) {
438 /* exiting xmon */
439 insert_bpts();
440 xmon_gate = 0;
441 wmb();
442 in_xmon = 0;
443 break;
444 }
445 /* have switched to some other cpu */
446 secondary = 1;
447 }
448 }
449 leave:
450 cpu_clear(cpu, cpus_in_xmon);
451 xmon_fault_jmp[cpu] = NULL;
452
453#else
454 /* UP is simple... */
455 if (in_xmon) {
456 printf("Exception %lx %s in xmon, returning to main loop\n",
457 regs->trap, getvecname(TRAP(regs)));
458 longjmp(xmon_fault_jmp[0], 1);
459 }
460 if (setjmp(recurse_jmp) == 0) {
461 xmon_fault_jmp[0] = recurse_jmp;
462 in_xmon = 1;
463
464 excprint(regs);
465 bp = at_breakpoint(regs->nip);
466 if (bp) {
467 printf("Stopped at breakpoint %x (", BP_NUM(bp));
468 xmon_print_symbol(regs->nip, " ", ")\n");
469 }
470 if ((regs->msr & MSR_RI) == 0)
471 printf("WARNING: exception is not recoverable, "
472 "can't continue\n");
473 remove_bpts();
474 disable_surveillance();
475 /* for breakpoint or single step, print the current instr. */
476 if (bp || TRAP(regs) == 0xd00)
477 ppc_inst_dump(regs->nip, 1, 0);
478 printf("enter ? for help\n");
479 }
480
481 cmd = cmds(regs);
482
483 insert_bpts();
484 in_xmon = 0;
485#endif
486
487 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
488 bp = at_breakpoint(regs->nip);
489 if (bp != NULL) {
490 int stepped = emulate_step(regs, bp->instr[0]);
491 if (stepped == 0) {
492 regs->nip = (unsigned long) &bp->instr[0];
493 atomic_inc(&bp->ref_count);
494 } else if (stepped < 0) {
495 printf("Couldn't single-step %s instruction\n",
496 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
497 }
498 }
499 }
500
501 insert_cpu_bpts();
502
f78541dc 503 mtmsr(msr); /* restore interrupt enable */
1da177e4
LT
504
505 return cmd != 'X';
506}
507
508int xmon(struct pt_regs *excp)
509{
510 struct pt_regs regs;
511
512 if (excp == NULL) {
f78541dc 513 xmon_save_regs(&regs);
1da177e4
LT
514 excp = &regs;
515 }
516 return xmon_core(excp, 0);
517}
f78541dc
PM
518EXPORT_SYMBOL(xmon);
519
520irqreturn_t
521xmon_irq(int irq, void *d, struct pt_regs *regs)
522{
523 unsigned long flags;
524 local_irq_save(flags);
525 printf("Keyboard interrupt\n");
526 xmon(regs);
527 local_irq_restore(flags);
528 return IRQ_HANDLED;
529}
1da177e4
LT
530
531int xmon_bpt(struct pt_regs *regs)
532{
533 struct bpt *bp;
534 unsigned long offset;
535
536 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
537 return 0;
538
539 /* Are we at the trap at bp->instr[1] for some bp? */
540 bp = in_breakpoint_table(regs->nip, &offset);
541 if (bp != NULL && offset == 4) {
542 regs->nip = bp->address + 4;
543 atomic_dec(&bp->ref_count);
544 return 1;
545 }
546
547 /* Are we at a breakpoint? */
548 bp = at_breakpoint(regs->nip);
549 if (!bp)
550 return 0;
551
552 xmon_core(regs, 0);
553
554 return 1;
555}
556
557int xmon_sstep(struct pt_regs *regs)
558{
559 if (user_mode(regs))
560 return 0;
561 xmon_core(regs, 0);
562 return 1;
563}
564
565int xmon_dabr_match(struct pt_regs *regs)
566{
567 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
568 return 0;
fd9648df
AB
569 if (dabr.enabled == 0)
570 return 0;
1da177e4
LT
571 xmon_core(regs, 0);
572 return 1;
573}
574
575int xmon_iabr_match(struct pt_regs *regs)
576{
577 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
578 return 0;
579 if (iabr == 0)
580 return 0;
581 xmon_core(regs, 0);
582 return 1;
583}
584
585int xmon_ipi(struct pt_regs *regs)
586{
587#ifdef CONFIG_SMP
588 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
589 xmon_core(regs, 1);
590#endif
591 return 0;
592}
593
594int xmon_fault_handler(struct pt_regs *regs)
595{
596 struct bpt *bp;
597 unsigned long offset;
598
599 if (in_xmon && catch_memory_errors)
600 handle_fault(regs); /* doesn't return */
601
602 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
603 bp = in_breakpoint_table(regs->nip, &offset);
604 if (bp != NULL) {
605 regs->nip = bp->address + offset;
606 atomic_dec(&bp->ref_count);
607 }
608 }
609
610 return 0;
611}
612
1da177e4
LT
613static struct bpt *at_breakpoint(unsigned long pc)
614{
615 int i;
616 struct bpt *bp;
617
618 bp = bpts;
619 for (i = 0; i < NBPTS; ++i, ++bp)
620 if (bp->enabled && pc == bp->address)
621 return bp;
622 return NULL;
623}
624
625static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
626{
627 unsigned long off;
628
629 off = nip - (unsigned long) bpts;
630 if (off >= sizeof(bpts))
631 return NULL;
632 off %= sizeof(struct bpt);
633 if (off != offsetof(struct bpt, instr[0])
634 && off != offsetof(struct bpt, instr[1]))
635 return NULL;
636 *offp = off - offsetof(struct bpt, instr[0]);
637 return (struct bpt *) (nip - off);
638}
639
640static struct bpt *new_breakpoint(unsigned long a)
641{
642 struct bpt *bp;
643
644 a &= ~3UL;
645 bp = at_breakpoint(a);
646 if (bp)
647 return bp;
648
649 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
650 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
651 bp->address = a;
652 bp->instr[1] = bpinstr;
653 store_inst(&bp->instr[1]);
654 return bp;
655 }
656 }
657
658 printf("Sorry, no free breakpoints. Please clear one first.\n");
659 return NULL;
660}
661
662static void insert_bpts(void)
663{
664 int i;
665 struct bpt *bp;
666
667 bp = bpts;
668 for (i = 0; i < NBPTS; ++i, ++bp) {
669 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
670 continue;
671 if (mread(bp->address, &bp->instr[0], 4) != 4) {
672 printf("Couldn't read instruction at %lx, "
673 "disabling breakpoint there\n", bp->address);
674 bp->enabled = 0;
675 continue;
676 }
677 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
678 printf("Breakpoint at %lx is on an mtmsrd or rfid "
679 "instruction, disabling it\n", bp->address);
680 bp->enabled = 0;
681 continue;
682 }
683 store_inst(&bp->instr[0]);
684 if (bp->enabled & BP_IABR)
685 continue;
686 if (mwrite(bp->address, &bpinstr, 4) != 4) {
687 printf("Couldn't write instruction at %lx, "
688 "disabling breakpoint there\n", bp->address);
689 bp->enabled &= ~BP_TRAP;
690 continue;
691 }
692 store_inst((void *)bp->address);
693 }
694}
695
696static void insert_cpu_bpts(void)
697{
698 if (dabr.enabled)
fd9648df 699 set_dabr(dabr.address | (dabr.enabled & 7));
1da177e4 700 if (iabr && cpu_has_feature(CPU_FTR_IABR))
f78541dc 701 mtspr(SPRN_IABR, iabr->address
1da177e4
LT
702 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
703}
704
705static void remove_bpts(void)
706{
707 int i;
708 struct bpt *bp;
709 unsigned instr;
710
711 bp = bpts;
712 for (i = 0; i < NBPTS; ++i, ++bp) {
713 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
714 continue;
715 if (mread(bp->address, &instr, 4) == 4
716 && instr == bpinstr
717 && mwrite(bp->address, &bp->instr, 4) != 4)
718 printf("Couldn't remove breakpoint at %lx\n",
719 bp->address);
720 else
721 store_inst((void *)bp->address);
722 }
723}
724
725static void remove_cpu_bpts(void)
726{
fd9648df 727 set_dabr(0);
1da177e4 728 if (cpu_has_feature(CPU_FTR_IABR))
f78541dc 729 mtspr(SPRN_IABR, 0);
1da177e4
LT
730}
731
732/* Command interpreting routine */
733static char *last_cmd;
734
735static int
736cmds(struct pt_regs *excp)
737{
738 int cmd = 0;
739
740 last_cmd = NULL;
741 xmon_regs = excp;
742 for(;;) {
743#ifdef CONFIG_SMP
744 printf("%x:", smp_processor_id());
745#endif /* CONFIG_SMP */
746 printf("mon> ");
1da177e4
LT
747 flush_input();
748 termch = 0;
749 cmd = skipbl();
750 if( cmd == '\n' ) {
751 if (last_cmd == NULL)
752 continue;
753 take_input(last_cmd);
754 last_cmd = NULL;
755 cmd = inchar();
756 }
757 switch (cmd) {
758 case 'm':
759 cmd = inchar();
760 switch (cmd) {
761 case 'm':
762 case 's':
763 case 'd':
764 memops(cmd);
765 break;
766 case 'l':
767 memlocate();
768 break;
769 case 'z':
770 memzcan();
771 break;
772 case 'i':
773 show_mem();
774 break;
775 default:
776 termch = cmd;
777 memex();
778 }
779 break;
780 case 'd':
781 dump();
782 break;
783 case 'l':
784 symbol_lookup();
785 break;
786 case 'r':
787 prregs(excp); /* print regs */
788 break;
789 case 'e':
790 excprint(excp);
791 break;
792 case 'S':
793 super_regs();
794 break;
795 case 't':
796 backtrace(excp);
797 break;
798 case 'f':
799 cacheflush();
800 break;
801 case 's':
802 if (do_step(excp))
803 return cmd;
804 break;
805 case 'x':
806 case 'X':
807 case EOF:
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;
1013 if (addr < KERNELBASE) {
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)) {
1064 if (dabr.address < KERNELBASE) {
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
1938#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1939 || ('a' <= (c) && (c) <= 'f') \
1940 || ('A' <= (c) && (c) <= 'F'))
1941void
1942dump(void)
1943{
1944 int c;
1945
1946 c = inchar();
1947 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1948 termch = c;
1949 scanhex((void *)&adrs);
1950 if (termch != '\n')
1951 termch = 0;
1952 if (c == 'i') {
1953 scanhex(&nidump);
1954 if (nidump == 0)
1955 nidump = 16;
1956 else if (nidump > MAX_DUMP)
1957 nidump = MAX_DUMP;
1958 adrs += ppc_inst_dump(adrs, nidump, 1);
1959 last_cmd = "di\n";
1960 } else {
1961 scanhex(&ndump);
1962 if (ndump == 0)
1963 ndump = 64;
1964 else if (ndump > MAX_DUMP)
1965 ndump = MAX_DUMP;
1966 prdump(adrs, ndump);
1967 adrs += ndump;
1968 last_cmd = "d\n";
1969 }
1970}
1971
1972void
1973prdump(unsigned long adrs, long ndump)
1974{
1975 long n, m, c, r, nr;
1976 unsigned char temp[16];
1977
1978 for (n = ndump; n > 0;) {
f78541dc 1979 printf(REG, adrs);
1da177e4
LT
1980 putchar(' ');
1981 r = n < 16? n: 16;
1982 nr = mread(adrs, temp, r);
1983 adrs += nr;
1984 for (m = 0; m < r; ++m) {
e1449ed9
PM
1985 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
1986 putchar(' ');
1da177e4
LT
1987 if (m < nr)
1988 printf("%.2x", temp[m]);
1989 else
1990 printf("%s", fault_chars[fault_type]);
1991 }
e1449ed9
PM
1992 for (; m < 16; ++m) {
1993 if ((m & (sizeof(long) - 1)) == 0)
1994 putchar(' ');
1da177e4 1995 printf(" ");
e1449ed9 1996 }
1da177e4
LT
1997 printf(" |");
1998 for (m = 0; m < r; ++m) {
1999 if (m < nr) {
2000 c = temp[m];
2001 putchar(' ' <= c && c <= '~'? c: '.');
2002 } else
2003 putchar(' ');
2004 }
2005 n -= r;
2006 for (; m < 16; ++m)
2007 putchar(' ');
2008 printf("|\n");
2009 if (nr < r)
2010 break;
2011 }
2012}
2013
2014int
2015ppc_inst_dump(unsigned long adr, long count, int praddr)
2016{
2017 int nr, dotted;
2018 unsigned long first_adr;
2019 unsigned long inst, last_inst = 0;
2020 unsigned char val[4];
2021
2022 dotted = 0;
2023 for (first_adr = adr; count > 0; --count, adr += 4) {
2024 nr = mread(adr, val, 4);
2025 if (nr == 0) {
2026 if (praddr) {
2027 const char *x = fault_chars[fault_type];
f78541dc 2028 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
1da177e4
LT
2029 }
2030 break;
2031 }
2032 inst = GETWORD(val);
2033 if (adr > first_adr && inst == last_inst) {
2034 if (!dotted) {
2035 printf(" ...\n");
2036 dotted = 1;
2037 }
2038 continue;
2039 }
2040 dotted = 0;
2041 last_inst = inst;
2042 if (praddr)
f78541dc 2043 printf(REG" %.8x", adr, inst);
1da177e4
LT
2044 printf("\t");
2045 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2046 printf("\n");
2047 }
2048 return adr - first_adr;
2049}
2050
2051void
2052print_address(unsigned long addr)
2053{
2054 xmon_print_symbol(addr, "\t# ", "");
2055}
2056
2057
2058/*
2059 * Memory operations - move, set, print differences
2060 */
2061static unsigned long mdest; /* destination address */
2062static unsigned long msrc; /* source address */
2063static unsigned long mval; /* byte value to set memory to */
2064static unsigned long mcount; /* # bytes to affect */
2065static unsigned long mdiffs; /* max # differences to print */
2066
2067void
2068memops(int cmd)
2069{
2070 scanhex((void *)&mdest);
2071 if( termch != '\n' )
2072 termch = 0;
2073 scanhex((void *)(cmd == 's'? &mval: &msrc));
2074 if( termch != '\n' )
2075 termch = 0;
2076 scanhex((void *)&mcount);
2077 switch( cmd ){
2078 case 'm':
2079 memmove((void *)mdest, (void *)msrc, mcount);
2080 break;
2081 case 's':
2082 memset((void *)mdest, mval, mcount);
2083 break;
2084 case 'd':
2085 if( termch != '\n' )
2086 termch = 0;
2087 scanhex((void *)&mdiffs);
2088 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2089 break;
2090 }
2091}
2092
2093void
2094memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2095{
2096 unsigned n, prt;
2097
2098 prt = 0;
2099 for( n = nb; n > 0; --n )
2100 if( *p1++ != *p2++ )
2101 if( ++prt <= maxpr )
2102 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2103 p1[-1], p2 - 1, p2[-1]);
2104 if( prt > maxpr )
2105 printf("Total of %d differences\n", prt);
2106}
2107
2108static unsigned mend;
2109static unsigned mask;
2110
2111void
2112memlocate(void)
2113{
2114 unsigned a, n;
2115 unsigned char val[4];
2116
2117 last_cmd = "ml";
2118 scanhex((void *)&mdest);
2119 if (termch != '\n') {
2120 termch = 0;
2121 scanhex((void *)&mend);
2122 if (termch != '\n') {
2123 termch = 0;
2124 scanhex((void *)&mval);
2125 mask = ~0;
2126 if (termch != '\n') termch = 0;
2127 scanhex((void *)&mask);
2128 }
2129 }
2130 n = 0;
2131 for (a = mdest; a < mend; a += 4) {
2132 if (mread(a, val, 4) == 4
2133 && ((GETWORD(val) ^ mval) & mask) == 0) {
2134 printf("%.16x: %.16x\n", a, GETWORD(val));
2135 if (++n >= 10)
2136 break;
2137 }
2138 }
2139}
2140
2141static unsigned long mskip = 0x1000;
2142static unsigned long mlim = 0xffffffff;
2143
2144void
2145memzcan(void)
2146{
2147 unsigned char v;
2148 unsigned a;
2149 int ok, ook;
2150
2151 scanhex(&mdest);
2152 if (termch != '\n') termch = 0;
2153 scanhex(&mskip);
2154 if (termch != '\n') termch = 0;
2155 scanhex(&mlim);
2156 ook = 0;
2157 for (a = mdest; a < mlim; a += mskip) {
2158 ok = mread(a, &v, 1);
2159 if (ok && !ook) {
2160 printf("%.8x .. ", a);
1da177e4
LT
2161 } else if (!ok && ook)
2162 printf("%.8x\n", a - mskip);
2163 ook = ok;
2164 if (a + mskip < a)
2165 break;
2166 }
2167 if (ook)
2168 printf("%.8x\n", a - mskip);
2169}
2170
f78541dc
PM
2171void proccall(void)
2172{
2173 unsigned long args[8];
2174 unsigned long ret;
2175 int i;
2176 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2177 unsigned long, unsigned long, unsigned long,
2178 unsigned long, unsigned long, unsigned long);
2179 callfunc_t func;
2180
2181 if (!scanhex(&adrs))
2182 return;
2183 if (termch != '\n')
2184 termch = 0;
2185 for (i = 0; i < 8; ++i)
2186 args[i] = 0;
2187 for (i = 0; i < 8; ++i) {
2188 if (!scanhex(&args[i]) || termch == '\n')
2189 break;
2190 termch = 0;
2191 }
2192 func = (callfunc_t) adrs;
2193 ret = 0;
2194 if (setjmp(bus_error_jmp) == 0) {
2195 catch_memory_errors = 1;
2196 sync();
2197 ret = func(args[0], args[1], args[2], args[3],
2198 args[4], args[5], args[6], args[7]);
2199 sync();
2200 printf("return value is %x\n", ret);
2201 } else {
2202 printf("*** %x exception occurred\n", fault_except);
2203 }
2204 catch_memory_errors = 0;
2205}
2206
1da177e4
LT
2207/* Input scanning routines */
2208int
2209skipbl(void)
2210{
2211 int c;
2212
2213 if( termch != 0 ){
2214 c = termch;
2215 termch = 0;
2216 } else
2217 c = inchar();
2218 while( c == ' ' || c == '\t' )
2219 c = inchar();
2220 return c;
2221}
2222
2223#define N_PTREGS 44
2224static char *regnames[N_PTREGS] = {
2225 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2226 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2227 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2228 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
f78541dc
PM
2229 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2230#ifdef CONFIG_PPC64
2231 "softe",
2232#else
2233 "mq",
2234#endif
1da177e4
LT
2235 "trap", "dar", "dsisr", "res"
2236};
2237
2238int
2239scanhex(unsigned long *vp)
2240{
2241 int c, d;
2242 unsigned long v;
2243
2244 c = skipbl();
2245 if (c == '%') {
2246 /* parse register name */
2247 char regname[8];
2248 int i;
2249
2250 for (i = 0; i < sizeof(regname) - 1; ++i) {
2251 c = inchar();
2252 if (!isalnum(c)) {
2253 termch = c;
2254 break;
2255 }
2256 regname[i] = c;
2257 }
2258 regname[i] = 0;
2259 for (i = 0; i < N_PTREGS; ++i) {
2260 if (strcmp(regnames[i], regname) == 0) {
2261 if (xmon_regs == NULL) {
2262 printf("regs not available\n");
2263 return 0;
2264 }
2265 *vp = ((unsigned long *)xmon_regs)[i];
2266 return 1;
2267 }
2268 }
2269 printf("invalid register name '%%%s'\n", regname);
2270 return 0;
2271 }
2272
2273 /* skip leading "0x" if any */
2274
2275 if (c == '0') {
2276 c = inchar();
2277 if (c == 'x') {
2278 c = inchar();
2279 } else {
2280 d = hexdigit(c);
2281 if (d == EOF) {
2282 termch = c;
2283 *vp = 0;
2284 return 1;
2285 }
2286 }
2287 } else if (c == '$') {
2288 int i;
2289 for (i=0; i<63; i++) {
2290 c = inchar();
2291 if (isspace(c)) {
2292 termch = c;
2293 break;
2294 }
2295 tmpstr[i] = c;
2296 }
2297 tmpstr[i++] = 0;
6879dc13
BH
2298 *vp = 0;
2299 if (setjmp(bus_error_jmp) == 0) {
2300 catch_memory_errors = 1;
2301 sync();
2302 *vp = kallsyms_lookup_name(tmpstr);
2303 sync();
2304 }
2305 catch_memory_errors = 0;
1da177e4
LT
2306 if (!(*vp)) {
2307 printf("unknown symbol '%s'\n", tmpstr);
2308 return 0;
2309 }
2310 return 1;
2311 }
2312
2313 d = hexdigit(c);
2314 if (d == EOF) {
2315 termch = c;
2316 return 0;
2317 }
2318 v = 0;
2319 do {
2320 v = (v << 4) + d;
2321 c = inchar();
2322 d = hexdigit(c);
2323 } while (d != EOF);
2324 termch = c;
2325 *vp = v;
2326 return 1;
2327}
2328
2329void
2330scannl(void)
2331{
2332 int c;
2333
2334 c = termch;
2335 termch = 0;
2336 while( c != '\n' )
2337 c = inchar();
2338}
2339
f78541dc 2340int hexdigit(int c)
1da177e4
LT
2341{
2342 if( '0' <= c && c <= '9' )
2343 return c - '0';
2344 if( 'A' <= c && c <= 'F' )
2345 return c - ('A' - 10);
2346 if( 'a' <= c && c <= 'f' )
2347 return c - ('a' - 10);
2348 return EOF;
2349}
2350
2351void
2352getstring(char *s, int size)
2353{
2354 int c;
2355
2356 c = skipbl();
2357 do {
2358 if( size > 1 ){
2359 *s++ = c;
2360 --size;
2361 }
2362 c = inchar();
2363 } while( c != ' ' && c != '\t' && c != '\n' );
2364 termch = c;
2365 *s = 0;
2366}
2367
2368static char line[256];
2369static char *lineptr;
2370
2371void
2372flush_input(void)
2373{
2374 lineptr = NULL;
2375}
2376
2377int
2378inchar(void)
2379{
2380 if (lineptr == NULL || *lineptr == 0) {
fca5dcd4 2381 if (xmon_gets(line, sizeof(line)) == NULL) {
1da177e4
LT
2382 lineptr = NULL;
2383 return EOF;
2384 }
2385 lineptr = line;
2386 }
2387 return *lineptr++;
2388}
2389
2390void
2391take_input(char *str)
2392{
2393 lineptr = str;
2394}
2395
2396
2397static void
2398symbol_lookup(void)
2399{
2400 int type = inchar();
2401 unsigned long addr;
2402 static char tmp[64];
2403
2404 switch (type) {
2405 case 'a':
2406 if (scanhex(&addr))
2407 xmon_print_symbol(addr, ": ", "\n");
2408 termch = 0;
2409 break;
2410 case 's':
2411 getstring(tmp, 64);
2412 if (setjmp(bus_error_jmp) == 0) {
2413 catch_memory_errors = 1;
2414 sync();
2415 addr = kallsyms_lookup_name(tmp);
2416 if (addr)
2417 printf("%s: %lx\n", tmp, addr);
2418 else
2419 printf("Symbol '%s' not found.\n", tmp);
2420 sync();
2421 }
2422 catch_memory_errors = 0;
2423 termch = 0;
2424 break;
2425 }
2426}
2427
2428
2429/* Print an address in numeric and symbolic form (if possible) */
2430static void xmon_print_symbol(unsigned long address, const char *mid,
2431 const char *after)
2432{
2433 char *modname;
2434 const char *name = NULL;
2435 unsigned long offset, size;
2436
f78541dc 2437 printf(REG, address);
1da177e4
LT
2438 if (setjmp(bus_error_jmp) == 0) {
2439 catch_memory_errors = 1;
2440 sync();
2441 name = kallsyms_lookup(address, &size, &offset, &modname,
2442 tmpstr);
2443 sync();
2444 /* wait a little while to see if we get a machine check */
2445 __delay(200);
2446 }
2447
2448 catch_memory_errors = 0;
2449
2450 if (name) {
2451 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2452 if (modname)
2453 printf(" [%s]", modname);
2454 }
2455 printf("%s", after);
2456}
2457
f78541dc 2458#ifdef CONFIG_PPC64
1da177e4
LT
2459static void dump_slb(void)
2460{
2461 int i;
2462 unsigned long tmp;
2463
2464 printf("SLB contents of cpu %x\n", smp_processor_id());
2465
2466 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2467 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2468 printf("%02d %016lx ", i, tmp);
2469
2470 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2471 printf("%016lx\n", tmp);
2472 }
2473}
2474
2475static void dump_stab(void)
2476{
2477 int i;
2478 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2479
2480 printf("Segment table contents of cpu %x\n", smp_processor_id());
2481
2482 for (i = 0; i < PAGE_SIZE/16; i++) {
2483 unsigned long a, b;
2484
2485 a = *tmp++;
2486 b = *tmp++;
2487
2488 if (a || b) {
2489 printf("%03d %016lx ", i, a);
2490 printf("%016lx\n", b);
2491 }
2492 }
2493}
2494
f78541dc
PM
2495void dump_segments(void)
2496{
2497 if (cpu_has_feature(CPU_FTR_SLB))
2498 dump_slb();
2499 else
2500 dump_stab();
2501}
2502#endif
2503
2504#ifdef CONFIG_PPC_STD_MMU_32
2505void dump_segments(void)
2506{
2507 int i;
2508
2509 printf("sr0-15 =");
2510 for (i = 0; i < 16; ++i)
2511 printf(" %x", mfsrin(i));
2512 printf("\n");
2513}
2514#endif
2515
b13cfd17
OH
2516void xmon_init(int enable)
2517{
2518 if (enable) {
2519 __debugger = xmon;
2520 __debugger_ipi = xmon_ipi;
2521 __debugger_bpt = xmon_bpt;
2522 __debugger_sstep = xmon_sstep;
2523 __debugger_iabr_match = xmon_iabr_match;
2524 __debugger_dabr_match = xmon_dabr_match;
2525 __debugger_fault_handler = xmon_fault_handler;
2526 } else {
2527 __debugger = NULL;
2528 __debugger_ipi = NULL;
2529 __debugger_bpt = NULL;
2530 __debugger_sstep = NULL;
2531 __debugger_iabr_match = NULL;
2532 __debugger_dabr_match = NULL;
2533 __debugger_fault_handler = NULL;
2534 }
fca5dcd4 2535 xmon_map_scc();
1da177e4 2536}
fca5dcd4
PM
2537
2538#ifdef CONFIG_MAGIC_SYSRQ
2539static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2540 struct tty_struct *tty)
2541{
2542 /* ensure xmon is enabled */
2543 xmon_init(1);
2544 debugger(pt_regs);
2545}
2546
2547static struct sysrq_key_op sysrq_xmon_op =
2548{
2549 .handler = sysrq_handle_xmon,
2550 .help_msg = "Xmon",
2551 .action_msg = "Entering xmon",
2552};
2553
2554static int __init setup_xmon_sysrq(void)
2555{
2556 register_sysrq_key('x', &sysrq_xmon_op);
2557 return 0;
2558}
2559__initcall(setup_xmon_sysrq);
2560#endif /* CONFIG_MAGIC_SYSRQ */