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