~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/xmon/xmon.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp