powerpc: convert hvconsole.c to export.h ; fix implicit use of errno.h
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / powerpc / xmon / xmon.c
CommitLineData
1da177e4
LT
1/*
2 * Routines providing a simple monitor for use on the PowerMac.
3 *
fca5dcd4 4 * Copyright (C) 1996-2005 Paul Mackerras.
47679283
ME
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
1da177e4
LT
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
1da177e4
LT
13#include <linux/errno.h>
14#include <linux/sched.h>
15#include <linux/smp.h>
16#include <linux/mm.h>
17#include <linux/reboot.h>
18#include <linux/delay.h>
19#include <linux/kallsyms.h>
20#include <linux/cpumask.h>
f78541dc 21#include <linux/module.h>
fca5dcd4 22#include <linux/sysrq.h>
4694ca02 23#include <linux/interrupt.h>
7d12e780 24#include <linux/irq.h>
73c9ceab 25#include <linux/bug.h>
1da177e4
LT
26
27#include <asm/ptrace.h>
28#include <asm/string.h>
29#include <asm/prom.h>
30#include <asm/machdep.h>
f78541dc 31#include <asm/xmon.h>
1da177e4
LT
32#include <asm/processor.h>
33#include <asm/pgtable.h>
34#include <asm/mmu.h>
35#include <asm/mmu_context.h>
1da177e4
LT
36#include <asm/cputable.h>
37#include <asm/rtas.h>
38#include <asm/sstep.h>
f583ffce 39#include <asm/irq_regs.h>
ff8a8f25
ME
40#include <asm/spu.h>
41#include <asm/spu_priv1.h>
1d13581d 42#include <asm/firmware.h>
c3b75bd7 43#include <asm/setjmp.h>
322b4394 44#include <asm/reg.h>
f78541dc
PM
45
46#ifdef CONFIG_PPC64
1da177e4 47#include <asm/hvcall.h>
f78541dc
PM
48#include <asm/paca.h>
49#endif
1da177e4
LT
50
51#include "nonstdio.h"
e0426047 52#include "dis-asm.h"
1da177e4
LT
53
54#define scanhex xmon_scanhex
55#define skipbl xmon_skipbl
56
57#ifdef CONFIG_SMP
1c8950ff 58static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
1da177e4
LT
59static unsigned long xmon_taken = 1;
60static int xmon_owner;
61static int xmon_gate;
62#endif /* CONFIG_SMP */
63
5be3492f 64static unsigned long in_xmon __read_mostly = 0;
1da177e4
LT
65
66static unsigned long adrs;
67static int size = 1;
68#define MAX_DUMP (128 * 1024)
69static unsigned long ndump = 64;
70static unsigned long nidump = 16;
71static unsigned long ncsum = 4096;
72static int termch;
73static char tmpstr[128];
74
1da177e4
LT
75static long bus_error_jmp[JMP_BUF_LEN];
76static int catch_memory_errors;
77static long *xmon_fault_jmp[NR_CPUS];
1da177e4
LT
78
79/* Breakpoint stuff */
80struct bpt {
81 unsigned long address;
82 unsigned int instr[2];
83 atomic_t ref_count;
84 int enabled;
85 unsigned long pad;
86};
87
88/* Bits in bpt.enabled */
89#define BP_IABR_TE 1 /* IABR translation enabled */
90#define BP_IABR 2
91#define BP_TRAP 8
92#define BP_DABR 0x10
93
94#define NBPTS 256
95static struct bpt bpts[NBPTS];
96static struct bpt dabr;
97static struct bpt *iabr;
98static unsigned bpinstr = 0x7fe00008; /* trap */
99
100#define BP_NUM(bp) ((bp) - bpts + 1)
101
102/* Prototypes */
103static int cmds(struct pt_regs *);
104static int mread(unsigned long, void *, int);
105static int mwrite(unsigned long, void *, int);
106static int handle_fault(struct pt_regs *);
107static void byterev(unsigned char *, int);
108static void memex(void);
109static int bsesc(void);
110static void dump(void);
111static void prdump(unsigned long, long);
112static int ppc_inst_dump(unsigned long, long, int);
f312deb4 113static void dump_log_buf(void);
1da177e4
LT
114static void backtrace(struct pt_regs *);
115static void excprint(struct pt_regs *);
116static void prregs(struct pt_regs *);
117static void memops(int);
118static void memlocate(void);
119static void memzcan(void);
120static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
121int skipbl(void);
122int scanhex(unsigned long *valp);
123static void scannl(void);
124static int hexdigit(int);
125void getstring(char *, int);
126static void flush_input(void);
127static int inchar(void);
128static void take_input(char *);
129static unsigned long read_spr(int);
130static void write_spr(int, unsigned long);
131static void super_regs(void);
132static void remove_bpts(void);
133static void insert_bpts(void);
134static void remove_cpu_bpts(void);
135static void insert_cpu_bpts(void);
136static struct bpt *at_breakpoint(unsigned long pc);
137static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
138static int do_step(struct pt_regs *);
139static void bpt_cmds(void);
140static void cacheflush(void);
141static int cpu_cmd(void);
142static void csum(void);
143static void bootcmds(void);
f78541dc 144static void proccall(void);
1da177e4
LT
145void dump_segments(void);
146static void symbol_lookup(void);
26c8af5f
OH
147static void xmon_show_stack(unsigned long sp, unsigned long lr,
148 unsigned long pc);
1da177e4
LT
149static void xmon_print_symbol(unsigned long address, const char *mid,
150 const char *after);
151static const char *getvecname(unsigned long vec);
152
ff8a8f25
ME
153static int do_spu_cmd(void);
154
5a8a1a28
BH
155#ifdef CONFIG_44x
156static void dump_tlb_44x(void);
157#endif
03247157
BH
158#ifdef CONFIG_PPC_BOOK3E
159static void dump_tlb_book3e(void);
160#endif
5a8a1a28 161
9f1067c2 162static int xmon_no_auto_backtrace;
26c8af5f 163
f78541dc
PM
164extern void xmon_enter(void);
165extern void xmon_leave(void);
166
f78541dc
PM
167#ifdef CONFIG_PPC64
168#define REG "%.16lx"
169#define REGS_PER_LINE 4
170#define LAST_VOLATILE 13
171#else
172#define REG "%.8lx"
173#define REGS_PER_LINE 8
174#define LAST_VOLATILE 12
175#endif
1da177e4
LT
176
177#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
178
179#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
180 || ('a' <= (c) && (c) <= 'f') \
181 || ('A' <= (c) && (c) <= 'F'))
182#define isalnum(c) (('0' <= (c) && (c) <= '9') \
183 || ('a' <= (c) && (c) <= 'z') \
184 || ('A' <= (c) && (c) <= 'Z'))
185#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
186
187static char *help_string = "\
188Commands:\n\
189 b show breakpoints\n\
190 bd set data breakpoint\n\
191 bi set instruction breakpoint\n\
192 bc clear breakpoint\n"
193#ifdef CONFIG_SMP
194 "\
195 c print cpus stopped in xmon\n\
196 c# try to switch to cpu number h (in hex)\n"
197#endif
198 "\
199 C checksum\n\
200 d dump bytes\n\
201 di dump instructions\n\
202 df dump float values\n\
203 dd dump double values\n\
f312deb4 204 dl dump the kernel log buffer\n\
7e5b5938 205 dr dump stream of raw bytes\n\
1da177e4
LT
206 e print exception information\n\
207 f flush cache\n\
208 la lookup symbol+offset of specified address\n\
209 ls lookup address of specified symbol\n\
210 m examine/change memory\n\
211 mm move a block of memory\n\
212 ms set a block of memory\n\
213 md compare two blocks of memory\n\
214 ml locate a block of memory\n\
215 mz zero a block of memory\n\
216 mi show information about memory allocation\n\
f78541dc 217 p call a procedure\n\
1da177e4 218 r print registers\n\
ff8a8f25 219 s single step\n"
e055595d 220#ifdef CONFIG_SPU_BASE
ff8a8f25 221" ss stop execution on all spus\n\
a8984970 222 sr restore execution on stopped spus\n\
24a24c85 223 sf # dump spu fields for spu # (in hex)\n\
c99176a2 224 sd # dump spu local store for spu # (in hex)\n\
af89fb80 225 sdi # disassemble spu local store for spu # (in hex)\n"
ff8a8f25
ME
226#endif
227" S print special registers\n\
1da177e4 228 t print backtrace\n\
1da177e4 229 x exit monitor and recover\n\
f78541dc
PM
230 X exit monitor and dont recover\n"
231#ifdef CONFIG_PPC64
232" u dump segment table or SLB\n"
233#endif
234#ifdef CONFIG_PPC_STD_MMU_32
235" u dump segment registers\n"
236#endif
5a8a1a28
BH
237#ifdef CONFIG_44x
238" u dump TLB\n"
239#endif
f78541dc
PM
240" ? help\n"
241" zr reboot\n\
1da177e4
LT
242 zh halt\n"
243;
244
245static struct pt_regs *xmon_regs;
246
f78541dc 247static inline void sync(void)
1da177e4
LT
248{
249 asm volatile("sync; isync");
250}
251
f78541dc
PM
252static inline void store_inst(void *p)
253{
254 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
255}
256
257static inline void cflush(void *p)
258{
259 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
260}
261
262static inline void cinval(void *p)
263{
264 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
265}
1da177e4
LT
266
267/*
268 * Disable surveillance (the service processor watchdog function)
269 * while we are in xmon.
270 * XXX we should re-enable it when we leave. :)
271 */
272#define SURVEILLANCE_TOKEN 9000
273
274static inline void disable_surveillance(void)
275{
276#ifdef CONFIG_PPC_PSERIES
277 /* Since this can't be a module, args should end up below 4GB. */
278 static struct rtas_args args;
279
280 /*
281 * At this point we have got all the cpus we can into
282 * xmon, so there is hopefully no other cpu calling RTAS
283 * at the moment, even though we don't take rtas.lock.
284 * If we did try to take rtas.lock there would be a
285 * real possibility of deadlock.
286 */
287 args.token = rtas_token("set-indicator");
288 if (args.token == RTAS_UNKNOWN_SERVICE)
289 return;
290 args.nargs = 3;
291 args.nret = 1;
292 args.rets = &args.args[3];
293 args.args[0] = SURVEILLANCE_TOKEN;
294 args.args[1] = 0;
295 args.args[2] = 0;
296 enter_rtas(__pa(&args));
297#endif /* CONFIG_PPC_PSERIES */
298}
299
300#ifdef CONFIG_SMP
301static int xmon_speaker;
302
303static void get_output_lock(void)
304{
305 int me = smp_processor_id() + 0x100;
306 int last_speaker = 0, prev;
307 long timeout;
308
309 if (xmon_speaker == me)
310 return;
311 for (;;) {
312 if (xmon_speaker == 0) {
313 last_speaker = cmpxchg(&xmon_speaker, 0, me);
314 if (last_speaker == 0)
315 return;
316 }
317 timeout = 10000000;
318 while (xmon_speaker == last_speaker) {
319 if (--timeout > 0)
320 continue;
321 /* hostile takeover */
322 prev = cmpxchg(&xmon_speaker, last_speaker, me);
323 if (prev == last_speaker)
324 return;
325 break;
326 }
327 }
328}
329
330static void release_output_lock(void)
331{
332 xmon_speaker = 0;
333}
1c8950ff
ME
334
335int cpus_are_in_xmon(void)
336{
104699c0 337 return !cpumask_empty(&cpus_in_xmon);
1c8950ff 338}
1da177e4
LT
339#endif
340
daf8f403
JB
341static inline int unrecoverable_excp(struct pt_regs *regs)
342{
343#ifdef CONFIG_4xx
344 /* We have no MSR_RI bit on 4xx, so we simply return false */
345 return 0;
346#else
347 return ((regs->msr & MSR_RI) == 0);
348#endif
349}
350
b0da9856 351static int xmon_core(struct pt_regs *regs, int fromipi)
1da177e4
LT
352{
353 int cmd = 0;
1da177e4
LT
354 struct bpt *bp;
355 long recurse_jmp[JMP_BUF_LEN];
356 unsigned long offset;
f13659e0 357 unsigned long flags;
1da177e4
LT
358#ifdef CONFIG_SMP
359 int cpu;
360 int secondary;
361 unsigned long timeout;
362#endif
363
f13659e0 364 local_irq_save(flags);
1da177e4
LT
365
366 bp = in_breakpoint_table(regs->nip, &offset);
367 if (bp != NULL) {
368 regs->nip = bp->address + offset;
369 atomic_dec(&bp->ref_count);
370 }
371
372 remove_cpu_bpts();
373
374#ifdef CONFIG_SMP
375 cpu = smp_processor_id();
104699c0 376 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1da177e4
LT
377 get_output_lock();
378 excprint(regs);
379 printf("cpu 0x%x: Exception %lx %s in xmon, "
380 "returning to main loop\n",
381 cpu, regs->trap, getvecname(TRAP(regs)));
5cb4cc0d 382 release_output_lock();
1da177e4
LT
383 longjmp(xmon_fault_jmp[cpu], 1);
384 }
385
386 if (setjmp(recurse_jmp) != 0) {
387 if (!in_xmon || !xmon_gate) {
5cb4cc0d 388 get_output_lock();
1da177e4
LT
389 printf("xmon: WARNING: bad recursive fault "
390 "on cpu 0x%x\n", cpu);
5cb4cc0d 391 release_output_lock();
1da177e4
LT
392 goto waiting;
393 }
394 secondary = !(xmon_taken && cpu == xmon_owner);
395 goto cmdloop;
396 }
397
398 xmon_fault_jmp[cpu] = recurse_jmp;
104699c0 399 cpumask_set_cpu(cpu, &cpus_in_xmon);
1da177e4
LT
400
401 bp = NULL;
9f0b0793 402 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
1da177e4 403 bp = at_breakpoint(regs->nip);
daf8f403 404 if (bp || unrecoverable_excp(regs))
1da177e4
LT
405 fromipi = 0;
406
407 if (!fromipi) {
408 get_output_lock();
409 excprint(regs);
410 if (bp) {
411 printf("cpu 0x%x stopped at breakpoint 0x%x (",
412 cpu, BP_NUM(bp));
413 xmon_print_symbol(regs->nip, " ", ")\n");
414 }
daf8f403 415 if (unrecoverable_excp(regs))
1da177e4
LT
416 printf("WARNING: exception is not recoverable, "
417 "can't continue\n");
418 release_output_lock();
419 }
420
421 waiting:
422 secondary = 1;
423 while (secondary && !xmon_gate) {
424 if (in_xmon == 0) {
425 if (fromipi)
426 goto leave;
427 secondary = test_and_set_bit(0, &in_xmon);
428 }
429 barrier();
430 }
431
432 if (!secondary && !xmon_gate) {
433 /* we are the first cpu to come in */
434 /* interrupt other cpu(s) */
435 int ncpus = num_online_cpus();
436
437 xmon_owner = cpu;
438 mb();
439 if (ncpus > 1) {
e0476371 440 smp_send_debugger_break();
1da177e4
LT
441 /* wait for other cpus to come in */
442 for (timeout = 100000000; timeout != 0; --timeout) {
104699c0 443 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
1da177e4
LT
444 break;
445 barrier();
446 }
447 }
448 remove_bpts();
449 disable_surveillance();
450 /* for breakpoint or single step, print the current instr. */
451 if (bp || TRAP(regs) == 0xd00)
452 ppc_inst_dump(regs->nip, 1, 0);
453 printf("enter ? for help\n");
454 mb();
455 xmon_gate = 1;
456 barrier();
457 }
458
459 cmdloop:
460 while (in_xmon) {
461 if (secondary) {
462 if (cpu == xmon_owner) {
463 if (!test_and_set_bit(0, &xmon_taken)) {
464 secondary = 0;
465 continue;
466 }
467 /* missed it */
468 while (cpu == xmon_owner)
469 barrier();
470 }
471 barrier();
472 } else {
473 cmd = cmds(regs);
474 if (cmd != 0) {
475 /* exiting xmon */
476 insert_bpts();
477 xmon_gate = 0;
478 wmb();
479 in_xmon = 0;
480 break;
481 }
482 /* have switched to some other cpu */
483 secondary = 1;
484 }
485 }
486 leave:
104699c0 487 cpumask_clear_cpu(cpu, &cpus_in_xmon);
1da177e4 488 xmon_fault_jmp[cpu] = NULL;
1da177e4
LT
489#else
490 /* UP is simple... */
491 if (in_xmon) {
492 printf("Exception %lx %s in xmon, returning to main loop\n",
493 regs->trap, getvecname(TRAP(regs)));
494 longjmp(xmon_fault_jmp[0], 1);
495 }
496 if (setjmp(recurse_jmp) == 0) {
497 xmon_fault_jmp[0] = recurse_jmp;
498 in_xmon = 1;
499
500 excprint(regs);
501 bp = at_breakpoint(regs->nip);
502 if (bp) {
503 printf("Stopped at breakpoint %x (", BP_NUM(bp));
504 xmon_print_symbol(regs->nip, " ", ")\n");
505 }
daf8f403 506 if (unrecoverable_excp(regs))
1da177e4
LT
507 printf("WARNING: exception is not recoverable, "
508 "can't continue\n");
509 remove_bpts();
510 disable_surveillance();
511 /* for breakpoint or single step, print the current instr. */
512 if (bp || TRAP(regs) == 0xd00)
513 ppc_inst_dump(regs->nip, 1, 0);
514 printf("enter ? for help\n");
515 }
516
517 cmd = cmds(regs);
518
519 insert_bpts();
520 in_xmon = 0;
521#endif
522
cdd3904d
JB
523#ifdef CONFIG_BOOKE
524 if (regs->msr & MSR_DE) {
525 bp = at_breakpoint(regs->nip);
526 if (bp != NULL) {
527 regs->nip = (unsigned long) &bp->instr[0];
528 atomic_inc(&bp->ref_count);
529 }
530 }
531#else
9f0b0793 532 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
1da177e4
LT
533 bp = at_breakpoint(regs->nip);
534 if (bp != NULL) {
535 int stepped = emulate_step(regs, bp->instr[0]);
536 if (stepped == 0) {
537 regs->nip = (unsigned long) &bp->instr[0];
538 atomic_inc(&bp->ref_count);
539 } else if (stepped < 0) {
540 printf("Couldn't single-step %s instruction\n",
541 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
542 }
543 }
544 }
cdd3904d 545#endif
1da177e4
LT
546 insert_cpu_bpts();
547
f13659e0 548 local_irq_restore(flags);
1da177e4 549
0a730ae5 550 return cmd != 'X' && cmd != EOF;
1da177e4
LT
551}
552
553int xmon(struct pt_regs *excp)
554{
555 struct pt_regs regs;
556
557 if (excp == NULL) {
322b4394 558 ppc_save_regs(&regs);
1da177e4
LT
559 excp = &regs;
560 }
ff8a8f25 561
1da177e4
LT
562 return xmon_core(excp, 0);
563}
f78541dc
PM
564EXPORT_SYMBOL(xmon);
565
f583ffce 566irqreturn_t xmon_irq(int irq, void *d)
f78541dc
PM
567{
568 unsigned long flags;
569 local_irq_save(flags);
570 printf("Keyboard interrupt\n");
f583ffce 571 xmon(get_irq_regs());
f78541dc
PM
572 local_irq_restore(flags);
573 return IRQ_HANDLED;
574}
1da177e4 575
b0da9856 576static int xmon_bpt(struct pt_regs *regs)
1da177e4
LT
577{
578 struct bpt *bp;
579 unsigned long offset;
580
9f0b0793 581 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4
LT
582 return 0;
583
584 /* Are we at the trap at bp->instr[1] for some bp? */
585 bp = in_breakpoint_table(regs->nip, &offset);
586 if (bp != NULL && offset == 4) {
587 regs->nip = bp->address + 4;
588 atomic_dec(&bp->ref_count);
589 return 1;
590 }
591
592 /* Are we at a breakpoint? */
593 bp = at_breakpoint(regs->nip);
594 if (!bp)
595 return 0;
596
597 xmon_core(regs, 0);
598
599 return 1;
600}
601
b0da9856 602static int xmon_sstep(struct pt_regs *regs)
1da177e4
LT
603{
604 if (user_mode(regs))
605 return 0;
606 xmon_core(regs, 0);
607 return 1;
608}
609
b0da9856 610static int xmon_dabr_match(struct pt_regs *regs)
1da177e4 611{
9f0b0793 612 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4 613 return 0;
fd9648df
AB
614 if (dabr.enabled == 0)
615 return 0;
1da177e4
LT
616 xmon_core(regs, 0);
617 return 1;
618}
619
b0da9856 620static int xmon_iabr_match(struct pt_regs *regs)
1da177e4 621{
9f0b0793 622 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4 623 return 0;
9f1067c2 624 if (iabr == NULL)
1da177e4
LT
625 return 0;
626 xmon_core(regs, 0);
627 return 1;
628}
629
b0da9856 630static int xmon_ipi(struct pt_regs *regs)
1da177e4
LT
631{
632#ifdef CONFIG_SMP
104699c0 633 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
1da177e4
LT
634 xmon_core(regs, 1);
635#endif
636 return 0;
637}
638
b0da9856 639static int xmon_fault_handler(struct pt_regs *regs)
1da177e4
LT
640{
641 struct bpt *bp;
642 unsigned long offset;
643
644 if (in_xmon && catch_memory_errors)
645 handle_fault(regs); /* doesn't return */
646
9f0b0793 647 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
1da177e4
LT
648 bp = in_breakpoint_table(regs->nip, &offset);
649 if (bp != NULL) {
650 regs->nip = bp->address + offset;
651 atomic_dec(&bp->ref_count);
652 }
653 }
654
655 return 0;
656}
657
1da177e4
LT
658static struct bpt *at_breakpoint(unsigned long pc)
659{
660 int i;
661 struct bpt *bp;
662
663 bp = bpts;
664 for (i = 0; i < NBPTS; ++i, ++bp)
665 if (bp->enabled && pc == bp->address)
666 return bp;
667 return NULL;
668}
669
670static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
671{
672 unsigned long off;
673
674 off = nip - (unsigned long) bpts;
675 if (off >= sizeof(bpts))
676 return NULL;
677 off %= sizeof(struct bpt);
678 if (off != offsetof(struct bpt, instr[0])
679 && off != offsetof(struct bpt, instr[1]))
680 return NULL;
681 *offp = off - offsetof(struct bpt, instr[0]);
682 return (struct bpt *) (nip - off);
683}
684
685static struct bpt *new_breakpoint(unsigned long a)
686{
687 struct bpt *bp;
688
689 a &= ~3UL;
690 bp = at_breakpoint(a);
691 if (bp)
692 return bp;
693
694 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
695 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
696 bp->address = a;
697 bp->instr[1] = bpinstr;
698 store_inst(&bp->instr[1]);
699 return bp;
700 }
701 }
702
703 printf("Sorry, no free breakpoints. Please clear one first.\n");
704 return NULL;
705}
706
707static void insert_bpts(void)
708{
709 int i;
710 struct bpt *bp;
711
712 bp = bpts;
713 for (i = 0; i < NBPTS; ++i, ++bp) {
714 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
715 continue;
716 if (mread(bp->address, &bp->instr[0], 4) != 4) {
717 printf("Couldn't read instruction at %lx, "
718 "disabling breakpoint there\n", bp->address);
719 bp->enabled = 0;
720 continue;
721 }
722 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
723 printf("Breakpoint at %lx is on an mtmsrd or rfid "
724 "instruction, disabling it\n", bp->address);
725 bp->enabled = 0;
726 continue;
727 }
728 store_inst(&bp->instr[0]);
729 if (bp->enabled & BP_IABR)
730 continue;
731 if (mwrite(bp->address, &bpinstr, 4) != 4) {
732 printf("Couldn't write instruction at %lx, "
733 "disabling breakpoint there\n", bp->address);
734 bp->enabled &= ~BP_TRAP;
735 continue;
736 }
737 store_inst((void *)bp->address);
738 }
739}
740
741static void insert_cpu_bpts(void)
742{
743 if (dabr.enabled)
fd9648df 744 set_dabr(dabr.address | (dabr.enabled & 7));
1da177e4 745 if (iabr && cpu_has_feature(CPU_FTR_IABR))
f78541dc 746 mtspr(SPRN_IABR, iabr->address
1da177e4
LT
747 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
748}
749
750static void remove_bpts(void)
751{
752 int i;
753 struct bpt *bp;
754 unsigned instr;
755
756 bp = bpts;
757 for (i = 0; i < NBPTS; ++i, ++bp) {
758 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
759 continue;
760 if (mread(bp->address, &instr, 4) == 4
761 && instr == bpinstr
762 && mwrite(bp->address, &bp->instr, 4) != 4)
763 printf("Couldn't remove breakpoint at %lx\n",
764 bp->address);
765 else
766 store_inst((void *)bp->address);
767 }
768}
769
770static void remove_cpu_bpts(void)
771{
fd9648df 772 set_dabr(0);
1da177e4 773 if (cpu_has_feature(CPU_FTR_IABR))
f78541dc 774 mtspr(SPRN_IABR, 0);
1da177e4
LT
775}
776
777/* Command interpreting routine */
778static char *last_cmd;
779
780static int
781cmds(struct pt_regs *excp)
782{
783 int cmd = 0;
784
785 last_cmd = NULL;
786 xmon_regs = excp;
26c8af5f
OH
787
788 if (!xmon_no_auto_backtrace) {
789 xmon_no_auto_backtrace = 1;
790 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
791 }
792
1da177e4
LT
793 for(;;) {
794#ifdef CONFIG_SMP
795 printf("%x:", smp_processor_id());
796#endif /* CONFIG_SMP */
797 printf("mon> ");
1da177e4
LT
798 flush_input();
799 termch = 0;
800 cmd = skipbl();
801 if( cmd == '\n' ) {
802 if (last_cmd == NULL)
803 continue;
804 take_input(last_cmd);
805 last_cmd = NULL;
806 cmd = inchar();
807 }
808 switch (cmd) {
809 case 'm':
810 cmd = inchar();
811 switch (cmd) {
812 case 'm':
813 case 's':
814 case 'd':
815 memops(cmd);
816 break;
817 case 'l':
818 memlocate();
819 break;
820 case 'z':
821 memzcan();
822 break;
823 case 'i':
b2b755b5 824 show_mem(0);
1da177e4
LT
825 break;
826 default:
827 termch = cmd;
828 memex();
829 }
830 break;
831 case 'd':
832 dump();
833 break;
834 case 'l':
835 symbol_lookup();
836 break;
837 case 'r':
838 prregs(excp); /* print regs */
839 break;
840 case 'e':
841 excprint(excp);
842 break;
843 case 'S':
844 super_regs();
845 break;
846 case 't':
847 backtrace(excp);
848 break;
849 case 'f':
850 cacheflush();
851 break;
852 case 's':
ff8a8f25
ME
853 if (do_spu_cmd() == 0)
854 break;
1da177e4
LT
855 if (do_step(excp))
856 return cmd;
857 break;
858 case 'x':
859 case 'X':
bb6b9b28 860 return cmd;
1da177e4 861 case EOF:
bb6b9b28
BH
862 printf(" <no input ...>\n");
863 mdelay(2000);
1da177e4
LT
864 return cmd;
865 case '?':
4d404edc 866 xmon_puts(help_string);
1da177e4 867 break;
1da177e4
LT
868 case 'b':
869 bpt_cmds();
870 break;
871 case 'C':
872 csum();
873 break;
874 case 'c':
875 if (cpu_cmd())
876 return 0;
877 break;
878 case 'z':
879 bootcmds();
880 break;
f78541dc
PM
881 case 'p':
882 proccall();
1da177e4 883 break;
f78541dc 884#ifdef CONFIG_PPC_STD_MMU
1da177e4
LT
885 case 'u':
886 dump_segments();
887 break;
5a8a1a28
BH
888#endif
889#ifdef CONFIG_4xx
890 case 'u':
891 dump_tlb_44x();
892 break;
03247157
BH
893#endif
894#ifdef CONFIG_PPC_BOOK3E
895 case 'u':
896 dump_tlb_book3e();
897 break;
f78541dc 898#endif
1da177e4
LT
899 default:
900 printf("Unrecognized command: ");
901 do {
902 if (' ' < cmd && cmd <= '~')
903 putchar(cmd);
904 else
905 printf("\\x%x", cmd);
906 cmd = inchar();
907 } while (cmd != '\n');
908 printf(" (type ? for help)\n");
909 break;
910 }
911 }
912}
913
cdd3904d
JB
914#ifdef CONFIG_BOOKE
915static int do_step(struct pt_regs *regs)
916{
917 regs->msr |= MSR_DE;
918 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
919 return 1;
920}
921#else
1da177e4
LT
922/*
923 * Step a single instruction.
924 * Some instructions we emulate, others we execute with MSR_SE set.
925 */
926static int do_step(struct pt_regs *regs)
927{
928 unsigned int instr;
929 int stepped;
930
931 /* check we are in 64-bit kernel mode, translation enabled */
9f0b0793 932 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
1da177e4
LT
933 if (mread(regs->nip, &instr, 4) == 4) {
934 stepped = emulate_step(regs, instr);
935 if (stepped < 0) {
936 printf("Couldn't single-step %s instruction\n",
937 (IS_RFID(instr)? "rfid": "mtmsrd"));
938 return 0;
939 }
940 if (stepped > 0) {
941 regs->trap = 0xd00 | (regs->trap & 1);
942 printf("stepped to ");
943 xmon_print_symbol(regs->nip, " ", "\n");
944 ppc_inst_dump(regs->nip, 1, 0);
945 return 0;
946 }
947 }
948 }
949 regs->msr |= MSR_SE;
950 return 1;
951}
cdd3904d 952#endif
1da177e4
LT
953
954static void bootcmds(void)
955{
956 int cmd;
957
958 cmd = inchar();
959 if (cmd == 'r')
960 ppc_md.restart(NULL);
961 else if (cmd == 'h')
962 ppc_md.halt();
963 else if (cmd == 'p')
964 ppc_md.power_off();
965}
966
967static int cpu_cmd(void)
968{
969#ifdef CONFIG_SMP
970 unsigned long cpu;
971 int timeout;
972 int count;
973
974 if (!scanhex(&cpu)) {
975 /* print cpus waiting or in xmon */
976 printf("cpus stopped:");
977 count = 0;
978 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
104699c0 979 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1da177e4
LT
980 if (count == 0)
981 printf(" %x", cpu);
982 ++count;
983 } else {
984 if (count > 1)
985 printf("-%x", cpu - 1);
986 count = 0;
987 }
988 }
989 if (count > 1)
990 printf("-%x", NR_CPUS - 1);
991 printf("\n");
992 return 0;
993 }
994 /* try to switch to cpu specified */
104699c0 995 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1da177e4
LT
996 printf("cpu 0x%x isn't in xmon\n", cpu);
997 return 0;
998 }
999 xmon_taken = 0;
1000 mb();
1001 xmon_owner = cpu;
1002 timeout = 10000000;
1003 while (!xmon_taken) {
1004 if (--timeout == 0) {
1005 if (test_and_set_bit(0, &xmon_taken))
1006 break;
1007 /* take control back */
1008 mb();
1009 xmon_owner = smp_processor_id();
1010 printf("cpu %u didn't take control\n", cpu);
1011 return 0;
1012 }
1013 barrier();
1014 }
1015 return 1;
1016#else
1017 return 0;
1018#endif /* CONFIG_SMP */
1019}
1020
1021static unsigned short fcstab[256] = {
1022 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1023 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1024 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1025 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1026 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1027 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1028 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1029 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1030 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1031 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1032 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1033 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1034 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1035 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1036 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1037 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1038 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1039 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1040 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1041 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1042 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1043 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1044 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1045 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1046 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1047 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1048 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1049 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1050 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1051 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1052 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1053 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1054};
1055
1056#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1057
1058static void
1059csum(void)
1060{
1061 unsigned int i;
1062 unsigned short fcs;
1063 unsigned char v;
1064
1065 if (!scanhex(&adrs))
1066 return;
1067 if (!scanhex(&ncsum))
1068 return;
1069 fcs = 0xffff;
1070 for (i = 0; i < ncsum; ++i) {
1071 if (mread(adrs+i, &v, 1) == 0) {
1072 printf("csum stopped at %x\n", adrs+i);
1073 break;
1074 }
1075 fcs = FCS(fcs, v);
1076 }
1077 printf("%x\n", fcs);
1078}
1079
1080/*
1081 * Check if this is a suitable place to put a breakpoint.
1082 */
1083static long check_bp_loc(unsigned long addr)
1084{
1085 unsigned int instr;
1086
1087 addr &= ~3;
51fae6de 1088 if (!is_kernel_addr(addr)) {
1da177e4
LT
1089 printf("Breakpoints may only be placed at kernel addresses\n");
1090 return 0;
1091 }
1092 if (!mread(addr, &instr, sizeof(instr))) {
1093 printf("Can't read instruction at address %lx\n", addr);
1094 return 0;
1095 }
1096 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1097 printf("Breakpoints may not be placed on mtmsrd or rfid "
1098 "instructions\n");
1099 return 0;
1100 }
1101 return 1;
1102}
1103
1104static char *breakpoint_help_string =
1105 "Breakpoint command usage:\n"
1106 "b show breakpoints\n"
1107 "b <addr> [cnt] set breakpoint at given instr addr\n"
1108 "bc clear all breakpoints\n"
1109 "bc <n/addr> clear breakpoint number n or at addr\n"
1110 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1111 "bd <addr> [cnt] set hardware data breakpoint\n"
1112 "";
1113
1114static void
1115bpt_cmds(void)
1116{
1117 int cmd;
1118 unsigned long a;
1119 int mode, i;
1120 struct bpt *bp;
1121 const char badaddr[] = "Only kernel addresses are permitted "
1122 "for breakpoints\n";
1123
1124 cmd = inchar();
1125 switch (cmd) {
f78541dc 1126#ifndef CONFIG_8xx
1da177e4
LT
1127 case 'd': /* bd - hardware data breakpoint */
1128 mode = 7;
1129 cmd = inchar();
1130 if (cmd == 'r')
1131 mode = 5;
1132 else if (cmd == 'w')
1133 mode = 6;
1134 else
1135 termch = cmd;
1136 dabr.address = 0;
1137 dabr.enabled = 0;
1138 if (scanhex(&dabr.address)) {
51fae6de 1139 if (!is_kernel_addr(dabr.address)) {
1da177e4
LT
1140 printf(badaddr);
1141 break;
1142 }
1143 dabr.address &= ~7;
1144 dabr.enabled = mode | BP_DABR;
1145 }
1146 break;
1147
1148 case 'i': /* bi - hardware instr breakpoint */
1149 if (!cpu_has_feature(CPU_FTR_IABR)) {
1150 printf("Hardware instruction breakpoint "
1151 "not supported on this cpu\n");
1152 break;
1153 }
1154 if (iabr) {
1155 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1156 iabr = NULL;
1157 }
1158 if (!scanhex(&a))
1159 break;
1160 if (!check_bp_loc(a))
1161 break;
1162 bp = new_breakpoint(a);
1163 if (bp != NULL) {
1164 bp->enabled |= BP_IABR | BP_IABR_TE;
1165 iabr = bp;
1166 }
1167 break;
f78541dc 1168#endif
1da177e4
LT
1169
1170 case 'c':
1171 if (!scanhex(&a)) {
1172 /* clear all breakpoints */
1173 for (i = 0; i < NBPTS; ++i)
1174 bpts[i].enabled = 0;
1175 iabr = NULL;
1176 dabr.enabled = 0;
1177 printf("All breakpoints cleared\n");
1178 break;
1179 }
1180
1181 if (a <= NBPTS && a >= 1) {
1182 /* assume a breakpoint number */
1183 bp = &bpts[a-1]; /* bp nums are 1 based */
1184 } else {
1185 /* assume a breakpoint address */
1186 bp = at_breakpoint(a);
9f1067c2 1187 if (bp == NULL) {
1da177e4
LT
1188 printf("No breakpoint at %x\n", a);
1189 break;
1190 }
1191 }
1192
1193 printf("Cleared breakpoint %x (", BP_NUM(bp));
1194 xmon_print_symbol(bp->address, " ", ")\n");
1195 bp->enabled = 0;
1196 break;
1197
1198 default:
1199 termch = cmd;
1200 cmd = skipbl();
1201 if (cmd == '?') {
1202 printf(breakpoint_help_string);
1203 break;
1204 }
1205 termch = cmd;
1206 if (!scanhex(&a)) {
1207 /* print all breakpoints */
1208 printf(" type address\n");
1209 if (dabr.enabled) {
f78541dc 1210 printf(" data "REG" [", dabr.address);
1da177e4
LT
1211 if (dabr.enabled & 1)
1212 printf("r");
1213 if (dabr.enabled & 2)
1214 printf("w");
1215 printf("]\n");
1216 }
1217 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1218 if (!bp->enabled)
1219 continue;
1220 printf("%2x %s ", BP_NUM(bp),
1221 (bp->enabled & BP_IABR)? "inst": "trap");
1222 xmon_print_symbol(bp->address, " ", "\n");
1223 }
1224 break;
1225 }
1226
1227 if (!check_bp_loc(a))
1228 break;
1229 bp = new_breakpoint(a);
1230 if (bp != NULL)
1231 bp->enabled |= BP_TRAP;
1232 break;
1233 }
1234}
1235
1236/* Very cheap human name for vector lookup. */
1237static
1238const char *getvecname(unsigned long vec)
1239{
1240 char *ret;
1241
1242 switch (vec) {
1243 case 0x100: ret = "(System Reset)"; break;
1244 case 0x200: ret = "(Machine Check)"; break;
1245 case 0x300: ret = "(Data Access)"; break;
1246 case 0x380: ret = "(Data SLB Access)"; break;
1247 case 0x400: ret = "(Instruction Access)"; break;
1248 case 0x480: ret = "(Instruction SLB Access)"; break;
1249 case 0x500: ret = "(Hardware Interrupt)"; break;
1250 case 0x600: ret = "(Alignment)"; break;
1251 case 0x700: ret = "(Program Check)"; break;
1252 case 0x800: ret = "(FPU Unavailable)"; break;
1253 case 0x900: ret = "(Decrementer)"; break;
1254 case 0xc00: ret = "(System Call)"; break;
1255 case 0xd00: ret = "(Single Step)"; break;
1256 case 0xf00: ret = "(Performance Monitor)"; break;
1257 case 0xf20: ret = "(Altivec Unavailable)"; break;
1258 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1259 default: ret = "";
1260 }
1261 return ret;
1262}
1263
1264static void get_function_bounds(unsigned long pc, unsigned long *startp,
1265 unsigned long *endp)
1266{
1267 unsigned long size, offset;
1268 const char *name;
1da177e4
LT
1269
1270 *startp = *endp = 0;
1271 if (pc == 0)
1272 return;
1273 if (setjmp(bus_error_jmp) == 0) {
1274 catch_memory_errors = 1;
1275 sync();
ffb45122 1276 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1da177e4
LT
1277 if (name != NULL) {
1278 *startp = pc - offset;
1279 *endp = pc - offset + size;
1280 }
1281 sync();
1282 }
1283 catch_memory_errors = 0;
1284}
1285
1286static int xmon_depth_to_print = 64;
1287
ec2b36b9
BH
1288#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1289#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1290
1291#ifdef __powerpc64__
f78541dc
PM
1292#define REGS_OFFSET 0x70
1293#else
f78541dc
PM
1294#define REGS_OFFSET 16
1295#endif
1296
1da177e4
LT
1297static void xmon_show_stack(unsigned long sp, unsigned long lr,
1298 unsigned long pc)
1299{
1300 unsigned long ip;
1301 unsigned long newsp;
1302 unsigned long marker;
1303 int count = 0;
1304 struct pt_regs regs;
1305
1306 do {
1307 if (sp < PAGE_OFFSET) {
1308 if (sp != 0)
1309 printf("SP (%lx) is in userspace\n", sp);
1310 break;
1311 }
1312
f78541dc 1313 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1da177e4
LT
1314 || !mread(sp, &newsp, sizeof(unsigned long))) {
1315 printf("Couldn't read stack frame at %lx\n", sp);
1316 break;
1317 }
1318
1319 /*
1320 * For the first stack frame, try to work out if
1321 * LR and/or the saved LR value in the bottommost
1322 * stack frame are valid.
1323 */
1324 if ((pc | lr) != 0) {
1325 unsigned long fnstart, fnend;
1326 unsigned long nextip;
1327 int printip = 1;
1328
1329 get_function_bounds(pc, &fnstart, &fnend);
1330 nextip = 0;
1331 if (newsp > sp)
f78541dc 1332 mread(newsp + LRSAVE_OFFSET, &nextip,
1da177e4
LT
1333 sizeof(unsigned long));
1334 if (lr == ip) {
1335 if (lr < PAGE_OFFSET
1336 || (fnstart <= lr && lr < fnend))
1337 printip = 0;
1338 } else if (lr == nextip) {
1339 printip = 0;
1340 } else if (lr >= PAGE_OFFSET
1341 && !(fnstart <= lr && lr < fnend)) {
1342 printf("[link register ] ");
1343 xmon_print_symbol(lr, " ", "\n");
1344 }
1345 if (printip) {
f78541dc 1346 printf("["REG"] ", sp);
1da177e4
LT
1347 xmon_print_symbol(ip, " ", " (unreliable)\n");
1348 }
1349 pc = lr = 0;
1350
1351 } else {
f78541dc 1352 printf("["REG"] ", sp);
1da177e4
LT
1353 xmon_print_symbol(ip, " ", "\n");
1354 }
1355
1356 /* Look for "regshere" marker to see if this is
1357 an exception frame. */
f78541dc 1358 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
ec2b36b9 1359 && marker == STACK_FRAME_REGS_MARKER) {
f78541dc 1360 if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1da177e4
LT
1361 != sizeof(regs)) {
1362 printf("Couldn't read registers at %lx\n",
f78541dc 1363 sp + REGS_OFFSET);
1da177e4
LT
1364 break;
1365 }
1366 printf("--- Exception: %lx %s at ", regs.trap,
1367 getvecname(TRAP(&regs)));
1368 pc = regs.nip;
1369 lr = regs.link;
1370 xmon_print_symbol(pc, " ", "\n");
1371 }
1372
1373 if (newsp == 0)
1374 break;
1375
1376 sp = newsp;
1377 } while (count++ < xmon_depth_to_print);
1378}
1379
1380static void backtrace(struct pt_regs *excp)
1381{
1382 unsigned long sp;
1383
1384 if (scanhex(&sp))
1385 xmon_show_stack(sp, 0, 0);
1386 else
1387 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1388 scannl();
1389}
1390
1391static void print_bug_trap(struct pt_regs *regs)
1392{
ebdba9af 1393#ifdef CONFIG_BUG
73c9ceab 1394 const struct bug_entry *bug;
1da177e4
LT
1395 unsigned long addr;
1396
1397 if (regs->msr & MSR_PR)
1398 return; /* not in kernel */
1399 addr = regs->nip; /* address of trap instruction */
1400 if (addr < PAGE_OFFSET)
1401 return;
1402 bug = find_bug(regs->nip);
1403 if (bug == NULL)
1404 return;
73c9ceab 1405 if (is_warning_bug(bug))
1da177e4
LT
1406 return;
1407
0a7c7efc 1408#ifdef CONFIG_DEBUG_BUGVERBOSE
73c9ceab
JF
1409 printf("kernel BUG at %s:%u!\n",
1410 bug->file, bug->line);
0a7c7efc
SR
1411#else
1412 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1413#endif
ebdba9af 1414#endif /* CONFIG_BUG */
1da177e4
LT
1415}
1416
9f1067c2 1417static void excprint(struct pt_regs *fp)
1da177e4
LT
1418{
1419 unsigned long trap;
1420
1421#ifdef CONFIG_SMP
1422 printf("cpu 0x%x: ", smp_processor_id());
1423#endif /* CONFIG_SMP */
1424
1425 trap = TRAP(fp);
1426 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1427 printf(" pc: ");
1428 xmon_print_symbol(fp->nip, ": ", "\n");
1429
1430 printf(" lr: ", fp->link);
1431 xmon_print_symbol(fp->link, ": ", "\n");
1432
1433 printf(" sp: %lx\n", fp->gpr[1]);
1434 printf(" msr: %lx\n", fp->msr);
1435
1436 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1437 printf(" dar: %lx\n", fp->dar);
1438 if (trap != 0x380)
1439 printf(" dsisr: %lx\n", fp->dsisr);
1440 }
1441
1442 printf(" current = 0x%lx\n", current);
f78541dc 1443#ifdef CONFIG_PPC64
1da177e4 1444 printf(" paca = 0x%lx\n", get_paca());
f78541dc 1445#endif
1da177e4
LT
1446 if (current) {
1447 printf(" pid = %ld, comm = %s\n",
1448 current->pid, current->comm);
1449 }
1450
1451 if (trap == 0x700)
1452 print_bug_trap(fp);
1453}
1454
9f1067c2 1455static void prregs(struct pt_regs *fp)
1da177e4 1456{
f78541dc 1457 int n, trap;
1da177e4
LT
1458 unsigned long base;
1459 struct pt_regs regs;
1460
1461 if (scanhex(&base)) {
1462 if (setjmp(bus_error_jmp) == 0) {
1463 catch_memory_errors = 1;
1464 sync();
1465 regs = *(struct pt_regs *)base;
1466 sync();
1467 __delay(200);
1468 } else {
1469 catch_memory_errors = 0;
f78541dc 1470 printf("*** Error reading registers from "REG"\n",
1da177e4
LT
1471 base);
1472 return;
1473 }
1474 catch_memory_errors = 0;
1475 fp = &regs;
1476 }
1477
f78541dc 1478#ifdef CONFIG_PPC64
1da177e4
LT
1479 if (FULL_REGS(fp)) {
1480 for (n = 0; n < 16; ++n)
f78541dc 1481 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1482 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1483 } else {
1484 for (n = 0; n < 7; ++n)
f78541dc 1485 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1486 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1487 }
f78541dc
PM
1488#else
1489 for (n = 0; n < 32; ++n) {
1490 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1491 (n & 3) == 3? "\n": " ");
1492 if (n == 12 && !FULL_REGS(fp)) {
1493 printf("\n");
1494 break;
1495 }
1496 }
1497#endif
1da177e4
LT
1498 printf("pc = ");
1499 xmon_print_symbol(fp->nip, " ", "\n");
48404f2e
PM
1500 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1501 printf("cfar= ");
1502 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1503 }
1da177e4
LT
1504 printf("lr = ");
1505 xmon_print_symbol(fp->link, " ", "\n");
f78541dc
PM
1506 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1507 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1da177e4 1508 fp->ctr, fp->xer, fp->trap);
f78541dc
PM
1509 trap = TRAP(fp);
1510 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1511 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1da177e4
LT
1512}
1513
9f1067c2 1514static void cacheflush(void)
1da177e4
LT
1515{
1516 int cmd;
1517 unsigned long nflush;
1518
1519 cmd = inchar();
1520 if (cmd != 'i')
1521 termch = cmd;
1522 scanhex((void *)&adrs);
1523 if (termch != '\n')
1524 termch = 0;
1525 nflush = 1;
1526 scanhex(&nflush);
1527 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1528 if (setjmp(bus_error_jmp) == 0) {
1529 catch_memory_errors = 1;
1530 sync();
1531
1532 if (cmd != 'i') {
1533 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1534 cflush((void *) adrs);
1535 } else {
1536 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1537 cinval((void *) adrs);
1538 }
1539 sync();
1540 /* wait a little while to see if we get a machine check */
1541 __delay(200);
1542 }
1543 catch_memory_errors = 0;
1544}
1545
9f1067c2 1546static unsigned long
1da177e4
LT
1547read_spr(int n)
1548{
1549 unsigned int instrs[2];
1550 unsigned long (*code)(void);
1da177e4 1551 unsigned long ret = -1UL;
548ccebc
PM
1552#ifdef CONFIG_PPC64
1553 unsigned long opd[3];
1da177e4 1554
1da177e4
LT
1555 opd[0] = (unsigned long)instrs;
1556 opd[1] = 0;
1557 opd[2] = 0;
548ccebc
PM
1558 code = (unsigned long (*)(void)) opd;
1559#else
1560 code = (unsigned long (*)(void)) instrs;
1561#endif
1562
1563 /* mfspr r3,n; blr */
1564 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1565 instrs[1] = 0x4e800020;
1da177e4
LT
1566 store_inst(instrs);
1567 store_inst(instrs+1);
1da177e4
LT
1568
1569 if (setjmp(bus_error_jmp) == 0) {
1570 catch_memory_errors = 1;
1571 sync();
1572
1573 ret = code();
1574
1575 sync();
1576 /* wait a little while to see if we get a machine check */
1577 __delay(200);
1578 n = size;
1579 }
1580
1581 return ret;
1582}
1583
9f1067c2 1584static void
1da177e4
LT
1585write_spr(int n, unsigned long val)
1586{
1587 unsigned int instrs[2];
1588 unsigned long (*code)(unsigned long);
548ccebc 1589#ifdef CONFIG_PPC64
1da177e4
LT
1590 unsigned long opd[3];
1591
1da177e4
LT
1592 opd[0] = (unsigned long)instrs;
1593 opd[1] = 0;
1594 opd[2] = 0;
548ccebc
PM
1595 code = (unsigned long (*)(unsigned long)) opd;
1596#else
1597 code = (unsigned long (*)(unsigned long)) instrs;
1598#endif
1599
1600 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1601 instrs[1] = 0x4e800020;
1da177e4
LT
1602 store_inst(instrs);
1603 store_inst(instrs+1);
1da177e4
LT
1604
1605 if (setjmp(bus_error_jmp) == 0) {
1606 catch_memory_errors = 1;
1607 sync();
1608
1609 code(val);
1610
1611 sync();
1612 /* wait a little while to see if we get a machine check */
1613 __delay(200);
1614 n = size;
1615 }
1616}
1617
1618static unsigned long regno;
1619extern char exc_prolog;
1620extern char dec_exc;
1621
9f1067c2 1622static void super_regs(void)
1da177e4
LT
1623{
1624 int cmd;
1625 unsigned long val;
1da177e4
LT
1626
1627 cmd = skipbl();
1628 if (cmd == '\n') {
1629 unsigned long sp, toc;
1630 asm("mr %0,1" : "=r" (sp) :);
1631 asm("mr %0,2" : "=r" (toc) :);
1632
f78541dc
PM
1633 printf("msr = "REG" sprg0= "REG"\n",
1634 mfmsr(), mfspr(SPRN_SPRG0));
1635 printf("pvr = "REG" sprg1= "REG"\n",
1636 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1637 printf("dec = "REG" sprg2= "REG"\n",
1638 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1639 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1640 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1da177e4 1641#ifdef CONFIG_PPC_ISERIES
1d13581d
SR
1642 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1643 struct paca_struct *ptrPaca;
1644 struct lppaca *ptrLpPaca;
1d13581d
SR
1645
1646 /* Dump out relevant Paca data areas. */
1647 printf("Paca: \n");
1648 ptrPaca = get_paca();
1649
1650 printf(" Local Processor Control Area (LpPaca): \n");
1651 ptrLpPaca = ptrPaca->lppaca_ptr;
1652 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1653 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1654 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1655 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
69ddb57c
GS
1656 printf(" Saved Gpr5=%.16lx \n",
1657 ptrLpPaca->gpr5_dword.saved_gpr5);
1d13581d 1658 }
1da177e4
LT
1659#endif
1660
1661 return;
1662 }
1663
1664 scanhex(&regno);
1665 switch (cmd) {
1666 case 'w':
1667 val = read_spr(regno);
1668 scanhex(&val);
1669 write_spr(regno, val);
1670 /* fall through */
1671 case 'r':
1672 printf("spr %lx = %lx\n", regno, read_spr(regno));
1673 break;
1da177e4
LT
1674 }
1675 scannl();
1676}
1677
1678/*
1679 * Stuff for reading and writing memory safely
1680 */
9f1067c2 1681static int
1da177e4
LT
1682mread(unsigned long adrs, void *buf, int size)
1683{
1684 volatile int n;
1685 char *p, *q;
1686
1687 n = 0;
1688 if (setjmp(bus_error_jmp) == 0) {
1689 catch_memory_errors = 1;
1690 sync();
1691 p = (char *)adrs;
1692 q = (char *)buf;
1693 switch (size) {
1694 case 2:
f78541dc 1695 *(u16 *)q = *(u16 *)p;
1da177e4
LT
1696 break;
1697 case 4:
f78541dc 1698 *(u32 *)q = *(u32 *)p;
1da177e4
LT
1699 break;
1700 case 8:
f78541dc 1701 *(u64 *)q = *(u64 *)p;
1da177e4
LT
1702 break;
1703 default:
1704 for( ; n < size; ++n) {
1705 *q++ = *p++;
1706 sync();
1707 }
1708 }
1709 sync();
1710 /* wait a little while to see if we get a machine check */
1711 __delay(200);
1712 n = size;
1713 }
1714 catch_memory_errors = 0;
1715 return n;
1716}
1717
9f1067c2 1718static int
1da177e4
LT
1719mwrite(unsigned long adrs, void *buf, int size)
1720{
1721 volatile int n;
1722 char *p, *q;
1723
1724 n = 0;
1725 if (setjmp(bus_error_jmp) == 0) {
1726 catch_memory_errors = 1;
1727 sync();
1728 p = (char *) adrs;
1729 q = (char *) buf;
1730 switch (size) {
1731 case 2:
f78541dc 1732 *(u16 *)p = *(u16 *)q;
1da177e4
LT
1733 break;
1734 case 4:
f78541dc 1735 *(u32 *)p = *(u32 *)q;
1da177e4
LT
1736 break;
1737 case 8:
f78541dc 1738 *(u64 *)p = *(u64 *)q;
1da177e4
LT
1739 break;
1740 default:
1741 for ( ; n < size; ++n) {
1742 *p++ = *q++;
1743 sync();
1744 }
1745 }
1746 sync();
1747 /* wait a little while to see if we get a machine check */
1748 __delay(200);
1749 n = size;
1750 } else {
1751 printf("*** Error writing address %x\n", adrs + n);
1752 }
1753 catch_memory_errors = 0;
1754 return n;
1755}
1756
1757static int fault_type;
f78541dc 1758static int fault_except;
1da177e4
LT
1759static char *fault_chars[] = { "--", "**", "##" };
1760
f78541dc 1761static int handle_fault(struct pt_regs *regs)
1da177e4 1762{
f78541dc 1763 fault_except = TRAP(regs);
1da177e4
LT
1764 switch (TRAP(regs)) {
1765 case 0x200:
1766 fault_type = 0;
1767 break;
1768 case 0x300:
1769 case 0x380:
1770 fault_type = 1;
1771 break;
1772 default:
1773 fault_type = 2;
1774 }
1775
1776 longjmp(bus_error_jmp, 1);
1777
1778 return 0;
1779}
1780
1781#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1782
9f1067c2 1783static void
1da177e4
LT
1784byterev(unsigned char *val, int size)
1785{
1786 int t;
1787
1788 switch (size) {
1789 case 2:
1790 SWAP(val[0], val[1], t);
1791 break;
1792 case 4:
1793 SWAP(val[0], val[3], t);
1794 SWAP(val[1], val[2], t);
1795 break;
1796 case 8: /* is there really any use for this? */
1797 SWAP(val[0], val[7], t);
1798 SWAP(val[1], val[6], t);
1799 SWAP(val[2], val[5], t);
1800 SWAP(val[3], val[4], t);
1801 break;
1802 }
1803}
1804
1805static int brev;
1806static int mnoread;
1807
1808static char *memex_help_string =
1809 "Memory examine command usage:\n"
1810 "m [addr] [flags] examine/change memory\n"
1811 " addr is optional. will start where left off.\n"
1812 " flags may include chars from this set:\n"
1813 " b modify by bytes (default)\n"
1814 " w modify by words (2 byte)\n"
1815 " l modify by longs (4 byte)\n"
1816 " d modify by doubleword (8 byte)\n"
1817 " r toggle reverse byte order mode\n"
1818 " n do not read memory (for i/o spaces)\n"
1819 " . ok to read (default)\n"
1820 "NOTE: flags are saved as defaults\n"
1821 "";
1822
1823static char *memex_subcmd_help_string =
1824 "Memory examine subcommands:\n"
1825 " hexval write this val to current location\n"
1826 " 'string' write chars from string to this location\n"
1827 " ' increment address\n"
1828 " ^ decrement address\n"
1829 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1830 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1831 " ` clear no-read flag\n"
1832 " ; stay at this addr\n"
1833 " v change to byte mode\n"
1834 " w change to word (2 byte) mode\n"
1835 " l change to long (4 byte) mode\n"
1836 " u change to doubleword (8 byte) mode\n"
1837 " m addr change current addr\n"
1838 " n toggle no-read flag\n"
1839 " r toggle byte reverse flag\n"
1840 " < count back up count bytes\n"
1841 " > count skip forward count bytes\n"
1842 " x exit this mode\n"
1843 "";
1844
9f1067c2 1845static void
1da177e4
LT
1846memex(void)
1847{
1848 int cmd, inc, i, nslash;
1849 unsigned long n;
1850 unsigned char val[16];
1851
1852 scanhex((void *)&adrs);
1853 cmd = skipbl();
1854 if (cmd == '?') {
1855 printf(memex_help_string);
1856 return;
1857 } else {
1858 termch = cmd;
1859 }
1860 last_cmd = "m\n";
1861 while ((cmd = skipbl()) != '\n') {
1862 switch( cmd ){
1863 case 'b': size = 1; break;
1864 case 'w': size = 2; break;
1865 case 'l': size = 4; break;
1866 case 'd': size = 8; break;
1867 case 'r': brev = !brev; break;
1868 case 'n': mnoread = 1; break;
1869 case '.': mnoread = 0; break;
1870 }
1871 }
1872 if( size <= 0 )
1873 size = 1;
1874 else if( size > 8 )
1875 size = 8;
1876 for(;;){
1877 if (!mnoread)
1878 n = mread(adrs, val, size);
e1449ed9 1879 printf(REG"%c", adrs, brev? 'r': ' ');
1da177e4
LT
1880 if (!mnoread) {
1881 if (brev)
1882 byterev(val, size);
1883 putchar(' ');
1884 for (i = 0; i < n; ++i)
1885 printf("%.2x", val[i]);
1886 for (; i < size; ++i)
1887 printf("%s", fault_chars[fault_type]);
1888 }
1889 putchar(' ');
1890 inc = size;
1891 nslash = 0;
1892 for(;;){
1893 if( scanhex(&n) ){
1894 for (i = 0; i < size; ++i)
1895 val[i] = n >> (i * 8);
1896 if (!brev)
1897 byterev(val, size);
1898 mwrite(adrs, val, size);
1899 inc = size;
1900 }
1901 cmd = skipbl();
1902 if (cmd == '\n')
1903 break;
1904 inc = 0;
1905 switch (cmd) {
1906 case '\'':
1907 for(;;){
1908 n = inchar();
1909 if( n == '\\' )
1910 n = bsesc();
1911 else if( n == '\'' )
1912 break;
1913 for (i = 0; i < size; ++i)
1914 val[i] = n >> (i * 8);
1915 if (!brev)
1916 byterev(val, size);
1917 mwrite(adrs, val, size);
1918 adrs += size;
1919 }
1920 adrs -= size;
1921 inc = size;
1922 break;
1923 case ',':
1924 adrs += size;
1925 break;
1926 case '.':
1927 mnoread = 0;
1928 break;
1929 case ';':
1930 break;
1931 case 'x':
1932 case EOF:
1933 scannl();
1934 return;
1935 case 'b':
1936 case 'v':
1937 size = 1;
1938 break;
1939 case 'w':
1940 size = 2;
1941 break;
1942 case 'l':
1943 size = 4;
1944 break;
1945 case 'u':
1946 size = 8;
1947 break;
1948 case '^':
1949 adrs -= size;
1950 break;
1951 break;
1952 case '/':
1953 if (nslash > 0)
1954 adrs -= 1 << nslash;
1955 else
1956 nslash = 0;
1957 nslash += 4;
1958 adrs += 1 << nslash;
1959 break;
1960 case '\\':
1961 if (nslash < 0)
1962 adrs += 1 << -nslash;
1963 else
1964 nslash = 0;
1965 nslash -= 4;
1966 adrs -= 1 << -nslash;
1967 break;
1968 case 'm':
1969 scanhex((void *)&adrs);
1970 break;
1971 case 'n':
1972 mnoread = 1;
1973 break;
1974 case 'r':
1975 brev = !brev;
1976 break;
1977 case '<':
1978 n = size;
1979 scanhex(&n);
1980 adrs -= n;
1981 break;
1982 case '>':
1983 n = size;
1984 scanhex(&n);
1985 adrs += n;
1986 break;
1987 case '?':
1988 printf(memex_subcmd_help_string);
1989 break;
1990 }
1991 }
1992 adrs += inc;
1993 }
1994}
1995
9f1067c2 1996static int
1da177e4
LT
1997bsesc(void)
1998{
1999 int c;
2000
2001 c = inchar();
2002 switch( c ){
2003 case 'n': c = '\n'; break;
2004 case 'r': c = '\r'; break;
2005 case 'b': c = '\b'; break;
2006 case 't': c = '\t'; break;
2007 }
2008 return c;
2009}
2010
7e5b5938
OH
2011static void xmon_rawdump (unsigned long adrs, long ndump)
2012{
2013 long n, m, r, nr;
2014 unsigned char temp[16];
2015
2016 for (n = ndump; n > 0;) {
2017 r = n < 16? n: 16;
2018 nr = mread(adrs, temp, r);
2019 adrs += nr;
2020 for (m = 0; m < r; ++m) {
2021 if (m < nr)
2022 printf("%.2x", temp[m]);
2023 else
2024 printf("%s", fault_chars[fault_type]);
2025 }
2026 n -= r;
2027 if (nr < r)
2028 break;
2029 }
2030 printf("\n");
2031}
2032
1da177e4
LT
2033#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2034 || ('a' <= (c) && (c) <= 'f') \
2035 || ('A' <= (c) && (c) <= 'F'))
9f1067c2 2036static void
1da177e4
LT
2037dump(void)
2038{
2039 int c;
2040
2041 c = inchar();
2042 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2043 termch = c;
2044 scanhex((void *)&adrs);
2045 if (termch != '\n')
2046 termch = 0;
2047 if (c == 'i') {
2048 scanhex(&nidump);
2049 if (nidump == 0)
2050 nidump = 16;
2051 else if (nidump > MAX_DUMP)
2052 nidump = MAX_DUMP;
2053 adrs += ppc_inst_dump(adrs, nidump, 1);
2054 last_cmd = "di\n";
f312deb4
VS
2055 } else if (c == 'l') {
2056 dump_log_buf();
7e5b5938
OH
2057 } else if (c == 'r') {
2058 scanhex(&ndump);
2059 if (ndump == 0)
2060 ndump = 64;
2061 xmon_rawdump(adrs, ndump);
2062 adrs += ndump;
2063 last_cmd = "dr\n";
1da177e4
LT
2064 } else {
2065 scanhex(&ndump);
2066 if (ndump == 0)
2067 ndump = 64;
2068 else if (ndump > MAX_DUMP)
2069 ndump = MAX_DUMP;
2070 prdump(adrs, ndump);
2071 adrs += ndump;
2072 last_cmd = "d\n";
2073 }
2074}
2075
9f1067c2 2076static void
1da177e4
LT
2077prdump(unsigned long adrs, long ndump)
2078{
2079 long n, m, c, r, nr;
2080 unsigned char temp[16];
2081
2082 for (n = ndump; n > 0;) {
f78541dc 2083 printf(REG, adrs);
1da177e4
LT
2084 putchar(' ');
2085 r = n < 16? n: 16;
2086 nr = mread(adrs, temp, r);
2087 adrs += nr;
2088 for (m = 0; m < r; ++m) {
e1449ed9
PM
2089 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2090 putchar(' ');
1da177e4
LT
2091 if (m < nr)
2092 printf("%.2x", temp[m]);
2093 else
2094 printf("%s", fault_chars[fault_type]);
2095 }
e1449ed9
PM
2096 for (; m < 16; ++m) {
2097 if ((m & (sizeof(long) - 1)) == 0)
2098 putchar(' ');
1da177e4 2099 printf(" ");
e1449ed9 2100 }
1da177e4
LT
2101 printf(" |");
2102 for (m = 0; m < r; ++m) {
2103 if (m < nr) {
2104 c = temp[m];
2105 putchar(' ' <= c && c <= '~'? c: '.');
2106 } else
2107 putchar(' ');
2108 }
2109 n -= r;
2110 for (; m < 16; ++m)
2111 putchar(' ');
2112 printf("|\n");
2113 if (nr < r)
2114 break;
2115 }
2116}
2117
4c4c8723
ME
2118typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2119
9f1067c2 2120static int
4c4c8723
ME
2121generic_inst_dump(unsigned long adr, long count, int praddr,
2122 instruction_dump_func dump_func)
1da177e4
LT
2123{
2124 int nr, dotted;
2125 unsigned long first_adr;
2126 unsigned long inst, last_inst = 0;
2127 unsigned char val[4];
2128
2129 dotted = 0;
2130 for (first_adr = adr; count > 0; --count, adr += 4) {
2131 nr = mread(adr, val, 4);
2132 if (nr == 0) {
2133 if (praddr) {
2134 const char *x = fault_chars[fault_type];
f78541dc 2135 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
1da177e4
LT
2136 }
2137 break;
2138 }
2139 inst = GETWORD(val);
2140 if (adr > first_adr && inst == last_inst) {
2141 if (!dotted) {
2142 printf(" ...\n");
2143 dotted = 1;
2144 }
2145 continue;
2146 }
2147 dotted = 0;
2148 last_inst = inst;
2149 if (praddr)
f78541dc 2150 printf(REG" %.8x", adr, inst);
1da177e4 2151 printf("\t");
4c4c8723 2152 dump_func(inst, adr);
1da177e4
LT
2153 printf("\n");
2154 }
2155 return adr - first_adr;
2156}
2157
9f1067c2 2158static int
4c4c8723
ME
2159ppc_inst_dump(unsigned long adr, long count, int praddr)
2160{
2161 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2162}
2163
1da177e4
LT
2164void
2165print_address(unsigned long addr)
2166{
2167 xmon_print_symbol(addr, "\t# ", "");
2168}
2169
f312deb4
VS
2170void
2171dump_log_buf(void)
2172{
2173 const unsigned long size = 128;
6d1386d5 2174 unsigned long end, addr;
f312deb4
VS
2175 unsigned char buf[size + 1];
2176
2177 addr = 0;
2178 buf[size] = '\0';
2179
2180 if (setjmp(bus_error_jmp) != 0) {
2181 printf("Unable to lookup symbol __log_buf!\n");
2182 return;
2183 }
2184
2185 catch_memory_errors = 1;
2186 sync();
2187 addr = kallsyms_lookup_name("__log_buf");
2188
2189 if (! addr)
2190 printf("Symbol __log_buf not found!\n");
2191 else {
2192 end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
2193 while (addr < end) {
2194 if (! mread(addr, buf, size)) {
2195 printf("Can't read memory at address 0x%lx\n", addr);
2196 break;
2197 }
2198
2199 printf("%s", buf);
2200
2201 if (strlen(buf) < size)
2202 break;
2203
2204 addr += size;
2205 }
2206 }
2207
2208 sync();
2209 /* wait a little while to see if we get a machine check */
2210 __delay(200);
2211 catch_memory_errors = 0;
2212}
1da177e4
LT
2213
2214/*
2215 * Memory operations - move, set, print differences
2216 */
2217static unsigned long mdest; /* destination address */
2218static unsigned long msrc; /* source address */
2219static unsigned long mval; /* byte value to set memory to */
2220static unsigned long mcount; /* # bytes to affect */
2221static unsigned long mdiffs; /* max # differences to print */
2222
9f1067c2 2223static void
1da177e4
LT
2224memops(int cmd)
2225{
2226 scanhex((void *)&mdest);
2227 if( termch != '\n' )
2228 termch = 0;
2229 scanhex((void *)(cmd == 's'? &mval: &msrc));
2230 if( termch != '\n' )
2231 termch = 0;
2232 scanhex((void *)&mcount);
2233 switch( cmd ){
2234 case 'm':
2235 memmove((void *)mdest, (void *)msrc, mcount);
2236 break;
2237 case 's':
2238 memset((void *)mdest, mval, mcount);
2239 break;
2240 case 'd':
2241 if( termch != '\n' )
2242 termch = 0;
2243 scanhex((void *)&mdiffs);
2244 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2245 break;
2246 }
2247}
2248
9f1067c2 2249static void
1da177e4
LT
2250memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2251{
2252 unsigned n, prt;
2253
2254 prt = 0;
2255 for( n = nb; n > 0; --n )
2256 if( *p1++ != *p2++ )
2257 if( ++prt <= maxpr )
2258 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2259 p1[-1], p2 - 1, p2[-1]);
2260 if( prt > maxpr )
2261 printf("Total of %d differences\n", prt);
2262}
2263
2264static unsigned mend;
2265static unsigned mask;
2266
9f1067c2 2267static void
1da177e4
LT
2268memlocate(void)
2269{
2270 unsigned a, n;
2271 unsigned char val[4];
2272
2273 last_cmd = "ml";
2274 scanhex((void *)&mdest);
2275 if (termch != '\n') {
2276 termch = 0;
2277 scanhex((void *)&mend);
2278 if (termch != '\n') {
2279 termch = 0;
2280 scanhex((void *)&mval);
2281 mask = ~0;
2282 if (termch != '\n') termch = 0;
2283 scanhex((void *)&mask);
2284 }
2285 }
2286 n = 0;
2287 for (a = mdest; a < mend; a += 4) {
2288 if (mread(a, val, 4) == 4
2289 && ((GETWORD(val) ^ mval) & mask) == 0) {
2290 printf("%.16x: %.16x\n", a, GETWORD(val));
2291 if (++n >= 10)
2292 break;
2293 }
2294 }
2295}
2296
2297static unsigned long mskip = 0x1000;
2298static unsigned long mlim = 0xffffffff;
2299
9f1067c2 2300static void
1da177e4
LT
2301memzcan(void)
2302{
2303 unsigned char v;
2304 unsigned a;
2305 int ok, ook;
2306
2307 scanhex(&mdest);
2308 if (termch != '\n') termch = 0;
2309 scanhex(&mskip);
2310 if (termch != '\n') termch = 0;
2311 scanhex(&mlim);
2312 ook = 0;
2313 for (a = mdest; a < mlim; a += mskip) {
2314 ok = mread(a, &v, 1);
2315 if (ok && !ook) {
2316 printf("%.8x .. ", a);
1da177e4
LT
2317 } else if (!ok && ook)
2318 printf("%.8x\n", a - mskip);
2319 ook = ok;
2320 if (a + mskip < a)
2321 break;
2322 }
2323 if (ook)
2324 printf("%.8x\n", a - mskip);
2325}
2326
9f1067c2 2327static void proccall(void)
f78541dc
PM
2328{
2329 unsigned long args[8];
2330 unsigned long ret;
2331 int i;
2332 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2333 unsigned long, unsigned long, unsigned long,
2334 unsigned long, unsigned long, unsigned long);
2335 callfunc_t func;
2336
2337 if (!scanhex(&adrs))
2338 return;
2339 if (termch != '\n')
2340 termch = 0;
2341 for (i = 0; i < 8; ++i)
2342 args[i] = 0;
2343 for (i = 0; i < 8; ++i) {
2344 if (!scanhex(&args[i]) || termch == '\n')
2345 break;
2346 termch = 0;
2347 }
2348 func = (callfunc_t) adrs;
2349 ret = 0;
2350 if (setjmp(bus_error_jmp) == 0) {
2351 catch_memory_errors = 1;
2352 sync();
2353 ret = func(args[0], args[1], args[2], args[3],
2354 args[4], args[5], args[6], args[7]);
2355 sync();
2356 printf("return value is %x\n", ret);
2357 } else {
2358 printf("*** %x exception occurred\n", fault_except);
2359 }
2360 catch_memory_errors = 0;
2361}
2362
1da177e4
LT
2363/* Input scanning routines */
2364int
2365skipbl(void)
2366{
2367 int c;
2368
2369 if( termch != 0 ){
2370 c = termch;
2371 termch = 0;
2372 } else
2373 c = inchar();
2374 while( c == ' ' || c == '\t' )
2375 c = inchar();
2376 return c;
2377}
2378
2379#define N_PTREGS 44
2380static char *regnames[N_PTREGS] = {
2381 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2382 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2383 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2384 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
f78541dc
PM
2385 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2386#ifdef CONFIG_PPC64
2387 "softe",
2388#else
2389 "mq",
2390#endif
1da177e4
LT
2391 "trap", "dar", "dsisr", "res"
2392};
2393
2394int
2395scanhex(unsigned long *vp)
2396{
2397 int c, d;
2398 unsigned long v;
2399
2400 c = skipbl();
2401 if (c == '%') {
2402 /* parse register name */
2403 char regname[8];
2404 int i;
2405
2406 for (i = 0; i < sizeof(regname) - 1; ++i) {
2407 c = inchar();
2408 if (!isalnum(c)) {
2409 termch = c;
2410 break;
2411 }
2412 regname[i] = c;
2413 }
2414 regname[i] = 0;
2415 for (i = 0; i < N_PTREGS; ++i) {
2416 if (strcmp(regnames[i], regname) == 0) {
2417 if (xmon_regs == NULL) {
2418 printf("regs not available\n");
2419 return 0;
2420 }
2421 *vp = ((unsigned long *)xmon_regs)[i];
2422 return 1;
2423 }
2424 }
2425 printf("invalid register name '%%%s'\n", regname);
2426 return 0;
2427 }
2428
2429 /* skip leading "0x" if any */
2430
2431 if (c == '0') {
2432 c = inchar();
2433 if (c == 'x') {
2434 c = inchar();
2435 } else {
2436 d = hexdigit(c);
2437 if (d == EOF) {
2438 termch = c;
2439 *vp = 0;
2440 return 1;
2441 }
2442 }
2443 } else if (c == '$') {
2444 int i;
2445 for (i=0; i<63; i++) {
2446 c = inchar();
2447 if (isspace(c)) {
2448 termch = c;
2449 break;
2450 }
2451 tmpstr[i] = c;
2452 }
2453 tmpstr[i++] = 0;
6879dc13
BH
2454 *vp = 0;
2455 if (setjmp(bus_error_jmp) == 0) {
2456 catch_memory_errors = 1;
2457 sync();
2458 *vp = kallsyms_lookup_name(tmpstr);
2459 sync();
2460 }
2461 catch_memory_errors = 0;
1da177e4
LT
2462 if (!(*vp)) {
2463 printf("unknown symbol '%s'\n", tmpstr);
2464 return 0;
2465 }
2466 return 1;
2467 }
2468
2469 d = hexdigit(c);
2470 if (d == EOF) {
2471 termch = c;
2472 return 0;
2473 }
2474 v = 0;
2475 do {
2476 v = (v << 4) + d;
2477 c = inchar();
2478 d = hexdigit(c);
2479 } while (d != EOF);
2480 termch = c;
2481 *vp = v;
2482 return 1;
2483}
2484
9f1067c2 2485static void
1da177e4
LT
2486scannl(void)
2487{
2488 int c;
2489
2490 c = termch;
2491 termch = 0;
2492 while( c != '\n' )
2493 c = inchar();
2494}
2495
9f1067c2 2496static int hexdigit(int c)
1da177e4
LT
2497{
2498 if( '0' <= c && c <= '9' )
2499 return c - '0';
2500 if( 'A' <= c && c <= 'F' )
2501 return c - ('A' - 10);
2502 if( 'a' <= c && c <= 'f' )
2503 return c - ('a' - 10);
2504 return EOF;
2505}
2506
2507void
2508getstring(char *s, int size)
2509{
2510 int c;
2511
2512 c = skipbl();
2513 do {
2514 if( size > 1 ){
2515 *s++ = c;
2516 --size;
2517 }
2518 c = inchar();
2519 } while( c != ' ' && c != '\t' && c != '\n' );
2520 termch = c;
2521 *s = 0;
2522}
2523
2524static char line[256];
2525static char *lineptr;
2526
9f1067c2 2527static void
1da177e4
LT
2528flush_input(void)
2529{
2530 lineptr = NULL;
2531}
2532
9f1067c2 2533static int
1da177e4
LT
2534inchar(void)
2535{
2536 if (lineptr == NULL || *lineptr == 0) {
fca5dcd4 2537 if (xmon_gets(line, sizeof(line)) == NULL) {
1da177e4
LT
2538 lineptr = NULL;
2539 return EOF;
2540 }
2541 lineptr = line;
2542 }
2543 return *lineptr++;
2544}
2545
9f1067c2 2546static void
1da177e4
LT
2547take_input(char *str)
2548{
2549 lineptr = str;
2550}
2551
2552
2553static void
2554symbol_lookup(void)
2555{
2556 int type = inchar();
2557 unsigned long addr;
2558 static char tmp[64];
2559
2560 switch (type) {
2561 case 'a':
2562 if (scanhex(&addr))
2563 xmon_print_symbol(addr, ": ", "\n");
2564 termch = 0;
2565 break;
2566 case 's':
2567 getstring(tmp, 64);
2568 if (setjmp(bus_error_jmp) == 0) {
2569 catch_memory_errors = 1;
2570 sync();
2571 addr = kallsyms_lookup_name(tmp);
2572 if (addr)
2573 printf("%s: %lx\n", tmp, addr);
2574 else
2575 printf("Symbol '%s' not found.\n", tmp);
2576 sync();
2577 }
2578 catch_memory_errors = 0;
2579 termch = 0;
2580 break;
2581 }
2582}
2583
2584
2585/* Print an address in numeric and symbolic form (if possible) */
2586static void xmon_print_symbol(unsigned long address, const char *mid,
2587 const char *after)
2588{
2589 char *modname;
2590 const char *name = NULL;
2591 unsigned long offset, size;
2592
f78541dc 2593 printf(REG, address);
1da177e4
LT
2594 if (setjmp(bus_error_jmp) == 0) {
2595 catch_memory_errors = 1;
2596 sync();
2597 name = kallsyms_lookup(address, &size, &offset, &modname,
2598 tmpstr);
2599 sync();
2600 /* wait a little while to see if we get a machine check */
2601 __delay(200);
2602 }
2603
2604 catch_memory_errors = 0;
2605
2606 if (name) {
2607 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2608 if (modname)
2609 printf(" [%s]", modname);
2610 }
2611 printf("%s", after);
2612}
2613
2d27cfd3 2614#ifdef CONFIG_PPC_BOOK3S_64
1da177e4
LT
2615static void dump_slb(void)
2616{
2617 int i;
b3b9595f 2618 unsigned long esid,vsid,valid;
2619 unsigned long llp;
1da177e4
LT
2620
2621 printf("SLB contents of cpu %x\n", smp_processor_id());
2622
584f8b71 2623 for (i = 0; i < mmu_slb_size; i++) {
b3b9595f 2624 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2625 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2626 valid = (esid & SLB_ESID_V);
2627 if (valid | esid | vsid) {
2628 printf("%02d %016lx %016lx", i, esid, vsid);
2629 if (valid) {
2630 llp = vsid & SLB_VSID_LLP;
2631 if (vsid & SLB_VSID_B_1T) {
2632 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2633 GET_ESID_1T(esid),
2634 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2635 llp);
2636 } else {
2637 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2638 GET_ESID(esid),
2639 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2640 llp);
2641 }
2642 } else
2643 printf("\n");
2644 }
1da177e4
LT
2645 }
2646}
2647
2648static void dump_stab(void)
2649{
2650 int i;
2651 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2652
2653 printf("Segment table contents of cpu %x\n", smp_processor_id());
2654
2655 for (i = 0; i < PAGE_SIZE/16; i++) {
2656 unsigned long a, b;
2657
2658 a = *tmp++;
2659 b = *tmp++;
2660
2661 if (a || b) {
2662 printf("%03d %016lx ", i, a);
2663 printf("%016lx\n", b);
2664 }
2665 }
2666}
2667
f78541dc
PM
2668void dump_segments(void)
2669{
44ae3ab3 2670 if (mmu_has_feature(MMU_FTR_SLB))
f78541dc
PM
2671 dump_slb();
2672 else
2673 dump_stab();
2674}
2675#endif
2676
2677#ifdef CONFIG_PPC_STD_MMU_32
2678void dump_segments(void)
2679{
2680 int i;
2681
2682 printf("sr0-15 =");
2683 for (i = 0; i < 16; ++i)
2684 printf(" %x", mfsrin(i));
2685 printf("\n");
2686}
2687#endif
2688
5a8a1a28
BH
2689#ifdef CONFIG_44x
2690static void dump_tlb_44x(void)
2691{
2692 int i;
2693
2694 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2695 unsigned long w0,w1,w2;
2696 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2697 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2698 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2699 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2700 if (w0 & PPC44x_TLB_VALID) {
2701 printf("V %08x -> %01x%08x %c%c%c%c%c",
2702 w0 & PPC44x_TLB_EPN_MASK,
2703 w1 & PPC44x_TLB_ERPN_MASK,
2704 w1 & PPC44x_TLB_RPN_MASK,
2705 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2706 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2707 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2708 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2709 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2710 }
2711 printf("\n");
2712 }
2713}
2714#endif /* CONFIG_44x */
9f1067c2 2715
03247157
BH
2716#ifdef CONFIG_PPC_BOOK3E
2717static void dump_tlb_book3e(void)
2718{
2719 u32 mmucfg, pidmask, lpidmask;
2720 u64 ramask;
2721 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2722 int mmu_version;
2723 static const char *pgsz_names[] = {
2724 " 1K",
2725 " 2K",
2726 " 4K",
2727 " 8K",
2728 " 16K",
2729 " 32K",
2730 " 64K",
2731 "128K",
2732 "256K",
2733 "512K",
2734 " 1M",
2735 " 2M",
2736 " 4M",
2737 " 8M",
2738 " 16M",
2739 " 32M",
2740 " 64M",
2741 "128M",
2742 "256M",
2743 "512M",
2744 " 1G",
2745 " 2G",
2746 " 4G",
2747 " 8G",
2748 " 16G",
2749 " 32G",
2750 " 64G",
2751 "128G",
2752 "256G",
2753 "512G",
2754 " 1T",
2755 " 2T",
2756 };
2757
2758 /* Gather some infos about the MMU */
2759 mmucfg = mfspr(SPRN_MMUCFG);
2760 mmu_version = (mmucfg & 3) + 1;
2761 ntlbs = ((mmucfg >> 2) & 3) + 1;
2762 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2763 lpidsz = (mmucfg >> 24) & 0xf;
2764 rasz = (mmucfg >> 16) & 0x7f;
2765 if ((mmu_version > 1) && (mmucfg & 0x10000))
2766 lrat = 1;
2767 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2768 mmu_version, ntlbs, pidsz, lpidsz, rasz);
2769 pidmask = (1ul << pidsz) - 1;
2770 lpidmask = (1ul << lpidsz) - 1;
2771 ramask = (1ull << rasz) - 1;
2772
2773 for (tlb = 0; tlb < ntlbs; tlb++) {
2774 u32 tlbcfg;
2775 int nent, assoc, new_cc = 1;
2776 printf("TLB %d:\n------\n", tlb);
2777 switch(tlb) {
2778 case 0:
2779 tlbcfg = mfspr(SPRN_TLB0CFG);
2780 break;
2781 case 1:
2782 tlbcfg = mfspr(SPRN_TLB1CFG);
2783 break;
2784 case 2:
2785 tlbcfg = mfspr(SPRN_TLB2CFG);
2786 break;
2787 case 3:
2788 tlbcfg = mfspr(SPRN_TLB3CFG);
2789 break;
2790 default:
2791 printf("Unsupported TLB number !\n");
2792 continue;
2793 }
2794 nent = tlbcfg & 0xfff;
2795 assoc = (tlbcfg >> 24) & 0xff;
2796 for (i = 0; i < nent; i++) {
2797 u32 mas0 = MAS0_TLBSEL(tlb);
2798 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2799 u64 mas2 = 0;
2800 u64 mas7_mas3;
2801 int esel = i, cc = i;
2802
2803 if (assoc != 0) {
2804 cc = i / assoc;
2805 esel = i % assoc;
2806 mas2 = cc * 0x1000;
2807 }
2808
2809 mas0 |= MAS0_ESEL(esel);
2810 mtspr(SPRN_MAS0, mas0);
2811 mtspr(SPRN_MAS1, mas1);
2812 mtspr(SPRN_MAS2, mas2);
2813 asm volatile("tlbre 0,0,0" : : : "memory");
2814 mas1 = mfspr(SPRN_MAS1);
2815 mas2 = mfspr(SPRN_MAS2);
2816 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2817 if (assoc && (i % assoc) == 0)
2818 new_cc = 1;
2819 if (!(mas1 & MAS1_VALID))
2820 continue;
2821 if (assoc == 0)
2822 printf("%04x- ", i);
2823 else if (new_cc)
2824 printf("%04x-%c", cc, 'A' + esel);
2825 else
2826 printf(" |%c", 'A' + esel);
2827 new_cc = 0;
2828 printf(" %016llx %04x %s %c%c AS%c",
2829 mas2 & ~0x3ffull,
2830 (mas1 >> 16) & 0x3fff,
2831 pgsz_names[(mas1 >> 7) & 0x1f],
2832 mas1 & MAS1_IND ? 'I' : ' ',
2833 mas1 & MAS1_IPROT ? 'P' : ' ',
2834 mas1 & MAS1_TS ? '1' : '0');
2835 printf(" %c%c%c%c%c%c%c",
2836 mas2 & MAS2_X0 ? 'a' : ' ',
2837 mas2 & MAS2_X1 ? 'v' : ' ',
2838 mas2 & MAS2_W ? 'w' : ' ',
2839 mas2 & MAS2_I ? 'i' : ' ',
2840 mas2 & MAS2_M ? 'm' : ' ',
2841 mas2 & MAS2_G ? 'g' : ' ',
2842 mas2 & MAS2_E ? 'e' : ' ');
2843 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2844 if (mas1 & MAS1_IND)
2845 printf(" %s\n",
2846 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2847 else
2848 printf(" U%c%c%c S%c%c%c\n",
2849 mas7_mas3 & MAS3_UX ? 'x' : ' ',
2850 mas7_mas3 & MAS3_UW ? 'w' : ' ',
2851 mas7_mas3 & MAS3_UR ? 'r' : ' ',
2852 mas7_mas3 & MAS3_SX ? 'x' : ' ',
2853 mas7_mas3 & MAS3_SW ? 'w' : ' ',
2854 mas7_mas3 & MAS3_SR ? 'r' : ' ');
2855 }
2856 }
2857}
2858#endif /* CONFIG_PPC_BOOK3E */
2859
9f1067c2 2860static void xmon_init(int enable)
b13cfd17 2861{
bbb68177
SR
2862#ifdef CONFIG_PPC_ISERIES
2863 if (firmware_has_feature(FW_FEATURE_ISERIES))
2864 return;
2865#endif
b13cfd17
OH
2866 if (enable) {
2867 __debugger = xmon;
2868 __debugger_ipi = xmon_ipi;
2869 __debugger_bpt = xmon_bpt;
2870 __debugger_sstep = xmon_sstep;
2871 __debugger_iabr_match = xmon_iabr_match;
2872 __debugger_dabr_match = xmon_dabr_match;
2873 __debugger_fault_handler = xmon_fault_handler;
2874 } else {
2875 __debugger = NULL;
2876 __debugger_ipi = NULL;
2877 __debugger_bpt = NULL;
2878 __debugger_sstep = NULL;
2879 __debugger_iabr_match = NULL;
2880 __debugger_dabr_match = NULL;
2881 __debugger_fault_handler = NULL;
2882 }
fca5dcd4 2883 xmon_map_scc();
1da177e4 2884}
fca5dcd4
PM
2885
2886#ifdef CONFIG_MAGIC_SYSRQ
1495cc9d 2887static void sysrq_handle_xmon(int key)
fca5dcd4
PM
2888{
2889 /* ensure xmon is enabled */
2890 xmon_init(1);
7d12e780 2891 debugger(get_irq_regs());
fca5dcd4
PM
2892}
2893
1495cc9d 2894static struct sysrq_key_op sysrq_xmon_op = {
fca5dcd4
PM
2895 .handler = sysrq_handle_xmon,
2896 .help_msg = "Xmon",
2897 .action_msg = "Entering xmon",
2898};
2899
2900static int __init setup_xmon_sysrq(void)
2901{
bbb68177
SR
2902#ifdef CONFIG_PPC_ISERIES
2903 if (firmware_has_feature(FW_FEATURE_ISERIES))
2904 return 0;
2905#endif
fca5dcd4
PM
2906 register_sysrq_key('x', &sysrq_xmon_op);
2907 return 0;
2908}
2909__initcall(setup_xmon_sysrq);
2910#endif /* CONFIG_MAGIC_SYSRQ */
47679283 2911
f5e6a280 2912static int __initdata xmon_early, xmon_off;
47679283
ME
2913
2914static int __init early_parse_xmon(char *p)
2915{
2916 if (!p || strncmp(p, "early", 5) == 0) {
2917 /* just "xmon" is equivalent to "xmon=early" */
2918 xmon_init(1);
2919 xmon_early = 1;
2920 } else if (strncmp(p, "on", 2) == 0)
2921 xmon_init(1);
2922 else if (strncmp(p, "off", 3) == 0)
2923 xmon_off = 1;
2924 else if (strncmp(p, "nobt", 4) == 0)
2925 xmon_no_auto_backtrace = 1;
2926 else
2927 return 1;
2928
2929 return 0;
2930}
2931early_param("xmon", early_parse_xmon);
2932
2933void __init xmon_setup(void)
2934{
2935#ifdef CONFIG_XMON_DEFAULT
2936 if (!xmon_off)
2937 xmon_init(1);
2938#endif
2939 if (xmon_early)
2940 debugger(NULL);
2941}
ff8a8f25 2942
e055595d 2943#ifdef CONFIG_SPU_BASE
ff8a8f25
ME
2944
2945struct spu_info {
2946 struct spu *spu;
2947 u64 saved_mfc_sr1_RW;
2948 u32 saved_spu_runcntl_RW;
24a24c85 2949 unsigned long dump_addr;
ff8a8f25
ME
2950 u8 stopped_ok;
2951};
2952
2953#define XMON_NUM_SPUS 16 /* Enough for current hardware */
2954
2955static struct spu_info spu_info[XMON_NUM_SPUS];
2956
2957void xmon_register_spus(struct list_head *list)
2958{
2959 struct spu *spu;
2960
2961 list_for_each_entry(spu, list, full_list) {
2962 if (spu->number >= XMON_NUM_SPUS) {
2963 WARN_ON(1);
2964 continue;
2965 }
2966
2967 spu_info[spu->number].spu = spu;
2968 spu_info[spu->number].stopped_ok = 0;
24a24c85
ME
2969 spu_info[spu->number].dump_addr = (unsigned long)
2970 spu_info[spu->number].spu->local_store;
ff8a8f25
ME
2971 }
2972}
2973
2974static void stop_spus(void)
2975{
2976 struct spu *spu;
2977 int i;
2978 u64 tmp;
2979
2980 for (i = 0; i < XMON_NUM_SPUS; i++) {
2981 if (!spu_info[i].spu)
2982 continue;
2983
2984 if (setjmp(bus_error_jmp) == 0) {
2985 catch_memory_errors = 1;
2986 sync();
2987
2988 spu = spu_info[i].spu;
2989
2990 spu_info[i].saved_spu_runcntl_RW =
2991 in_be32(&spu->problem->spu_runcntl_RW);
2992
2993 tmp = spu_mfc_sr1_get(spu);
2994 spu_info[i].saved_mfc_sr1_RW = tmp;
2995
2996 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2997 spu_mfc_sr1_set(spu, tmp);
2998
2999 sync();
3000 __delay(200);
3001
3002 spu_info[i].stopped_ok = 1;
2a14442b
ME
3003
3004 printf("Stopped spu %.2d (was %s)\n", i,
3005 spu_info[i].saved_spu_runcntl_RW ?
3006 "running" : "stopped");
ff8a8f25
ME
3007 } else {
3008 catch_memory_errors = 0;
3009 printf("*** Error stopping spu %.2d\n", i);
3010 }
3011 catch_memory_errors = 0;
3012 }
3013}
3014
3015static void restart_spus(void)
3016{
3017 struct spu *spu;
3018 int i;
3019
3020 for (i = 0; i < XMON_NUM_SPUS; i++) {
3021 if (!spu_info[i].spu)
3022 continue;
3023
3024 if (!spu_info[i].stopped_ok) {
3025 printf("*** Error, spu %d was not successfully stopped"
3026 ", not restarting\n", i);
3027 continue;
3028 }
3029
3030 if (setjmp(bus_error_jmp) == 0) {
3031 catch_memory_errors = 1;
3032 sync();
3033
3034 spu = spu_info[i].spu;
3035 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3036 out_be32(&spu->problem->spu_runcntl_RW,
3037 spu_info[i].saved_spu_runcntl_RW);
3038
3039 sync();
3040 __delay(200);
3041
3042 printf("Restarted spu %.2d\n", i);
3043 } else {
3044 catch_memory_errors = 0;
3045 printf("*** Error restarting spu %.2d\n", i);
3046 }
3047 catch_memory_errors = 0;
3048 }
3049}
3050
a8984970 3051#define DUMP_WIDTH 23
437a0706 3052#define DUMP_VALUE(format, field, value) \
a8984970
ME
3053do { \
3054 if (setjmp(bus_error_jmp) == 0) { \
3055 catch_memory_errors = 1; \
3056 sync(); \
3057 printf(" %-*s = "format"\n", DUMP_WIDTH, \
437a0706 3058 #field, value); \
a8984970
ME
3059 sync(); \
3060 __delay(200); \
3061 } else { \
3062 catch_memory_errors = 0; \
3063 printf(" %-*s = *** Error reading field.\n", \
3064 DUMP_WIDTH, #field); \
3065 } \
3066 catch_memory_errors = 0; \
3067} while (0)
3068
437a0706
ME
3069#define DUMP_FIELD(obj, format, field) \
3070 DUMP_VALUE(format, field, obj->field)
3071
a8984970
ME
3072static void dump_spu_fields(struct spu *spu)
3073{
3074 printf("Dumping spu fields at address %p:\n", spu);
3075
3076 DUMP_FIELD(spu, "0x%x", number);
3077 DUMP_FIELD(spu, "%s", name);
a8984970
ME
3078 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3079 DUMP_FIELD(spu, "0x%p", local_store);
3080 DUMP_FIELD(spu, "0x%lx", ls_size);
3081 DUMP_FIELD(spu, "0x%x", node);
3082 DUMP_FIELD(spu, "0x%lx", flags);
a8984970 3083 DUMP_FIELD(spu, "%d", class_0_pending);
f3d69e05 3084 DUMP_FIELD(spu, "0x%lx", class_0_dar);
f3d69e05
LB
3085 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3086 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
a8984970
ME
3087 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3088 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3089 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3090 DUMP_FIELD(spu, "0x%x", slb_replace);
3091 DUMP_FIELD(spu, "%d", pid);
a8984970
ME
3092 DUMP_FIELD(spu, "0x%p", mm);
3093 DUMP_FIELD(spu, "0x%p", ctx);
3094 DUMP_FIELD(spu, "0x%p", rq);
3095 DUMP_FIELD(spu, "0x%p", timestamp);
3096 DUMP_FIELD(spu, "0x%lx", problem_phys);
3097 DUMP_FIELD(spu, "0x%p", problem);
437a0706
ME
3098 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3099 in_be32(&spu->problem->spu_runcntl_RW));
3100 DUMP_VALUE("0x%x", problem->spu_status_R,
3101 in_be32(&spu->problem->spu_status_R));
3102 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3103 in_be32(&spu->problem->spu_npc_RW));
a8984970 3104 DUMP_FIELD(spu, "0x%p", priv2);
a985239b 3105 DUMP_FIELD(spu, "0x%p", pdata);
a8984970
ME
3106}
3107
af89fb80
ME
3108int
3109spu_inst_dump(unsigned long adr, long count, int praddr)
3110{
3111 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3112}
3113
3114static void dump_spu_ls(unsigned long num, int subcmd)
24a24c85
ME
3115{
3116 unsigned long offset, addr, ls_addr;
3117
3118 if (setjmp(bus_error_jmp) == 0) {
3119 catch_memory_errors = 1;
3120 sync();
3121 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3122 sync();
3123 __delay(200);
3124 } else {
3125 catch_memory_errors = 0;
3126 printf("*** Error: accessing spu info for spu %d\n", num);
3127 return;
3128 }
3129 catch_memory_errors = 0;
3130
3131 if (scanhex(&offset))
3132 addr = ls_addr + offset;
3133 else
3134 addr = spu_info[num].dump_addr;
3135
3136 if (addr >= ls_addr + LS_SIZE) {
3137 printf("*** Error: address outside of local store\n");
3138 return;
3139 }
3140
af89fb80
ME
3141 switch (subcmd) {
3142 case 'i':
3143 addr += spu_inst_dump(addr, 16, 1);
3144 last_cmd = "sdi\n";
3145 break;
3146 default:
3147 prdump(addr, 64);
3148 addr += 64;
3149 last_cmd = "sd\n";
3150 break;
3151 }
24a24c85
ME
3152
3153 spu_info[num].dump_addr = addr;
3154}
3155
ff8a8f25
ME
3156static int do_spu_cmd(void)
3157{
24a24c85 3158 static unsigned long num = 0;
af89fb80 3159 int cmd, subcmd = 0;
ff8a8f25
ME
3160
3161 cmd = inchar();
3162 switch (cmd) {
3163 case 's':
3164 stop_spus();
3165 break;
3166 case 'r':
3167 restart_spus();
3168 break;
24a24c85 3169 case 'd':
af89fb80
ME
3170 subcmd = inchar();
3171 if (isxdigit(subcmd) || subcmd == '\n')
3172 termch = subcmd;
3173 case 'f':
24a24c85
ME
3174 scanhex(&num);
3175 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
a8984970 3176 printf("*** Error: invalid spu number\n");
24a24c85
ME
3177 return 0;
3178 }
3179
3180 switch (cmd) {
3181 case 'f':
3182 dump_spu_fields(spu_info[num].spu);
3183 break;
3184 default:
af89fb80 3185 dump_spu_ls(num, subcmd);
24a24c85
ME
3186 break;
3187 }
3188
a8984970 3189 break;
ff8a8f25
ME
3190 default:
3191 return -1;
3192 }
3193
3194 return 0;
3195}
e055595d 3196#else /* ! CONFIG_SPU_BASE */
ff8a8f25
ME
3197static int do_spu_cmd(void)
3198{
3199 return -1;
3200}
3201#endif