aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mn10300/Kconfig10
-rw-r--r--arch/mn10300/Kconfig.debug17
-rw-r--r--arch/mn10300/include/asm/debugger.h43
-rw-r--r--arch/mn10300/include/asm/div64.h21
-rw-r--r--arch/mn10300/include/asm/fpu.h2
-rw-r--r--arch/mn10300/include/asm/irqflags.h2
-rw-r--r--arch/mn10300/include/asm/kgdb.h81
-rw-r--r--arch/mn10300/include/asm/smp.h6
-rw-r--r--arch/mn10300/include/asm/thread_info.h4
-rw-r--r--arch/mn10300/kernel/Makefile5
-rw-r--r--arch/mn10300/kernel/entry.S67
-rw-r--r--arch/mn10300/kernel/fpu.c18
-rw-r--r--arch/mn10300/kernel/gdb-cache.S105
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c8
-rw-r--r--arch/mn10300/kernel/gdb-stub.c41
-rw-r--r--arch/mn10300/kernel/internal.h7
-rw-r--r--arch/mn10300/kernel/irq.c2
-rw-r--r--arch/mn10300/kernel/kgdb.c502
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c75
-rw-r--r--arch/mn10300/kernel/process.c6
-rw-r--r--arch/mn10300/kernel/smp.c26
-rw-r--r--arch/mn10300/kernel/switch_to.S111
-rw-r--r--arch/mn10300/kernel/traps.c406
-rw-r--r--arch/mn10300/mm/Kconfig.cache46
-rw-r--r--arch/mn10300/mm/Makefile9
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-reg.S160
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-tag.S114
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-reg.S69
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-tag.S120
-rw-r--r--arch/mn10300/mm/cache-dbg-inv.S47
-rw-r--r--arch/mn10300/mm/cache-flush-by-tag.S13
-rw-r--r--arch/mn10300/mm/cache-inv-by-reg.S22
-rw-r--r--arch/mn10300/mm/cache-inv-by-tag.S86
-rw-r--r--arch/mn10300/mm/cache.inc133
-rw-r--r--arch/mn10300/mm/fault.c9
-rw-r--r--arch/mn10300/proc-mn103e010/include/proc/cache.h1
-rw-r--r--arch/mn10300/proc-mn2ws0050/include/proc/cache.h1
-rw-r--r--include/linux/kgdb.h1
-rw-r--r--kernel/debug/gdbstub.c30
39 files changed, 1924 insertions, 502 deletions
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 10971be43061..d8ab97a73db2 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -3,6 +3,8 @@ config MN10300
3 select HAVE_OPROFILE 3 select HAVE_OPROFILE
4 select HAVE_GENERIC_HARDIRQS 4 select HAVE_GENERIC_HARDIRQS
5 select GENERIC_HARDIRQS_NO_DEPRECATED 5 select GENERIC_HARDIRQS_NO_DEPRECATED
6 select HAVE_ARCH_TRACEHOOK
7 select HAVE_ARCH_KGDB
6 8
7config AM33_2 9config AM33_2
8 def_bool n 10 def_bool n
@@ -401,9 +403,9 @@ comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highes
401comment "____Non-maskable interrupt levels____" 403comment "____Non-maskable interrupt levels____"
402comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial" 404comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
403 405
404config GDBSTUB_IRQ_LEVEL 406config DEBUGGER_IRQ_LEVEL
405 int "GDBSTUB interrupt priority" 407 int "DEBUGGER interrupt priority"
406 depends on GDBSTUB 408 depends on KERNEL_DEBUGGER
407 range 0 1 if LINUX_CLI_LEVEL = 2 409 range 0 1 if LINUX_CLI_LEVEL = 2
408 range 0 2 if LINUX_CLI_LEVEL = 3 410 range 0 2 if LINUX_CLI_LEVEL = 3
409 range 0 3 if LINUX_CLI_LEVEL = 4 411 range 0 3 if LINUX_CLI_LEVEL = 4
@@ -437,7 +439,7 @@ config LINUX_CLI_LEVEL
437 EPSW.IM from 7. Any interrupt is permitted for which the level is 439 EPSW.IM from 7. Any interrupt is permitted for which the level is
438 lower than EPSW.IM. 440 lower than EPSW.IM.
439 441
440 Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip 442 Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip
441 serial DMA interrupts are allowed to interrupt normal disabled 443 serial DMA interrupts are allowed to interrupt normal disabled
442 sections. 444 sections.
443 445
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug
index ce83c74b3fd7..bdbfd444a9ff 100644
--- a/arch/mn10300/Kconfig.debug
+++ b/arch/mn10300/Kconfig.debug
@@ -36,7 +36,7 @@ config KPROBES
36 36
37config GDBSTUB 37config GDBSTUB
38 bool "Remote GDB kernel debugging" 38 bool "Remote GDB kernel debugging"
39 depends on DEBUG_KERNEL 39 depends on DEBUG_KERNEL && DEPRECATED
40 select DEBUG_INFO 40 select DEBUG_INFO
41 select FRAME_POINTER 41 select FRAME_POINTER
42 help 42 help
@@ -46,6 +46,9 @@ config GDBSTUB
46 RAM to avoid excessive linking time. This is only useful for kernel 46 RAM to avoid excessive linking time. This is only useful for kernel
47 hackers. If unsure, say N. 47 hackers. If unsure, say N.
48 48
49 This is deprecated in favour of KGDB and will be removed in a later
50 version.
51
49config GDBSTUB_IMMEDIATE 52config GDBSTUB_IMMEDIATE
50 bool "Break into GDB stub immediately" 53 bool "Break into GDB stub immediately"
51 depends on GDBSTUB 54 depends on GDBSTUB
@@ -54,6 +57,14 @@ config GDBSTUB_IMMEDIATE
54 possible, leaving the program counter at the beginning of 57 possible, leaving the program counter at the beginning of
55 start_kernel() in init/main.c. 58 start_kernel() in init/main.c.
56 59
60config GDBSTUB_ALLOW_SINGLE_STEP
61 bool "Allow software single-stepping in GDB stub"
62 depends on GDBSTUB && !SMP && !PREEMPT
63 help
64 Allow GDB stub to perform software single-stepping through the
65 kernel. This doesn't work very well on SMP or preemptible kernels as
66 it uses temporary breakpoints to emulate single-stepping.
67
57config GDB_CONSOLE 68config GDB_CONSOLE
58 bool "Console output to GDB" 69 bool "Console output to GDB"
59 depends on GDBSTUB 70 depends on GDBSTUB
@@ -142,3 +153,7 @@ config GDBSTUB_ON_TTYSx
142 default y 153 default y
143 154
144endmenu 155endmenu
156
157config KERNEL_DEBUGGER
158 def_bool y
159 depends on GDBSTUB || KGDB
diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h
new file mode 100644
index 000000000000..e1d3b083696c
--- /dev/null
+++ b/arch/mn10300/include/asm/debugger.h
@@ -0,0 +1,43 @@
1/* Kernel debugger for MN10300
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#ifndef _ASM_DEBUGGER_H
13#define _ASM_DEBUGGER_H
14
15#if defined(CONFIG_KERNEL_DEBUGGER)
16
17extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *);
18extern int at_debugger_breakpoint(struct pt_regs *);
19
20#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH
21extern void debugger_local_cache_flushinv(void);
22extern void debugger_local_cache_flushinv_one(u8 *);
23#else
24static inline void debugger_local_cache_flushinv(void) {}
25static inline void debugger_local_cache_flushinv_one(u8 *addr) {}
26#endif
27
28#else /* CONFIG_KERNEL_DEBUGGER */
29
30static inline int debugger_intercept(enum exception_code excep,
31 int signo, int si_code,
32 struct pt_regs *regs)
33{
34 return 0;
35}
36
37static inline int at_debugger_breakpoint(struct pt_regs *regs)
38{
39 return 0;
40}
41
42#endif /* CONFIG_KERNEL_DEBUGGER */
43#endif /* _ASM_DEBUGGER_H */
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
@@ -16,6 +16,19 @@
16extern void ____unhandled_size_in_do_div___(void); 16extern void ____unhandled_size_in_do_div___(void);
17 17
18/* 18/*
19 * Beginning with gcc 4.6, the MDR register is represented explicitly. We
20 * must, therefore, at least explicitly clobber the register when we make
21 * changes to it. The following assembly fragments *could* be rearranged in
22 * order to leave the moves to/from the MDR register to the compiler, but the
23 * gains would be minimal at best.
24 */
25#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
26# define CLOBBER_MDR_CC "mdr", "cc"
27#else
28# define CLOBBER_MDR_CC "cc"
29#endif
30
31/*
19 * divide n by base, leaving the result in n and returning the remainder 32 * divide n by base, leaving the result in n and returning the remainder
20 * - we can do this quite efficiently on the MN10300 by cascading the divides 33 * - we can do this quite efficiently on the MN10300 by cascading the divides
21 * through the MDR register 34 * through the MDR register
@@ -29,7 +42,7 @@ extern void ____unhandled_size_in_do_div___(void);
29 "mov mdr,%1 \n" \ 42 "mov mdr,%1 \n" \
30 : "+r"(n), "=d"(__rem) \ 43 : "+r"(n), "=d"(__rem) \
31 : "r"(base), "1"(__rem) \ 44 : "r"(base), "1"(__rem) \
32 : "cc" \ 45 : CLOBBER_MDR_CC \
33 ); \ 46 ); \
34 } else if (sizeof(n) <= 8) { \ 47 } else if (sizeof(n) <= 8) { \
35 union { \ 48 union { \
@@ -48,7 +61,7 @@ extern void ____unhandled_size_in_do_div___(void);
48 : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \ 61 : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \
49 : "r"(base), "0"(__rem), "1"(__quot.w[1]), \ 62 : "r"(base), "0"(__rem), "1"(__quot.w[1]), \
50 "2"(__quot.w[0]) \ 63 "2"(__quot.w[0]) \
51 : "cc" \ 64 : CLOBBER_MDR_CC \
52 ); \ 65 ); \
53 n = __quot.l; \ 66 n = __quot.l; \
54 } else { \ 67 } else { \
@@ -72,7 +85,7 @@ unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
72 * MDR = MDR:val%div */ 85 * MDR = MDR:val%div */
73 : "=r"(result) 86 : "=r"(result)
74 : "0"(val), "ir"(mult), "r"(div) 87 : "0"(val), "ir"(mult), "r"(div)
75 : "cc" 88 : CLOBBER_MDR_CC
76 ); 89 );
77 90
78 return result; 91 return result;
@@ -93,7 +106,7 @@ signed __muldiv64s(signed val, signed mult, signed div)
93 * MDR = MDR:val%div */ 106 * MDR = MDR:val%div */
94 : "=r"(result) 107 : "=r"(result)
95 : "0"(val), "ir"(mult), "r"(div) 108 : "0"(val), "ir"(mult), "r"(div)
96 : "cc" 109 : CLOBBER_MDR_CC
97 ); 110 );
98 111
99 return result; 112 return result;
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)
55 55
56extern asmlinkage void fpu_kill_state(struct task_struct *); 56extern asmlinkage void fpu_kill_state(struct task_struct *);
57extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); 57extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
58extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
59extern asmlinkage void fpu_init_state(void); 58extern asmlinkage void fpu_init_state(void);
60extern asmlinkage void fpu_save(struct fpu_state_struct *); 59extern asmlinkage void fpu_save(struct fpu_state_struct *);
61extern int fpu_setup_sigcontext(struct fpucontext *buf); 60extern int fpu_setup_sigcontext(struct fpucontext *buf);
@@ -113,7 +112,6 @@ static inline void flush_fpu(void)
113 112
114extern asmlinkage 113extern asmlinkage
115void unexpected_fpu_exception(struct pt_regs *, enum exception_code); 114void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
116#define fpu_invalid_op unexpected_fpu_exception
117#define fpu_exception unexpected_fpu_exception 115#define fpu_exception unexpected_fpu_exception
118 116
119struct task_struct; 117struct 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 @@
20/* 20/*
21 * interrupt control 21 * interrupt control
22 * - "disabled": run in IM1/2 22 * - "disabled": run in IM1/2
23 * - level 0 - GDB stub 23 * - level 0 - kernel debugger
24 * - level 1 - virtual serial DMA (if present) 24 * - level 1 - virtual serial DMA (if present)
25 * - level 5 - normal interrupt priority 25 * - level 5 - normal interrupt priority
26 * - level 6 - timer interrupt 26 * - level 6 - timer interrupt
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 @@
1/* Kernel debugger for MN10300
2 *
3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#ifndef _ASM_KGDB_H
13#define _ASM_KGDB_H
14
15/*
16 * BUFMAX defines the maximum number of characters in inbound/outbound
17 * buffers at least NUMREGBYTES*2 are needed for register packets
18 * Longer buffer is needed to list all threads
19 */
20#define BUFMAX 1024
21
22/*
23 * Note that this register image is in a different order than the register
24 * image that Linux produces at interrupt time.
25 */
26enum regnames {
27 GDB_FR_D0 = 0,
28 GDB_FR_D1 = 1,
29 GDB_FR_D2 = 2,
30 GDB_FR_D3 = 3,
31 GDB_FR_A0 = 4,
32 GDB_FR_A1 = 5,
33 GDB_FR_A2 = 6,
34 GDB_FR_A3 = 7,
35
36 GDB_FR_SP = 8,
37 GDB_FR_PC = 9,
38 GDB_FR_MDR = 10,
39 GDB_FR_EPSW = 11,
40 GDB_FR_LIR = 12,
41 GDB_FR_LAR = 13,
42 GDB_FR_MDRQ = 14,
43
44 GDB_FR_E0 = 15,
45 GDB_FR_E1 = 16,
46 GDB_FR_E2 = 17,
47 GDB_FR_E3 = 18,
48 GDB_FR_E4 = 19,
49 GDB_FR_E5 = 20,
50 GDB_FR_E6 = 21,
51 GDB_FR_E7 = 22,
52
53 GDB_FR_SSP = 23,
54 GDB_FR_MSP = 24,
55 GDB_FR_USP = 25,
56 GDB_FR_MCRH = 26,
57 GDB_FR_MCRL = 27,
58 GDB_FR_MCVF = 28,
59
60 GDB_FR_FPCR = 29,
61 GDB_FR_DUMMY0 = 30,
62 GDB_FR_DUMMY1 = 31,
63
64 GDB_FR_FS0 = 32,
65
66 GDB_FR_SIZE = 64,
67};
68
69#define GDB_ORIG_D0 41
70#define NUMREGBYTES (GDB_FR_SIZE*4)
71
72static inline void arch_kgdb_breakpoint(void)
73{
74 asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break");
75}
76extern u8 __arch_kgdb_breakpoint;
77
78#define BREAK_INSTR_SIZE 1
79#define CACHE_FLUSH_IS_SAFE 1
80
81#endif /* _ASM_KGDB_H */
diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h
index a3930e43a958..6745dbe64944 100644
--- a/arch/mn10300/include/asm/smp.h
+++ b/arch/mn10300/include/asm/smp.h
@@ -34,7 +34,7 @@
34#define LOCAL_TIMER_IPI 193 34#define LOCAL_TIMER_IPI 193
35#define FLUSH_CACHE_IPI 194 35#define FLUSH_CACHE_IPI 194
36#define CALL_FUNCTION_NMI_IPI 195 36#define CALL_FUNCTION_NMI_IPI 195
37#define GDB_NMI_IPI 196 37#define DEBUGGER_NMI_IPI 196
38 38
39#define SMP_BOOT_IRQ 195 39#define SMP_BOOT_IRQ 195
40 40
@@ -43,6 +43,7 @@
43#define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4 43#define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4
44#define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0 44#define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0
45#define SMP_BOOT_GxICR_LV GxICR_LEVEL_0 45#define SMP_BOOT_GxICR_LV GxICR_LEVEL_0
46#define DEBUGGER_GxICR_LV CONFIG_DEBUGGER_IRQ_LEVEL
46 47
47#define TIME_OUT_COUNT_BOOT_IPI 100 48#define TIME_OUT_COUNT_BOOT_IPI 100
48#define DELAY_TIME_BOOT_IPI 75000 49#define DELAY_TIME_BOOT_IPI 75000
@@ -61,8 +62,9 @@
61 * An alternate way of dealing with this could be to use the EPSW.S bits to 62 * An alternate way of dealing with this could be to use the EPSW.S bits to
62 * cache this information for systems with up to four CPUs. 63 * cache this information for systems with up to four CPUs.
63 */ 64 */
65#define arch_smp_processor_id() (CPUID)
64#if 0 66#if 0
65#define raw_smp_processor_id() (CPUID) 67#define raw_smp_processor_id() (arch_smp_processor_id())
66#else 68#else
67#define raw_smp_processor_id() (current_thread_info()->cpu) 69#define raw_smp_processor_id() (current_thread_info()->cpu)
68#endif 70#endif
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
index 8d53f09c878d..87c213002d4c 100644
--- a/arch/mn10300/include/asm/thread_info.h
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -131,7 +131,11 @@ static inline unsigned long current_stack_pointer(void)
131 kmalloc_node(THREAD_SIZE, GFP_KERNEL, node) 131 kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
132#endif 132#endif
133 133
134#ifndef CONFIG_KGDB
134#define free_thread_info(ti) kfree((ti)) 135#define free_thread_info(ti) kfree((ti))
136#else
137extern void free_thread_info(struct thread_info *);
138#endif
135#define get_thread_info(ti) get_task_struct((ti)->task) 139#define get_thread_info(ti) get_task_struct((ti)->task)
136#define put_thread_info(ti) put_task_struct((ti)->task) 140#define put_thread_info(ti) put_task_struct((ti)->task)
137 141
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index a06a2e10051d..47ed30fe8178 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -21,11 +21,8 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
21obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o 21obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
22obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o 22obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
23 23
24ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
25obj-$(CONFIG_GDBSTUB) += gdb-cache.o
26endif
27
28obj-$(CONFIG_MN10300_RTC) += rtc.o 24obj-$(CONFIG_MN10300_RTC) += rtc.o
29obj-$(CONFIG_PROFILE) += profile.o profile-low.o 25obj-$(CONFIG_PROFILE) += profile.o profile-low.o
30obj-$(CONFIG_MODULES) += module.o 26obj-$(CONFIG_MODULES) += module.o
31obj-$(CONFIG_KPROBES) += kprobes.o 27obj-$(CONFIG_KPROBES) += kprobes.o
28obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index f00b9bafcd3e..fb93ad720b82 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -266,7 +266,11 @@ ENTRY(raw_bus_error)
266 266
267############################################################################### 267###############################################################################
268# 268#
269# Miscellaneous exception entry points 269# NMI exception entry points
270#
271# This is used by ordinary interrupt channels that have the GxICR_NMI bit set
272# in addition to the main NMI and Watchdog channels. SMP NMI IPIs use this
273# facility.
270# 274#
271############################################################################### 275###############################################################################
272ENTRY(nmi_handler) 276ENTRY(nmi_handler)
@@ -281,7 +285,7 @@ ENTRY(nmi_handler)
281 and NMIAGR_GN,d0 285 and NMIAGR_GN,d0
282 lsr 0x2,d0 286 lsr 0x2,d0
283 cmp CALL_FUNCTION_NMI_IPI,d0 287 cmp CALL_FUNCTION_NMI_IPI,d0
284 bne 5f # if not call function, jump 288 bne nmi_not_smp_callfunc # if not call function, jump
285 289
286 # function call nmi ipi 290 # function call nmi ipi
287 add 4,sp # no need to store TBR 291 add 4,sp # no need to store TBR
@@ -295,59 +299,38 @@ ENTRY(nmi_handler)
295 call smp_nmi_call_function_interrupt[],0 299 call smp_nmi_call_function_interrupt[],0
296 RESTORE_ALL 300 RESTORE_ALL
297 301
2985: 302nmi_not_smp_callfunc:
299#ifdef CONFIG_GDBSTUB 303#ifdef CONFIG_KERNEL_DEBUGGER
300 cmp GDB_NMI_IPI,d0 304 cmp DEBUGGER_NMI_IPI,d0
301 bne 3f # if not gdb nmi ipi, jump 305 bne nmi_not_debugger # if not kernel debugger NMI IPI, jump
302 306
303 # gdb nmi ipi 307 # kernel debugger NMI IPI
304 add 4,sp # no need to store TBR 308 add 4,sp # no need to store TBR
305 mov GxICR_DETECT,d0 # clear NMI 309 mov GxICR_DETECT,d0 # clear NMI
306 movbu d0,(GxICR(GDB_NMI_IPI)) 310 movbu d0,(GxICR(DEBUGGER_NMI_IPI))
307 movhu (GxICR(GDB_NMI_IPI)),d0 311 movhu (GxICR(DEBUGGER_NMI_IPI)),d0
308 and ~EPSW_NMID,epsw # enable NMI 312 and ~EPSW_NMID,epsw # enable NMI
309#ifdef CONFIG_MN10300_CACHE_ENABLED 313
310 mov (gdbstub_nmi_opr_type),d0
311 cmp GDBSTUB_NMI_CACHE_PURGE,d0
312 bne 4f # if not gdb cache purge, jump
313
314 # gdb cache purge nmi ipi
315 add -20,sp
316 mov d1,(4,sp)
317 mov a0,(8,sp)
318 mov a1,(12,sp)
319 mov mdr,d0
320 mov d0,(16,sp)
321 call gdbstub_local_purge_cache[],0
322 mov 0x1,d0
323 mov (CPUID),d1
324 asl d1,d0
325 mov gdbstub_nmi_cpumask,a0
326 bclr d0,(a0)
327 mov (4,sp),d1
328 mov (8,sp),a0
329 mov (12,sp),a1
330 mov (16,sp),d0
331 mov d0,mdr
332 add 20,sp
333 mov (sp),d0
334 add 4,sp
335 rti
3364:
337#endif /* CONFIG_MN10300_CACHE_ENABLED */
338 # gdb wait nmi ipi
339 mov (sp),d0 314 mov (sp),d0
340 SAVE_ALL 315 SAVE_ALL
341 call gdbstub_nmi_wait[],0 316 mov fp,d0 # arg 0: stacked register file
317 mov a2,d1 # arg 1: exception number
318 call debugger_nmi_interrupt[],0
342 RESTORE_ALL 319 RESTORE_ALL
3433: 320
344#endif /* CONFIG_GDBSTUB */ 321nmi_not_debugger:
322#endif /* CONFIG_KERNEL_DEBUGGER */
345 mov (sp),d0 # restore TBR to d0 323 mov (sp),d0 # restore TBR to d0
346 add 4,sp 324 add 4,sp
347#endif /* CONFIG_SMP */ 325#endif /* CONFIG_SMP */
348 326
349 bra __common_exception_nonmi 327 bra __common_exception_nonmi
350 328
329###############################################################################
330#
331# General exception entry point
332#
333###############################################################################
351ENTRY(__common_exception) 334ENTRY(__common_exception)
352 add -4,sp 335 add -4,sp
353 mov d0,(sp) 336 mov d0,(sp)
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
index 5f9c3fa19a85..bb5fa7df6c44 100644
--- a/arch/mn10300/kernel/fpu.c
+++ b/arch/mn10300/kernel/fpu.c
@@ -70,24 +70,6 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
70} 70}
71 71
72/* 72/*
73 * handle an FPU invalid_op exception
74 * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
75 */
76asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
77{
78 siginfo_t info;
79
80 if (!user_mode(regs))
81 die_if_no_fixup("FPU invalid opcode", regs, code);
82
83 info.si_signo = SIGILL;
84 info.si_errno = 0;
85 info.si_code = ILL_COPROC;
86 info.si_addr = (void *) regs->pc;
87 force_sig_info(info.si_signo, &info, current);
88}
89
90/*
91 * save the FPU state to a signal context 73 * save the FPU state to a signal context
92 */ 74 */
93int fpu_setup_sigcontext(struct fpucontext *fpucontext) 75int fpu_setup_sigcontext(struct fpucontext *fpucontext)
diff --git a/arch/mn10300/kernel/gdb-cache.S b/arch/mn10300/kernel/gdb-cache.S
deleted file mode 100644
index 1108badc3d32..000000000000
--- a/arch/mn10300/kernel/gdb-cache.S
+++ /dev/null
@@ -1,105 +0,0 @@
1###############################################################################
2#
3# MN10300 Low-level cache purging routines for gdbstub
4#
5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
6# Written by David Howells (dhowells@redhat.com)
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public Licence
10# as published by the Free Software Foundation; either version
11# 2 of the Licence, or (at your option) any later version.
12#
13###############################################################################
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <asm/smp.h>
17#include <asm/cache.h>
18#include <asm/cpu-regs.h>
19#include <asm/exceptions.h>
20#include <asm/frame.inc>
21#include <asm/serial-regs.h>
22
23 .text
24
25###############################################################################
26#
27# GDB stub cache purge
28#
29###############################################################################
30 .type gdbstub_purge_cache,@function
31ENTRY(gdbstub_purge_cache)
32 #######################################################################
33 # read the addresses tagged in the cache's tag RAM and attempt to flush
34 # those addresses specifically
35 # - we rely on the hardware to filter out invalid tag entry addresses
36 mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
37 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
38 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
39
40mn10300_dcache_flush_loop:
41 mov (a0),d0
42 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
43 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
44 # cache
45 mov d0,(a1) # conditional purge
46
47mn10300_dcache_flush_skip:
48 add L1_CACHE_BYTES,a0
49 add L1_CACHE_BYTES,a1
50 add -1,d1
51 bne mn10300_dcache_flush_loop
52
53;; # unconditionally flush and invalidate the dcache
54;; mov DCACHE_PURGE(0,0),a1 # dcache purge request address
55;; mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of
56;; # entries
57;;
58;; gdbstub_purge_cache__dcache_loop:
59;; mov (a1),d0 # unconditional purge
60;;
61;; add L1_CACHE_BYTES,a1
62;; add -1,d1
63;; bne gdbstub_purge_cache__dcache_loop
64
65 #######################################################################
66 # now invalidate the icache
67 mov CHCTR,a0
68 movhu (a0),a1
69
70 mov epsw,d1
71 and ~EPSW_IE,epsw
72 nop
73 nop
74
75 # disable the icache
76 and ~CHCTR_ICEN,d0
77 movhu d0,(a0)
78
79 # and wait for it to calm down
80 setlb
81 movhu (a0),d0
82 btst CHCTR_ICBUSY,d0
83 lne
84
85 # invalidate
86 or CHCTR_ICINV,d0
87 movhu d0,(a0)
88
89 # wait for the cache to finish
90 mov CHCTR,a0
91 setlb
92 movhu (a0),d0
93 btst CHCTR_ICBUSY,d0
94 lne
95
96 # and reenable it
97 movhu a1,(a0)
98 movhu (a0),d0 # read back to flush
99 # (SIGILLs all over without this)
100
101 mov d1,epsw
102
103 ret [],0
104
105 .size gdbstub_purge_cache,.-gdbstub_purge_cache
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
index abdeea153c89..c859cacbb9c3 100644
--- a/arch/mn10300/kernel/gdb-io-ttysm.c
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -59,10 +59,10 @@ void __init gdbstub_io_init(void)
59 59
60 /* we want to get serial receive interrupts */ 60 /* we want to get serial receive interrupts */
61 set_intr_level(gdbstub_port->rx_irq, 61 set_intr_level(gdbstub_port->rx_irq,
62 NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); 62 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
63 set_intr_level(gdbstub_port->tx_irq, 63 set_intr_level(gdbstub_port->tx_irq,
64 NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); 64 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
65 set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), 65 set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL),
66 gdbstub_io_rx_handler); 66 gdbstub_io_rx_handler);
67 67
68 *gdbstub_port->rx_icr |= GxICR_ENABLE; 68 *gdbstub_port->rx_icr |= GxICR_ENABLE;
@@ -88,7 +88,7 @@ void __init gdbstub_io_init(void)
88 88
89 /* permit level 0 IRQs only */ 89 /* permit level 0 IRQs only */
90 arch_local_change_intr_mask_level( 90 arch_local_change_intr_mask_level(
91 NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); 91 NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
92} 92}
93 93
94/* 94/*
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
index b169d99d9f20..538266b2c9bc 100644
--- a/arch/mn10300/kernel/gdb-stub.c
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -133,7 +133,7 @@
133#include <asm/system.h> 133#include <asm/system.h>
134#include <asm/gdb-stub.h> 134#include <asm/gdb-stub.h>
135#include <asm/exceptions.h> 135#include <asm/exceptions.h>
136#include <asm/cacheflush.h> 136#include <asm/debugger.h>
137#include <asm/serial-regs.h> 137#include <asm/serial-regs.h>
138#include <asm/busctl-regs.h> 138#include <asm/busctl-regs.h>
139#include <unit/leds.h> 139#include <unit/leds.h>
@@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue)
405 return (numChars); 405 return (numChars);
406} 406}
407 407
408#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
408/* 409/*
409 * We single-step by setting breakpoints. When an exception 410 * We single-step by setting breakpoints. When an exception
410 * is handled, we need to restore the instructions hoisted 411 * is handled, we need to restore the instructions hoisted
@@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs)
729 __gdbstub_restore_bp(); 730 __gdbstub_restore_bp();
730 return -EFAULT; 731 return -EFAULT;
731} 732}
733#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */
732 734
733#ifdef CONFIG_GDBSTUB_CONSOLE 735#ifdef CONFIG_GDBSTUB_CONSOLE
734 736
@@ -1171,7 +1173,7 @@ int gdbstub_clear_breakpoint(u8 *addr, int len)
1171 1173
1172/* 1174/*
1173 * This function does all command processing for interfacing to gdb 1175 * This function does all command processing for interfacing to gdb
1174 * - returns 1 if the exception should be skipped, 0 otherwise. 1176 * - returns 0 if the exception should be skipped, -ERROR otherwise.
1175 */ 1177 */
1176static int gdbstub(struct pt_regs *regs, enum exception_code excep) 1178static int gdbstub(struct pt_regs *regs, enum exception_code excep)
1177{ 1179{
@@ -1186,7 +1188,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
1186 int loop; 1188 int loop;
1187 1189
1188 if (excep == EXCEP_FPU_DISABLED) 1190 if (excep == EXCEP_FPU_DISABLED)
1189 return 0; 1191 return -ENOTSUPP;
1190 1192
1191 gdbstub_flush_caches = 0; 1193 gdbstub_flush_caches = 0;
1192 1194
@@ -1195,7 +1197,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
1195 asm volatile("mov mdr,%0" : "=d"(mdr)); 1197 asm volatile("mov mdr,%0" : "=d"(mdr));
1196 local_save_flags(epsw); 1198 local_save_flags(epsw);
1197 arch_local_change_intr_mask_level( 1199 arch_local_change_intr_mask_level(
1198 NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); 1200 NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
1199 1201
1200 gdbstub_store_fpu(); 1202 gdbstub_store_fpu();
1201 1203
@@ -1208,11 +1210,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
1208 /* if we were single stepping, restore the opcodes hoisted for the 1210 /* if we were single stepping, restore the opcodes hoisted for the
1209 * breakpoint[s] */ 1211 * breakpoint[s] */
1210 broke = 0; 1212 broke = 0;
1213#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
1211 if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) || 1214 if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
1212 (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc)) 1215 (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
1213 broke = 1; 1216 broke = 1;
1214 1217
1215 __gdbstub_restore_bp(); 1218 __gdbstub_restore_bp();
1219#endif
1216 1220
1217 if (gdbstub_rx_unget) { 1221 if (gdbstub_rx_unget) {
1218 sigval = SIGINT; 1222 sigval = SIGINT;
@@ -1548,17 +1552,21 @@ packet_waiting:
1548 * Step to next instruction 1552 * Step to next instruction
1549 */ 1553 */
1550 case 's': 1554 case 's':
1551 /* 1555 /* Using the T flag doesn't seem to perform single
1552 * using the T flag doesn't seem to perform single
1553 * stepping (it seems to wind up being caught by the 1556 * stepping (it seems to wind up being caught by the
1554 * JTAG unit), so we have to use breakpoints and 1557 * JTAG unit), so we have to use breakpoints and
1555 * continue instead. 1558 * continue instead.
1556 */ 1559 */
1560#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
1557 if (gdbstub_single_step(regs) < 0) 1561 if (gdbstub_single_step(regs) < 0)
1558 /* ignore any fault error for now */ 1562 /* ignore any fault error for now */
1559 gdbstub_printk("unable to set single-step" 1563 gdbstub_printk("unable to set single-step"
1560 " bp\n"); 1564 " bp\n");
1561 goto done; 1565 goto done;
1566#else
1567 gdbstub_strcpy(output_buffer, "E01");
1568 break;
1569#endif
1562 1570
1563 /* 1571 /*
1564 * Set baud rate (bBB) 1572 * Set baud rate (bBB)
@@ -1657,7 +1665,7 @@ done:
1657 * NB: We flush both caches, just to be sure... 1665 * NB: We flush both caches, just to be sure...
1658 */ 1666 */
1659 if (gdbstub_flush_caches) 1667 if (gdbstub_flush_caches)
1660 gdbstub_purge_cache(); 1668 debugger_local_cache_flushinv();
1661 1669
1662 gdbstub_load_fpu(); 1670 gdbstub_load_fpu();
1663 mn10300_set_gdbleds(0); 1671 mn10300_set_gdbleds(0);
@@ -1667,14 +1675,23 @@ done:
1667 touch_softlockup_watchdog(); 1675 touch_softlockup_watchdog();
1668 1676
1669 local_irq_restore(epsw); 1677 local_irq_restore(epsw);
1670 return 1; 1678 return 0;
1679}
1680
1681/*
1682 * Determine if we hit a debugger special breakpoint that needs skipping over
1683 * automatically.
1684 */
1685int at_debugger_breakpoint(struct pt_regs *regs)
1686{
1687 return 0;
1671} 1688}
1672 1689
1673/* 1690/*
1674 * handle event interception 1691 * handle event interception
1675 */ 1692 */
1676asmlinkage int gdbstub_intercept(struct pt_regs *regs, 1693asmlinkage int debugger_intercept(enum exception_code excep,
1677 enum exception_code excep) 1694 int signo, int si_code, struct pt_regs *regs)
1678{ 1695{
1679 static u8 notfirst = 1; 1696 static u8 notfirst = 1;
1680 int ret; 1697 int ret;
@@ -1688,7 +1705,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs,
1688 asm("mov mdr,%0" : "=d"(mdr)); 1705 asm("mov mdr,%0" : "=d"(mdr));
1689 1706
1690 gdbstub_entry( 1707 gdbstub_entry(
1691 "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", 1708 "--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
1692 regs, excep, mdr, regs->pc); 1709 regs, excep, mdr, regs->pc);
1693 1710
1694 gdbstub_entry( 1711 gdbstub_entry(
@@ -1722,7 +1739,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs,
1722 1739
1723 ret = gdbstub(regs, excep); 1740 ret = gdbstub(regs, excep);
1724 1741
1725 gdbstub_entry("<-- gdbstub_intercept()\n"); 1742 gdbstub_entry("<-- debugger_intercept()\n");
1726 gdbstub_busy = 0; 1743 gdbstub_busy = 0;
1727 return ret; 1744 return ret;
1728} 1745}
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
index ea946613f46d..a5ac755dd69f 100644
--- a/arch/mn10300/kernel/internal.h
+++ b/arch/mn10300/kernel/internal.h
@@ -30,6 +30,13 @@ extern void mn10300_low_ipi_handler(void);
30#endif 30#endif
31 31
32/* 32/*
33 * smp.c
34 */
35#ifdef CONFIG_SMP
36extern void smp_jump_to_debugger(void);
37#endif
38
39/*
33 * time.c 40 * time.c
34 */ 41 */
35extern irqreturn_t local_timer_interrupt(void); 42extern irqreturn_t local_timer_interrupt(void);
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index f09fed5e6afc..5f7fc3eb45e6 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -153,7 +153,7 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
153 case LOCAL_TIMER_IPI: 153 case LOCAL_TIMER_IPI:
154 case FLUSH_CACHE_IPI: 154 case FLUSH_CACHE_IPI:
155 case CALL_FUNCTION_NMI_IPI: 155 case CALL_FUNCTION_NMI_IPI:
156 case GDB_NMI_IPI: 156 case DEBUGGER_NMI_IPI:
157#ifdef CONFIG_MN10300_TTYSM0 157#ifdef CONFIG_MN10300_TTYSM0
158 case SC0RXIRQ: 158 case SC0RXIRQ:
159 case SC0TXIRQ: 159 case SC0TXIRQ:
diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c
new file mode 100644
index 000000000000..f6c981db2a36
--- /dev/null
+++ b/arch/mn10300/kernel/kgdb.c
@@ -0,0 +1,502 @@
1/* kgdb support for MN10300
2 *
3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/slab.h>
13#include <linux/ptrace.h>
14#include <linux/kgdb.h>
15#include <linux/uaccess.h>
16#include <unit/leds.h>
17#include <unit/serial.h>
18#include <asm/debugger.h>
19#include <asm/serial-regs.h>
20#include "internal.h"
21
22/*
23 * Software single-stepping breakpoint save (used by __switch_to())
24 */
25static struct thread_info *kgdb_sstep_thread;
26u8 *kgdb_sstep_bp_addr[2];
27u8 kgdb_sstep_bp[2];
28
29/*
30 * Copy kernel exception frame registers to the GDB register file
31 */
32void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
33{
34 unsigned long ssp = (unsigned long) (regs + 1);
35
36 gdb_regs[GDB_FR_D0] = regs->d0;
37 gdb_regs[GDB_FR_D1] = regs->d1;
38 gdb_regs[GDB_FR_D2] = regs->d2;
39 gdb_regs[GDB_FR_D3] = regs->d3;
40 gdb_regs[GDB_FR_A0] = regs->a0;
41 gdb_regs[GDB_FR_A1] = regs->a1;
42 gdb_regs[GDB_FR_A2] = regs->a2;
43 gdb_regs[GDB_FR_A3] = regs->a3;
44 gdb_regs[GDB_FR_SP] = (regs->epsw & EPSW_nSL) ? regs->sp : ssp;
45 gdb_regs[GDB_FR_PC] = regs->pc;
46 gdb_regs[GDB_FR_MDR] = regs->mdr;
47 gdb_regs[GDB_FR_EPSW] = regs->epsw;
48 gdb_regs[GDB_FR_LIR] = regs->lir;
49 gdb_regs[GDB_FR_LAR] = regs->lar;
50 gdb_regs[GDB_FR_MDRQ] = regs->mdrq;
51 gdb_regs[GDB_FR_E0] = regs->e0;
52 gdb_regs[GDB_FR_E1] = regs->e1;
53 gdb_regs[GDB_FR_E2] = regs->e2;
54 gdb_regs[GDB_FR_E3] = regs->e3;
55 gdb_regs[GDB_FR_E4] = regs->e4;
56 gdb_regs[GDB_FR_E5] = regs->e5;
57 gdb_regs[GDB_FR_E6] = regs->e6;
58 gdb_regs[GDB_FR_E7] = regs->e7;
59 gdb_regs[GDB_FR_SSP] = ssp;
60 gdb_regs[GDB_FR_MSP] = 0;
61 gdb_regs[GDB_FR_USP] = regs->sp;
62 gdb_regs[GDB_FR_MCRH] = regs->mcrh;
63 gdb_regs[GDB_FR_MCRL] = regs->mcrl;
64 gdb_regs[GDB_FR_MCVF] = regs->mcvf;
65 gdb_regs[GDB_FR_DUMMY0] = 0;
66 gdb_regs[GDB_FR_DUMMY1] = 0;
67 gdb_regs[GDB_FR_FS0] = 0;
68}
69
70/*
71 * Extracts kernel SP/PC values understandable by gdb from the values
72 * saved by switch_to().
73 */
74void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
75{
76 gdb_regs[GDB_FR_SSP] = p->thread.sp;
77 gdb_regs[GDB_FR_PC] = p->thread.pc;
78 gdb_regs[GDB_FR_A3] = p->thread.a3;
79 gdb_regs[GDB_FR_USP] = p->thread.usp;
80 gdb_regs[GDB_FR_FPCR] = p->thread.fpu_state.fpcr;
81}
82
83/*
84 * Fill kernel exception frame registers from the GDB register file
85 */
86void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
87{
88 regs->d0 = gdb_regs[GDB_FR_D0];
89 regs->d1 = gdb_regs[GDB_FR_D1];
90 regs->d2 = gdb_regs[GDB_FR_D2];
91 regs->d3 = gdb_regs[GDB_FR_D3];
92 regs->a0 = gdb_regs[GDB_FR_A0];
93 regs->a1 = gdb_regs[GDB_FR_A1];
94 regs->a2 = gdb_regs[GDB_FR_A2];
95 regs->a3 = gdb_regs[GDB_FR_A3];
96 regs->sp = gdb_regs[GDB_FR_SP];
97 regs->pc = gdb_regs[GDB_FR_PC];
98 regs->mdr = gdb_regs[GDB_FR_MDR];
99 regs->epsw = gdb_regs[GDB_FR_EPSW];
100 regs->lir = gdb_regs[GDB_FR_LIR];
101 regs->lar = gdb_regs[GDB_FR_LAR];
102 regs->mdrq = gdb_regs[GDB_FR_MDRQ];
103 regs->e0 = gdb_regs[GDB_FR_E0];
104 regs->e1 = gdb_regs[GDB_FR_E1];
105 regs->e2 = gdb_regs[GDB_FR_E2];
106 regs->e3 = gdb_regs[GDB_FR_E3];
107 regs->e4 = gdb_regs[GDB_FR_E4];
108 regs->e5 = gdb_regs[GDB_FR_E5];
109 regs->e6 = gdb_regs[GDB_FR_E6];
110 regs->e7 = gdb_regs[GDB_FR_E7];
111 regs->sp = gdb_regs[GDB_FR_SSP];
112 /* gdb_regs[GDB_FR_MSP]; */
113 // regs->usp = gdb_regs[GDB_FR_USP];
114 regs->mcrh = gdb_regs[GDB_FR_MCRH];
115 regs->mcrl = gdb_regs[GDB_FR_MCRL];
116 regs->mcvf = gdb_regs[GDB_FR_MCVF];
117 /* gdb_regs[GDB_FR_DUMMY0]; */
118 /* gdb_regs[GDB_FR_DUMMY1]; */
119
120 // regs->fpcr = gdb_regs[GDB_FR_FPCR];
121 // regs->fs0 = gdb_regs[GDB_FR_FS0];
122}
123
124struct kgdb_arch arch_kgdb_ops = {
125 .gdb_bpt_instr = { 0xff },
126 .flags = KGDB_HW_BREAKPOINT,
127};
128
129static const unsigned char mn10300_kgdb_insn_sizes[256] =
130{
131 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
132 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */
133 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
134 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
135 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
136 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
137 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
138 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
139 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
140 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
141 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
142 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
143 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
147 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */
148};
149
150/*
151 * Attempt to emulate single stepping by means of breakpoint instructions.
152 * Although there is a single-step trace flag in EPSW, its use is not
153 * sufficiently documented and is only intended for use with the JTAG debugger.
154 */
155static int kgdb_arch_do_singlestep(struct pt_regs *regs)
156{
157 unsigned long arg;
158 unsigned size;
159 u8 *pc = (u8 *)regs->pc, *sp = (u8 *)(regs + 1), cur;
160 u8 *x = NULL, *y = NULL;
161 int ret;
162
163 ret = probe_kernel_read(&cur, pc, 1);
164 if (ret < 0)
165 return ret;
166
167 size = mn10300_kgdb_insn_sizes[cur];
168 if (size > 0) {
169 x = pc + size;
170 goto set_x;
171 }
172
173 switch (cur) {
174 /* Bxx (d8,PC) */
175 case 0xc0 ... 0xca:
176 ret = probe_kernel_read(&arg, pc + 1, 1);
177 if (ret < 0)
178 return ret;
179 x = pc + 2;
180 if (arg >= 0 && arg <= 2)
181 goto set_x;
182 y = pc + (s8)arg;
183 goto set_x_and_y;
184
185 /* LXX (d8,PC) */
186 case 0xd0 ... 0xda:
187 x = pc + 1;
188 if (regs->pc == regs->lar)
189 goto set_x;
190 y = (u8 *)regs->lar;
191 goto set_x_and_y;
192
193 /* SETLB - loads the next four bytes into the LIR register
194 * (which mustn't include a breakpoint instruction) */
195 case 0xdb:
196 x = pc + 5;
197 goto set_x;
198
199 /* JMP (d16,PC) or CALL (d16,PC) */
200 case 0xcc:
201 case 0xcd:
202 ret = probe_kernel_read(&arg, pc + 1, 2);
203 if (ret < 0)
204 return ret;
205 x = pc + (s16)arg;
206 goto set_x;
207
208 /* JMP (d32,PC) or CALL (d32,PC) */
209 case 0xdc:
210 case 0xdd:
211 ret = probe_kernel_read(&arg, pc + 1, 4);
212 if (ret < 0)
213 return ret;
214 x = pc + (s32)arg;
215 goto set_x;
216
217 /* RETF */
218 case 0xde:
219 x = (u8 *)regs->mdr;
220 goto set_x;
221
222 /* RET */
223 case 0xdf:
224 ret = probe_kernel_read(&arg, pc + 2, 1);
225 if (ret < 0)
226 return ret;
227 ret = probe_kernel_read(&x, sp + (s8)arg, 4);
228 if (ret < 0)
229 return ret;
230 goto set_x;
231
232 case 0xf0:
233 ret = probe_kernel_read(&cur, pc + 1, 1);
234 if (ret < 0)
235 return ret;
236
237 if (cur >= 0xf0 && cur <= 0xf7) {
238 /* JMP (An) / CALLS (An) */
239 switch (cur & 3) {
240 case 0: x = (u8 *)regs->a0; break;
241 case 1: x = (u8 *)regs->a1; break;
242 case 2: x = (u8 *)regs->a2; break;
243 case 3: x = (u8 *)regs->a3; break;
244 }
245 goto set_x;
246 } else if (cur == 0xfc) {
247 /* RETS */
248 ret = probe_kernel_read(&x, sp, 4);
249 if (ret < 0)
250 return ret;
251 goto set_x;
252 } else if (cur == 0xfd) {
253 /* RTI */
254 ret = probe_kernel_read(&x, sp + 4, 4);
255 if (ret < 0)
256 return ret;
257 goto set_x;
258 } else {
259 x = pc + 2;
260 goto set_x;
261 }
262 break;
263
264 /* potential 3-byte conditional branches */
265 case 0xf8:
266 ret = probe_kernel_read(&cur, pc + 1, 1);
267 if (ret < 0)
268 return ret;
269 x = pc + 3;
270
271 if (cur >= 0xe8 && cur <= 0xeb) {
272 ret = probe_kernel_read(&arg, pc + 2, 1);
273 if (ret < 0)
274 return ret;
275 if (arg >= 0 && arg <= 3)
276 goto set_x;
277 y = pc + (s8)arg;
278 goto set_x_and_y;
279 }
280 goto set_x;
281
282 case 0xfa:
283 ret = probe_kernel_read(&cur, pc + 1, 1);
284 if (ret < 0)
285 return ret;
286
287 if (cur == 0xff) {
288 /* CALLS (d16,PC) */
289 ret = probe_kernel_read(&arg, pc + 2, 2);
290 if (ret < 0)
291 return ret;
292 x = pc + (s16)arg;
293 goto set_x;
294 }
295
296 x = pc + 4;
297 goto set_x;
298
299 case 0xfc:
300 ret = probe_kernel_read(&cur, pc + 1, 1);
301 if (ret < 0)
302 return ret;
303
304 if (cur == 0xff) {
305 /* CALLS (d32,PC) */
306 ret = probe_kernel_read(&arg, pc + 2, 4);
307 if (ret < 0)
308 return ret;
309 x = pc + (s32)arg;
310 goto set_x;
311 }
312
313 x = pc + 6;
314 goto set_x;
315 }
316
317 return 0;
318
319set_x:
320 kgdb_sstep_bp_addr[0] = x;
321 kgdb_sstep_bp_addr[1] = NULL;
322 ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
323 if (ret < 0)
324 return ret;
325 ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
326 if (ret < 0)
327 return ret;
328 kgdb_sstep_thread = current_thread_info();
329 debugger_local_cache_flushinv_one(x);
330 return ret;
331
332set_x_and_y:
333 kgdb_sstep_bp_addr[0] = x;
334 kgdb_sstep_bp_addr[1] = y;
335 ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
336 if (ret < 0)
337 return ret;
338 ret = probe_kernel_read(&kgdb_sstep_bp[1], y, 1);
339 if (ret < 0)
340 return ret;
341 ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
342 if (ret < 0)
343 return ret;
344 ret = probe_kernel_write(y, &arch_kgdb_ops.gdb_bpt_instr, 1);
345 if (ret < 0) {
346 probe_kernel_write(kgdb_sstep_bp_addr[0],
347 &kgdb_sstep_bp[0], 1);
348 } else {
349 kgdb_sstep_thread = current_thread_info();
350 }
351 debugger_local_cache_flushinv_one(x);
352 debugger_local_cache_flushinv_one(y);
353 return ret;
354}
355
356/*
357 * Remove emplaced single-step breakpoints, returning true if we hit one of
358 * them.
359 */
360static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
361{
362 bool hit = false;
363 u8 *x = kgdb_sstep_bp_addr[0], *y = kgdb_sstep_bp_addr[1];
364 u8 opcode;
365
366 if (kgdb_sstep_thread == current_thread_info()) {
367 if (x) {
368 if (x == (u8 *)regs->pc)
369 hit = true;
370 if (probe_kernel_read(&opcode, x,
371 1) < 0 ||
372 opcode != 0xff)
373 BUG();
374 probe_kernel_write(x, &kgdb_sstep_bp[0], 1);
375 debugger_local_cache_flushinv_one(x);
376 }
377 if (y) {
378 if (y == (u8 *)regs->pc)
379 hit = true;
380 if (probe_kernel_read(&opcode, y,
381 1) < 0 ||
382 opcode != 0xff)
383 BUG();
384 probe_kernel_write(y, &kgdb_sstep_bp[1], 1);
385 debugger_local_cache_flushinv_one(y);
386 }
387 }
388
389 kgdb_sstep_bp_addr[0] = NULL;
390 kgdb_sstep_bp_addr[1] = NULL;
391 kgdb_sstep_thread = NULL;
392 return hit;
393}
394
395/*
396 * Catch a single-step-pending thread being deleted and make sure the global
397 * single-step state is cleared. At this point the breakpoints should have
398 * been removed by __switch_to().
399 */
400void free_thread_info(struct thread_info *ti)
401{
402 if (kgdb_sstep_thread == ti) {
403 kgdb_sstep_thread = NULL;
404
405 /* However, we may now be running in degraded mode, with most
406 * of the CPUs disabled until such a time as KGDB is reentered,
407 * so force immediate reentry */
408 kgdb_breakpoint();
409 }
410 kfree(ti);
411}
412
413/*
414 * Handle unknown packets and [CcsDk] packets
415 * - at this point breakpoints have been installed
416 */
417int kgdb_arch_handle_exception(int vector, int signo, int err_code,
418 char *remcom_in_buffer, char *remcom_out_buffer,
419 struct pt_regs *regs)
420{
421 long addr;
422 char *ptr;
423
424 switch (remcom_in_buffer[0]) {
425 case 'c':
426 case 's':
427 /* try to read optional parameter, pc unchanged if no parm */
428 ptr = &remcom_in_buffer[1];
429 if (kgdb_hex2long(&ptr, &addr))
430 regs->pc = addr;
431 case 'D':
432 case 'k':
433 atomic_set(&kgdb_cpu_doing_single_step, -1);
434
435 if (remcom_in_buffer[0] == 's') {
436 kgdb_arch_do_singlestep(regs);
437 kgdb_single_step = 1;
438 atomic_set(&kgdb_cpu_doing_single_step,
439 raw_smp_processor_id());
440 }
441 return 0;
442 }
443 return -1; /* this means that we do not want to exit from the handler */
444}
445
446/*
447 * Handle event interception
448 * - returns 0 if the exception should be skipped, -ERROR otherwise.
449 */
450int debugger_intercept(enum exception_code excep, int signo, int si_code,
451 struct pt_regs *regs)
452{
453 int ret;
454
455 if (kgdb_arch_undo_singlestep(regs)) {
456 excep = EXCEP_TRAP;
457 signo = SIGTRAP;
458 si_code = TRAP_TRACE;
459 }
460
461 ret = kgdb_handle_exception(excep, signo, si_code, regs);
462
463 debugger_local_cache_flushinv();
464
465 return ret;
466}
467
468/*
469 * Determine if we've hit a debugger special breakpoint
470 */
471int at_debugger_breakpoint(struct pt_regs *regs)
472{
473 return regs->pc == (unsigned long)&__arch_kgdb_breakpoint;
474}
475
476/*
477 * Initialise kgdb
478 */
479int kgdb_arch_init(void)
480{
481 return 0;
482}
483
484/*
485 * Do something, perhaps, but don't know what.
486 */
487void kgdb_arch_exit(void)
488{
489}
490
491#ifdef CONFIG_SMP
492void debugger_nmi_interrupt(struct pt_regs *regs, enum exception_code code)
493{
494 kgdb_nmicallback(arch_smp_processor_id(), regs);
495 debugger_local_cache_flushinv();
496}
497
498void kgdb_roundup_cpus(unsigned long flags)
499{
500 smp_jump_to_debugger();
501}
502#endif
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index 93c53739cfc9..efca426a2ed4 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -119,6 +119,10 @@ static int mn10300_serial_request_port(struct uart_port *);
119static void mn10300_serial_config_port(struct uart_port *, int); 119static void mn10300_serial_config_port(struct uart_port *, int);
120static int mn10300_serial_verify_port(struct uart_port *, 120static int mn10300_serial_verify_port(struct uart_port *,
121 struct serial_struct *); 121 struct serial_struct *);
122#ifdef CONFIG_CONSOLE_POLL
123static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char);
124static int mn10300_serial_poll_get_char(struct uart_port *);
125#endif
122 126
123static const struct uart_ops mn10300_serial_ops = { 127static const struct uart_ops mn10300_serial_ops = {
124 .tx_empty = mn10300_serial_tx_empty, 128 .tx_empty = mn10300_serial_tx_empty,
@@ -138,6 +142,10 @@ static const struct uart_ops mn10300_serial_ops = {
138 .request_port = mn10300_serial_request_port, 142 .request_port = mn10300_serial_request_port,
139 .config_port = mn10300_serial_config_port, 143 .config_port = mn10300_serial_config_port,
140 .verify_port = mn10300_serial_verify_port, 144 .verify_port = mn10300_serial_verify_port,
145#ifdef CONFIG_CONSOLE_POLL
146 .poll_put_char = mn10300_serial_poll_put_char,
147 .poll_get_char = mn10300_serial_poll_get_char,
148#endif
141}; 149};
142 150
143static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); 151static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
@@ -1634,3 +1642,70 @@ static int __init mn10300_serial_console_init(void)
1634 1642
1635console_initcall(mn10300_serial_console_init); 1643console_initcall(mn10300_serial_console_init);
1636#endif 1644#endif
1645
1646#ifdef CONFIG_CONSOLE_POLL
1647/*
1648 * Polled character reception for the kernel debugger
1649 */
1650static int mn10300_serial_poll_get_char(struct uart_port *_port)
1651{
1652 struct mn10300_serial_port *port =
1653 container_of(_port, struct mn10300_serial_port, uart);
1654 unsigned ix;
1655 u8 st, ch;
1656
1657 _enter("%s", port->name);
1658
1659 do {
1660 /* pull chars out of the hat */
1661 ix = port->rx_outp;
1662 if (ix == port->rx_inp)
1663 return NO_POLL_CHAR;
1664
1665 ch = port->rx_buffer[ix++];
1666 st = port->rx_buffer[ix++];
1667 smp_rmb();
1668 port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
1669
1670 } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
1671
1672 return ch;
1673}
1674
1675
1676/*
1677 * Polled character transmission for the kernel debugger
1678 */
1679static void mn10300_serial_poll_put_char(struct uart_port *_port,
1680 unsigned char ch)
1681{
1682 struct mn10300_serial_port *port =
1683 container_of(_port, struct mn10300_serial_port, uart);
1684 u8 intr, tmp;
1685
1686 /* wait for the transmitter to finish anything it might be doing (and
1687 * this includes the virtual DMA handler, so it might take a while) */
1688 while (*port->_status & (SC01STR_TBF | SC01STR_TXF))
1689 continue;
1690
1691 /* disable the Tx ready interrupt */
1692 intr = *port->_intr;
1693 *port->_intr = intr & ~SC01ICR_TI;
1694 tmp = *port->_intr;
1695
1696 if (ch == 0x0a) {
1697 *(u8 *) port->_txb = 0x0d;
1698 while (*port->_status & SC01STR_TBF)
1699 continue;
1700 }
1701
1702 *(u8 *) port->_txb = ch;
1703 while (*port->_status & SC01STR_TBF)
1704 continue;
1705
1706 /* restore the Tx interrupt flag */
1707 *port->_intr = intr;
1708 tmp = *port->_intr;
1709}
1710
1711#endif /* CONFIG_CONSOLE_POLL */
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index e1b14a6ed544..28eec3102535 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -135,7 +135,7 @@ void release_segments(struct mm_struct *mm)
135 135
136void machine_restart(char *cmd) 136void machine_restart(char *cmd)
137{ 137{
138#ifdef CONFIG_GDBSTUB 138#ifdef CONFIG_KERNEL_DEBUGGER
139 gdbstub_exit(0); 139 gdbstub_exit(0);
140#endif 140#endif
141 141
@@ -148,14 +148,14 @@ void machine_restart(char *cmd)
148 148
149void machine_halt(void) 149void machine_halt(void)
150{ 150{
151#ifdef CONFIG_GDBSTUB 151#ifdef CONFIG_KERNEL_DEBUGGER
152 gdbstub_exit(0); 152 gdbstub_exit(0);
153#endif 153#endif
154} 154}
155 155
156void machine_power_off(void) 156void machine_power_off(void)
157{ 157{
158#ifdef CONFIG_GDBSTUB 158#ifdef CONFIG_KERNEL_DEBUGGER
159 gdbstub_exit(0); 159 gdbstub_exit(0);
160#endif 160#endif
161} 161}
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
index 1ebb79f1650d..51c02f97dcea 100644
--- a/arch/mn10300/kernel/smp.c
+++ b/arch/mn10300/kernel/smp.c
@@ -440,6 +440,22 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
440} 440}
441 441
442/** 442/**
443 * smp_jump_to_debugger - Make other CPUs enter the debugger by sending an IPI
444 *
445 * Send a non-maskable request to all other CPUs in the system, instructing
446 * them to jump into the debugger. The caller is responsible for checking that
447 * the other CPUs responded to the instruction.
448 *
449 * The caller should make sure that this CPU's debugger IPI is disabled.
450 */
451void smp_jump_to_debugger(void)
452{
453 if (num_online_cpus() > 1)
454 /* Send a message to all other CPUs */
455 send_IPI_allbutself(DEBUGGER_NMI_IPI);
456}
457
458/**
443 * stop_this_cpu - Callback to stop a CPU. 459 * stop_this_cpu - Callback to stop a CPU.
444 * @unused: Callback context (ignored). 460 * @unused: Callback context (ignored).
445 */ 461 */
@@ -603,7 +619,7 @@ static void __init smp_cpu_init(void)
603/** 619/**
604 * smp_prepare_cpu_init - Initialise CPU in startup_secondary 620 * smp_prepare_cpu_init - Initialise CPU in startup_secondary
605 * 621 *
606 * Set interrupt level 0-6 setting and init ICR of gdbstub. 622 * Set interrupt level 0-6 setting and init ICR of the kernel debugger.
607 */ 623 */
608void smp_prepare_cpu_init(void) 624void smp_prepare_cpu_init(void)
609{ 625{
@@ -622,15 +638,15 @@ void smp_prepare_cpu_init(void)
622 for (loop = 0; loop < GxICR_NUM_IRQS; loop++) 638 for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
623 GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; 639 GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
624 640
625#ifdef CONFIG_GDBSTUB 641#ifdef CONFIG_KERNEL_DEBUGGER
626 /* initialise GDB-stub */ 642 /* initialise the kernel debugger interrupt */
627 do { 643 do {
628 unsigned long flags; 644 unsigned long flags;
629 u16 tmp16; 645 u16 tmp16;
630 646
631 flags = arch_local_cli_save(); 647 flags = arch_local_cli_save();
632 GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; 648 GxICR(DEBUGGER_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
633 tmp16 = GxICR(GDB_NMI_IPI); 649 tmp16 = GxICR(DEBUGGER_NMI_IPI);
634 arch_local_irq_restore(flags); 650 arch_local_irq_restore(flags);
635 } while (0); 651 } while (0);
636#endif 652#endif
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
index 9074d0fb8788..de3e74fc9ea0 100644
--- a/arch/mn10300/kernel/switch_to.S
+++ b/arch/mn10300/kernel/switch_to.S
@@ -39,11 +39,17 @@ ENTRY(__switch_to)
39 39
40 # save prev context 40 # save prev context
41 mov __switch_back,d0 41 mov __switch_back,d0
42 mov d0,(THREAD_PC,a0)
43 mov sp,a2 42 mov sp,a2
44 mov a2,(THREAD_SP,a0) 43 mov a2,(THREAD_SP,a0)
45 mov a3,(THREAD_A3,a0) 44 mov a3,(THREAD_A3,a0)
46 45
46#ifdef CONFIG_KGDB
47 btst 0xff,(kgdb_single_step)
48 bne __switch_to__lift_sstep_bp
49__switch_to__continue:
50#endif
51 mov d0,(THREAD_PC,a0)
52
47 mov (THREAD_A3,a1),a3 53 mov (THREAD_A3,a1),a3
48 mov (THREAD_SP,a1),a2 54 mov (THREAD_SP,a1),a2
49 55
@@ -68,3 +74,106 @@ ENTRY(__switch_to)
68__switch_back: 74__switch_back:
69 and ~EPSW_NMID,epsw 75 and ~EPSW_NMID,epsw
70 ret [d2,d3,a2,a3,exreg1],32 76 ret [d2,d3,a2,a3,exreg1],32
77
78#ifdef CONFIG_KGDB
79###############################################################################
80#
81# Lift the single-step breakpoints when the task being traced is switched out
82# A0 = prev
83# A1 = next
84#
85###############################################################################
86__switch_to__lift_sstep_bp:
87 add -12,sp
88 mov a0,e4
89 mov a1,e5
90
91 # Clear the single-step flag to prevent us coming this way until we get
92 # switched back in
93 bclr 0xff,(kgdb_single_step)
94
95 # Remove first breakpoint
96 mov (kgdb_sstep_bp_addr),a2
97 cmp 0,a2
98 beq 1f
99 movbu (kgdb_sstep_bp),d0
100 movbu d0,(a2)
101#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
102 mov a2,d0
103 mov a2,d1
104 add 1,d1
105 calls flush_icache_range
106#endif
1071:
108
109 # Remove second breakpoint
110 mov (kgdb_sstep_bp_addr+4),a2
111 cmp 0,a2
112 beq 2f
113 movbu (kgdb_sstep_bp+1),d0
114 movbu d0,(a2)
115#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
116 mov a2,d0
117 mov a2,d1
118 add 1,d1
119 calls flush_icache_range
120#endif
1212:
122
123 # Change the resumption address and return
124 mov __switch_back__reinstall_sstep_bp,d0
125 mov e4,a0
126 mov e5,a1
127 add 12,sp
128 bra __switch_to__continue
129
130###############################################################################
131#
132# Reinstall the single-step breakpoints when the task being traced is switched
133# back in (A1 points to the new thread_struct).
134#
135###############################################################################
136__switch_back__reinstall_sstep_bp:
137 add -12,sp
138 mov a0,e4 # save the return value
139 mov 0xff,d3
140
141 # Reinstall first breakpoint
142 mov (kgdb_sstep_bp_addr),a2
143 cmp 0,a2
144 beq 1f
145 movbu (a2),d0
146 movbu d0,(kgdb_sstep_bp)
147 movbu d3,(a2)
148#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
149 mov a2,d0
150 mov a2,d1
151 add 1,d1
152 calls flush_icache_range
153#endif
1541:
155
156 # Reinstall second breakpoint
157 mov (kgdb_sstep_bp_addr+4),a2
158 cmp 0,a2
159 beq 2f
160 movbu (a2),d0
161 movbu d0,(kgdb_sstep_bp+1)
162 movbu d3,(a2)
163#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
164 mov a2,d0
165 mov a2,d1
166 add 1,d1
167 calls flush_icache_range
168#endif
1692:
170
171 mov d3,(kgdb_single_step)
172
173 # Restore the return value (the previous thread_struct pointer)
174 mov e4,a0
175 mov a0,d0
176 add 12,sp
177 bra __switch_back
178
179#endif /* CONFIG_KGDB */
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index b90c3f160c77..f03cb278828f 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -38,8 +38,9 @@
38#include <asm/busctl-regs.h> 38#include <asm/busctl-regs.h>
39#include <unit/leds.h> 39#include <unit/leds.h>
40#include <asm/fpu.h> 40#include <asm/fpu.h>
41#include <asm/gdb-stub.h>
42#include <asm/sections.h> 41#include <asm/sections.h>
42#include <asm/debugger.h>
43#include "internal.h"
43 44
44#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff) 45#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff)
45#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" 46#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
@@ -49,63 +50,169 @@ int kstack_depth_to_print = 24;
49 50
50spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); 51spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
51 52
52ATOMIC_NOTIFIER_HEAD(mn10300_die_chain); 53struct exception_to_signal_map {
54 u8 signo;
55 u32 si_code;
56};
57
58static const struct exception_to_signal_map exception_to_signal_map[256] = {
59 /* MMU exceptions */
60 [EXCEP_ITLBMISS >> 3] = { 0, 0 },
61 [EXCEP_DTLBMISS >> 3] = { 0, 0 },
62 [EXCEP_IAERROR >> 3] = { 0, 0 },
63 [EXCEP_DAERROR >> 3] = { 0, 0 },
64
65 /* system exceptions */
66 [EXCEP_TRAP >> 3] = { SIGTRAP, TRAP_BRKPT },
67 [EXCEP_ISTEP >> 3] = { SIGTRAP, TRAP_TRACE }, /* Monitor */
68 [EXCEP_IBREAK >> 3] = { SIGTRAP, TRAP_HWBKPT }, /* Monitor */
69 [EXCEP_OBREAK >> 3] = { SIGTRAP, TRAP_HWBKPT }, /* Monitor */
70 [EXCEP_PRIVINS >> 3] = { SIGILL, ILL_PRVOPC },
71 [EXCEP_UNIMPINS >> 3] = { SIGILL, ILL_ILLOPC },
72 [EXCEP_UNIMPEXINS >> 3] = { SIGILL, ILL_ILLOPC },
73 [EXCEP_MEMERR >> 3] = { SIGSEGV, SEGV_ACCERR },
74 [EXCEP_MISALIGN >> 3] = { SIGBUS, BUS_ADRALN },
75 [EXCEP_BUSERROR >> 3] = { SIGBUS, BUS_ADRERR },
76 [EXCEP_ILLINSACC >> 3] = { SIGSEGV, SEGV_ACCERR },
77 [EXCEP_ILLDATACC >> 3] = { SIGSEGV, SEGV_ACCERR },
78 [EXCEP_IOINSACC >> 3] = { SIGSEGV, SEGV_ACCERR },
79 [EXCEP_PRIVINSACC >> 3] = { SIGSEGV, SEGV_ACCERR }, /* userspace */
80 [EXCEP_PRIVDATACC >> 3] = { SIGSEGV, SEGV_ACCERR }, /* userspace */
81 [EXCEP_DATINSACC >> 3] = { SIGSEGV, SEGV_ACCERR },
82 [EXCEP_DOUBLE_FAULT >> 3] = { SIGILL, ILL_BADSTK },
83
84 /* FPU exceptions */
85 [EXCEP_FPU_DISABLED >> 3] = { SIGILL, ILL_COPROC },
86 [EXCEP_FPU_UNIMPINS >> 3] = { SIGILL, ILL_COPROC },
87 [EXCEP_FPU_OPERATION >> 3] = { SIGFPE, FPE_INTDIV },
88
89 /* interrupts */
90 [EXCEP_WDT >> 3] = { SIGALRM, 0 },
91 [EXCEP_NMI >> 3] = { SIGQUIT, 0 },
92 [EXCEP_IRQ_LEVEL0 >> 3] = { SIGINT, 0 },
93 [EXCEP_IRQ_LEVEL1 >> 3] = { 0, 0 },
94 [EXCEP_IRQ_LEVEL2 >> 3] = { 0, 0 },
95 [EXCEP_IRQ_LEVEL3 >> 3] = { 0, 0 },
96 [EXCEP_IRQ_LEVEL4 >> 3] = { 0, 0 },
97 [EXCEP_IRQ_LEVEL5 >> 3] = { 0, 0 },
98 [EXCEP_IRQ_LEVEL6 >> 3] = { 0, 0 },
99
100 /* system calls */
101 [EXCEP_SYSCALL0 >> 3] = { 0, 0 },
102 [EXCEP_SYSCALL1 >> 3] = { SIGILL, ILL_ILLTRP },
103 [EXCEP_SYSCALL2 >> 3] = { SIGILL, ILL_ILLTRP },
104 [EXCEP_SYSCALL3 >> 3] = { SIGILL, ILL_ILLTRP },
105 [EXCEP_SYSCALL4 >> 3] = { SIGILL, ILL_ILLTRP },
106 [EXCEP_SYSCALL5 >> 3] = { SIGILL, ILL_ILLTRP },
107 [EXCEP_SYSCALL6 >> 3] = { SIGILL, ILL_ILLTRP },
108 [EXCEP_SYSCALL7 >> 3] = { SIGILL, ILL_ILLTRP },
109 [EXCEP_SYSCALL8 >> 3] = { SIGILL, ILL_ILLTRP },
110 [EXCEP_SYSCALL9 >> 3] = { SIGILL, ILL_ILLTRP },
111 [EXCEP_SYSCALL10 >> 3] = { SIGILL, ILL_ILLTRP },
112 [EXCEP_SYSCALL11 >> 3] = { SIGILL, ILL_ILLTRP },
113 [EXCEP_SYSCALL12 >> 3] = { SIGILL, ILL_ILLTRP },
114 [EXCEP_SYSCALL13 >> 3] = { SIGILL, ILL_ILLTRP },
115 [EXCEP_SYSCALL14 >> 3] = { SIGILL, ILL_ILLTRP },
116 [EXCEP_SYSCALL15 >> 3] = { SIGABRT, 0 },
117};
53 118
54/* 119/*
55 * These constants are for searching for possible module text 120 * Handle kernel exceptions.
56 * segments. MODULE_RANGE is a guess of how much space is likely 121 *
57 * to be vmalloced. 122 * See if there's a fixup handler we can force a jump to when an exception
123 * happens due to something kernel code did
58 */ 124 */
59#define MODULE_RANGE (8 * 1024 * 1024) 125int die_if_no_fixup(const char *str, struct pt_regs *regs,
60 126 enum exception_code code)
61#define DO_ERROR(signr, prologue, str, name) \ 127{
62asmlinkage void name(struct pt_regs *regs, u32 intcode) \ 128 u8 opcode;
63{ \ 129 int signo, si_code;
64 prologue; \ 130
65 if (die_if_no_fixup(str, regs, intcode)) \ 131 if (user_mode(regs))
66 return; \ 132 return 0;
67 force_sig(signr, current); \ 133
68} 134 peripheral_leds_display_exception(code);
135
136 signo = exception_to_signal_map[code >> 3].signo;
137 si_code = exception_to_signal_map[code >> 3].si_code;
138
139 switch (code) {
140 /* see if we can fixup the kernel accessing memory */
141 case EXCEP_ITLBMISS:
142 case EXCEP_DTLBMISS:
143 case EXCEP_IAERROR:
144 case EXCEP_DAERROR:
145 case EXCEP_MEMERR:
146 case EXCEP_MISALIGN:
147 case EXCEP_BUSERROR:
148 case EXCEP_ILLDATACC:
149 case EXCEP_IOINSACC:
150 case EXCEP_PRIVINSACC:
151 case EXCEP_PRIVDATACC:
152 case EXCEP_DATINSACC:
153 if (fixup_exception(regs))
154 return 1;
155 break;
69 156
70#define DO_EINFO(signr, prologue, str, name, sicode) \ 157 case EXCEP_TRAP:
71asmlinkage void name(struct pt_regs *regs, u32 intcode) \ 158 case EXCEP_UNIMPINS:
72{ \ 159 if (get_user(opcode, (uint8_t __user *)regs->pc) != 0)
73 siginfo_t info; \ 160 break;
74 prologue; \ 161 if (opcode == 0xff) {
75 if (die_if_no_fixup(str, regs, intcode)) \ 162 if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
76 return; \ 163 return 1;
77 info.si_signo = signr; \ 164 if (at_debugger_breakpoint(regs))
78 if (signr == SIGILL && sicode == ILL_ILLOPC) { \ 165 regs->pc++;
79 uint8_t opcode; \ 166 signo = SIGTRAP;
80 if (get_user(opcode, (uint8_t __user *)regs->pc) == 0) \ 167 si_code = TRAP_BRKPT;
81 if (opcode == 0xff) \ 168 }
82 info.si_signo = SIGTRAP; \ 169 break;
83 } \ 170
84 info.si_errno = 0; \ 171 case EXCEP_SYSCALL1 ... EXCEP_SYSCALL14:
85 info.si_code = sicode; \ 172 /* syscall return addr is _after_ the instruction */
86 info.si_addr = (void *) regs->pc; \ 173 regs->pc -= 2;
87 force_sig_info(info.si_signo, &info, current); \ 174 break;
175
176 case EXCEP_SYSCALL15:
177 if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_WARN)
178 return 1;
179
180 /* syscall return addr is _after_ the instruction */
181 regs->pc -= 2;
182 break;
183
184 default:
185 break;
186 }
187
188 if (debugger_intercept(code, signo, si_code, regs) == 0)
189 return 1;
190
191 if (notify_die(DIE_GPF, str, regs, code, 0, 0))
192 return 1;
193
194 /* make the process die as the last resort */
195 die(str, regs, code);
88} 196}
89 197
90DO_ERROR(SIGTRAP, {}, "trap", trap); 198/*
91DO_ERROR(SIGSEGV, {}, "ibreak", ibreak); 199 * General exception handler
92DO_ERROR(SIGSEGV, {}, "obreak", obreak); 200 */
93DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR); 201asmlinkage void handle_exception(struct pt_regs *regs, u32 intcode)
94DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR); 202{
95DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR); 203 siginfo_t info;
96DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC); 204
97DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); 205 /* deal with kernel exceptions here */
98DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); 206 if (die_if_no_fixup(NULL, regs, intcode))
99DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); 207 return;
100DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); 208
101 209 /* otherwise it's a userspace exception */
102DO_ERROR(SIGTRAP, 210 info.si_signo = exception_to_signal_map[intcode >> 3].signo;
103#ifndef CONFIG_MN10300_USING_JTAG 211 info.si_code = exception_to_signal_map[intcode >> 3].si_code;
104 DCR &= ~0x0001, 212 info.si_errno = 0;
105#else 213 info.si_addr = (void *) regs->pc;
106 {}, 214 force_sig_info(info.si_signo, &info, current);
107#endif 215}
108 "single step", istep);
109 216
110/* 217/*
111 * handle NMI 218 * handle NMI
@@ -113,10 +220,8 @@ DO_ERROR(SIGTRAP,
113asmlinkage void nmi(struct pt_regs *regs, enum exception_code code) 220asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
114{ 221{
115 /* see if gdbstub wants to deal with it */ 222 /* see if gdbstub wants to deal with it */
116#ifdef CONFIG_GDBSTUB 223 if (debugger_intercept(code, SIGQUIT, 0, regs))
117 if (gdbstub_intercept(regs, code))
118 return; 224 return;
119#endif
120 225
121 printk(KERN_WARNING "--- Register Dump ---\n"); 226 printk(KERN_WARNING "--- Register Dump ---\n");
122 show_registers(regs); 227 show_registers(regs);
@@ -128,29 +233,36 @@ asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
128 */ 233 */
129void show_trace(unsigned long *sp) 234void show_trace(unsigned long *sp)
130{ 235{
131 unsigned long *stack, addr, module_start, module_end; 236 unsigned long bottom, stack, addr, fp, raslot;
132 int i; 237
133 238 printk(KERN_EMERG "\nCall Trace:\n");
134 printk(KERN_EMERG "\nCall Trace:"); 239
135 240 //stack = (unsigned long)sp;
136 stack = sp; 241 asm("mov sp,%0" : "=a"(stack));
137 i = 0; 242 asm("mov a3,%0" : "=r"(fp));
138 module_start = VMALLOC_START; 243
139 module_end = VMALLOC_END; 244 raslot = ULONG_MAX;
245 bottom = (stack + THREAD_SIZE) & ~(THREAD_SIZE - 1);
246 for (; stack < bottom; stack += sizeof(addr)) {
247 addr = *(unsigned long *)stack;
248 if (stack == fp) {
249 if (addr > stack && addr < bottom) {
250 fp = addr;
251 raslot = stack + sizeof(addr);
252 continue;
253 }
254 fp = 0;
255 raslot = ULONG_MAX;
256 }
140 257
141 while (((long) stack & (THREAD_SIZE - 1)) != 0) {
142 addr = *stack++;
143 if (__kernel_text_address(addr)) { 258 if (__kernel_text_address(addr)) {
144#if 1
145 printk(" [<%08lx>]", addr); 259 printk(" [<%08lx>]", addr);
260 if (stack >= raslot)
261 raslot = ULONG_MAX;
262 else
263 printk(" ?");
146 print_symbol(" %s", addr); 264 print_symbol(" %s", addr);
147 printk("\n"); 265 printk("\n");
148#else
149 if ((i % 6) == 0)
150 printk(KERN_EMERG " ");
151 printk("[<%08lx>] ", addr);
152 i++;
153#endif
154 } 266 }
155 } 267 }
156 268
@@ -323,86 +435,6 @@ void die(const char *str, struct pt_regs *regs, enum exception_code code)
323} 435}
324 436
325/* 437/*
326 * see if there's a fixup handler we can force a jump to when an exception
327 * happens due to something kernel code did
328 */
329int die_if_no_fixup(const char *str, struct pt_regs *regs,
330 enum exception_code code)
331{
332 if (user_mode(regs))
333 return 0;
334
335 peripheral_leds_display_exception(code);
336
337 switch (code) {
338 /* see if we can fixup the kernel accessing memory */
339 case EXCEP_ITLBMISS:
340 case EXCEP_DTLBMISS:
341 case EXCEP_IAERROR:
342 case EXCEP_DAERROR:
343 case EXCEP_MEMERR:
344 case EXCEP_MISALIGN:
345 case EXCEP_BUSERROR:
346 case EXCEP_ILLDATACC:
347 case EXCEP_IOINSACC:
348 case EXCEP_PRIVINSACC:
349 case EXCEP_PRIVDATACC:
350 case EXCEP_DATINSACC:
351 if (fixup_exception(regs))
352 return 1;
353 case EXCEP_UNIMPINS:
354 if (regs->pc && *(uint8_t *)regs->pc == 0xff)
355 if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
356 return 1;
357 break;
358 default:
359 break;
360 }
361
362 /* see if gdbstub wants to deal with it */
363#ifdef CONFIG_GDBSTUB
364 if (gdbstub_intercept(regs, code))
365 return 1;
366#endif
367
368 if (notify_die(DIE_GPF, str, regs, code, 0, 0))
369 return 1;
370
371 /* make the process die as the last resort */
372 die(str, regs, code);
373}
374
375/*
376 * handle unsupported syscall instructions (syscall 1-15)
377 */
378static asmlinkage void unsupported_syscall(struct pt_regs *regs,
379 enum exception_code code)
380{
381 struct task_struct *tsk = current;
382 siginfo_t info;
383
384 /* catch a kernel BUG() */
385 if (code == EXCEP_SYSCALL15 && !user_mode(regs)) {
386 if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) {
387#ifdef CONFIG_GDBSTUB
388 gdbstub_intercept(regs, code);
389#endif
390 }
391 }
392
393 regs->pc -= 2; /* syscall return addr is _after_ the instruction */
394
395 die_if_no_fixup("An unsupported syscall insn was used by the kernel\n",
396 regs, code);
397
398 info.si_signo = SIGILL;
399 info.si_errno = ENOSYS;
400 info.si_code = ILL_ILLTRP;
401 info.si_addr = (void *) regs->pc;
402 force_sig_info(SIGILL, &info, tsk);
403}
404
405/*
406 * display the register file when the stack pointer gets clobbered 438 * display the register file when the stack pointer gets clobbered
407 */ 439 */
408asmlinkage void do_double_fault(struct pt_regs *regs) 440asmlinkage void do_double_fault(struct pt_regs *regs)
@@ -481,10 +513,8 @@ asmlinkage void uninitialised_exception(struct pt_regs *regs,
481{ 513{
482 514
483 /* see if gdbstub wants to deal with it */ 515 /* see if gdbstub wants to deal with it */
484#ifdef CONFIG_GDBSTUB 516 if (debugger_intercept(code, SIGSYS, 0, regs) == 0)
485 if (gdbstub_intercept(regs, code))
486 return; 517 return;
487#endif
488 518
489 peripheral_leds_display_exception(code); 519 peripheral_leds_display_exception(code);
490 printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF); 520 printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF);
@@ -549,43 +579,43 @@ void __init set_intr_stub(enum exception_code code, void *handler)
549 */ 579 */
550void __init trap_init(void) 580void __init trap_init(void)
551{ 581{
552 set_excp_vector(EXCEP_TRAP, trap); 582 set_excp_vector(EXCEP_TRAP, handle_exception);
553 set_excp_vector(EXCEP_ISTEP, istep); 583 set_excp_vector(EXCEP_ISTEP, handle_exception);
554 set_excp_vector(EXCEP_IBREAK, ibreak); 584 set_excp_vector(EXCEP_IBREAK, handle_exception);
555 set_excp_vector(EXCEP_OBREAK, obreak); 585 set_excp_vector(EXCEP_OBREAK, handle_exception);
556 586
557 set_excp_vector(EXCEP_PRIVINS, priv_op); 587 set_excp_vector(EXCEP_PRIVINS, handle_exception);
558 set_excp_vector(EXCEP_UNIMPINS, invalid_op); 588 set_excp_vector(EXCEP_UNIMPINS, handle_exception);
559 set_excp_vector(EXCEP_UNIMPEXINS, invalid_exop); 589 set_excp_vector(EXCEP_UNIMPEXINS, handle_exception);
560 set_excp_vector(EXCEP_MEMERR, mem_error); 590 set_excp_vector(EXCEP_MEMERR, handle_exception);
561 set_excp_vector(EXCEP_MISALIGN, misalignment); 591 set_excp_vector(EXCEP_MISALIGN, misalignment);
562 set_excp_vector(EXCEP_BUSERROR, bus_error); 592 set_excp_vector(EXCEP_BUSERROR, handle_exception);
563 set_excp_vector(EXCEP_ILLINSACC, insn_acc_error); 593 set_excp_vector(EXCEP_ILLINSACC, handle_exception);
564 set_excp_vector(EXCEP_ILLDATACC, data_acc_error); 594 set_excp_vector(EXCEP_ILLDATACC, handle_exception);
565 set_excp_vector(EXCEP_IOINSACC, insn_acc_error); 595 set_excp_vector(EXCEP_IOINSACC, handle_exception);
566 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); 596 set_excp_vector(EXCEP_PRIVINSACC, handle_exception);
567 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); 597 set_excp_vector(EXCEP_PRIVDATACC, handle_exception);
568 set_excp_vector(EXCEP_DATINSACC, insn_acc_error); 598 set_excp_vector(EXCEP_DATINSACC, handle_exception);
569 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); 599 set_excp_vector(EXCEP_FPU_UNIMPINS, handle_exception);
570 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); 600 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
571 601
572 set_excp_vector(EXCEP_NMI, nmi); 602 set_excp_vector(EXCEP_NMI, nmi);
573 603
574 set_excp_vector(EXCEP_SYSCALL1, unsupported_syscall); 604 set_excp_vector(EXCEP_SYSCALL1, handle_exception);
575 set_excp_vector(EXCEP_SYSCALL2, unsupported_syscall); 605 set_excp_vector(EXCEP_SYSCALL2, handle_exception);
576 set_excp_vector(EXCEP_SYSCALL3, unsupported_syscall); 606 set_excp_vector(EXCEP_SYSCALL3, handle_exception);
577 set_excp_vector(EXCEP_SYSCALL4, unsupported_syscall); 607 set_excp_vector(EXCEP_SYSCALL4, handle_exception);
578 set_excp_vector(EXCEP_SYSCALL5, unsupported_syscall); 608 set_excp_vector(EXCEP_SYSCALL5, handle_exception);
579 set_excp_vector(EXCEP_SYSCALL6, unsupported_syscall); 609 set_excp_vector(EXCEP_SYSCALL6, handle_exception);
580 set_excp_vector(EXCEP_SYSCALL7, unsupported_syscall); 610 set_excp_vector(EXCEP_SYSCALL7, handle_exception);
581 set_excp_vector(EXCEP_SYSCALL8, unsupported_syscall); 611 set_excp_vector(EXCEP_SYSCALL8, handle_exception);
582 set_excp_vector(EXCEP_SYSCALL9, unsupported_syscall); 612 set_excp_vector(EXCEP_SYSCALL9, handle_exception);
583 set_excp_vector(EXCEP_SYSCALL10, unsupported_syscall); 613 set_excp_vector(EXCEP_SYSCALL10, handle_exception);
584 set_excp_vector(EXCEP_SYSCALL11, unsupported_syscall); 614 set_excp_vector(EXCEP_SYSCALL11, handle_exception);
585 set_excp_vector(EXCEP_SYSCALL12, unsupported_syscall); 615 set_excp_vector(EXCEP_SYSCALL12, handle_exception);
586 set_excp_vector(EXCEP_SYSCALL13, unsupported_syscall); 616 set_excp_vector(EXCEP_SYSCALL13, handle_exception);
587 set_excp_vector(EXCEP_SYSCALL14, unsupported_syscall); 617 set_excp_vector(EXCEP_SYSCALL14, handle_exception);
588 set_excp_vector(EXCEP_SYSCALL15, unsupported_syscall); 618 set_excp_vector(EXCEP_SYSCALL15, handle_exception);
589} 619}
590 620
591/* 621/*
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache
index c4fd923a55a0..bfbe52691f2c 100644
--- a/arch/mn10300/mm/Kconfig.cache
+++ b/arch/mn10300/mm/Kconfig.cache
@@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE
99 help 99 help
100 Set if we need the icache to be invalidated, even if the dcache is in 100 Set if we need the icache to be invalidated, even if the dcache is in
101 write-through mode and doesn't need flushing. 101 write-through mode and doesn't need flushing.
102
103#
104# The kernel debugger gets its own separate cache flushing functions
105#
106config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG
107 def_bool y if KERNEL_DEBUGGER && \
108 MN10300_CACHE_WBACK && \
109 !MN10300_CACHE_SNOOP && \
110 MN10300_CACHE_MANAGE_BY_TAG
111 help
112 Set if the debugger needs to flush the dcache and invalidate the
113 icache using the cache tag registers to make breakpoints work.
114
115config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG
116 def_bool y if KERNEL_DEBUGGER && \
117 MN10300_CACHE_WBACK && \
118 !MN10300_CACHE_SNOOP && \
119 MN10300_CACHE_MANAGE_BY_REG
120 help
121 Set if the debugger needs to flush the dcache and invalidate the
122 icache using automatic purge registers to make breakpoints work.
123
124config MN10300_DEBUGGER_CACHE_INV_BY_TAG
125 def_bool y if KERNEL_DEBUGGER && \
126 MN10300_CACHE_WTHRU && \
127 !MN10300_CACHE_SNOOP && \
128 MN10300_CACHE_MANAGE_BY_TAG
129 help
130 Set if the debugger needs to invalidate the icache using the cache
131 tag registers to make breakpoints work.
132
133config MN10300_DEBUGGER_CACHE_INV_BY_REG
134 def_bool y if KERNEL_DEBUGGER && \
135 MN10300_CACHE_WTHRU && \
136 !MN10300_CACHE_SNOOP && \
137 MN10300_CACHE_MANAGE_BY_REG
138 help
139 Set if the debugger needs to invalidate the icache using automatic
140 purge registers to make breakpoints work.
141
142config MN10300_DEBUGGER_CACHE_NO_FLUSH
143 def_bool y if KERNEL_DEBUGGER && \
144 (MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP)
145 help
146 Set if the debugger does not need to flush the dcache and/or
147 invalidate the icache to make breakpoints work.
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
index 203fee23f7d7..11f38466ac28 100644
--- a/arch/mn10300/mm/Makefile
+++ b/arch/mn10300/mm/Makefile
@@ -13,6 +13,15 @@ cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
13cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o 13cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
14cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o 14cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
15 15
16cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \
17 cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o
18cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \
19 cache-dbg-flush-by-reg.o
20cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \
21 cache-dbg-inv-by-tag.o cache-dbg-inv.o
22cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \
23 cache-dbg-inv-by-reg.o cache-dbg-inv.o
24
16cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o 25cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
17 26
18obj-y := \ 27obj-y := \
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
new file mode 100644
index 000000000000..665919f2ab62
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
@@ -0,0 +1,160 @@
1/* MN10300 CPU cache invalidation routines, using automatic purge registers
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18#include "cache.inc"
19
20 .am33_2
21
22###############################################################################
23#
24# void debugger_local_cache_flushinv(void)
25# Flush the entire data cache back to RAM and invalidate the icache
26#
27###############################################################################
28 ALIGN
29 .globl debugger_local_cache_flushinv
30 .type debugger_local_cache_flushinv,@function
31debugger_local_cache_flushinv:
32 #
33 # firstly flush the dcache
34 #
35 movhu (CHCTR),d0
36 btst CHCTR_DCEN|CHCTR_ICEN,d0
37 beq debugger_local_cache_flushinv_end
38
39 mov DCPGCR,a0
40
41 mov epsw,d1
42 and ~EPSW_IE,epsw
43 or EPSW_NMID,epsw
44 nop
45
46 btst CHCTR_DCEN,d0
47 beq debugger_local_cache_flushinv_no_dcache
48
49 # wait for busy bit of area purge
50 setlb
51 mov (a0),d0
52 btst DCPGCR_DCPGBSY,d0
53 lne
54
55 # set mask
56 clr d0
57 mov d0,(DCPGMR)
58
59 # area purge
60 #
61 # DCPGCR = DCPGCR_DCP
62 #
63 mov DCPGCR_DCP,d0
64 mov d0,(a0)
65
66 # wait for busy bit of area purge
67 setlb
68 mov (a0),d0
69 btst DCPGCR_DCPGBSY,d0
70 lne
71
72debugger_local_cache_flushinv_no_dcache:
73 #
74 # secondly, invalidate the icache if it is enabled
75 #
76 mov CHCTR,a0
77 movhu (a0),d0
78 btst CHCTR_ICEN,d0
79 beq debugger_local_cache_flushinv_done
80
81 invalidate_icache 0
82
83debugger_local_cache_flushinv_done:
84 mov d1,epsw
85
86debugger_local_cache_flushinv_end:
87 ret [],0
88 .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
89
90###############################################################################
91#
92# void debugger_local_cache_flushinv_one(u8 *addr)
93#
94# Invalidate one particular cacheline if it's in the icache
95#
96###############################################################################
97 ALIGN
98 .globl debugger_local_cache_flushinv_one
99 .type debugger_local_cache_flushinv_one,@function
100debugger_local_cache_flushinv_one:
101 movhu (CHCTR),d1
102 btst CHCTR_DCEN|CHCTR_ICEN,d1
103 beq debugger_local_cache_flushinv_one_end
104 btst CHCTR_DCEN,d1
105 beq debugger_local_cache_flushinv_one_no_dcache
106
107 # round cacheline addr down
108 and L1_CACHE_TAG_MASK,d0
109 mov d0,a1
110 mov d0,d1
111
112 # determine the dcache purge control reg address
113 mov DCACHE_PURGE(0,0),a0
114 and L1_CACHE_TAG_ENTRY,d0
115 add d0,a0
116
117 # retain valid entries in the cache
118 or L1_CACHE_TAG_VALID,d1
119
120 # conditionally purge this line in all ways
121 mov d1,(L1_CACHE_WAYDISP*0,a0)
122
123debugger_local_cache_flushinv_no_dcache:
124 #
125 # now try to flush the icache
126 #
127 mov CHCTR,a0
128 movhu (a0),d0
129 btst CHCTR_ICEN,d0
130 beq mn10300_local_icache_inv_range_reg_end
131
132 LOCAL_CLI_SAVE(d1)
133
134 mov ICIVCR,a0
135
136 # wait for the invalidator to quiesce
137 setlb
138 mov (a0),d0
139 btst ICIVCR_ICIVBSY,d0
140 lne
141
142 # set the mask
143 mov L1_CACHE_TAG_MASK,d0
144 mov d0,(ICIVMR)
145
146 # invalidate the cache line at the given address
147 or ICIVCR_ICI,a1
148 mov a1,(a0)
149
150 # wait for the invalidator to quiesce again
151 setlb
152 mov (a0),d0
153 btst ICIVCR_ICIVBSY,d0
154 lne
155
156 LOCAL_IRQ_RESTORE(d1)
157
158debugger_local_cache_flushinv_one_end:
159 ret [],0
160 .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
new file mode 100644
index 000000000000..bf56930e6e70
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
@@ -0,0 +1,114 @@
1/* MN10300 CPU cache invalidation routines, using direct tag flushing
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18#include "cache.inc"
19
20 .am33_2
21
22###############################################################################
23#
24# void debugger_local_cache_flushinv(void)
25#
26# Flush the entire data cache back to RAM and invalidate the icache
27#
28###############################################################################
29 ALIGN
30 .globl debugger_local_cache_flushinv
31 .type debugger_local_cache_flushinv,@function
32debugger_local_cache_flushinv:
33 #
34 # firstly flush the dcache
35 #
36 movhu (CHCTR),d0
37 btst CHCTR_DCEN|CHCTR_ICEN,d0
38 beq debugger_local_cache_flushinv_end
39
40 btst CHCTR_DCEN,d0
41 beq debugger_local_cache_flushinv_no_dcache
42
43 # read the addresses tagged in the cache's tag RAM and attempt to flush
44 # those addresses specifically
45 # - we rely on the hardware to filter out invalid tag entry addresses
46 mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
47 mov DCACHE_PURGE(0,0),a1 # dcache purge request address
48 mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0 # total number of entries
49
50mn10300_local_dcache_flush_loop:
51 mov (a0),d0
52 and L1_CACHE_TAG_MASK,d0
53 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
54 # cache
55 mov d0,(a1) # conditional purge
56
57 add L1_CACHE_BYTES,a0
58 add L1_CACHE_BYTES,a1
59 add -1,e0
60 bne mn10300_local_dcache_flush_loop
61
62debugger_local_cache_flushinv_no_dcache:
63 #
64 # secondly, invalidate the icache if it is enabled
65 #
66 mov CHCTR,a0
67 movhu (a0),d0
68 btst CHCTR_ICEN,d0
69 beq debugger_local_cache_flushinv_end
70
71 invalidate_icache 1
72
73debugger_local_cache_flushinv_end:
74 ret [],0
75 .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
76
77###############################################################################
78#
79# void debugger_local_cache_flushinv_one(u8 *addr)
80#
81# Invalidate one particular cacheline if it's in the icache
82#
83###############################################################################
84 ALIGN
85 .globl debugger_local_cache_flushinv_one
86 .type debugger_local_cache_flushinv_one,@function
87debugger_local_cache_flushinv_one:
88 movhu (CHCTR),d1
89 btst CHCTR_DCEN|CHCTR_ICEN,d1
90 beq debugger_local_cache_flushinv_one_end
91 btst CHCTR_DCEN,d1
92 beq debugger_local_cache_flushinv_one_icache
93
94 # round cacheline addr down
95 and L1_CACHE_TAG_MASK,d0
96 mov d0,a1
97
98 # determine the dcache purge control reg address
99 mov DCACHE_PURGE(0,0),a0
100 and L1_CACHE_TAG_ENTRY,d0
101 add d0,a0
102
103 # retain valid entries in the cache
104 or L1_CACHE_TAG_VALID,a1
105
106 # conditionally purge this line in all ways
107 mov a1,(L1_CACHE_WAYDISP*0,a0)
108
109 # now go and do the icache
110 bra debugger_local_cache_flushinv_one_icache
111
112debugger_local_cache_flushinv_one_end:
113 ret [],0
114 .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
new file mode 100644
index 000000000000..c4e6252941b1
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
@@ -0,0 +1,69 @@
1/* MN10300 CPU cache invalidation routines, using automatic purge registers
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/cache.h>
14#include <asm/irqflags.h>
15#include <asm/cacheflush.h>
16#include "cache.inc"
17
18 .am33_2
19
20 .globl debugger_local_cache_flushinv_one
21
22###############################################################################
23#
24# void debugger_local_cache_flushinv_one(u8 *addr)
25#
26# Invalidate one particular cacheline if it's in the icache
27#
28###############################################################################
29 ALIGN
30 .globl debugger_local_cache_flushinv_one
31 .type debugger_local_cache_flushinv_one,@function
32debugger_local_cache_flushinv_one:
33 mov d0,a1
34
35 mov CHCTR,a0
36 movhu (a0),d0
37 btst CHCTR_ICEN,d0
38 beq mn10300_local_icache_inv_range_reg_end
39
40 LOCAL_CLI_SAVE(d1)
41
42 mov ICIVCR,a0
43
44 # wait for the invalidator to quiesce
45 setlb
46 mov (a0),d0
47 btst ICIVCR_ICIVBSY,d0
48 lne
49
50 # set the mask
51 mov ~L1_CACHE_TAG_MASK,d0
52 mov d0,(ICIVMR)
53
54 # invalidate the cache line at the given address
55 and ~L1_CACHE_TAG_MASK,a1
56 or ICIVCR_ICI,a1
57 mov a1,(a0)
58
59 # wait for the invalidator to quiesce again
60 setlb
61 mov (a0),d0
62 btst ICIVCR_ICIVBSY,d0
63 lne
64
65 LOCAL_IRQ_RESTORE(d1)
66
67mn10300_local_icache_inv_range_reg_end:
68 ret [],0
69 .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
new file mode 100644
index 000000000000..d8ec821e5f88
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
@@ -0,0 +1,120 @@
1/* MN10300 CPU cache invalidation routines, using direct tag flushing
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18#include "cache.inc"
19
20 .am33_2
21
22 .globl debugger_local_cache_flushinv_one_icache
23
24###############################################################################
25#
26# void debugger_local_cache_flushinv_one(u8 *addr)
27#
28# Invalidate one particular cacheline if it's in the icache
29#
30###############################################################################
31 ALIGN
32 .globl debugger_local_cache_flushinv_one_icache
33 .type debugger_local_cache_flushinv_one_icache,@function
34debugger_local_cache_flushinv_one_icache:
35 movm [d3,a2],(sp)
36
37 mov CHCTR,a2
38 movhu (a2),d0
39 btst CHCTR_ICEN,d0
40 beq debugger_local_cache_flushinv_one_icache_end
41
42 mov d0,a1
43 and L1_CACHE_TAG_MASK,a1
44
45 # read the tags from the tag RAM, and if they indicate a matching valid
46 # cache line then we invalidate that line
47 mov ICACHE_TAG(0,0),a0
48 mov a1,d0
49 and L1_CACHE_TAG_ENTRY,d0
50 add d0,a0 # starting icache tag RAM
51 # access address
52
53 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
54 or L1_CACHE_TAG_VALID,a1
55 mov L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1
56
57 LOCAL_CLI_SAVE(d3)
58
59 # disable the icache
60 movhu (a2),d0
61 and ~CHCTR_ICEN,d0
62 movhu d0,(a2)
63
64 # and wait for it to calm down
65 setlb
66 movhu (a2),d0
67 btst CHCTR_ICBUSY,d0
68 lne
69
70 # check all the way tags for this cache entry
71 mov (a0),d0 # read the tag in the way 0 slot
72 xor a1,d0
73 and d1,d0
74 beq debugger_local_icache_kill # jump if matched
75
76 add L1_CACHE_WAYDISP,a0
77 mov (a0),d0 # read the tag in the way 1 slot
78 xor a1,d0
79 and d1,d0
80 beq debugger_local_icache_kill # jump if matched
81
82 add L1_CACHE_WAYDISP,a0
83 mov (a0),d0 # read the tag in the way 2 slot
84 xor a1,d0
85 and d1,d0
86 beq debugger_local_icache_kill # jump if matched
87
88 add L1_CACHE_WAYDISP,a0
89 mov (a0),d0 # read the tag in the way 3 slot
90 xor a1,d0
91 and d1,d0
92 bne debugger_local_icache_finish # jump if not matched
93
94debugger_local_icache_kill:
95 mov d0,(a0) # kill the tag (D0 is 0 at this point)
96
97debugger_local_icache_finish:
98 # wait for the cache to finish what it's doing
99 setlb
100 movhu (a2),d0
101 btst CHCTR_ICBUSY,d0
102 lne
103
104 # and reenable it
105 or CHCTR_ICEN,d0
106 movhu d0,(a2)
107 movhu (a2),d0
108
109 # re-enable interrupts
110 LOCAL_IRQ_RESTORE(d3)
111
112debugger_local_cache_flushinv_one_icache_end:
113 ret [d3,a2],8
114 .size debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache
115
116#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG
117 .globl debugger_local_cache_flushinv_one
118 .type debugger_local_cache_flushinv_one,@function
119debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache
120#endif
diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S
new file mode 100644
index 000000000000..eba2d6dca066
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv.S
@@ -0,0 +1,47 @@
1/* MN10300 CPU cache invalidation routines
2 *
3 * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
18#include "cache.inc"
19
20 .am33_2
21
22 .globl debugger_local_cache_flushinv
23
24###############################################################################
25#
26# void debugger_local_cache_flushinv(void)
27#
28# Invalidate the entire icache
29#
30###############################################################################
31 ALIGN
32 .globl debugger_local_cache_flushinv
33 .type debugger_local_cache_flushinv,@function
34debugger_local_cache_flushinv:
35 #
36 # we only need to invalidate the icache in this cache mode
37 #
38 mov CHCTR,a0
39 movhu (a0),d0
40 btst CHCTR_ICEN,d0
41 beq debugger_local_cache_flushinv_end
42
43 invalidate_icache 1
44
45debugger_local_cache_flushinv_end:
46 ret [],0
47 .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S
index 5cd6a27dd63e..1ddc06849242 100644
--- a/arch/mn10300/mm/cache-flush-by-tag.S
+++ b/arch/mn10300/mm/cache-flush-by-tag.S
@@ -62,7 +62,7 @@ mn10300_local_dcache_flush:
62 62
63mn10300_local_dcache_flush_loop: 63mn10300_local_dcache_flush_loop:
64 mov (a0),d0 64 mov (a0),d0
65 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 65 and L1_CACHE_TAG_MASK,d0
66 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the 66 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
67 # cache 67 # cache
68 mov d0,(a1) # conditional purge 68 mov d0,(a1) # conditional purge
@@ -112,11 +112,11 @@ mn10300_local_dcache_flush_range:
1121: 1121:
113 113
114 # round start addr down 114 # round start addr down
115 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 115 and L1_CACHE_TAG_MASK,d0
116 mov d0,a1 116 mov d0,a1
117 117
118 add L1_CACHE_BYTES,d1 # round end addr up 118 add L1_CACHE_BYTES,d1 # round end addr up
119 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 119 and L1_CACHE_TAG_MASK,d1
120 120
121 # write a request to flush all instances of an address from the cache 121 # write a request to flush all instances of an address from the cache
122 mov DCACHE_PURGE(0,0),a0 122 mov DCACHE_PURGE(0,0),a0
@@ -215,12 +215,11 @@ mn10300_local_dcache_flush_inv_range:
215 bra mn10300_local_dcache_flush_inv 215 bra mn10300_local_dcache_flush_inv
2161: 2161:
217 217
218 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start 218 and L1_CACHE_TAG_MASK,d0 # round start addr down
219 # addr down
220 mov d0,a1 219 mov d0,a1
221 220
222 add L1_CACHE_BYTES,d1 # round end addr up 221 add L1_CACHE_BYTES,d1 # round end addr up
223 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 222 and L1_CACHE_TAG_MASK,d1
224 223
225 # write a request to flush and invalidate all instances of an address 224 # write a request to flush and invalidate all instances of an address
226 # from the cache 225 # from the cache
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S
index c8950861ed77..a60825b91e77 100644
--- a/arch/mn10300/mm/cache-inv-by-reg.S
+++ b/arch/mn10300/mm/cache-inv-by-reg.S
@@ -15,6 +15,7 @@
15#include <asm/cache.h> 15#include <asm/cache.h>
16#include <asm/irqflags.h> 16#include <asm/irqflags.h>
17#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
18#include "cache.inc"
18 19
19#define mn10300_local_dcache_inv_range_intr_interval \ 20#define mn10300_local_dcache_inv_range_intr_interval \
20 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) 21 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -62,10 +63,7 @@ mn10300_local_icache_inv:
62 btst CHCTR_ICEN,d0 63 btst CHCTR_ICEN,d0
63 beq mn10300_local_icache_inv_end 64 beq mn10300_local_icache_inv_end
64 65
65 # invalidate 66 invalidate_icache 1
66 or CHCTR_ICINV,d0
67 movhu d0,(a0)
68 movhu (a0),d0
69 67
70mn10300_local_icache_inv_end: 68mn10300_local_icache_inv_end:
71 ret [],0 69 ret [],0
@@ -87,11 +85,8 @@ mn10300_local_dcache_inv:
87 btst CHCTR_DCEN,d0 85 btst CHCTR_DCEN,d0
88 beq mn10300_local_dcache_inv_end 86 beq mn10300_local_dcache_inv_end
89 87
90 # invalidate 88 invalidate_dcache 1
91 or CHCTR_DCINV,d0 89
92 movhu d0,(a0)
93 movhu (a0),d0
94
95mn10300_local_dcache_inv_end: 90mn10300_local_dcache_inv_end:
96 ret [],0 91 ret [],0
97 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv 92 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
@@ -121,9 +116,9 @@ mn10300_local_dcache_inv_range:
121 # and if they're not cacheline-aligned, we must flush any bits outside 116 # and if they're not cacheline-aligned, we must flush any bits outside
122 # the range that share cachelines with stuff inside the range 117 # the range that share cachelines with stuff inside the range
123#ifdef CONFIG_MN10300_CACHE_WBACK 118#ifdef CONFIG_MN10300_CACHE_WBACK
124 btst ~(L1_CACHE_BYTES-1),d0 119 btst ~L1_CACHE_TAG_MASK,d0
125 bne 1f 120 bne 1f
126 btst ~(L1_CACHE_BYTES-1),d1 121 btst ~L1_CACHE_TAG_MASK,d1
127 beq 2f 122 beq 2f
1281: 1231:
129 bra mn10300_local_dcache_flush_inv_range 124 bra mn10300_local_dcache_flush_inv_range
@@ -141,12 +136,11 @@ mn10300_local_dcache_inv_range:
141 # writeback mode, in which case we would be in flush and invalidate by 136 # writeback mode, in which case we would be in flush and invalidate by
142 # now 137 # now
143#ifndef CONFIG_MN10300_CACHE_WBACK 138#ifndef CONFIG_MN10300_CACHE_WBACK
144 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start 139 and L1_CACHE_TAG_MASK,d0 # round start addr down
145 # addr down
146 140
147 mov L1_CACHE_BYTES-1,d2 141 mov L1_CACHE_BYTES-1,d2
148 add d2,d1 142 add d2,d1
149 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 # round end addr up 143 and L1_CACHE_TAG_MASK,d1 # round end addr up
150#endif /* !CONFIG_MN10300_CACHE_WBACK */ 144#endif /* !CONFIG_MN10300_CACHE_WBACK */
151 145
152 sub d0,d1,d2 # calculate the total size 146 sub d0,d1,d2 # calculate the total size
diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S
index e9713b40c0ff..ccedce9c144d 100644
--- a/arch/mn10300/mm/cache-inv-by-tag.S
+++ b/arch/mn10300/mm/cache-inv-by-tag.S
@@ -15,6 +15,7 @@
15#include <asm/cache.h> 15#include <asm/cache.h>
16#include <asm/irqflags.h> 16#include <asm/irqflags.h>
17#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
18#include "cache.inc"
18 19
19#define mn10300_local_dcache_inv_range_intr_interval \ 20#define mn10300_local_dcache_inv_range_intr_interval \
20 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) 21 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -70,43 +71,7 @@ mn10300_local_icache_inv:
70 btst CHCTR_ICEN,d0 71 btst CHCTR_ICEN,d0
71 beq mn10300_local_icache_inv_end 72 beq mn10300_local_icache_inv_end
72 73
73#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) 74 invalidate_icache 1
74 LOCAL_CLI_SAVE(d1)
75
76 # disable the icache
77 and ~CHCTR_ICEN,d0
78 movhu d0,(a0)
79
80 # and wait for it to calm down
81 setlb
82 movhu (a0),d0
83 btst CHCTR_ICBUSY,d0
84 lne
85
86 # invalidate
87 or CHCTR_ICINV,d0
88 movhu d0,(a0)
89
90 # wait for the cache to finish
91 mov CHCTR,a0
92 setlb
93 movhu (a0),d0
94 btst CHCTR_ICBUSY,d0
95 lne
96
97 # and reenable it
98 and ~CHCTR_ICINV,d0
99 or CHCTR_ICEN,d0
100 movhu d0,(a0)
101 movhu (a0),d0
102
103 LOCAL_IRQ_RESTORE(d1)
104#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
105 # invalidate
106 or CHCTR_ICINV,d0
107 movhu d0,(a0)
108 movhu (a0),d0
109#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
110 75
111mn10300_local_icache_inv_end: 76mn10300_local_icache_inv_end:
112 ret [],0 77 ret [],0
@@ -128,43 +93,7 @@ mn10300_local_dcache_inv:
128 btst CHCTR_DCEN,d0 93 btst CHCTR_DCEN,d0
129 beq mn10300_local_dcache_inv_end 94 beq mn10300_local_dcache_inv_end
130 95
131#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) 96 invalidate_dcache 1
132 LOCAL_CLI_SAVE(d1)
133
134 # disable the dcache
135 and ~CHCTR_DCEN,d0
136 movhu d0,(a0)
137
138 # and wait for it to calm down
139 setlb
140 movhu (a0),d0
141 btst CHCTR_DCBUSY,d0
142 lne
143
144 # invalidate
145 or CHCTR_DCINV,d0
146 movhu d0,(a0)
147
148 # wait for the cache to finish
149 mov CHCTR,a0
150 setlb
151 movhu (a0),d0
152 btst CHCTR_DCBUSY,d0
153 lne
154
155 # and reenable it
156 and ~CHCTR_DCINV,d0
157 or CHCTR_DCEN,d0
158 movhu d0,(a0)
159 movhu (a0),d0
160
161 LOCAL_IRQ_RESTORE(d1)
162#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
163 # invalidate
164 or CHCTR_DCINV,d0
165 movhu d0,(a0)
166 movhu (a0),d0
167#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
168 97
169mn10300_local_dcache_inv_end: 98mn10300_local_dcache_inv_end:
170 ret [],0 99 ret [],0
@@ -195,9 +124,9 @@ mn10300_local_dcache_inv_range:
195 # and if they're not cacheline-aligned, we must flush any bits outside 124 # and if they're not cacheline-aligned, we must flush any bits outside
196 # the range that share cachelines with stuff inside the range 125 # the range that share cachelines with stuff inside the range
197#ifdef CONFIG_MN10300_CACHE_WBACK 126#ifdef CONFIG_MN10300_CACHE_WBACK
198 btst ~(L1_CACHE_BYTES-1),d0 127 btst ~L1_CACHE_TAG_MASK,d0
199 bne 1f 128 bne 1f
200 btst ~(L1_CACHE_BYTES-1),d1 129 btst ~L1_CACHE_TAG_MASK,d1
201 beq 2f 130 beq 2f
2021: 1311:
203 bra mn10300_local_dcache_flush_inv_range 132 bra mn10300_local_dcache_flush_inv_range
@@ -212,11 +141,10 @@ mn10300_local_dcache_inv_range:
212 beq mn10300_local_dcache_inv_range_end 141 beq mn10300_local_dcache_inv_range_end
213 142
214#ifndef CONFIG_MN10300_CACHE_WBACK 143#ifndef CONFIG_MN10300_CACHE_WBACK
215 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start 144 and L1_CACHE_TAG_MASK,d0 # round start addr down
216 # addr down
217 145
218 add L1_CACHE_BYTES,d1 # round end addr up 146 add L1_CACHE_BYTES,d1 # round end addr up
219 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 147 and L1_CACHE_TAG_MASK,d1
220#endif /* !CONFIG_MN10300_CACHE_WBACK */ 148#endif /* !CONFIG_MN10300_CACHE_WBACK */
221 mov d0,a1 149 mov d0,a1
222 150
diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc
new file mode 100644
index 000000000000..394a119b9c73
--- /dev/null
+++ b/arch/mn10300/mm/cache.inc
@@ -0,0 +1,133 @@
1/* MN10300 CPU core caching macros -*- asm -*-
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12
13###############################################################################
14#
15# Invalidate the instruction cache.
16# A0: Should hold CHCTR
17# D0: Should have been read from CHCTR
18# D1: Will be clobbered
19#
20# On some cores it is necessary to disable the icache whilst we do this.
21#
22###############################################################################
23 .macro invalidate_icache,disable_irq
24
25#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
26 .if \disable_irq
27 # don't want an interrupt routine seeing a disabled cache
28 mov epsw,d1
29 and ~EPSW_IE,epsw
30 or EPSW_NMID,epsw
31 nop
32 nop
33 .endif
34
35 # disable the icache
36 and ~CHCTR_ICEN,d0
37 movhu d0,(a0)
38
39 # and wait for it to calm down
40 setlb
41 movhu (a0),d0
42 btst CHCTR_ICBUSY,d0
43 lne
44
45 # invalidate
46 or CHCTR_ICINV,d0
47 movhu d0,(a0)
48
49 # wait for the cache to finish
50 setlb
51 movhu (a0),d0
52 btst CHCTR_ICBUSY,d0
53 lne
54
55 # and reenable it
56 or CHCTR_ICEN,d0
57 movhu d0,(a0)
58 movhu (a0),d0
59
60 .if \disable_irq
61 LOCAL_IRQ_RESTORE(d1)
62 .endif
63
64#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
65
66 # invalidate
67 or CHCTR_ICINV,d0
68 movhu d0,(a0)
69 movhu (a0),d0
70
71#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
72 .endm
73
74###############################################################################
75#
76# Invalidate the data cache.
77# A0: Should hold CHCTR
78# D0: Should have been read from CHCTR
79# D1: Will be clobbered
80#
81# On some cores it is necessary to disable the dcache whilst we do this.
82#
83###############################################################################
84 .macro invalidate_dcache,disable_irq
85
86#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
87 .if \disable_irq
88 # don't want an interrupt routine seeing a disabled cache
89 mov epsw,d1
90 and ~EPSW_IE,epsw
91 or EPSW_NMID,epsw
92 nop
93 nop
94 .endif
95
96 # disable the dcache
97 and ~CHCTR_DCEN,d0
98 movhu d0,(a0)
99
100 # and wait for it to calm down
101 setlb
102 movhu (a0),d0
103 btst CHCTR_DCBUSY,d0
104 lne
105
106 # invalidate
107 or CHCTR_DCINV,d0
108 movhu d0,(a0)
109
110 # wait for the cache to finish
111 setlb
112 movhu (a0),d0
113 btst CHCTR_DCBUSY,d0
114 lne
115
116 # and reenable it
117 or CHCTR_DCEN,d0
118 movhu d0,(a0)
119 movhu (a0),d0
120
121 .if \disable_irq
122 LOCAL_IRQ_RESTORE(d1)
123 .endif
124
125#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
126
127 # invalidate
128 or CHCTR_DCINV,d0
129 movhu d0,(a0)
130 movhu (a0),d0
131
132#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
133 .endm
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 59c3da49d9d9..0945409a8022 100644
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -28,8 +28,9 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/pgalloc.h> 29#include <asm/pgalloc.h>
30#include <asm/hardirq.h> 30#include <asm/hardirq.h>
31#include <asm/gdb-stub.h>
32#include <asm/cpu-regs.h> 31#include <asm/cpu-regs.h>
32#include <asm/debugger.h>
33#include <asm/gdb-stub.h>
33 34
34/* 35/*
35 * Unlock any spinlocks which will prevent us from getting the 36 * Unlock any spinlocks which will prevent us from getting the
@@ -306,10 +307,8 @@ no_context:
306 printk(" printing pc:\n"); 307 printk(" printing pc:\n");
307 printk(KERN_ALERT "%08lx\n", regs->pc); 308 printk(KERN_ALERT "%08lx\n", regs->pc);
308 309
309#ifdef CONFIG_GDBSTUB 310 debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR,
310 gdbstub_intercept( 311 SIGSEGV, SEGV_ACCERR, regs);
311 regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR);
312#endif
313 312
314 page = PTBR; 313 page = PTBR;
315 page = ((unsigned long *) __va(page))[address >> 22]; 314 page = ((unsigned long *) __va(page))[address >> 22];
diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h
index c1528004163c..967d144f307e 100644
--- a/arch/mn10300/proc-mn103e010/include/proc/cache.h
+++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h
@@ -23,6 +23,7 @@
23#define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ 23#define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */
24#define L1_CACHE_TAG_ENTRY 0x00000ff0 /* cache tag entry address mask */ 24#define L1_CACHE_TAG_ENTRY 0x00000ff0 /* cache tag entry address mask */
25#define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ 25#define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */
26#define L1_CACHE_TAG_MASK +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
26 27
27/* 28/*
28 * specification of the interval between interrupt checking intervals whilst 29 * specification of the interval between interrupt checking intervals whilst
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
index cafd7b5b55b4..bcb5df2d892f 100644
--- a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
@@ -29,6 +29,7 @@
29#define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ 29#define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */
30#define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */ 30#define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */
31#define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ 31#define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */
32#define L1_CACHE_TAG_MASK +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
32 33
33/* 34/*
34 * specification of the interval between interrupt checking intervals whilst 35 * specification of the interval between interrupt checking intervals whilst
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 092e4250a458..10ca03d0a250 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -297,6 +297,7 @@ extern int
297kgdb_handle_exception(int ex_vector, int signo, int err_code, 297kgdb_handle_exception(int ex_vector, int signo, int err_code,
298 struct pt_regs *regs); 298 struct pt_regs *regs);
299extern int kgdb_nmicallback(int cpu, void *regs); 299extern int kgdb_nmicallback(int cpu, void *regs);
300extern void gdbstub_exit(int status);
300 301
301extern int kgdb_single_step; 302extern int kgdb_single_step;
302extern atomic_t kgdb_active; 303extern atomic_t kgdb_active;
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index 481a7bd2dfe7..a11db956dd62 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -1093,3 +1093,33 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd)
1093 put_packet(remcom_out_buffer); 1093 put_packet(remcom_out_buffer);
1094 return 0; 1094 return 0;
1095} 1095}
1096
1097/**
1098 * gdbstub_exit - Send an exit message to GDB
1099 * @status: The exit code to report.
1100 */
1101void gdbstub_exit(int status)
1102{
1103 unsigned char checksum, ch, buffer[3];
1104 int loop;
1105
1106 buffer[0] = 'W';
1107 buffer[1] = hex_asc_hi(status);
1108 buffer[2] = hex_asc_lo(status);
1109
1110 dbg_io_ops->write_char('$');
1111 checksum = 0;
1112
1113 for (loop = 0; loop < 3; loop++) {
1114 ch = buffer[loop];
1115 checksum += ch;
1116 dbg_io_ops->write_char(ch);
1117 }
1118
1119 dbg_io_ops->write_char('#');
1120 dbg_io_ops->write_char(hex_asc_hi(checksum));
1121 dbg_io_ops->write_char(hex_asc_lo(checksum));
1122
1123 /* make sure the output is flushed, lest the bootloader clobber it */
1124 dbg_io_ops->flush();
1125}