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