diff options
author | David Howells <dhowells@redhat.com> | 2011-03-18 12:54:30 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2011-03-18 12:54:30 -0400 |
commit | 67ddb4052daac9d449caf2643ac365d42a04219a (patch) | |
tree | 7c610973a19b7e70b47294c540b182f203680fde | |
parent | 7f386ac3272e057fbf51e5b5712fad1a80e77125 (diff) |
MN10300: Create generic kernel debugger hooks
Create generic kernel debugger hooks in the MN10300 arch and make gdbstub use
them. This is a preparation for KGDB support.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | arch/mn10300/Kconfig | 6 | ||||
-rw-r--r-- | arch/mn10300/include/asm/debugger.h | 15 | ||||
-rw-r--r-- | arch/mn10300/include/asm/fpu.h | 2 | ||||
-rw-r--r-- | arch/mn10300/include/asm/irqflags.h | 2 | ||||
-rw-r--r-- | arch/mn10300/include/asm/smp.h | 3 | ||||
-rw-r--r-- | arch/mn10300/kernel/entry.S | 36 | ||||
-rw-r--r-- | arch/mn10300/kernel/fpu.c | 18 | ||||
-rw-r--r-- | arch/mn10300/kernel/gdb-io-ttysm.c | 8 | ||||
-rw-r--r-- | arch/mn10300/kernel/gdb-stub.c | 25 | ||||
-rw-r--r-- | arch/mn10300/kernel/internal.h | 7 | ||||
-rw-r--r-- | arch/mn10300/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/mn10300/kernel/smp.c | 26 | ||||
-rw-r--r-- | arch/mn10300/kernel/traps.c | 406 | ||||
-rw-r--r-- | arch/mn10300/mm/fault.c | 9 |
14 files changed, 317 insertions, 248 deletions
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 25e6a0bc62ab..6e9cac970024 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -401,8 +401,8 @@ comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highes | |||
401 | comment "____Non-maskable interrupt levels____" | 401 | comment "____Non-maskable interrupt levels____" |
402 | comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial" | 402 | comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial" |
403 | 403 | ||
404 | config GDBSTUB_IRQ_LEVEL | 404 | config DEBUGGER_IRQ_LEVEL |
405 | int "GDBSTUB interrupt priority" | 405 | int "DEBUGGER interrupt priority" |
406 | depends on KERNEL_DEBUGGER | 406 | depends on KERNEL_DEBUGGER |
407 | range 0 1 if LINUX_CLI_LEVEL = 2 | 407 | range 0 1 if LINUX_CLI_LEVEL = 2 |
408 | range 0 2 if LINUX_CLI_LEVEL = 3 | 408 | range 0 2 if LINUX_CLI_LEVEL = 3 |
@@ -437,7 +437,7 @@ config LINUX_CLI_LEVEL | |||
437 | EPSW.IM from 7. Any interrupt is permitted for which the level is | 437 | EPSW.IM from 7. Any interrupt is permitted for which the level is |
438 | lower than EPSW.IM. | 438 | lower than EPSW.IM. |
439 | 439 | ||
440 | Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip | 440 | Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip |
441 | serial DMA interrupts are allowed to interrupt normal disabled | 441 | serial DMA interrupts are allowed to interrupt normal disabled |
442 | sections. | 442 | sections. |
443 | 443 | ||
diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h index 4517f839a999..e1d3b083696c 100644 --- a/arch/mn10300/include/asm/debugger.h +++ b/arch/mn10300/include/asm/debugger.h | |||
@@ -14,6 +14,9 @@ | |||
14 | 14 | ||
15 | #if defined(CONFIG_KERNEL_DEBUGGER) | 15 | #if defined(CONFIG_KERNEL_DEBUGGER) |
16 | 16 | ||
17 | extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *); | ||
18 | extern int at_debugger_breakpoint(struct pt_regs *); | ||
19 | |||
17 | #ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH | 20 | #ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH |
18 | extern void debugger_local_cache_flushinv(void); | 21 | extern void debugger_local_cache_flushinv(void); |
19 | extern void debugger_local_cache_flushinv_one(u8 *); | 22 | extern void debugger_local_cache_flushinv_one(u8 *); |
@@ -24,5 +27,17 @@ static inline void debugger_local_cache_flushinv_one(u8 *addr) {} | |||
24 | 27 | ||
25 | #else /* CONFIG_KERNEL_DEBUGGER */ | 28 | #else /* CONFIG_KERNEL_DEBUGGER */ |
26 | 29 | ||
30 | static 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 | |||
37 | static inline int at_debugger_breakpoint(struct pt_regs *regs) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | |||
27 | #endif /* CONFIG_KERNEL_DEBUGGER */ | 42 | #endif /* CONFIG_KERNEL_DEBUGGER */ |
28 | #endif /* _ASM_DEBUGGER_H */ | 43 | #endif /* _ASM_DEBUGGER_H */ |
diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h index b7625de8eade..738ff72659d5 100644 --- a/arch/mn10300/include/asm/fpu.h +++ b/arch/mn10300/include/asm/fpu.h | |||
@@ -55,7 +55,6 @@ static inline void clear_using_fpu(struct task_struct *tsk) | |||
55 | 55 | ||
56 | extern asmlinkage void fpu_kill_state(struct task_struct *); | 56 | extern asmlinkage void fpu_kill_state(struct task_struct *); |
57 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); | 57 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); |
58 | extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code); | ||
59 | extern asmlinkage void fpu_init_state(void); | 58 | extern asmlinkage void fpu_init_state(void); |
60 | extern asmlinkage void fpu_save(struct fpu_state_struct *); | 59 | extern asmlinkage void fpu_save(struct fpu_state_struct *); |
61 | extern int fpu_setup_sigcontext(struct fpucontext *buf); | 60 | extern int fpu_setup_sigcontext(struct fpucontext *buf); |
@@ -113,7 +112,6 @@ static inline void flush_fpu(void) | |||
113 | 112 | ||
114 | extern asmlinkage | 113 | extern asmlinkage |
115 | void unexpected_fpu_exception(struct pt_regs *, enum exception_code); | 114 | void 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 | ||
119 | struct task_struct; | 117 | struct task_struct; |
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index 7a7ae12c7119..678f68d5f37b 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h | |||
@@ -20,7 +20,7 @@ | |||
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/smp.h b/arch/mn10300/include/asm/smp.h index a3930e43a958..e3d13a899855 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h | |||
@@ -34,7 +34,7 @@ | |||
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 |
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 8e79a04f1cb0..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 | ############################################################################### |
272 | ENTRY(nmi_handler) | 276 | ENTRY(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,30 +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 | ||
298 | 5: | 302 | nmi_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 | 313 | ||
310 | mov (sp),d0 | 314 | mov (sp),d0 |
311 | SAVE_ALL | 315 | SAVE_ALL |
312 | 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 | ||
313 | RESTORE_ALL | 319 | RESTORE_ALL |
314 | 3: | 320 | |
315 | #endif /* CONFIG_GDBSTUB */ | 321 | nmi_not_debugger: |
322 | #endif /* CONFIG_KERNEL_DEBUGGER */ | ||
316 | mov (sp),d0 # restore TBR to d0 | 323 | mov (sp),d0 # restore TBR to d0 |
317 | add 4,sp | 324 | add 4,sp |
318 | #endif /* CONFIG_SMP */ | 325 | #endif /* CONFIG_SMP */ |
319 | 326 | ||
320 | bra __common_exception_nonmi | 327 | bra __common_exception_nonmi |
321 | 328 | ||
329 | ############################################################################### | ||
330 | # | ||
331 | # General exception entry point | ||
332 | # | ||
333 | ############################################################################### | ||
322 | ENTRY(__common_exception) | 334 | ENTRY(__common_exception) |
323 | add -4,sp | 335 | add -4,sp |
324 | 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 | */ | ||
76 | asmlinkage 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 | */ |
93 | int fpu_setup_sigcontext(struct fpucontext *fpucontext) | 75 | int fpu_setup_sigcontext(struct fpucontext *fpucontext) |
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 1e8f24f00637..538266b2c9bc 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c | |||
@@ -1173,7 +1173,7 @@ int gdbstub_clear_breakpoint(u8 *addr, int len) | |||
1173 | 1173 | ||
1174 | /* | 1174 | /* |
1175 | * This function does all command processing for interfacing to gdb | 1175 | * This function does all command processing for interfacing to gdb |
1176 | * - returns 1 if the exception should be skipped, 0 otherwise. | 1176 | * - returns 0 if the exception should be skipped, -ERROR otherwise. |
1177 | */ | 1177 | */ |
1178 | static int gdbstub(struct pt_regs *regs, enum exception_code excep) | 1178 | static int gdbstub(struct pt_regs *regs, enum exception_code excep) |
1179 | { | 1179 | { |
@@ -1188,7 +1188,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) | |||
1188 | int loop; | 1188 | int loop; |
1189 | 1189 | ||
1190 | if (excep == EXCEP_FPU_DISABLED) | 1190 | if (excep == EXCEP_FPU_DISABLED) |
1191 | return 0; | 1191 | return -ENOTSUPP; |
1192 | 1192 | ||
1193 | gdbstub_flush_caches = 0; | 1193 | gdbstub_flush_caches = 0; |
1194 | 1194 | ||
@@ -1197,7 +1197,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) | |||
1197 | asm volatile("mov mdr,%0" : "=d"(mdr)); | 1197 | asm volatile("mov mdr,%0" : "=d"(mdr)); |
1198 | local_save_flags(epsw); | 1198 | local_save_flags(epsw); |
1199 | arch_local_change_intr_mask_level( | 1199 | arch_local_change_intr_mask_level( |
1200 | NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); | 1200 | NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1)); |
1201 | 1201 | ||
1202 | gdbstub_store_fpu(); | 1202 | gdbstub_store_fpu(); |
1203 | 1203 | ||
@@ -1675,14 +1675,23 @@ done: | |||
1675 | touch_softlockup_watchdog(); | 1675 | touch_softlockup_watchdog(); |
1676 | 1676 | ||
1677 | local_irq_restore(epsw); | 1677 | local_irq_restore(epsw); |
1678 | return 1; | 1678 | return 0; |
1679 | } | ||
1680 | |||
1681 | /* | ||
1682 | * Determine if we hit a debugger special breakpoint that needs skipping over | ||
1683 | * automatically. | ||
1684 | */ | ||
1685 | int at_debugger_breakpoint(struct pt_regs *regs) | ||
1686 | { | ||
1687 | return 0; | ||
1679 | } | 1688 | } |
1680 | 1689 | ||
1681 | /* | 1690 | /* |
1682 | * handle event interception | 1691 | * handle event interception |
1683 | */ | 1692 | */ |
1684 | asmlinkage int gdbstub_intercept(struct pt_regs *regs, | 1693 | asmlinkage int debugger_intercept(enum exception_code excep, |
1685 | enum exception_code excep) | 1694 | int signo, int si_code, struct pt_regs *regs) |
1686 | { | 1695 | { |
1687 | static u8 notfirst = 1; | 1696 | static u8 notfirst = 1; |
1688 | int ret; | 1697 | int ret; |
@@ -1696,7 +1705,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, | |||
1696 | asm("mov mdr,%0" : "=d"(mdr)); | 1705 | asm("mov mdr,%0" : "=d"(mdr)); |
1697 | 1706 | ||
1698 | gdbstub_entry( | 1707 | gdbstub_entry( |
1699 | "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", | 1708 | "--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", |
1700 | regs, excep, mdr, regs->pc); | 1709 | regs, excep, mdr, regs->pc); |
1701 | 1710 | ||
1702 | gdbstub_entry( | 1711 | gdbstub_entry( |
@@ -1730,7 +1739,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, | |||
1730 | 1739 | ||
1731 | ret = gdbstub(regs, excep); | 1740 | ret = gdbstub(regs, excep); |
1732 | 1741 | ||
1733 | gdbstub_entry("<-- gdbstub_intercept()\n"); | 1742 | gdbstub_entry("<-- debugger_intercept()\n"); |
1734 | gdbstub_busy = 0; | 1743 | gdbstub_busy = 0; |
1735 | return ret; | 1744 | return ret; |
1736 | } | 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 | ||
36 | extern void smp_jump_to_debugger(void); | ||
37 | #endif | ||
38 | |||
39 | /* | ||
33 | * time.c | 40 | * time.c |
34 | */ | 41 | */ |
35 | extern irqreturn_t local_timer_interrupt(void); | 42 | extern 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/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 | */ | ||
451 | void 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 | */ |
608 | void smp_prepare_cpu_init(void) | 624 | void 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/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 | ||
50 | spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); | 51 | spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); |
51 | 52 | ||
52 | ATOMIC_NOTIFIER_HEAD(mn10300_die_chain); | 53 | struct exception_to_signal_map { |
54 | u8 signo; | ||
55 | u32 si_code; | ||
56 | }; | ||
57 | |||
58 | static 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) | 125 | int 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 | { |
62 | asmlinkage 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: |
71 | asmlinkage 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 | ||
90 | DO_ERROR(SIGTRAP, {}, "trap", trap); | 198 | /* |
91 | DO_ERROR(SIGSEGV, {}, "ibreak", ibreak); | 199 | * General exception handler |
92 | DO_ERROR(SIGSEGV, {}, "obreak", obreak); | 200 | */ |
93 | DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR); | 201 | asmlinkage void handle_exception(struct pt_regs *regs, u32 intcode) |
94 | DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR); | 202 | { |
95 | DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR); | 203 | siginfo_t info; |
96 | DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC); | 204 | |
97 | DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); | 205 | /* deal with kernel exceptions here */ |
98 | DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); | 206 | if (die_if_no_fixup(NULL, regs, intcode)) |
99 | DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); | 207 | return; |
100 | DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); | 208 | |
101 | 209 | /* otherwise it's a userspace exception */ | |
102 | DO_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, | |||
113 | asmlinkage void nmi(struct pt_regs *regs, enum exception_code code) | 220 | asmlinkage 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 | */ |
129 | void show_trace(unsigned long *sp) | 234 | void 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 | */ | ||
329 | int 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 | */ | ||
378 | static 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 | */ |
408 | asmlinkage void do_double_fault(struct pt_regs *regs) | 440 | asmlinkage 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 | */ |
550 | void __init trap_init(void) | 580 | void __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/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]; |