diff options
author | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
commit | b32e3dc7860d00124fa432dba09667e647cb9bcc (patch) | |
tree | 2fa6e56f389431dfb84609d3d7572cad76e88e71 /arch/mn10300/kernel | |
parent | 6604271c5bc658a6067ed0c3deba4d89e0e50382 (diff) | |
parent | 96120d86fe302c006259baee9061eea9e1b9e486 (diff) |
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
Diffstat (limited to 'arch/mn10300/kernel')
-rw-r--r-- | arch/mn10300/kernel/Makefile | 10 | ||||
-rw-r--r-- | arch/mn10300/kernel/cevt-mn10300.c | 11 | ||||
-rw-r--r-- | arch/mn10300/kernel/csrc-mn10300.c | 3 | ||||
-rw-r--r-- | arch/mn10300/kernel/entry.S | 67 | ||||
-rw-r--r-- | arch/mn10300/kernel/fpu.c | 18 | ||||
-rw-r--r-- | arch/mn10300/kernel/gdb-cache.S | 105 | ||||
-rw-r--r-- | arch/mn10300/kernel/gdb-io-ttysm.c | 8 | ||||
-rw-r--r-- | arch/mn10300/kernel/gdb-stub.c | 41 | ||||
-rw-r--r-- | arch/mn10300/kernel/internal.h | 13 | ||||
-rw-r--r-- | arch/mn10300/kernel/irq.c | 172 | ||||
-rw-r--r-- | arch/mn10300/kernel/kgdb.c | 502 | ||||
-rw-r--r-- | arch/mn10300/kernel/mn10300-serial.c | 93 | ||||
-rw-r--r-- | arch/mn10300/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/mn10300/kernel/smp.c | 68 | ||||
-rw-r--r-- | arch/mn10300/kernel/switch_to.S | 111 | ||||
-rw-r--r-- | arch/mn10300/kernel/time.c | 82 | ||||
-rw-r--r-- | arch/mn10300/kernel/traps.c | 406 |
17 files changed, 1092 insertions, 624 deletions
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 8f5f1e81baf5..47ed30fe8178 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile | |||
@@ -8,7 +8,8 @@ fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o | |||
8 | 8 | ||
9 | obj-y := process.o signal.o entry.o traps.o irq.o \ | 9 | obj-y := process.o signal.o entry.o traps.o irq.o \ |
10 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ | 10 | ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ |
11 | switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) | 11 | switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \ |
12 | csrc-mn10300.o cevt-mn10300.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_SMP) += smp.o smp-low.o | 14 | obj-$(CONFIG_SMP) += smp.o smp-low.o |
14 | 15 | ||
@@ -20,13 +21,8 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o | |||
20 | obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o | 21 | obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o |
21 | obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o | 22 | obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o |
22 | 23 | ||
23 | ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y) | ||
24 | obj-$(CONFIG_GDBSTUB) += gdb-cache.o | ||
25 | endif | ||
26 | |||
27 | obj-$(CONFIG_MN10300_RTC) += rtc.o | 24 | obj-$(CONFIG_MN10300_RTC) += rtc.o |
28 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o | 25 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o |
29 | obj-$(CONFIG_MODULES) += module.o | 26 | obj-$(CONFIG_MODULES) += module.o |
30 | obj-$(CONFIG_KPROBES) += kprobes.o | 27 | obj-$(CONFIG_KPROBES) += kprobes.o |
31 | obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o | 28 | obj-$(CONFIG_KGDB) += kgdb.o |
32 | obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o | ||
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index d4cb535bf786..69cae0260786 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c | |||
@@ -89,9 +89,10 @@ int __init init_clockevents(void) | |||
89 | cd->name = "Timestamp"; | 89 | cd->name = "Timestamp"; |
90 | cd->features = CLOCK_EVT_FEAT_ONESHOT; | 90 | cd->features = CLOCK_EVT_FEAT_ONESHOT; |
91 | 91 | ||
92 | /* Calculate the min / max delta */ | 92 | /* Calculate shift/mult. We want to spawn at least 1 second */ |
93 | clockevent_set_clock(cd, MN10300_JCCLK); | 93 | clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1); |
94 | 94 | ||
95 | /* Calculate the min / max delta */ | ||
95 | cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); | 96 | cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); |
96 | cd->min_delta_ns = clockevent_delta2ns(100, cd); | 97 | cd->min_delta_ns = clockevent_delta2ns(100, cd); |
97 | 98 | ||
@@ -110,9 +111,9 @@ int __init init_clockevents(void) | |||
110 | #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | 111 | #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) |
111 | /* setup timer irq affinity so it only runs on this cpu */ | 112 | /* setup timer irq affinity so it only runs on this cpu */ |
112 | { | 113 | { |
113 | struct irq_desc *desc; | 114 | struct irq_data *data; |
114 | desc = irq_to_desc(cd->irq); | 115 | data = irq_get_irq_data(cd->irq); |
115 | cpumask_copy(desc->affinity, cpumask_of(cpu)); | 116 | cpumask_copy(data->affinity, cpumask_of(cpu)); |
116 | iact->flags |= IRQF_NOBALANCING; | 117 | iact->flags |= IRQF_NOBALANCING; |
117 | } | 118 | } |
118 | #endif | 119 | #endif |
diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c index ba2f0c4d6e01..45644cf18c41 100644 --- a/arch/mn10300/kernel/csrc-mn10300.c +++ b/arch/mn10300/kernel/csrc-mn10300.c | |||
@@ -29,7 +29,6 @@ static struct clocksource clocksource_mn10300 = { | |||
29 | int __init init_clocksource(void) | 29 | int __init init_clocksource(void) |
30 | { | 30 | { |
31 | startup_timestamp_counter(); | 31 | startup_timestamp_counter(); |
32 | clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK); | 32 | clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK); |
33 | clocksource_register(&clocksource_mn10300); | ||
34 | return 0; | 33 | return 0; |
35 | } | 34 | } |
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 | ############################################################################### |
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,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 | ||
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 | #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 | ||
336 | 4: | ||
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 |
343 | 3: | 320 | |
344 | #endif /* CONFIG_GDBSTUB */ | 321 | nmi_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 | ############################################################################### | ||
351 | ENTRY(__common_exception) | 334 | ENTRY(__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 | */ | ||
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-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 | ||
31 | ENTRY(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 | |||
40 | mn10300_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 | |||
47 | mn10300_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 | */ |
1176 | static int gdbstub(struct pt_regs *regs, enum exception_code excep) | 1178 | static 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 | */ | ||
1685 | int 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 | */ |
1676 | asmlinkage int gdbstub_intercept(struct pt_regs *regs, | 1693 | asmlinkage 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 6a064ab5af07..a5ac755dd69f 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h | |||
@@ -30,16 +30,13 @@ extern void mn10300_low_ipi_handler(void); | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * time.c | 33 | * smp.c |
34 | */ | 34 | */ |
35 | extern irqreturn_t local_timer_interrupt(void); | 35 | #ifdef CONFIG_SMP |
36 | extern void smp_jump_to_debugger(void); | ||
37 | #endif | ||
36 | 38 | ||
37 | /* | 39 | /* |
38 | * time.c | 40 | * time.c |
39 | */ | 41 | */ |
40 | #ifdef CONFIG_CEVT_MN10300 | 42 | extern irqreturn_t local_timer_interrupt(void); |
41 | extern void clockevent_set_clock(struct clock_event_device *, unsigned int); | ||
42 | #endif | ||
43 | #ifdef CONFIG_CSRC_MN10300 | ||
44 | extern void clocksource_set_clock(struct clocksource *, unsigned int); | ||
45 | #endif | ||
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index ac11754ecec5..86af0d7d0771 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
@@ -37,8 +37,9 @@ atomic_t irq_err_count; | |||
37 | /* | 37 | /* |
38 | * MN10300 interrupt controller operations | 38 | * MN10300 interrupt controller operations |
39 | */ | 39 | */ |
40 | static void mn10300_cpupic_ack(unsigned int irq) | 40 | static void mn10300_cpupic_ack(struct irq_data *d) |
41 | { | 41 | { |
42 | unsigned int irq = d->irq; | ||
42 | unsigned long flags; | 43 | unsigned long flags; |
43 | u16 tmp; | 44 | u16 tmp; |
44 | 45 | ||
@@ -61,13 +62,14 @@ static void __mask_and_set_icr(unsigned int irq, | |||
61 | arch_local_irq_restore(flags); | 62 | arch_local_irq_restore(flags); |
62 | } | 63 | } |
63 | 64 | ||
64 | static void mn10300_cpupic_mask(unsigned int irq) | 65 | static void mn10300_cpupic_mask(struct irq_data *d) |
65 | { | 66 | { |
66 | __mask_and_set_icr(irq, GxICR_LEVEL, 0); | 67 | __mask_and_set_icr(d->irq, GxICR_LEVEL, 0); |
67 | } | 68 | } |
68 | 69 | ||
69 | static void mn10300_cpupic_mask_ack(unsigned int irq) | 70 | static void mn10300_cpupic_mask_ack(struct irq_data *d) |
70 | { | 71 | { |
72 | unsigned int irq = d->irq; | ||
71 | #ifdef CONFIG_SMP | 73 | #ifdef CONFIG_SMP |
72 | unsigned long flags; | 74 | unsigned long flags; |
73 | u16 tmp; | 75 | u16 tmp; |
@@ -85,7 +87,7 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) | |||
85 | tmp2 = GxICR(irq); | 87 | tmp2 = GxICR(irq); |
86 | 88 | ||
87 | irq_affinity_online[irq] = | 89 | irq_affinity_online[irq] = |
88 | any_online_cpu(*irq_desc[irq].affinity); | 90 | any_online_cpu(*d->affinity); |
89 | CROSS_GxICR(irq, irq_affinity_online[irq]) = | 91 | CROSS_GxICR(irq, irq_affinity_online[irq]) = |
90 | (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; | 92 | (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; |
91 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); | 93 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); |
@@ -97,13 +99,14 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) | |||
97 | #endif /* CONFIG_SMP */ | 99 | #endif /* CONFIG_SMP */ |
98 | } | 100 | } |
99 | 101 | ||
100 | static void mn10300_cpupic_unmask(unsigned int irq) | 102 | static void mn10300_cpupic_unmask(struct irq_data *d) |
101 | { | 103 | { |
102 | __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE); | 104 | __mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE); |
103 | } | 105 | } |
104 | 106 | ||
105 | static void mn10300_cpupic_unmask_clear(unsigned int irq) | 107 | static void mn10300_cpupic_unmask_clear(struct irq_data *d) |
106 | { | 108 | { |
109 | unsigned int irq = d->irq; | ||
107 | /* the MN10300 PIC latches its interrupt request bit, even after the | 110 | /* the MN10300 PIC latches its interrupt request bit, even after the |
108 | * device has ceased to assert its interrupt line and the interrupt | 111 | * device has ceased to assert its interrupt line and the interrupt |
109 | * channel has been disabled in the PIC, so for level-triggered | 112 | * channel has been disabled in the PIC, so for level-triggered |
@@ -121,7 +124,7 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) | |||
121 | } else { | 124 | } else { |
122 | tmp = GxICR(irq); | 125 | tmp = GxICR(irq); |
123 | 126 | ||
124 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | 127 | irq_affinity_online[irq] = any_online_cpu(*d->affinity); |
125 | CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | 128 | CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; |
126 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); | 129 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); |
127 | } | 130 | } |
@@ -134,7 +137,8 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) | |||
134 | 137 | ||
135 | #ifdef CONFIG_SMP | 138 | #ifdef CONFIG_SMP |
136 | static int | 139 | static int |
137 | mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) | 140 | mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask, |
141 | bool force) | ||
138 | { | 142 | { |
139 | unsigned long flags; | 143 | unsigned long flags; |
140 | int err; | 144 | int err; |
@@ -142,14 +146,14 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) | |||
142 | flags = arch_local_cli_save(); | 146 | flags = arch_local_cli_save(); |
143 | 147 | ||
144 | /* check irq no */ | 148 | /* check irq no */ |
145 | switch (irq) { | 149 | switch (d->irq) { |
146 | case TMJCIRQ: | 150 | case TMJCIRQ: |
147 | case RESCHEDULE_IPI: | 151 | case RESCHEDULE_IPI: |
148 | case CALL_FUNC_SINGLE_IPI: | 152 | case CALL_FUNC_SINGLE_IPI: |
149 | case LOCAL_TIMER_IPI: | 153 | case LOCAL_TIMER_IPI: |
150 | case FLUSH_CACHE_IPI: | 154 | case FLUSH_CACHE_IPI: |
151 | case CALL_FUNCTION_NMI_IPI: | 155 | case CALL_FUNCTION_NMI_IPI: |
152 | case GDB_NMI_IPI: | 156 | case DEBUGGER_NMI_IPI: |
153 | #ifdef CONFIG_MN10300_TTYSM0 | 157 | #ifdef CONFIG_MN10300_TTYSM0 |
154 | case SC0RXIRQ: | 158 | case SC0RXIRQ: |
155 | case SC0TXIRQ: | 159 | case SC0TXIRQ: |
@@ -181,7 +185,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) | |||
181 | break; | 185 | break; |
182 | 186 | ||
183 | default: | 187 | default: |
184 | set_bit(irq, irq_affinity_request); | 188 | set_bit(d->irq, irq_affinity_request); |
185 | err = 0; | 189 | err = 0; |
186 | break; | 190 | break; |
187 | } | 191 | } |
@@ -202,15 +206,15 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) | |||
202 | * mask_ack() is provided), and mask_ack() just masks. | 206 | * mask_ack() is provided), and mask_ack() just masks. |
203 | */ | 207 | */ |
204 | static struct irq_chip mn10300_cpu_pic_level = { | 208 | static struct irq_chip mn10300_cpu_pic_level = { |
205 | .name = "cpu_l", | 209 | .name = "cpu_l", |
206 | .disable = mn10300_cpupic_mask, | 210 | .irq_disable = mn10300_cpupic_mask, |
207 | .enable = mn10300_cpupic_unmask_clear, | 211 | .irq_enable = mn10300_cpupic_unmask_clear, |
208 | .ack = NULL, | 212 | .irq_ack = NULL, |
209 | .mask = mn10300_cpupic_mask, | 213 | .irq_mask = mn10300_cpupic_mask, |
210 | .mask_ack = mn10300_cpupic_mask, | 214 | .irq_mask_ack = mn10300_cpupic_mask, |
211 | .unmask = mn10300_cpupic_unmask_clear, | 215 | .irq_unmask = mn10300_cpupic_unmask_clear, |
212 | #ifdef CONFIG_SMP | 216 | #ifdef CONFIG_SMP |
213 | .set_affinity = mn10300_cpupic_setaffinity, | 217 | .irq_set_affinity = mn10300_cpupic_setaffinity, |
214 | #endif | 218 | #endif |
215 | }; | 219 | }; |
216 | 220 | ||
@@ -220,15 +224,15 @@ static struct irq_chip mn10300_cpu_pic_level = { | |||
220 | * We use the latch clearing function of the PIC as the 'ACK' function. | 224 | * We use the latch clearing function of the PIC as the 'ACK' function. |
221 | */ | 225 | */ |
222 | static struct irq_chip mn10300_cpu_pic_edge = { | 226 | static struct irq_chip mn10300_cpu_pic_edge = { |
223 | .name = "cpu_e", | 227 | .name = "cpu_e", |
224 | .disable = mn10300_cpupic_mask, | 228 | .irq_disable = mn10300_cpupic_mask, |
225 | .enable = mn10300_cpupic_unmask, | 229 | .irq_enable = mn10300_cpupic_unmask, |
226 | .ack = mn10300_cpupic_ack, | 230 | .irq_ack = mn10300_cpupic_ack, |
227 | .mask = mn10300_cpupic_mask, | 231 | .irq_mask = mn10300_cpupic_mask, |
228 | .mask_ack = mn10300_cpupic_mask_ack, | 232 | .irq_mask_ack = mn10300_cpupic_mask_ack, |
229 | .unmask = mn10300_cpupic_unmask, | 233 | .irq_unmask = mn10300_cpupic_unmask, |
230 | #ifdef CONFIG_SMP | 234 | #ifdef CONFIG_SMP |
231 | .set_affinity = mn10300_cpupic_setaffinity, | 235 | .irq_set_affinity = mn10300_cpupic_setaffinity, |
232 | #endif | 236 | #endif |
233 | }; | 237 | }; |
234 | 238 | ||
@@ -252,31 +256,6 @@ void set_intr_level(int irq, u16 level) | |||
252 | __mask_and_set_icr(irq, GxICR_ENABLE, level); | 256 | __mask_and_set_icr(irq, GxICR_ENABLE, level); |
253 | } | 257 | } |
254 | 258 | ||
255 | void mn10300_intc_set_level(unsigned int irq, unsigned int level) | ||
256 | { | ||
257 | set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL); | ||
258 | } | ||
259 | |||
260 | void mn10300_intc_clear(unsigned int irq) | ||
261 | { | ||
262 | __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT); | ||
263 | } | ||
264 | |||
265 | void mn10300_intc_set(unsigned int irq) | ||
266 | { | ||
267 | __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT); | ||
268 | } | ||
269 | |||
270 | void mn10300_intc_enable(unsigned int irq) | ||
271 | { | ||
272 | mn10300_cpupic_unmask(irq); | ||
273 | } | ||
274 | |||
275 | void mn10300_intc_disable(unsigned int irq) | ||
276 | { | ||
277 | mn10300_cpupic_mask(irq); | ||
278 | } | ||
279 | |||
280 | /* | 259 | /* |
281 | * mark an interrupt to be ACK'd after interrupt handlers have been run rather | 260 | * mark an interrupt to be ACK'd after interrupt handlers have been run rather |
282 | * than before | 261 | * than before |
@@ -284,7 +263,7 @@ void mn10300_intc_disable(unsigned int irq) | |||
284 | */ | 263 | */ |
285 | void mn10300_set_lateack_irq_type(int irq) | 264 | void mn10300_set_lateack_irq_type(int irq) |
286 | { | 265 | { |
287 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, | 266 | irq_set_chip_and_handler(irq, &mn10300_cpu_pic_level, |
288 | handle_level_irq); | 267 | handle_level_irq); |
289 | } | 268 | } |
290 | 269 | ||
@@ -296,12 +275,12 @@ void __init init_IRQ(void) | |||
296 | int irq; | 275 | int irq; |
297 | 276 | ||
298 | for (irq = 0; irq < NR_IRQS; irq++) | 277 | for (irq = 0; irq < NR_IRQS; irq++) |
299 | if (irq_desc[irq].chip == &no_irq_chip) | 278 | if (irq_get_chip(irq) == &no_irq_chip) |
300 | /* due to the PIC latching interrupt requests, even | 279 | /* due to the PIC latching interrupt requests, even |
301 | * when the IRQ is disabled, IRQ_PENDING is superfluous | 280 | * when the IRQ is disabled, IRQ_PENDING is superfluous |
302 | * and we can use handle_level_irq() for edge-triggered | 281 | * and we can use handle_level_irq() for edge-triggered |
303 | * interrupts */ | 282 | * interrupts */ |
304 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, | 283 | irq_set_chip_and_handler(irq, &mn10300_cpu_pic_edge, |
305 | handle_level_irq); | 284 | handle_level_irq); |
306 | 285 | ||
307 | unit_init_IRQ(); | 286 | unit_init_IRQ(); |
@@ -356,91 +335,42 @@ asmlinkage void do_IRQ(void) | |||
356 | /* | 335 | /* |
357 | * Display interrupt management information through /proc/interrupts | 336 | * Display interrupt management information through /proc/interrupts |
358 | */ | 337 | */ |
359 | int show_interrupts(struct seq_file *p, void *v) | 338 | int arch_show_interrupts(struct seq_file *p, int prec) |
360 | { | 339 | { |
361 | int i = *(loff_t *) v, j, cpu; | ||
362 | struct irqaction *action; | ||
363 | unsigned long flags; | ||
364 | |||
365 | switch (i) { | ||
366 | /* display column title bar naming CPUs */ | ||
367 | case 0: | ||
368 | seq_printf(p, " "); | ||
369 | for (j = 0; j < NR_CPUS; j++) | ||
370 | if (cpu_online(j)) | ||
371 | seq_printf(p, "CPU%d ", j); | ||
372 | seq_putc(p, '\n'); | ||
373 | break; | ||
374 | |||
375 | /* display information rows, one per active CPU */ | ||
376 | case 1 ... NR_IRQS - 1: | ||
377 | raw_spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
378 | |||
379 | action = irq_desc[i].action; | ||
380 | if (action) { | ||
381 | seq_printf(p, "%3d: ", i); | ||
382 | for_each_present_cpu(cpu) | ||
383 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); | ||
384 | |||
385 | if (i < NR_CPU_IRQS) | ||
386 | seq_printf(p, " %14s.%u", | ||
387 | irq_desc[i].chip->name, | ||
388 | (GxICR(i) & GxICR_LEVEL) >> | ||
389 | GxICR_LEVEL_SHIFT); | ||
390 | else | ||
391 | seq_printf(p, " %14s", | ||
392 | irq_desc[i].chip->name); | ||
393 | |||
394 | seq_printf(p, " %s", action->name); | ||
395 | |||
396 | for (action = action->next; | ||
397 | action; | ||
398 | action = action->next) | ||
399 | seq_printf(p, ", %s", action->name); | ||
400 | |||
401 | seq_putc(p, '\n'); | ||
402 | } | ||
403 | |||
404 | raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
405 | break; | ||
406 | |||
407 | /* polish off with NMI and error counters */ | ||
408 | case NR_IRQS: | ||
409 | #ifdef CONFIG_MN10300_WD_TIMER | 340 | #ifdef CONFIG_MN10300_WD_TIMER |
410 | seq_printf(p, "NMI: "); | 341 | int j; |
411 | for (j = 0; j < NR_CPUS; j++) | ||
412 | if (cpu_online(j)) | ||
413 | seq_printf(p, "%10u ", nmi_count(j)); | ||
414 | seq_putc(p, '\n'); | ||
415 | #endif | ||
416 | 342 | ||
417 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | 343 | seq_printf(p, "%*s: ", prec, "NMI"); |
418 | break; | 344 | for (j = 0; j < NR_CPUS; j++) |
419 | } | 345 | if (cpu_online(j)) |
346 | seq_printf(p, "%10u ", nmi_count(j)); | ||
347 | seq_putc(p, '\n'); | ||
348 | #endif | ||
420 | 349 | ||
350 | seq_printf(p, "%*s: ", prec, "ERR"); | ||
351 | seq_printf(p, "%10u\n", atomic_read(&irq_err_count)); | ||
421 | return 0; | 352 | return 0; |
422 | } | 353 | } |
423 | 354 | ||
424 | #ifdef CONFIG_HOTPLUG_CPU | 355 | #ifdef CONFIG_HOTPLUG_CPU |
425 | void migrate_irqs(void) | 356 | void migrate_irqs(void) |
426 | { | 357 | { |
427 | irq_desc_t *desc; | ||
428 | int irq; | 358 | int irq; |
429 | unsigned int self, new; | 359 | unsigned int self, new; |
430 | unsigned long flags; | 360 | unsigned long flags; |
431 | 361 | ||
432 | self = smp_processor_id(); | 362 | self = smp_processor_id(); |
433 | for (irq = 0; irq < NR_IRQS; irq++) { | 363 | for (irq = 0; irq < NR_IRQS; irq++) { |
434 | desc = irq_desc + irq; | 364 | struct irq_data *data = irq_get_irq_data(irq); |
435 | 365 | ||
436 | if (desc->status == IRQ_PER_CPU) | 366 | if (irqd_is_per_cpu(data)) |
437 | continue; | 367 | continue; |
438 | 368 | ||
439 | if (cpu_isset(self, irq_desc[irq].affinity) && | 369 | if (cpu_isset(self, data->affinity) && |
440 | !cpus_intersects(irq_affinity[irq], cpu_online_map)) { | 370 | !cpus_intersects(irq_affinity[irq], cpu_online_map)) { |
441 | int cpu_id; | 371 | int cpu_id; |
442 | cpu_id = first_cpu(cpu_online_map); | 372 | cpu_id = first_cpu(cpu_online_map); |
443 | cpu_set(cpu_id, irq_desc[irq].affinity); | 373 | cpu_set(cpu_id, data->affinity); |
444 | } | 374 | } |
445 | /* We need to operate irq_affinity_online atomically. */ | 375 | /* We need to operate irq_affinity_online atomically. */ |
446 | arch_local_cli_save(flags); | 376 | arch_local_cli_save(flags); |
@@ -451,7 +381,7 @@ void migrate_irqs(void) | |||
451 | GxICR(irq) = x & GxICR_LEVEL; | 381 | GxICR(irq) = x & GxICR_LEVEL; |
452 | tmp = GxICR(irq); | 382 | tmp = GxICR(irq); |
453 | 383 | ||
454 | new = any_online_cpu(irq_desc[irq].affinity); | 384 | new = any_online_cpu(data->affinity); |
455 | irq_affinity_online[irq] = new; | 385 | irq_affinity_online[irq] = new; |
456 | 386 | ||
457 | CROSS_GxICR(irq, new) = | 387 | CROSS_GxICR(irq, new) = |
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 | */ | ||
25 | static struct thread_info *kgdb_sstep_thread; | ||
26 | u8 *kgdb_sstep_bp_addr[2]; | ||
27 | u8 kgdb_sstep_bp[2]; | ||
28 | |||
29 | /* | ||
30 | * Copy kernel exception frame registers to the GDB register file | ||
31 | */ | ||
32 | void 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 | */ | ||
74 | void 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 | */ | ||
86 | void 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 | |||
124 | struct kgdb_arch arch_kgdb_ops = { | ||
125 | .gdb_bpt_instr = { 0xff }, | ||
126 | .flags = KGDB_HW_BREAKPOINT, | ||
127 | }; | ||
128 | |||
129 | static 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 | */ | ||
155 | static 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 | |||
319 | set_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 | |||
332 | set_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 | */ | ||
360 | static 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 | */ | ||
400 | void 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 | */ | ||
417 | int 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 | */ | ||
450 | int 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 | */ | ||
471 | int at_debugger_breakpoint(struct pt_regs *regs) | ||
472 | { | ||
473 | return regs->pc == (unsigned long)&__arch_kgdb_breakpoint; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * Initialise kgdb | ||
478 | */ | ||
479 | int kgdb_arch_init(void) | ||
480 | { | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * Do something, perhaps, but don't know what. | ||
486 | */ | ||
487 | void kgdb_arch_exit(void) | ||
488 | { | ||
489 | } | ||
490 | |||
491 | #ifdef CONFIG_SMP | ||
492 | void 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 | |||
498 | void 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 996384dba45d..94901c56baf1 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 *); | |||
119 | static void mn10300_serial_config_port(struct uart_port *, int); | 119 | static void mn10300_serial_config_port(struct uart_port *, int); |
120 | static int mn10300_serial_verify_port(struct uart_port *, | 120 | static int mn10300_serial_verify_port(struct uart_port *, |
121 | struct serial_struct *); | 121 | struct serial_struct *); |
122 | #ifdef CONFIG_CONSOLE_POLL | ||
123 | static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char); | ||
124 | static int mn10300_serial_poll_get_char(struct uart_port *); | ||
125 | #endif | ||
122 | 126 | ||
123 | static const struct uart_ops mn10300_serial_ops = { | 127 | static 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 | ||
143 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); | 151 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); |
@@ -384,17 +392,21 @@ static void mn10300_serial_mask_ack(unsigned int irq) | |||
384 | arch_local_irq_restore(flags); | 392 | arch_local_irq_restore(flags); |
385 | } | 393 | } |
386 | 394 | ||
387 | static void mn10300_serial_nop(unsigned int irq) | 395 | static void mn10300_serial_chip_mask_ack(struct irq_data *d) |
396 | { | ||
397 | mn10300_serial_mask_ack(d->irq); | ||
398 | } | ||
399 | |||
400 | static void mn10300_serial_nop(struct irq_data *d) | ||
388 | { | 401 | { |
389 | } | 402 | } |
390 | 403 | ||
391 | static struct irq_chip mn10300_serial_pic = { | 404 | static struct irq_chip mn10300_serial_pic = { |
392 | .name = "mnserial", | 405 | .name = "mnserial", |
393 | .ack = mn10300_serial_mask_ack, | 406 | .irq_ack = mn10300_serial_chip_mask_ack, |
394 | .mask = mn10300_serial_mask_ack, | 407 | .irq_mask = mn10300_serial_chip_mask_ack, |
395 | .mask_ack = mn10300_serial_mask_ack, | 408 | .irq_mask_ack = mn10300_serial_chip_mask_ack, |
396 | .unmask = mn10300_serial_nop, | 409 | .irq_unmask = mn10300_serial_nop, |
397 | .end = mn10300_serial_nop, | ||
398 | }; | 410 | }; |
399 | 411 | ||
400 | 412 | ||
@@ -921,7 +933,7 @@ static int mn10300_serial_startup(struct uart_port *_port) | |||
921 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | 933 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); |
922 | set_intr_level(port->tx_irq, | 934 | set_intr_level(port->tx_irq, |
923 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | 935 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); |
924 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); | 936 | irq_set_chip(port->tm_irq, &mn10300_serial_pic); |
925 | 937 | ||
926 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | 938 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, |
927 | IRQF_DISABLED, port->rx_name, port) < 0) | 939 | IRQF_DISABLED, port->rx_name, port) < 0) |
@@ -1630,3 +1642,70 @@ static int __init mn10300_serial_console_init(void) | |||
1630 | 1642 | ||
1631 | console_initcall(mn10300_serial_console_init); | 1643 | console_initcall(mn10300_serial_console_init); |
1632 | #endif | 1644 | #endif |
1645 | |||
1646 | #ifdef CONFIG_CONSOLE_POLL | ||
1647 | /* | ||
1648 | * Polled character reception for the kernel debugger | ||
1649 | */ | ||
1650 | static 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 | */ | ||
1679 | static 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 | ||
136 | void machine_restart(char *cmd) | 136 | void 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 | ||
149 | void machine_halt(void) | 149 | void 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 | ||
156 | void machine_power_off(void) | 156 | void 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 0dcd1c686ba8..226c826a2194 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c | |||
@@ -113,15 +113,17 @@ static void init_ipi(void); | |||
113 | */ | 113 | */ |
114 | static void mn10300_ipi_disable(unsigned int irq); | 114 | static void mn10300_ipi_disable(unsigned int irq); |
115 | static void mn10300_ipi_enable(unsigned int irq); | 115 | static void mn10300_ipi_enable(unsigned int irq); |
116 | static void mn10300_ipi_ack(unsigned int irq); | 116 | static void mn10300_ipi_chip_disable(struct irq_data *d); |
117 | static void mn10300_ipi_nop(unsigned int irq); | 117 | static void mn10300_ipi_chip_enable(struct irq_data *d); |
118 | static void mn10300_ipi_ack(struct irq_data *d); | ||
119 | static void mn10300_ipi_nop(struct irq_data *d); | ||
118 | 120 | ||
119 | static struct irq_chip mn10300_ipi_type = { | 121 | static struct irq_chip mn10300_ipi_type = { |
120 | .name = "cpu_ipi", | 122 | .name = "cpu_ipi", |
121 | .disable = mn10300_ipi_disable, | 123 | .irq_disable = mn10300_ipi_chip_disable, |
122 | .enable = mn10300_ipi_enable, | 124 | .irq_enable = mn10300_ipi_chip_enable, |
123 | .ack = mn10300_ipi_ack, | 125 | .irq_ack = mn10300_ipi_ack, |
124 | .eoi = mn10300_ipi_nop | 126 | .irq_eoi = mn10300_ipi_nop |
125 | }; | 127 | }; |
126 | 128 | ||
127 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); | 129 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); |
@@ -154,15 +156,15 @@ static void init_ipi(void) | |||
154 | u16 tmp16; | 156 | u16 tmp16; |
155 | 157 | ||
156 | /* set up the reschedule IPI */ | 158 | /* set up the reschedule IPI */ |
157 | set_irq_chip_and_handler(RESCHEDULE_IPI, | 159 | irq_set_chip_and_handler(RESCHEDULE_IPI, &mn10300_ipi_type, |
158 | &mn10300_ipi_type, handle_percpu_irq); | 160 | handle_percpu_irq); |
159 | setup_irq(RESCHEDULE_IPI, &reschedule_ipi); | 161 | setup_irq(RESCHEDULE_IPI, &reschedule_ipi); |
160 | set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV); | 162 | set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV); |
161 | mn10300_ipi_enable(RESCHEDULE_IPI); | 163 | mn10300_ipi_enable(RESCHEDULE_IPI); |
162 | 164 | ||
163 | /* set up the call function IPI */ | 165 | /* set up the call function IPI */ |
164 | set_irq_chip_and_handler(CALL_FUNC_SINGLE_IPI, | 166 | irq_set_chip_and_handler(CALL_FUNC_SINGLE_IPI, &mn10300_ipi_type, |
165 | &mn10300_ipi_type, handle_percpu_irq); | 167 | handle_percpu_irq); |
166 | setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi); | 168 | setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi); |
167 | set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV); | 169 | set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV); |
168 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); | 170 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); |
@@ -170,8 +172,8 @@ static void init_ipi(void) | |||
170 | /* set up the local timer IPI */ | 172 | /* set up the local timer IPI */ |
171 | #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \ | 173 | #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \ |
172 | defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | 174 | defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) |
173 | set_irq_chip_and_handler(LOCAL_TIMER_IPI, | 175 | irq_set_chip_and_handler(LOCAL_TIMER_IPI, &mn10300_ipi_type, |
174 | &mn10300_ipi_type, handle_percpu_irq); | 176 | handle_percpu_irq); |
175 | setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi); | 177 | setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi); |
176 | set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV); | 178 | set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV); |
177 | mn10300_ipi_enable(LOCAL_TIMER_IPI); | 179 | mn10300_ipi_enable(LOCAL_TIMER_IPI); |
@@ -236,6 +238,11 @@ static void mn10300_ipi_enable(unsigned int irq) | |||
236 | arch_local_irq_restore(flags); | 238 | arch_local_irq_restore(flags); |
237 | } | 239 | } |
238 | 240 | ||
241 | static void mn10300_ipi_chip_enable(struct irq_data *d) | ||
242 | { | ||
243 | mn10300_ipi_enable(d->irq); | ||
244 | } | ||
245 | |||
239 | /** | 246 | /** |
240 | * mn10300_ipi_disable - Disable an IPI | 247 | * mn10300_ipi_disable - Disable an IPI |
241 | * @irq: The IPI to be disabled. | 248 | * @irq: The IPI to be disabled. |
@@ -254,6 +261,12 @@ static void mn10300_ipi_disable(unsigned int irq) | |||
254 | arch_local_irq_restore(flags); | 261 | arch_local_irq_restore(flags); |
255 | } | 262 | } |
256 | 263 | ||
264 | static void mn10300_ipi_chip_disable(struct irq_data *d) | ||
265 | { | ||
266 | mn10300_ipi_disable(d->irq); | ||
267 | } | ||
268 | |||
269 | |||
257 | /** | 270 | /** |
258 | * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC | 271 | * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC |
259 | * @irq: The IPI to be acknowledged. | 272 | * @irq: The IPI to be acknowledged. |
@@ -261,8 +274,9 @@ static void mn10300_ipi_disable(unsigned int irq) | |||
261 | * Clear the interrupt detection flag for the IPI on the appropriate interrupt | 274 | * Clear the interrupt detection flag for the IPI on the appropriate interrupt |
262 | * channel in the PIC. | 275 | * channel in the PIC. |
263 | */ | 276 | */ |
264 | static void mn10300_ipi_ack(unsigned int irq) | 277 | static void mn10300_ipi_ack(struct irq_data *d) |
265 | { | 278 | { |
279 | unsigned int irq = d->irq; | ||
266 | unsigned long flags; | 280 | unsigned long flags; |
267 | u16 tmp; | 281 | u16 tmp; |
268 | 282 | ||
@@ -276,7 +290,7 @@ static void mn10300_ipi_ack(unsigned int irq) | |||
276 | * mn10300_ipi_nop - Dummy IPI action | 290 | * mn10300_ipi_nop - Dummy IPI action |
277 | * @irq: The IPI to be acted upon. | 291 | * @irq: The IPI to be acted upon. |
278 | */ | 292 | */ |
279 | static void mn10300_ipi_nop(unsigned int irq) | 293 | static void mn10300_ipi_nop(struct irq_data *d) |
280 | { | 294 | { |
281 | } | 295 | } |
282 | 296 | ||
@@ -426,6 +440,22 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) | |||
426 | } | 440 | } |
427 | 441 | ||
428 | /** | 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 | /** | ||
429 | * stop_this_cpu - Callback to stop a CPU. | 459 | * stop_this_cpu - Callback to stop a CPU. |
430 | * @unused: Callback context (ignored). | 460 | * @unused: Callback context (ignored). |
431 | */ | 461 | */ |
@@ -589,7 +619,7 @@ static void __init smp_cpu_init(void) | |||
589 | /** | 619 | /** |
590 | * smp_prepare_cpu_init - Initialise CPU in startup_secondary | 620 | * smp_prepare_cpu_init - Initialise CPU in startup_secondary |
591 | * | 621 | * |
592 | * 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. |
593 | */ | 623 | */ |
594 | void smp_prepare_cpu_init(void) | 624 | void smp_prepare_cpu_init(void) |
595 | { | 625 | { |
@@ -608,15 +638,15 @@ void smp_prepare_cpu_init(void) | |||
608 | for (loop = 0; loop < GxICR_NUM_IRQS; loop++) | 638 | for (loop = 0; loop < GxICR_NUM_IRQS; loop++) |
609 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; | 639 | GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; |
610 | 640 | ||
611 | #ifdef CONFIG_GDBSTUB | 641 | #ifdef CONFIG_KERNEL_DEBUGGER |
612 | /* initialise GDB-stub */ | 642 | /* initialise the kernel debugger interrupt */ |
613 | do { | 643 | do { |
614 | unsigned long flags; | 644 | unsigned long flags; |
615 | u16 tmp16; | 645 | u16 tmp16; |
616 | 646 | ||
617 | flags = arch_local_cli_save(); | 647 | flags = arch_local_cli_save(); |
618 | GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; | 648 | GxICR(DEBUGGER_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; |
619 | tmp16 = GxICR(GDB_NMI_IPI); | 649 | tmp16 = GxICR(DEBUGGER_NMI_IPI); |
620 | arch_local_irq_restore(flags); | 650 | arch_local_irq_restore(flags); |
621 | } while (0); | 651 | } while (0); |
622 | #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 | ||
107 | 1: | ||
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 | ||
121 | 2: | ||
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 | ||
154 | 1: | ||
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 | ||
169 | 2: | ||
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/time.c b/arch/mn10300/kernel/time.c index 5b955000626d..67c6416a58f8 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c | |||
@@ -93,79 +93,6 @@ irqreturn_t local_timer_interrupt(void) | |||
93 | return IRQ_HANDLED; | 93 | return IRQ_HANDLED; |
94 | } | 94 | } |
95 | 95 | ||
96 | #ifndef CONFIG_GENERIC_TIME | ||
97 | /* | ||
98 | * advance the kernel's time keeping clocks (xtime and jiffies) | ||
99 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time | ||
100 | * there's a need to update | ||
101 | */ | ||
102 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
103 | { | ||
104 | unsigned tsc, elapse; | ||
105 | irqreturn_t ret; | ||
106 | |||
107 | while (tsc = get_cycles(), | ||
108 | elapse = tsc - mn10300_last_tsc, /* time elapsed since last | ||
109 | * tick */ | ||
110 | elapse > MN10300_TSC_PER_HZ | ||
111 | ) { | ||
112 | mn10300_last_tsc += MN10300_TSC_PER_HZ; | ||
113 | |||
114 | /* advance the kernel's time tracking system */ | ||
115 | xtime_update(1); | ||
116 | } | ||
117 | |||
118 | ret = local_timer_interrupt(); | ||
119 | #ifdef CONFIG_SMP | ||
120 | send_IPI_allbutself(LOCAL_TIMER_IPI); | ||
121 | #endif | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static struct irqaction timer_irq = { | ||
126 | .handler = timer_interrupt, | ||
127 | .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER, | ||
128 | .name = "timer", | ||
129 | }; | ||
130 | #endif /* CONFIG_GENERIC_TIME */ | ||
131 | |||
132 | #ifdef CONFIG_CSRC_MN10300 | ||
133 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) | ||
134 | { | ||
135 | u64 temp; | ||
136 | u32 shift; | ||
137 | |||
138 | /* Find a shift value */ | ||
139 | for (shift = 32; shift > 0; shift--) { | ||
140 | temp = (u64) NSEC_PER_SEC << shift; | ||
141 | do_div(temp, clock); | ||
142 | if ((temp >> 32) == 0) | ||
143 | break; | ||
144 | } | ||
145 | cs->shift = shift; | ||
146 | cs->mult = (u32) temp; | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | #if CONFIG_CEVT_MN10300 | ||
151 | void __cpuinit clockevent_set_clock(struct clock_event_device *cd, | ||
152 | unsigned int clock) | ||
153 | { | ||
154 | u64 temp; | ||
155 | u32 shift; | ||
156 | |||
157 | /* Find a shift value */ | ||
158 | for (shift = 32; shift > 0; shift--) { | ||
159 | temp = (u64) clock << shift; | ||
160 | do_div(temp, NSEC_PER_SEC); | ||
161 | if ((temp >> 32) == 0) | ||
162 | break; | ||
163 | } | ||
164 | cd->shift = shift; | ||
165 | cd->mult = (u32) temp; | ||
166 | } | ||
167 | #endif | ||
168 | |||
169 | /* | 96 | /* |
170 | * initialise the various timers used by the main part of the kernel | 97 | * initialise the various timers used by the main part of the kernel |
171 | */ | 98 | */ |
@@ -177,11 +104,7 @@ void __init time_init(void) | |||
177 | */ | 104 | */ |
178 | TMPSCNT |= TMPSCNT_ENABLE; | 105 | TMPSCNT |= TMPSCNT_ENABLE; |
179 | 106 | ||
180 | #ifdef CONFIG_GENERIC_TIME | ||
181 | init_clocksource(); | 107 | init_clocksource(); |
182 | #else | ||
183 | startup_timestamp_counter(); | ||
184 | #endif | ||
185 | 108 | ||
186 | printk(KERN_INFO | 109 | printk(KERN_INFO |
187 | "timestamp counter I/O clock running at %lu.%02lu" | 110 | "timestamp counter I/O clock running at %lu.%02lu" |
@@ -190,12 +113,7 @@ void __init time_init(void) | |||
190 | 113 | ||
191 | mn10300_last_tsc = read_timestamp_counter(); | 114 | mn10300_last_tsc = read_timestamp_counter(); |
192 | 115 | ||
193 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
194 | init_clockevents(); | 116 | init_clockevents(); |
195 | #else | ||
196 | reload_jiffies_counter(MN10300_JC_PER_HZ - 1); | ||
197 | setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL); | ||
198 | #endif | ||
199 | 117 | ||
200 | #ifdef CONFIG_MN10300_WD_TIMER | 118 | #ifdef CONFIG_MN10300_WD_TIMER |
201 | /* start the watchdog timer */ | 119 | /* start the watchdog timer */ |
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 | /* |