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