diff options
| author | Michal Simek <monstr@monstr.eu> | 2010-08-03 05:45:08 -0400 |
|---|---|---|
| committer | Michal Simek <monstr@monstr.eu> | 2010-08-04 04:45:17 -0400 |
| commit | 2d5973cb5ac5d04662f86e19a06a4c52fa4c4ae3 (patch) | |
| tree | 21ddc58eed5ccad856fc44dfb0ee794da41d5b16 | |
| parent | 751f1605e03533a6279ccf456e938e9595c7d888 (diff) | |
microblaze: Add KGDB support
Kgdb uses brki r16, 0x18 instruction to call
low level _debug_exception function which save
current state to pt_regs and call microblaze_kgdb_break
function. _debug_exception should be called only from
the kernel space. User space calling is not supported
because user application debugging uses different handling.
pt_regs_to_gdb_regs loads additional special registers
which can't be changed
* Enable KGDB in Kconfig
* Remove ancient not-tested KGDB support
* Remove ancient _debug_exception code from entry.S
Only MMU KGDB support is supported.
Signed-off-by: Michal Simek <monstr@monstr.eu>
CC: Jason Wessel <jason.wessel@windriver.com>
CC: John Williams <john.williams@petalogix.com>
CC: Edgar E. Iglesias <edgar.iglesias@petalogix.com>
CC: linux-kernel@vger.kernel.org
Acked-by: Jason Wessel <jason.wessel@windriver.com>
| -rw-r--r-- | arch/microblaze/Kconfig | 1 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/exceptions.h | 16 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/kgdb.h | 28 | ||||
| -rw-r--r-- | arch/microblaze/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/microblaze/kernel/entry.S | 106 | ||||
| -rw-r--r-- | arch/microblaze/kernel/exceptions.c | 1 | ||||
| -rw-r--r-- | arch/microblaze/kernel/kgdb.c | 147 | ||||
| -rw-r--r-- | arch/microblaze/mm/fault.c | 15 |
8 files changed, 234 insertions, 81 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index a51742190c12..be3855250db6 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
| @@ -14,6 +14,7 @@ config MICROBLAZE | |||
| 14 | select USB_ARCH_HAS_EHCI | 14 | select USB_ARCH_HAS_EHCI |
| 15 | select ARCH_WANT_OPTIONAL_GPIOLIB | 15 | select ARCH_WANT_OPTIONAL_GPIOLIB |
| 16 | select HAVE_OPROFILE | 16 | select HAVE_OPROFILE |
| 17 | select HAVE_ARCH_KGDB | ||
| 17 | select HAVE_DMA_ATTRS | 18 | select HAVE_DMA_ATTRS |
| 18 | select HAVE_DMA_API_DEBUG | 19 | select HAVE_DMA_API_DEBUG |
| 19 | select TRACING_SUPPORT | 20 | select TRACING_SUPPORT |
diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h index fa0e36657fdd..6479097b802b 100644 --- a/arch/microblaze/include/asm/exceptions.h +++ b/arch/microblaze/include/asm/exceptions.h | |||
| @@ -69,22 +69,6 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, | |||
| 69 | void die(const char *str, struct pt_regs *fp, long err); | 69 | void die(const char *str, struct pt_regs *fp, long err); |
| 70 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr); | 70 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr); |
| 71 | 71 | ||
| 72 | #if defined(CONFIG_KGDB) | ||
| 73 | void (*debugger)(struct pt_regs *regs); | ||
| 74 | int (*debugger_bpt)(struct pt_regs *regs); | ||
| 75 | int (*debugger_sstep)(struct pt_regs *regs); | ||
| 76 | int (*debugger_iabr_match)(struct pt_regs *regs); | ||
| 77 | int (*debugger_dabr_match)(struct pt_regs *regs); | ||
| 78 | void (*debugger_fault_handler)(struct pt_regs *regs); | ||
| 79 | #else | ||
| 80 | #define debugger(regs) do { } while (0) | ||
| 81 | #define debugger_bpt(regs) 0 | ||
| 82 | #define debugger_sstep(regs) 0 | ||
| 83 | #define debugger_iabr_match(regs) 0 | ||
| 84 | #define debugger_dabr_match(regs) 0 | ||
| 85 | #define debugger_fault_handler ((void (*)(struct pt_regs *))0) | ||
| 86 | #endif | ||
| 87 | |||
| 88 | #endif /*__ASSEMBLY__ */ | 72 | #endif /*__ASSEMBLY__ */ |
| 89 | #endif /* __KERNEL__ */ | 73 | #endif /* __KERNEL__ */ |
| 90 | #endif /* _ASM_MICROBLAZE_EXCEPTIONS_H */ | 74 | #endif /* _ASM_MICROBLAZE_EXCEPTIONS_H */ |
diff --git a/arch/microblaze/include/asm/kgdb.h b/arch/microblaze/include/asm/kgdb.h new file mode 100644 index 000000000000..78b17d40b235 --- /dev/null +++ b/arch/microblaze/include/asm/kgdb.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #ifdef __KERNEL__ | ||
| 2 | #ifndef __MICROBLAZE_KGDB_H__ | ||
| 3 | #define __MICROBLAZE_KGDB_H__ | ||
| 4 | |||
| 5 | #ifndef __ASSEMBLY__ | ||
| 6 | |||
| 7 | #define CACHE_FLUSH_IS_SAFE 1 | ||
| 8 | #define BUFMAX 2048 | ||
| 9 | |||
| 10 | /* | ||
| 11 | * 32 32-bit general purpose registers (r0-r31) | ||
| 12 | * 6 32-bit special registers (pc, msr, ear, esr, fsr, btr) | ||
| 13 | * 12 32-bit PVR | ||
| 14 | * 7 32-bit MMU Regs (redr, rpid, rzpr, rtlbx, rtlbsx, rtlblo, rtlbhi) | ||
| 15 | * ------ | ||
| 16 | * 57 registers | ||
| 17 | */ | ||
| 18 | #define NUMREGBYTES (57 * 4) | ||
| 19 | |||
| 20 | #define BREAK_INSTR_SIZE 4 | ||
| 21 | static inline void arch_kgdb_breakpoint(void) | ||
| 22 | { | ||
| 23 | __asm__ __volatile__("brki r16, 0x18;"); | ||
| 24 | } | ||
| 25 | |||
| 26 | #endif /* __ASSEMBLY__ */ | ||
| 27 | #endif /* __MICROBLAZE_KGDB_H__ */ | ||
| 28 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d66ddef53c07..5eecc9f1fbd9 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile | |||
| @@ -28,5 +28,6 @@ obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o | |||
| 28 | obj-$(CONFIG_MMU) += misc.o | 28 | obj-$(CONFIG_MMU) += misc.o |
| 29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
| 30 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o | 30 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o |
| 31 | obj-$(CONFIG_KGDB) += kgdb.o | ||
| 31 | 32 | ||
| 32 | obj-y += entry$(MMU).o | 33 | obj-y += entry$(MMU).o |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 5a5cb5842938..304882e56459 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
| @@ -745,11 +745,8 @@ IRQ_return: /* MS: Make global symbol for debugging */ | |||
| 745 | nop | 745 | nop |
| 746 | 746 | ||
| 747 | /* | 747 | /* |
| 748 | * `Debug' trap | 748 | * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18 |
| 749 | * We enter dbtrap in "BIP" (breakpoint) mode. | 749 | * and call handling function with saved pt_regs |
| 750 | * So we exit the breakpoint mode with an 'rtbd' and proceed with the | ||
| 751 | * original dbtrap. | ||
| 752 | * however, wait to save state first | ||
| 753 | */ | 750 | */ |
| 754 | C_ENTRY(_debug_exception): | 751 | C_ENTRY(_debug_exception): |
| 755 | /* BIP bit is set on entry, no interrupts can occur */ | 752 | /* BIP bit is set on entry, no interrupts can occur */ |
| @@ -759,18 +756,44 @@ C_ENTRY(_debug_exception): | |||
| 759 | nop | 756 | nop |
| 760 | andi r1, r1, MSR_UMS | 757 | andi r1, r1, MSR_UMS |
| 761 | bnei r1, 1f | 758 | bnei r1, 1f |
| 762 | /* Kernel-mode state save. */ | 759 | /* MS: Kernel-mode state save - kgdb */ |
| 763 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ | 760 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ |
| 764 | tophys(r1,r1); | ||
| 765 | 761 | ||
| 766 | addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ | 762 | /* BIP bit is set on entry, no interrupts can occur */ |
| 763 | addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; | ||
| 767 | SAVE_REGS; | 764 | SAVE_REGS; |
| 765 | /* save all regs to pt_reg structure */ | ||
| 766 | swi r0, r1, PTO+PT_R0; /* R0 must be saved too */ | ||
| 767 | swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */ | ||
| 768 | swi r16, r1, PTO+PT_R16 | ||
| 769 | swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */ | ||
| 770 | swi r17, r1, PTO+PT_R17 | ||
| 771 | /* save special purpose registers to pt_regs */ | ||
| 772 | mfs r11, rear; | ||
| 773 | swi r11, r1, PTO+PT_EAR; | ||
| 774 | mfs r11, resr; | ||
| 775 | swi r11, r1, PTO+PT_ESR; | ||
| 776 | mfs r11, rfsr; | ||
| 777 | swi r11, r1, PTO+PT_FSR; | ||
| 778 | |||
| 779 | /* stack pointer is in physical address at it is decrease | ||
| 780 | * by STATE_SAVE_SIZE but we need to get correct R1 value */ | ||
| 781 | addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE; | ||
| 782 | swi r11, r1, PTO+PT_R1 | ||
| 783 | /* MS: r31 - current pointer isn't changed */ | ||
| 784 | tovirt(r1,r1) | ||
| 785 | #ifdef CONFIG_KGDB | ||
| 786 | addi r5, r1, PTO /* pass pt_reg address as the first arg */ | ||
| 787 | la r15, r0, dbtrap_call; /* return address */ | ||
| 788 | rtbd r0, microblaze_kgdb_break | ||
| 789 | nop; | ||
| 790 | #endif | ||
| 791 | /* MS: Place handler for brki from kernel space if KGDB is OFF. | ||
| 792 | * It is very unlikely that another brki instruction is called. */ | ||
| 793 | bri 0 | ||
| 768 | 794 | ||
| 769 | swi r1, r1, PTO + PT_MODE; | 795 | /* MS: User-mode state save - gdb */ |
| 770 | brid 2f; | 796 | 1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ |
| 771 | nop; /* Fill delay slot */ | ||
| 772 | 1: /* User-mode state save. */ | ||
| 773 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ | ||
| 774 | tophys(r1,r1); | 797 | tophys(r1,r1); |
| 775 | lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ | 798 | lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ |
| 776 | addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ | 799 | addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ |
| @@ -781,36 +804,32 @@ C_ENTRY(_debug_exception): | |||
| 781 | swi r17, r1, PTO+PT_R17; | 804 | swi r17, r1, PTO+PT_R17; |
| 782 | swi r16, r1, PTO+PT_R16; | 805 | swi r16, r1, PTO+PT_R16; |
| 783 | swi r16, r1, PTO+PT_PC; /* Save LP */ | 806 | swi r16, r1, PTO+PT_PC; /* Save LP */ |
| 784 | |||
| 785 | swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ | 807 | swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ |
| 786 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); | 808 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); |
| 787 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ | 809 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ |
| 788 | 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); | 810 | lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); |
| 789 | tovirt(r1,r1) | 811 | tovirt(r1,r1) |
| 790 | |||
| 791 | set_vms; | 812 | set_vms; |
| 792 | addik r5, r1, PTO; | 813 | addik r5, r1, PTO; |
| 793 | addik r15, r0, dbtrap_call; | 814 | addik r15, r0, dbtrap_call; |
| 794 | dbtrap_call: /* < | ||
