]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/powerpc/xmon/xmon.c
powerpc: Initialize secondary CPU setup for 32-bit SMP
[net-next-2.6.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);
1470 unsigned long opd[3];
1471 unsigned long ret = -1UL;
1472
1473 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1474 instrs[1] = 0x4e800020;
1475 opd[0] = (unsigned long)instrs;
1476 opd[1] = 0;
1477 opd[2] = 0;
1478 store_inst(instrs);
1479 store_inst(instrs+1);
1480 code = (unsigned long (*)(void)) opd;
1481
1482 if (setjmp(bus_error_jmp) == 0) {
1483 catch_memory_errors = 1;
1484 sync();
1485
1486 ret = code();
1487
1488 sync();
1489 /* wait a little while to see if we get a machine check */
1490 __delay(200);
1491 n = size;
1492 }
1493
1494 return ret;
1495}
1496
1497void
1498write_spr(int n, unsigned long val)
1499{
1500 unsigned int instrs[2];
1501 unsigned long (*code)(unsigned long);
1502 unsigned long opd[3];
1503
1504 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1505 instrs[1] = 0x4e800020;
1506 opd[0] = (unsigned long)instrs;
1507 opd[1] = 0;
1508 opd[2] = 0;
1509 store_inst(instrs);
1510 store_inst(instrs+1);
1511 code = (unsigned long (*)(unsigned long)) opd;
1512
1513 if (setjmp(bus_error_jmp) == 0) {
1514 catch_memory_errors = 1;
1515 sync();
1516
1517 code(val);
1518
1519 sync();
1520 /* wait a little while to see if we get a machine check */
1521 __delay(200);
1522 n = size;
1523 }
1524}
1525
1526static unsigned long regno;
1527extern char exc_prolog;
1528extern char dec_exc;
1529
f78541dc 1530void super_regs(void)
1da177e4
LT
1531{
1532 int cmd;
1533 unsigned long val;
1534#ifdef CONFIG_PPC_ISERIES
1535 struct paca_struct *ptrPaca = NULL;
1536 struct lppaca *ptrLpPaca = NULL;
1537 struct ItLpRegSave *ptrLpRegSave = NULL;
1538#endif
1539
1540 cmd = skipbl();
1541 if (cmd == '\n') {
1542 unsigned long sp, toc;
1543 asm("mr %0,1" : "=r" (sp) :);
1544 asm("mr %0,2" : "=r" (toc) :);
1545
f78541dc
PM
1546 printf("msr = "REG" sprg0= "REG"\n",
1547 mfmsr(), mfspr(SPRN_SPRG0));
1548 printf("pvr = "REG" sprg1= "REG"\n",
1549 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1550 printf("dec = "REG" sprg2= "REG"\n",
1551 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1552 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1553 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1da177e4
LT
1554#ifdef CONFIG_PPC_ISERIES
1555 // Dump out relevant Paca data areas.
1556 printf("Paca: \n");
1557 ptrPaca = get_paca();
1558
1559 printf(" Local Processor Control Area (LpPaca): \n");
1560 ptrLpPaca = ptrPaca->lppaca_ptr;
1561 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1562 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1563 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1564 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1565 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1566
1567 printf(" Local Processor Register Save Area (LpRegSave): \n");
1568 ptrLpRegSave = ptrPaca->reg_save_ptr;
1569 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1570 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1571 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1572 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1573 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1574 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1575#endif
1576
1577 return;
1578 }
1579
1580 scanhex(&regno);
1581 switch (cmd) {
1582 case 'w':
1583 val = read_spr(regno);
1584 scanhex(&val);
1585 write_spr(regno, val);
1586 /* fall through */
1587 case 'r':
1588 printf("spr %lx = %lx\n", regno, read_spr(regno));
1589 break;
1da177e4
LT
1590 }
1591 scannl();
1592}
1593
1594/*
1595 * Stuff for reading and writing memory safely
1596 */
1597int
1598mread(unsigned long adrs, void *buf, int size)
1599{
1600 volatile int n;
1601 char *p, *q;
1602
1603 n = 0;
1604 if (setjmp(bus_error_jmp) == 0) {
1605 catch_memory_errors = 1;
1606 sync();
1607 p = (char *)adrs;
1608 q = (char *)buf;
1609 switch (size) {
1610 case 2:
f78541dc 1611 *(u16 *)q = *(u16 *)p;
1da177e4
LT
1612 break;
1613 case 4:
f78541dc 1614 *(u32 *)q = *(u32 *)p;
1da177e4
LT
1615 break;
1616 case 8:
f78541dc 1617 *(u64 *)q = *(u64 *)p;
1da177e4
LT
1618 break;
1619 default:
1620 for( ; n < size; ++n) {
1621 *q++ = *p++;
1622 sync();
1623 }
1624 }
1625 sync();
1626 /* wait a little while to see if we get a machine check */
1627 __delay(200);
1628 n = size;
1629 }
1630 catch_memory_errors = 0;
1631 return n;
1632}
1633
1634int
1635mwrite(unsigned long adrs, void *buf, int size)
1636{
1637 volatile int n;
1638 char *p, *q;
1639
1640 n = 0;
1641 if (setjmp(bus_error_jmp) == 0) {
1642 catch_memory_errors = 1;
1643 sync();
1644 p = (char *) adrs;
1645 q = (char *) buf;
1646 switch (size) {
1647 case 2:
f78541dc 1648 *(u16 *)p = *(u16 *)q;
1da177e4
LT
1649 break;
1650 case 4:
f78541dc 1651 *(u32 *)p = *(u32 *)q;
1da177e4
LT
1652 break;
1653 case 8:
f78541dc 1654 *(u64 *)p = *(u64 *)q;
1da177e4
LT
1655 break;
1656 default:
1657 for ( ; n < size; ++n) {
1658 *p++ = *q++;
1659 sync();
1660 }
1661 }
1662 sync();
1663 /* wait a little while to see if we get a machine check */
1664 __delay(200);
1665 n = size;
1666 } else {
1667 printf("*** Error writing address %x\n", adrs + n);
1668 }
1669 catch_memory_errors = 0;
1670 return n;
1671}
1672
1673static int fault_type;
f78541dc 1674static int fault_except;
1da177e4
LT
1675static char *fault_chars[] = { "--", "**", "##" };
1676
f78541dc 1677static int handle_fault(struct pt_regs *regs)
1da177e4 1678{
f78541dc 1679 fault_except = TRAP(regs);
1da177e4
LT
1680 switch (TRAP(regs)) {
1681 case 0x200:
1682 fault_type = 0;
1683 break;
1684 case 0x300:
1685 case 0x380:
1686 fault_type = 1;
1687 break;
1688 default:
1689 fault_type = 2;
1690 }
1691
1692 longjmp(bus_error_jmp, 1);
1693
1694 return 0;
1695}
1696
1697#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1698
1699void
1700byterev(unsigned char *val, int size)
1701{
1702 int t;
1703
1704 switch (size) {
1705 case 2:
1706 SWAP(val[0], val[1], t);
1707 break;
1708 case 4:
1709 SWAP(val[0], val[3], t);
1710 SWAP(val[1], val[2], t);
1711 break;
1712 case 8: /* is there really any use for this? */
1713 SWAP(val[0], val[7], t);
1714 SWAP(val[1], val[6], t);
1715 SWAP(val[2], val[5], t);
1716 SWAP(val[3], val[4], t);
1717 break;
1718 }
1719}
1720
1721static int brev;
1722static int mnoread;
1723
1724static char *memex_help_string =
1725 "Memory examine command usage:\n"
1726 "m [addr] [flags] examine/change memory\n"
1727 " addr is optional. will start where left off.\n"
1728 " flags may include chars from this set:\n"
1729 " b modify by bytes (default)\n"
1730 " w modify by words (2 byte)\n"
1731 " l modify by longs (4 byte)\n"
1732 " d modify by doubleword (8 byte)\n"
1733 " r toggle reverse byte order mode\n"
1734 " n do not read memory (for i/o spaces)\n"
1735 " . ok to read (default)\n"
1736 "NOTE: flags are saved as defaults\n"
1737 "";
1738
1739static char *memex_subcmd_help_string =
1740 "Memory examine subcommands:\n"
1741 " hexval write this val to current location\n"
1742 " 'string' write chars from string to this location\n"
1743 " ' increment address\n"
1744 " ^ decrement address\n"
1745 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1746 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1747 " ` clear no-read flag\n"
1748 " ; stay at this addr\n"
1749 " v change to byte mode\n"
1750 " w change to word (2 byte) mode\n"
1751 " l change to long (4 byte) mode\n"
1752 " u change to doubleword (8 byte) mode\n"
1753 " m addr change current addr\n"
1754 " n toggle no-read flag\n"
1755 " r toggle byte reverse flag\n"
1756 " < count back up count bytes\n"
1757 " > count skip forward count bytes\n"
1758 " x exit this mode\n"
1759 "";
1760
1761void
1762memex(void)
1763{
1764 int cmd, inc, i, nslash;
1765 unsigned long n;
1766 unsigned char val[16];
1767
1768 scanhex((void *)&adrs);
1769 cmd = skipbl();
1770 if (cmd == '?') {
1771 printf(memex_help_string);
1772 return;
1773 } else {
1774 termch = cmd;
1775 }
1776 last_cmd = "m\n";
1777 while ((cmd = skipbl()) != '\n') {
1778 switch( cmd ){
1779 case 'b': size = 1; break;
1780 case 'w': size = 2; break;
1781 case 'l': size = 4; break;
1782 case 'd': size = 8; break;
1783 case 'r': brev = !brev; break;
1784 case 'n': mnoread = 1; break;
1785 case '.': mnoread = 0; break;
1786 }
1787 }
1788 if( size <= 0 )
1789 size = 1;
1790 else if( size > 8 )
1791 size = 8;
1792 for(;;){
1793 if (!mnoread)
1794 n = mread(adrs, val, size);
e1449ed9 1795 printf(REG"%c", adrs, brev? 'r': ' ');
1da177e4
LT
1796 if (!mnoread) {
1797 if (brev)
1798 byterev(val, size);
1799 putchar(' ');
1800 for (i = 0; i < n; ++i)
1801 printf("%.2x", val[i]);
1802 for (; i < size; ++i)
1803 printf("%s", fault_chars[fault_type]);
1804 }
1805 putchar(' ');
1806 inc = size;
1807 nslash = 0;
1808 for(;;){
1809 if( scanhex(&n) ){
1810 for (i = 0; i < size; ++i)
1811 val[i] = n >> (i * 8);
1812 if (!brev)
1813 byterev(val, size);
1814 mwrite(adrs, val, size);
1815 inc = size;
1816 }
1817 cmd = skipbl();
1818 if (cmd == '\n')
1819 break;
1820 inc = 0;
1821 switch (cmd) {
1822 case '\'':
1823 for(;;){
1824 n = inchar();
1825 if( n == '\\' )
1826 n = bsesc();
1827 else if( n == '\'' )
1828 break;
1829 for (i = 0; i < size; ++i)
1830 val[i] = n >> (i * 8);
1831 if (!brev)
1832 byterev(val, size);
1833 mwrite(adrs, val, size);
1834 adrs += size;
1835 }
1836 adrs -= size;
1837 inc = size;
1838 break;
1839 case ',':
1840 adrs += size;
1841 break;
1842 case '.':
1843 mnoread = 0;
1844 break;
1845 case ';':
1846 break;
1847 case 'x':
1848 case EOF:
1849 scannl();
1850 return;
1851 case 'b':
1852 case 'v':
1853 size = 1;
1854 break;
1855 case 'w':
1856 size = 2;
1857 break;
1858 case 'l':
1859 size = 4;
1860 break;
1861 case 'u':
1862 size = 8;
1863 break;
1864 case '^':
1865 adrs -= size;
1866 break;
1867 break;
1868 case '/':
1869 if (nslash > 0)
1870 adrs -= 1 << nslash;
1871 else
1872 nslash = 0;
1873 nslash += 4;
1874 adrs += 1 << nslash;
1875 break;
1876 case '\\':
1877 if (nslash < 0)
1878 adrs += 1 << -nslash;
1879 else
1880 nslash = 0;
1881 nslash -= 4;
1882 adrs -= 1 << -nslash;
1883 break;
1884 case 'm':
1885 scanhex((void *)&adrs);
1886 break;
1887 case 'n':
1888 mnoread = 1;
1889 break;
1890 case 'r':
1891 brev = !brev;
1892 break;
1893 case '<':
1894 n = size;
1895 scanhex(&n);
1896 adrs -= n;
1897 break;
1898 case '>':
1899 n = size;
1900 scanhex(&n);
1901 adrs += n;
1902 break;
1903 case '?':
1904 printf(memex_subcmd_help_string);
1905 break;
1906 }
1907 }
1908 adrs += inc;
1909 }
1910}
1911
1912int
1913bsesc(void)
1914{
1915 int c;
1916
1917 c = inchar();
1918 switch( c ){
1919 case 'n': c = '\n'; break;
1920 case 'r': c = '\r'; break;
1921 case 'b': c = '\b'; break;
1922 case 't': c = '\t'; break;
1923 }
1924 return c;
1925}
1926
1927#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1928 || ('a' <= (c) && (c) <= 'f') \
1929 || ('A' <= (c) && (c) <= 'F'))
1930void
1931dump(void)
1932{
1933 int c;
1934
1935 c = inchar();
1936 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1937 termch = c;
1938 scanhex((void *)&adrs);
1939 if (termch != '\n')
1940 termch = 0;
1941 if (c == 'i') {
1942 scanhex(&nidump);
1943 if (nidump == 0)
1944 nidump = 16;
1945 else if (nidump > MAX_DUMP)
1946 nidump = MAX_DUMP;
1947 adrs += ppc_inst_dump(adrs, nidump, 1);
1948 last_cmd = "di\n";
1949 } else {
1950 scanhex(&ndump);
1951 if (ndump == 0)
1952 ndump = 64;
1953 else if (ndump > MAX_DUMP)
1954 ndump = MAX_DUMP;
1955 prdump(adrs, ndump);
1956 adrs += ndump;
1957 last_cmd = "d\n";
1958 }
1959}
1960
1961void
1962prdump(unsigned long adrs, long ndump)
1963{
1964 long n, m, c, r, nr;
1965 unsigned char temp[16];
1966
1967 for (n = ndump; n > 0;) {
f78541dc 1968 printf(REG, adrs);
1da177e4
LT
1969 putchar(' ');
1970 r = n < 16? n: 16;
1971 nr = mread(adrs, temp, r);
1972 adrs += nr;
1973 for (m = 0; m < r; ++m) {
e1449ed9
PM
1974 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
1975 putchar(' ');
1da177e4
LT
1976 if (m < nr)
1977 printf("%.2x", temp[m]);
1978 else
1979 printf("%s", fault_chars[fault_type]);
1980 }
e1449ed9
PM
1981 for (; m < 16; ++m) {
1982 if ((m & (sizeof(long) - 1)) == 0)
1983 putchar(' ');
1da177e4 1984 printf(" ");
e1449ed9 1985 }
1da177e4
LT
1986 printf(" |");
1987 for (m = 0; m < r; ++m) {
1988 if (m < nr) {
1989 c = temp[m];
1990 putchar(' ' <= c && c <= '~'? c: '.');
1991 } else
1992 putchar(' ');
1993 }
1994 n -= r;
1995 for (; m < 16; ++m)
1996 putchar(' ');
1997 printf("|\n");
1998 if (nr < r)
1999 break;
2000 }
2001}
2002
2003int
2004ppc_inst_dump(unsigned long adr, long count, int praddr)
2005{
2006 int nr, dotted;
2007 unsigned long first_adr;
2008 unsigned long inst, last_inst = 0;
2009 unsigned char val[4];
2010
2011 dotted = 0;
2012 for (first_adr = adr; count > 0; --count, adr += 4) {
2013 nr = mread(adr, val, 4);
2014 if (nr == 0) {
2015 if (praddr) {
2016 const char *x = fault_chars[fault_type];
f78541dc 2017 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
1da177e4
LT
2018 }
2019 break;
2020 }
2021 inst = GETWORD(val);
2022 if (adr > first_adr && inst == last_inst) {
2023 if (!dotted) {
2024 printf(" ...\n");
2025 dotted = 1;
2026 }
2027 continue;
2028 }
2029 dotted = 0;
2030 last_inst = inst;
2031 if (praddr)
f78541dc 2032 printf(REG" %.8x", adr, inst);
1da177e4
LT
2033 printf("\t");
2034 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2035 printf("\n");
2036 }
2037 return adr - first_adr;
2038}
2039
2040void
2041print_address(unsigned long addr)
2042{
2043 xmon_print_symbol(addr, "\t# ", "");
2044}
2045
2046
2047/*
2048 * Memory operations - move, set, print differences
2049 */
2050static unsigned long mdest; /* destination address */
2051static unsigned long msrc; /* source address */
2052static unsigned long mval; /* byte value to set memory to */
2053static unsigned long mcount; /* # bytes to affect */
2054static unsigned long mdiffs; /* max # differences to print */
2055
2056void
2057memops(int cmd)
2058{
2059 scanhex((void *)&mdest);
2060 if( termch != '\n' )
2061 termch = 0;
2062 scanhex((void *)(cmd == 's'? &mval: &msrc));
2063 if( termch != '\n' )
2064 termch = 0;
2065 scanhex((void *)&mcount);
2066 switch( cmd ){
2067 case 'm':
2068 memmove((void *)mdest, (void *)msrc, mcount);
2069 break;
2070 case 's':
2071 memset((void *)mdest, mval, mcount);
2072 break;
2073 case 'd':
2074 if( termch != '\n' )
2075 termch = 0;
2076 scanhex((void *)&mdiffs);
2077 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2078 break;
2079 }
2080}
2081
2082void
2083memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2084{
2085 unsigned n, prt;
2086
2087 prt = 0;
2088 for( n = nb; n > 0; --n )
2089 if( *p1++ != *p2++ )
2090 if( ++prt <= maxpr )
2091 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2092 p1[-1], p2 - 1, p2[-1]);
2093 if( prt > maxpr )
2094 printf("Total of %d differences\n", prt);
2095}
2096
2097static unsigned mend;
2098static unsigned mask;
2099
2100void
2101memlocate(void)
2102{
2103 unsigned a, n;
2104 unsigned char val[4];
2105
2106 last_cmd = "ml";
2107 scanhex((void *)&mdest);
2108 if (termch != '\n') {
2109 termch = 0;
2110 scanhex((void *)&mend);
2111 if (termch != '\n') {
2112 termch = 0;
2113 scanhex((void *)&mval);
2114 mask = ~0;
2115 if (termch != '\n') termch = 0;
2116 scanhex((void *)&mask);
2117 }
2118 }
2119 n = 0;
2120 for (a = mdest; a < mend; a += 4) {
2121 if (mread(a, val, 4) == 4
2122 && ((GETWORD(val) ^ mval) & mask) == 0) {
2123 printf("%.16x: %.16x\n", a, GETWORD(val));
2124 if (++n >= 10)
2125 break;
2126 }
2127 }
2128}
2129
2130static unsigned long mskip = 0x1000;
2131static unsigned long mlim = 0xffffffff;
2132
2133void
2134memzcan(void)
2135{
2136 unsigned char v;
2137 unsigned a;
2138 int ok, ook;
2139
2140 scanhex(&mdest);
2141 if (termch != '\n') termch = 0;
2142 scanhex(&mskip);
2143 if (termch != '\n') termch = 0;
2144 scanhex(&mlim);
2145 ook = 0;
2146 for (a = mdest; a < mlim; a += mskip) {
2147 ok = mread(a, &v, 1);
2148 if (ok && !ook) {
2149 printf("%.8x .. ", a);
1da177e4
LT
2150 } else if (!ok && ook)
2151 printf("%.8x\n", a - mskip);
2152 ook = ok;
2153 if (a + mskip < a)
2154 break;
2155 }
2156 if (ook)
2157 printf("%.8x\n", a - mskip);
2158}
2159
f78541dc
PM
2160void proccall(void)
2161{
2162 unsigned long args[8];
2163 unsigned long ret;
2164 int i;
2165 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2166 unsigned long, unsigned long, unsigned long,
2167 unsigned long, unsigned long, unsigned long);
2168 callfunc_t func;
2169
2170 if (!scanhex(&adrs))
2171 return;
2172 if (termch != '\n')
2173 termch = 0;
2174 for (i = 0; i < 8; ++i)
2175 args[i] = 0;
2176 for (i = 0; i < 8; ++i) {
2177 if (!scanhex(&args[i]) || termch == '\n')
2178 break;
2179 termch = 0;
2180 }
2181 func = (callfunc_t) adrs;
2182 ret = 0;
2183 if (setjmp(bus_error_jmp) == 0) {
2184 catch_memory_errors = 1;
2185 sync();
2186 ret = func(args[0], args[1], args[2], args[3],
2187 args[4], args[5], args[6], args[7]);
2188 sync();
2189 printf("return value is %x\n", ret);
2190 } else {
2191 printf("*** %x exception occurred\n", fault_except);
2192 }
2193 catch_memory_errors = 0;
2194}
2195
1da177e4
LT
2196/* Input scanning routines */
2197int
2198skipbl(void)
2199{
2200 int c;
2201
2202 if( termch != 0 ){
2203 c = termch;
2204 termch = 0;
2205 } else
2206 c = inchar();
2207 while( c == ' ' || c == '\t' )
2208 c = inchar();
2209 return c;
2210}
2211
2212#define N_PTREGS 44
2213static char *regnames[N_PTREGS] = {
2214 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2215 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2216 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2217 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
f78541dc
PM
2218 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2219#ifdef CONFIG_PPC64
2220 "softe",
2221#else
2222 "mq",
2223#endif
1da177e4
LT
2224 "trap", "dar", "dsisr", "res"
2225};
2226
2227int
2228scanhex(unsigned long *vp)
2229{
2230 int c, d;
2231 unsigned long v;
2232
2233 c = skipbl();
2234 if (c == '%') {
2235 /* parse register name */
2236 char regname[8];
2237 int i;
2238
2239 for (i = 0; i < sizeof(regname) - 1; ++i) {
2240 c = inchar();
2241 if (!isalnum(c)) {
2242 termch = c;
2243 break;
2244 }
2245 regname[i] = c;
2246 }
2247 regname[i] = 0;
2248 for (i = 0; i < N_PTREGS; ++i) {
2249 if (strcmp(regnames[i], regname) == 0) {
2250 if (xmon_regs == NULL) {
2251 printf("regs not available\n");
2252 return 0;
2253 }
2254 *vp = ((unsigned long *)xmon_regs)[i];
2255 return 1;
2256 }
2257 }
2258 printf("invalid register name '%%%s'\n", regname);
2259 return 0;
2260 }
2261
2262 /* skip leading "0x" if any */
2263
2264 if (c == '0') {
2265 c = inchar();
2266 if (c == 'x') {
2267 c = inchar();
2268 } else {
2269 d = hexdigit(c);
2270 if (d == EOF) {
2271 termch = c;
2272 *vp = 0;
2273 return 1;
2274 }
2275 }
2276 } else if (c == '$') {
2277 int i;
2278 for (i=0; i<63; i++) {
2279 c = inchar();
2280 if (isspace(c)) {
2281 termch = c;
2282 break;
2283 }
2284 tmpstr[i] = c;
2285 }
2286 tmpstr[i++] = 0;
6879dc13
BH
2287 *vp = 0;
2288 if (setjmp(bus_error_jmp) == 0) {
2289 catch_memory_errors = 1;
2290 sync();
2291 *vp = kallsyms_lookup_name(tmpstr);
2292 sync();
2293 }
2294 catch_memory_errors = 0;
1da177e4
LT
2295 if (!(*vp)) {
2296 printf("unknown symbol '%s'\n", tmpstr);
2297 return 0;
2298 }
2299 return 1;
2300 }
2301
2302 d = hexdigit(c);
2303 if (d == EOF) {
2304 termch = c;
2305 return 0;
2306 }
2307 v = 0;
2308 do {
2309 v = (v << 4) + d;
2310 c = inchar();
2311 d = hexdigit(c);
2312 } while (d != EOF);
2313 termch = c;
2314 *vp = v;
2315 return 1;
2316}
2317
2318void
2319scannl(void)
2320{
2321 int c;
2322
2323 c = termch;
2324 termch = 0;
2325 while( c != '\n' )
2326 c = inchar();
2327}
2328
f78541dc 2329int hexdigit(int c)
1da177e4
LT
2330{
2331 if( '0' <= c && c <= '9' )
2332 return c - '0';
2333 if( 'A' <= c && c <= 'F' )
2334 return c - ('A' - 10);
2335 if( 'a' <= c && c <= 'f' )
2336 return c - ('a' - 10);
2337 return EOF;
2338}
2339
2340void
2341getstring(char *s, int size)
2342{
2343 int c;
2344
2345 c = skipbl();
2346 do {
2347 if( size > 1 ){
2348 *s++ = c;
2349 --size;
2350 }
2351 c = inchar();
2352 } while( c != ' ' && c != '\t' && c != '\n' );
2353 termch = c;
2354 *s = 0;
2355}
2356
2357static char line[256];
2358static char *lineptr;
2359
2360void
2361flush_input(void)
2362{
2363 lineptr = NULL;
2364}
2365
2366int
2367inchar(void)
2368{
2369 if (lineptr == NULL || *lineptr == 0) {
fca5dcd4 2370 if (xmon_gets(line, sizeof(line)) == NULL) {
1da177e4
LT
2371 lineptr = NULL;
2372 return EOF;
2373 }
2374 lineptr = line;
2375 }
2376 return *lineptr++;
2377}
2378
2379void
2380take_input(char *str)
2381{
2382 lineptr = str;
2383}
2384
2385
2386static void
2387symbol_lookup(void)
2388{
2389 int type = inchar();
2390 unsigned long addr;
2391 static char tmp[64];
2392
2393 switch (type) {
2394 case 'a':
2395 if (scanhex(&addr))
2396 xmon_print_symbol(addr, ": ", "\n");
2397 termch = 0;
2398 break;
2399 case 's':
2400 getstring(tmp, 64);
2401 if (setjmp(bus_error_jmp) == 0) {
2402 catch_memory_errors = 1;
2403 sync();
2404 addr = kallsyms_lookup_name(tmp);
2405 if (addr)
2406 printf("%s: %lx\n", tmp, addr);
2407 else
2408 printf("Symbol '%s' not found.\n", tmp);
2409 sync();
2410 }
2411 catch_memory_errors = 0;
2412 termch = 0;
2413 break;
2414 }
2415}
2416
2417
2418/* Print an address in numeric and symbolic form (if possible) */
2419static void xmon_print_symbol(unsigned long address, const char *mid,
2420 const char *after)
2421{
2422 char *modname;
2423 const char *name = NULL;
2424 unsigned long offset, size;
2425
f78541dc 2426 printf(REG, address);
1da177e4
LT
2427 if (setjmp(bus_error_jmp) == 0) {
2428 catch_memory_errors = 1;
2429 sync();
2430 name = kallsyms_lookup(address, &size, &offset, &modname,
2431 tmpstr);
2432 sync();
2433 /* wait a little while to see if we get a machine check */
2434 __delay(200);
2435 }
2436
2437 catch_memory_errors = 0;
2438
2439 if (name) {
2440 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2441 if (modname)
2442 printf(" [%s]", modname);
2443 }
2444 printf("%s", after);
2445}
2446
f78541dc 2447#ifdef CONFIG_PPC64
1da177e4
LT
2448static void dump_slb(void)
2449{
2450 int i;
2451 unsigned long tmp;
2452
2453 printf("SLB contents of cpu %x\n", smp_processor_id());
2454
2455 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2456 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2457 printf("%02d %016lx ", i, tmp);
2458
2459 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2460 printf("%016lx\n", tmp);
2461 }
2462}
2463
2464static void dump_stab(void)
2465{
2466 int i;
2467 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2468
2469 printf("Segment table contents of cpu %x\n", smp_processor_id());
2470
2471 for (i = 0; i < PAGE_SIZE/16; i++) {
2472 unsigned long a, b;
2473
2474 a = *tmp++;
2475 b = *tmp++;
2476
2477 if (a || b) {
2478 printf("%03d %016lx ", i, a);
2479 printf("%016lx\n", b);
2480 }
2481 }
2482}
2483
f78541dc
PM
2484void dump_segments(void)
2485{
2486 if (cpu_has_feature(CPU_FTR_SLB))
2487 dump_slb();
2488 else
2489 dump_stab();
2490}
2491#endif
2492
2493#ifdef CONFIG_PPC_STD_MMU_32
2494void dump_segments(void)
2495{
2496 int i;
2497
2498 printf("sr0-15 =");
2499 for (i = 0; i < 16; ++i)
2500 printf(" %x", mfsrin(i));
2501 printf("\n");
2502}
2503#endif
2504
b13cfd17
OH
2505void xmon_init(int enable)
2506{
2507 if (enable) {
2508 __debugger = xmon;
2509 __debugger_ipi = xmon_ipi;
2510 __debugger_bpt = xmon_bpt;
2511 __debugger_sstep = xmon_sstep;
2512 __debugger_iabr_match = xmon_iabr_match;
2513 __debugger_dabr_match = xmon_dabr_match;
2514 __debugger_fault_handler = xmon_fault_handler;
2515 } else {
2516 __debugger = NULL;
2517 __debugger_ipi = NULL;
2518 __debugger_bpt = NULL;
2519 __debugger_sstep = NULL;
2520 __debugger_iabr_match = NULL;
2521 __debugger_dabr_match = NULL;
2522 __debugger_fault_handler = NULL;
2523 }
fca5dcd4 2524 xmon_map_scc();
1da177e4 2525}
fca5dcd4
PM
2526
2527#ifdef CONFIG_MAGIC_SYSRQ
2528static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2529 struct tty_struct *tty)
2530{
2531 /* ensure xmon is enabled */
2532 xmon_init(1);
2533 debugger(pt_regs);
2534}
2535
2536static struct sysrq_key_op sysrq_xmon_op =
2537{
2538 .handler = sysrq_handle_xmon,
2539 .help_msg = "Xmon",
2540 .action_msg = "Entering xmon",
2541};
2542
2543static int __init setup_xmon_sysrq(void)
2544{
2545 register_sysrq_key('x', &sysrq_xmon_op);
2546 return 0;
2547}
2548__initcall(setup_xmon_sysrq);
2549#endif /* CONFIG_MAGIC_SYSRQ */