From 792576b1c5a4da16700f1003b1c3fc1e22cd9e07 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: MN10300: Introduce a general config option for kernel debugger hooks Introduce a general config option for kernel debugger hooks so that both gdbstub and kgdb can use it and add a header file for both debuggers to use. Signed-off-by: David Howells --- arch/mn10300/include/asm/debugger.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 arch/mn10300/include/asm/debugger.h (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h new file mode 100644 index 000000000000..4816f0dc28b5 --- /dev/null +++ b/arch/mn10300/include/asm/debugger.h @@ -0,0 +1,20 @@ +/* Kernel debugger for MN10300 + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_DEBUGGER_H +#define _ASM_DEBUGGER_H + +#if defined(CONFIG_KERNEL_DEBUGGER) + +#else /* CONFIG_KERNEL_DEBUGGER */ + +#endif /* CONFIG_KERNEL_DEBUGGER */ +#endif /* _ASM_DEBUGGER_H */ -- cgit v1.2.3 From 7f386ac3272e057fbf51e5b5712fad1a80e77125 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: MN10300: Create general kernel debugger cache flushing Create general kernel debugger cache flushing for MN10300 and get rid of the old stuff that gdbstub was using. Signed-off-by: David Howells --- arch/mn10300/include/asm/debugger.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h index 4816f0dc28b5..4517f839a999 100644 --- a/arch/mn10300/include/asm/debugger.h +++ b/arch/mn10300/include/asm/debugger.h @@ -14,6 +14,14 @@ #if defined(CONFIG_KERNEL_DEBUGGER) +#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH +extern void debugger_local_cache_flushinv(void); +extern void debugger_local_cache_flushinv_one(u8 *); +#else +static inline void debugger_local_cache_flushinv(void) {} +static inline void debugger_local_cache_flushinv_one(u8 *addr) {} +#endif + #else /* CONFIG_KERNEL_DEBUGGER */ #endif /* CONFIG_KERNEL_DEBUGGER */ -- cgit v1.2.3 From 67ddb4052daac9d449caf2643ac365d42a04219a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: MN10300: Create generic kernel debugger hooks Create generic kernel debugger hooks in the MN10300 arch and make gdbstub use them. This is a preparation for KGDB support. Signed-off-by: David Howells --- arch/mn10300/include/asm/debugger.h | 15 +++++++++++++++ arch/mn10300/include/asm/fpu.h | 2 -- arch/mn10300/include/asm/irqflags.h | 2 +- arch/mn10300/include/asm/smp.h | 3 ++- 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h index 4517f839a999..e1d3b083696c 100644 --- a/arch/mn10300/include/asm/debugger.h +++ b/arch/mn10300/include/asm/debugger.h @@ -14,6 +14,9 @@ #if defined(CONFIG_KERNEL_DEBUGGER) +extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *); +extern int at_debugger_breakpoint(struct pt_regs *); + #ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH extern void debugger_local_cache_flushinv(void); extern void debugger_local_cache_flushinv_one(u8 *); @@ -24,5 +27,17 @@ static inline void debugger_local_cache_flushinv_one(u8 *addr) {} #else /* CONFIG_KERNEL_DEBUGGER */ +static inline int debugger_intercept(enum exception_code excep, + int signo, int si_code, + struct pt_regs *regs) +{ + return 0; +} + +static inline int at_debugger_breakpoint(struct pt_regs *regs) +{ + return 0; +} + #endif /* CONFIG_KERNEL_DEBUGGER */ #endif /* _ASM_DEBUGGER_H */ diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h index b7625de8eade..738ff72659d5 100644 --- a/arch/mn10300/include/asm/fpu.h +++ b/arch/mn10300/include/asm/fpu.h @@ -55,7 +55,6 @@ static inline void clear_using_fpu(struct task_struct *tsk) extern asmlinkage void fpu_kill_state(struct task_struct *); extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); -extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code); extern asmlinkage void fpu_init_state(void); extern asmlinkage void fpu_save(struct fpu_state_struct *); extern int fpu_setup_sigcontext(struct fpucontext *buf); @@ -113,7 +112,6 @@ static inline void flush_fpu(void) extern asmlinkage void unexpected_fpu_exception(struct pt_regs *, enum exception_code); -#define fpu_invalid_op unexpected_fpu_exception #define fpu_exception unexpected_fpu_exception struct task_struct; diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index 7a7ae12c7119..678f68d5f37b 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h @@ -20,7 +20,7 @@ /* * interrupt control * - "disabled": run in IM1/2 - * - level 0 - GDB stub + * - level 0 - kernel debugger * - level 1 - virtual serial DMA (if present) * - level 5 - normal interrupt priority * - level 6 - timer interrupt diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index a3930e43a958..e3d13a899855 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h @@ -34,7 +34,7 @@ #define LOCAL_TIMER_IPI 193 #define FLUSH_CACHE_IPI 194 #define CALL_FUNCTION_NMI_IPI 195 -#define GDB_NMI_IPI 196 +#define DEBUGGER_NMI_IPI 196 #define SMP_BOOT_IRQ 195 @@ -43,6 +43,7 @@ #define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4 #define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0 #define SMP_BOOT_GxICR_LV GxICR_LEVEL_0 +#define DEBUGGER_GxICR_LV CONFIG_DEBUGGER_IRQ_LEVEL #define TIME_OUT_COUNT_BOOT_IPI 100 #define DELAY_TIME_BOOT_IPI 75000 -- cgit v1.2.3 From e460d64405c04581e42aa9cbae76815a2d4e9abe Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:31 +0000 Subject: MN10300: Use KGDB --- arch/mn10300/include/asm/kgdb.h | 81 +++++++++++++++++++++++++++++++++++++++++ arch/mn10300/include/asm/smp.h | 3 +- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 arch/mn10300/include/asm/kgdb.h (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/kgdb.h b/arch/mn10300/include/asm/kgdb.h new file mode 100644 index 000000000000..eb245f18a708 --- /dev/null +++ b/arch/mn10300/include/asm/kgdb.h @@ -0,0 +1,81 @@ +/* Kernel debugger for MN10300 + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_KGDB_H +#define _ASM_KGDB_H + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound + * buffers at least NUMREGBYTES*2 are needed for register packets + * Longer buffer is needed to list all threads + */ +#define BUFMAX 1024 + +/* + * Note that this register image is in a different order than the register + * image that Linux produces at interrupt time. + */ +enum regnames { + GDB_FR_D0 = 0, + GDB_FR_D1 = 1, + GDB_FR_D2 = 2, + GDB_FR_D3 = 3, + GDB_FR_A0 = 4, + GDB_FR_A1 = 5, + GDB_FR_A2 = 6, + GDB_FR_A3 = 7, + + GDB_FR_SP = 8, + GDB_FR_PC = 9, + GDB_FR_MDR = 10, + GDB_FR_EPSW = 11, + GDB_FR_LIR = 12, + GDB_FR_LAR = 13, + GDB_FR_MDRQ = 14, + + GDB_FR_E0 = 15, + GDB_FR_E1 = 16, + GDB_FR_E2 = 17, + GDB_FR_E3 = 18, + GDB_FR_E4 = 19, + GDB_FR_E5 = 20, + GDB_FR_E6 = 21, + GDB_FR_E7 = 22, + + GDB_FR_SSP = 23, + GDB_FR_MSP = 24, + GDB_FR_USP = 25, + GDB_FR_MCRH = 26, + GDB_FR_MCRL = 27, + GDB_FR_MCVF = 28, + + GDB_FR_FPCR = 29, + GDB_FR_DUMMY0 = 30, + GDB_FR_DUMMY1 = 31, + + GDB_FR_FS0 = 32, + + GDB_FR_SIZE = 64, +}; + +#define GDB_ORIG_D0 41 +#define NUMREGBYTES (GDB_FR_SIZE*4) + +static inline void arch_kgdb_breakpoint(void) +{ + asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break"); +} +extern u8 __arch_kgdb_breakpoint; + +#define BREAK_INSTR_SIZE 1 +#define CACHE_FLUSH_IS_SAFE 1 + +#endif /* _ASM_KGDB_H */ diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index e3d13a899855..6745dbe64944 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h @@ -62,8 +62,9 @@ * An alternate way of dealing with this could be to use the EPSW.S bits to * cache this information for systems with up to four CPUs. */ +#define arch_smp_processor_id() (CPUID) #if 0 -#define raw_smp_processor_id() (CPUID) +#define raw_smp_processor_id() (arch_smp_processor_id()) #else #define raw_smp_processor_id() (current_thread_info()->cpu) #endif -- cgit v1.2.3 From 5141c46c6137f4866eb5f29e25ed0556bcc4c634 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:32 +0000 Subject: MN10300: Emulate single stepping in KGDB on MN10300 Emulate single stepping in KGDB on MN10300 by way of temporary breakpoint insertion. These breakpoints are never actually seen by KGDB, and will overlay KGDB's own breakpoints. The breakpoints are removed by switch_to() and reinstalled on switching back so that if preemption occurs, the preempting task doesn't hit them (though it will still hit KGDB's regular breakpoints). If KGDB is reentered for any reason, then the single step breakpoint is completely erased and must be set again by the debugger. We take advantage of the fact that KGDB will effectively halt all other CPUs whilst this CPU is single-stepping to avoid SMP problems. If the single-stepping task is preempted and killed without KGDB being reinvoked, then the breakpoint(s) will be cleared and KGDB will be jumped back into. Signed-off-by: David Howells --- arch/mn10300/include/asm/thread_info.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h index aa07a4a5d794..c139fa17e2e4 100644 --- a/arch/mn10300/include/asm/thread_info.h +++ b/arch/mn10300/include/asm/thread_info.h @@ -129,7 +129,11 @@ static inline unsigned long current_stack_pointer(void) #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) #endif +#ifndef CONFIG_KGDB #define free_thread_info(ti) kfree((ti)) +#else +extern void free_thread_info(struct thread_info *); +#endif #define get_thread_info(ti) get_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task) -- cgit v1.2.3 From 5a4b65ab506398ba5a35c37e06edddd387cc0add Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 23 Mar 2011 17:42:49 +0000 Subject: MN10300: gcc 4.6 vs am33 inline assembly GCC 4.6 explicitly represents the MDR register. It may be accessed via the "z" constraint. Perhaps more importantly, it tracks when the MDR register is clobbered and uses the RETF instruction if the incoming value is still valid. Thus it is important to (at least) clobber the MDR register in relevant inline assembly fragments, lest RETF be used incorrectly. The only instances I could find are here. There are reads of the MDR register in kernel/gdb-stub.c, but that's harmless. Although, frankly, __builtin_return_address(0) might be a better thing in those cases. Certainly MDR isn't going to contain anything else that might be useful... Signed-off-by: Richard Henderson Signed-off-by: David Howells --- arch/mn10300/include/asm/div64.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'arch/mn10300/include') diff --git a/arch/mn10300/include/asm/div64.h b/arch/mn10300/include/asm/div64.h index 34dcb8e68309..503efab2a516 100644 --- a/arch/mn10300/include/asm/div64.h +++ b/arch/mn10300/include/asm/div64.h @@ -15,6 +15,19 @@ extern void ____unhandled_size_in_do_div___(void); +/* + * Beginning with gcc 4.6, the MDR register is represented explicitly. We + * must, therefore, at least explicitly clobber the register when we make + * changes to it. The following assembly fragments *could* be rearranged in + * order to leave the moves to/from the MDR register to the compiler, but the + * gains would be minimal at best. + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# define CLOBBER_MDR_CC "mdr", "cc" +#else +# define CLOBBER_MDR_CC "cc" +#endif + /* * divide n by base, leaving the result in n and returning the remainder * - we can do this quite efficiently on the MN10300 by cascading the divides @@ -29,7 +42,7 @@ extern void ____unhandled_size_in_do_div___(void); "mov mdr,%1 \n" \ : "+r"(n), "=d"(__rem) \ : "r"(base), "1"(__rem) \ - : "cc" \ + : CLOBBER_MDR_CC \ ); \ } else if (sizeof(n) <= 8) { \ union { \ @@ -48,7 +61,7 @@ extern void ____unhandled_size_in_do_div___(void); : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \ : "r"(base), "0"(__rem), "1"(__quot.w[1]), \ "2"(__quot.w[0]) \ - : "cc" \ + : CLOBBER_MDR_CC \ ); \ n = __quot.l; \ } else { \ @@ -72,7 +85,7 @@ unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div) * MDR = MDR:val%div */ : "=r"(result) : "0"(val), "ir"(mult), "r"(div) - : "cc" + : CLOBBER_MDR_CC ); return result; @@ -93,7 +106,7 @@ signed __muldiv64s(signed val, signed mult, signed div) * MDR = MDR:val%div */ : "=r"(result) : "0"(val), "ir"(mult), "r"(div) - : "cc" + : CLOBBER_MDR_CC ); return result; -- cgit v1.2.3