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