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

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

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

~ [ 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