diff options
Diffstat (limited to 'arch/powerpc/xmon/xmon.c')
| -rw-r--r-- | arch/powerpc/xmon/xmon.c | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1124f1146202..ef4356b29a97 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Routines providing a simple monitor for use on the PowerMac. | 2 | * Routines providing a simple monitor for use on the PowerMac. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1996 Paul Mackerras. | 4 | * Copyright (C) 1996-2005 Paul Mackerras. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/kallsyms.h> | 18 | #include <linux/kallsyms.h> |
| 19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/sysrq.h> | ||
| 21 | 22 | ||
| 22 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
| 23 | #include <asm/string.h> | 24 | #include <asm/string.h> |
| @@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
| 144 | static const char *getvecname(unsigned long vec); | 145 | static const char *getvecname(unsigned long vec); |
| 145 | 146 | ||
| 146 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 147 | extern int print_insn_powerpc(unsigned long, unsigned long, int); |
| 147 | extern void printf(const char *fmt, ...); | ||
| 148 | extern void xmon_vfprintf(void *f, const char *fmt, va_list ap); | ||
| 149 | extern int xmon_putc(int c, void *f); | ||
| 150 | extern int putchar(int ch); | ||
| 151 | 148 | ||
| 152 | extern void xmon_enter(void); | 149 | extern void xmon_enter(void); |
| 153 | extern void xmon_leave(void); | 150 | extern void xmon_leave(void); |
| 154 | 151 | ||
| 155 | extern int xmon_read_poll(void); | ||
| 156 | extern long setjmp(long *); | 152 | extern long setjmp(long *); |
| 157 | extern void longjmp(long *, long); | 153 | extern void longjmp(long *, long); |
| 158 | extern void xmon_save_regs(struct pt_regs *); | 154 | extern void xmon_save_regs(struct pt_regs *); |
| @@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) | |||
| 748 | printf("%x:", smp_processor_id()); | 744 | printf("%x:", smp_processor_id()); |
| 749 | #endif /* CONFIG_SMP */ | 745 | #endif /* CONFIG_SMP */ |
| 750 | printf("mon> "); | 746 | printf("mon> "); |
| 751 | fflush(stdout); | ||
| 752 | flush_input(); | 747 | flush_input(); |
| 753 | termch = 0; | 748 | termch = 0; |
| 754 | cmd = skipbl(); | 749 | cmd = skipbl(); |
| @@ -1472,17 +1467,23 @@ read_spr(int n) | |||
| 1472 | { | 1467 | { |
| 1473 | unsigned int instrs[2]; | 1468 | unsigned int instrs[2]; |
| 1474 | unsigned long (*code)(void); | 1469 | unsigned long (*code)(void); |
| 1475 | unsigned long opd[3]; | ||
| 1476 | unsigned long ret = -1UL; | 1470 | unsigned long ret = -1UL; |
| 1471 | #ifdef CONFIG_PPC64 | ||
| 1472 | unsigned long opd[3]; | ||
| 1477 | 1473 | ||
| 1478 | instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); | ||
| 1479 | instrs[1] = 0x4e800020; | ||
| 1480 | opd[0] = (unsigned long)instrs; | 1474 | opd[0] = (unsigned long)instrs; |
| 1481 | opd[1] = 0; | 1475 | opd[1] = 0; |
| 1482 | opd[2] = 0; | 1476 | opd[2] = 0; |
| 1477 | code = (unsigned long (*)(void)) opd; | ||
| 1478 | #else | ||
| 1479 | code = (unsigned long (*)(void)) instrs; | ||
| 1480 | #endif | ||
| 1481 | |||
| 1482 | /* mfspr r3,n; blr */ | ||
| 1483 | instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); | ||
| 1484 | instrs[1] = 0x4e800020; | ||
| 1483 | store_inst(instrs); | 1485 | store_inst(instrs); |
| 1484 | store_inst(instrs+1); | 1486 | store_inst(instrs+1); |
| 1485 | code = (unsigned long (*)(void)) opd; | ||
| 1486 | 1487 | ||
| 1487 | if (setjmp(bus_error_jmp) == 0) { | 1488 | if (setjmp(bus_error_jmp) == 0) { |
| 1488 | catch_memory_errors = 1; | 1489 | catch_memory_errors = 1; |
| @@ -1504,16 +1505,21 @@ write_spr(int n, unsigned long val) | |||
| 1504 | { | 1505 | { |
| 1505 | unsigned int instrs[2]; | 1506 | unsigned int instrs[2]; |
| 1506 | unsigned long (*code)(unsigned long); | 1507 | unsigned long (*code)(unsigned long); |
| 1508 | #ifdef CONFIG_PPC64 | ||
| 1507 | unsigned long opd[3]; | 1509 | unsigned long opd[3]; |
| 1508 | 1510 | ||
| 1509 | instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); | ||
| 1510 | instrs[1] = 0x4e800020; | ||
| 1511 | opd[0] = (unsigned long)instrs; | 1511 | opd[0] = (unsigned long)instrs; |
| 1512 | opd[1] = 0; | 1512 | opd[1] = 0; |
| 1513 | opd[2] = 0; | 1513 | opd[2] = 0; |
| 1514 | code = (unsigned long (*)(unsigned long)) opd; | ||
| 1515 | #else | ||
| 1516 | code = (unsigned long (*)(unsigned long)) instrs; | ||
| 1517 | #endif | ||
| 1518 | |||
| 1519 | instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); | ||
| 1520 | instrs[1] = 0x4e800020; | ||
| 1514 | store_inst(instrs); | 1521 | store_inst(instrs); |
| 1515 | store_inst(instrs+1); | 1522 | store_inst(instrs+1); |
| 1516 | code = (unsigned long (*)(unsigned long)) opd; | ||
| 1517 | 1523 | ||
| 1518 | if (setjmp(bus_error_jmp) == 0) { | 1524 | if (setjmp(bus_error_jmp) == 0) { |
| 1519 | catch_memory_errors = 1; | 1525 | catch_memory_errors = 1; |
| @@ -1797,7 +1803,7 @@ memex(void) | |||
| 1797 | for(;;){ | 1803 | for(;;){ |
| 1798 | if (!mnoread) | 1804 | if (!mnoread) |
| 1799 | n = mread(adrs, val, size); | 1805 | n = mread(adrs, val, size); |
| 1800 | printf("%.16x%c", adrs, brev? 'r': ' '); | 1806 | printf(REG"%c", adrs, brev? 'r': ' '); |
| 1801 | if (!mnoread) { | 1807 | if (!mnoread) { |
| 1802 | if (brev) | 1808 | if (brev) |
| 1803 | byterev(val, size); | 1809 | byterev(val, size); |
| @@ -1976,17 +1982,18 @@ prdump(unsigned long adrs, long ndump) | |||
| 1976 | nr = mread(adrs, temp, r); | 1982 | nr = mread(adrs, temp, r); |
| 1977 | adrs += nr; | 1983 | adrs += nr; |
| 1978 | for (m = 0; m < r; ++m) { | 1984 | for (m = 0; m < r; ++m) { |
| 1979 | if ((m & 7) == 0 && m > 0) | 1985 | if ((m & (sizeof(long) - 1)) == 0 && m > 0) |
| 1980 | putchar(' '); | 1986 | putchar(' '); |
| 1981 | if (m < nr) | 1987 | if (m < nr) |
| 1982 | printf("%.2x", temp[m]); | 1988 | printf("%.2x", temp[m]); |
| 1983 | else | 1989 | else |
| 1984 | printf("%s", fault_chars[fault_type]); | 1990 | printf("%s", fault_chars[fault_type]); |
| 1985 | } | 1991 | } |
| 1986 | if (m <= 8) | 1992 | for (; m < 16; ++m) { |
| 1987 | printf(" "); | 1993 | if ((m & (sizeof(long) - 1)) == 0) |
| 1988 | for (; m < 16; ++m) | 1994 | putchar(' '); |
| 1989 | printf(" "); | 1995 | printf(" "); |
| 1996 | } | ||
| 1990 | printf(" |"); | 1997 | printf(" |"); |
| 1991 | for (m = 0; m < r; ++m) { | 1998 | for (m = 0; m < r; ++m) { |
| 1992 | if (m < nr) { | 1999 | if (m < nr) { |
| @@ -2151,7 +2158,6 @@ memzcan(void) | |||
| 2151 | ok = mread(a, &v, 1); | 2158 | ok = mread(a, &v, 1); |
| 2152 | if (ok && !ook) { | 2159 | if (ok && !ook) { |
| 2153 | printf("%.8x .. ", a); | 2160 | printf("%.8x .. ", a); |
| 2154 | fflush(stdout); | ||
| 2155 | } else if (!ok && ook) | 2161 | } else if (!ok && ook) |
| 2156 | printf("%.8x\n", a - mskip); | 2162 | printf("%.8x\n", a - mskip); |
| 2157 | ook = ok; | 2163 | ook = ok; |
| @@ -2372,7 +2378,7 @@ int | |||
| 2372 | inchar(void) | 2378 | inchar(void) |
| 2373 | { | 2379 | { |
| 2374 | if (lineptr == NULL || *lineptr == 0) { | 2380 | if (lineptr == NULL || *lineptr == 0) { |
| 2375 | if (fgets(line, sizeof(line), stdin) == NULL) { | 2381 | if (xmon_gets(line, sizeof(line)) == NULL) { |
| 2376 | lineptr = NULL; | 2382 | lineptr = NULL; |
| 2377 | return EOF; | 2383 | return EOF; |
| 2378 | } | 2384 | } |
| @@ -2526,4 +2532,29 @@ void xmon_init(int enable) | |||
| 2526 | __debugger_dabr_match = NULL; | 2532 | __debugger_dabr_match = NULL; |
| 2527 | __debugger_fault_handler = NULL; | 2533 | __debugger_fault_handler = NULL; |
| 2528 | } | 2534 | } |
| 2535 | xmon_map_scc(); | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 2539 | static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, | ||
| 2540 | struct tty_struct *tty) | ||
| 2541 | { | ||
| 2542 | /* ensure xmon is enabled */ | ||
| 2543 | xmon_init(1); | ||
| 2544 | debugger(pt_regs); | ||
| 2545 | } | ||
| 2546 | |||
| 2547 | static struct sysrq_key_op sysrq_xmon_op = | ||
| 2548 | { | ||
| 2549 | .handler = sysrq_handle_xmon, | ||
| 2550 | .help_msg = "Xmon", | ||
| 2551 | .action_msg = "Entering xmon", | ||
| 2552 | }; | ||
| 2553 | |||
| 2554 | static int __init setup_xmon_sysrq(void) | ||
| 2555 | { | ||
| 2556 | register_sysrq_key('x', &sysrq_xmon_op); | ||
| 2557 | return 0; | ||
| 2529 | } | 2558 | } |
| 2559 | __initcall(setup_xmon_sysrq); | ||
| 2560 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
