aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-08-03 05:45:08 -0400
committerMichal Simek <monstr@monstr.eu>2010-08-04 04:45:17 -0400
commit2d5973cb5ac5d04662f86e19a06a4c52fa4c4ae3 (patch)
tree21ddc58eed5ccad856fc44dfb0ee794da41d5b16
parent751f1605e03533a6279ccf456e938e9595c7d888 (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/Kconfig1
-rw-r--r--arch/microblaze/include/asm/exceptions.h16
-rw-r--r--arch/microblaze/include/asm/kgdb.h28
-rw-r--r--arch/microblaze/kernel/Makefile1
-rw-r--r--arch/microblaze/kernel/entry.S106
-rw-r--r--arch/microblaze/kernel/exceptions.c1
-rw-r--r--arch/microblaze/kernel/kgdb.c147
-rw-r--r--arch/microblaze/mm/fault.c15
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,
69void die(const char *str, struct pt_regs *fp, long err); 69void die(const char *str, struct pt_regs *fp, long err);
70void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr); 70void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
71 71
72#if defined(CONFIG_KGDB)
73void (*debugger)(struct pt_regs *regs);
74int (*debugger_bpt)(struct pt_regs *regs);
75int (*debugger_sstep)(struct pt_regs *regs);
76int (*debugger_iabr_match)(struct pt_regs *regs);
77int (*debugger_dabr_match)(struct pt_regs *regs);
78void (*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
21static 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
28obj-$(CONFIG_MMU) += misc.o 28obj-$(CONFIG_MMU) += misc.o
29obj-$(CONFIG_STACKTRACE) += stacktrace.o 29obj-$(CONFIG_STACKTRACE) += stacktrace.o
30obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o 30obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o
31obj-$(CONFIG_KGDB) += kgdb.o
31 32
32obj-y += entry$(MMU).o 33obj-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 */
754C_ENTRY(_debug_exception): 751C_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; 7961: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
771 nop; /* Fill delay slot */
7721: /* 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. */
7882: 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;
794dbtrap_call: /* <