diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2008-07-29 16:58:52 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-07-30 16:54:42 -0400 |
commit | 8d60a903d986ffa26c41f0092320a3b9da20bfaf (patch) | |
tree | f05a8ae48e275d55fcfd3acfb7b3b1b601da56ea /arch/mips/kernel | |
parent | 8f8da9adebdf04bfb3b812a7de8706fbf179fd2c (diff) |
[MIPS] kgdb: Remove existing implementation
This patch explicitly removes the kgdb implementation, for mips which
is intended to be followed by a patch that adds a kgdb implementation
for MIPS that makes use of the kgdb core in the kernel.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/gdb-low.S | 394 | ||||
-rw-r--r-- | arch/mips/kernel/gdb-stub.c | 1155 | ||||
-rw-r--r-- | arch/mips/kernel/irq.c | 21 |
4 files changed, 0 insertions, 1571 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 0fd31974ba28..73ff048eaa55 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -71,7 +71,6 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o | |||
71 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o | 71 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o |
72 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o | 72 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o |
73 | 73 | ||
74 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o | ||
75 | obj-$(CONFIG_PROC_FS) += proc.o | 74 | obj-$(CONFIG_PROC_FS) += proc.o |
76 | 75 | ||
77 | obj-$(CONFIG_64BIT) += cpu-bugs64.o | 76 | obj-$(CONFIG_64BIT) += cpu-bugs64.o |
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S deleted file mode 100644 index 2c446063636a..000000000000 --- a/arch/mips/kernel/gdb-low.S +++ /dev/null | |||
@@ -1,394 +0,0 @@ | |||
1 | /* | ||
2 | * gdb-low.S contains the low-level trap handler for the GDB stub. | ||
3 | * | ||
4 | * Copyright (C) 1995 Andreas Busse | ||
5 | */ | ||
6 | #include <linux/sys.h> | ||
7 | |||
8 | #include <asm/asm.h> | ||
9 | #include <asm/errno.h> | ||
10 | #include <asm/irqflags.h> | ||
11 | #include <asm/mipsregs.h> | ||
12 | #include <asm/regdef.h> | ||
13 | #include <asm/stackframe.h> | ||
14 | #include <asm/gdb-stub.h> | ||
15 | |||
16 | #ifdef CONFIG_32BIT | ||
17 | #define DMFC0 mfc0 | ||
18 | #define DMTC0 mtc0 | ||
19 | #define LDC1 lwc1 | ||
20 | #define SDC1 lwc1 | ||
21 | #endif | ||
22 | #ifdef CONFIG_64BIT | ||
23 | #define DMFC0 dmfc0 | ||
24 | #define DMTC0 dmtc0 | ||
25 | #define LDC1 ldc1 | ||
26 | #define SDC1 ldc1 | ||
27 | #endif | ||
28 | |||
29 | /* | ||
30 | * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed) | ||
31 | * part is used to store registers and passed to exception handler. | ||
32 | * The upper part is reserved for "call func" feature where gdb client | ||
33 | * saves some of the regs, setups call frame and passes args. | ||
34 | * | ||
35 | * A trace shows about 200 bytes are used to store about half of all regs. | ||
36 | * The rest should be big enough for frame setup and passing args. | ||
37 | */ | ||
38 | |||
39 | /* | ||
40 | * The low level trap handler | ||
41 | */ | ||
42 | .align 5 | ||
43 | NESTED(trap_low, GDB_FR_SIZE, sp) | ||
44 | .set noat | ||
45 | .set noreorder | ||
46 | |||
47 | mfc0 k0, CP0_STATUS | ||
48 | sll k0, 3 /* extract cu0 bit */ | ||
49 | bltz k0, 1f | ||
50 | move k1, sp | ||
51 | |||
52 | /* | ||
53 | * Called from user mode, go somewhere else. | ||
54 | */ | ||
55 | mfc0 k0, CP0_CAUSE | ||
56 | andi k0, k0, 0x7c | ||
57 | #ifdef CONFIG_64BIT | ||
58 | dsll k0, k0, 1 | ||
59 | #endif | ||
60 | PTR_L k1, saved_vectors(k0) | ||
61 | jr k1 | ||
62 | nop | ||
63 | 1: | ||
64 | move k0, sp | ||
65 | PTR_SUBU sp, k1, GDB_FR_SIZE*2 # see comment above | ||
66 | LONG_S k0, GDB_FR_REG29(sp) | ||
67 | LONG_S $2, GDB_FR_REG2(sp) | ||
68 | |||
69 | /* | ||
70 | * First save the CP0 and special registers | ||
71 | */ | ||
72 | |||
73 | mfc0 v0, CP0_STATUS | ||
74 | LONG_S v0, GDB_FR_STATUS(sp) | ||
75 | mfc0 v0, CP0_CAUSE | ||
76 | LONG_S v0, GDB_FR_CAUSE(sp) | ||
77 | DMFC0 v0, CP0_EPC | ||
78 | LONG_S v0, GDB_FR_EPC(sp) | ||
79 | DMFC0 v0, CP0_BADVADDR | ||
80 | LONG_S v0, GDB_FR_BADVADDR(sp) | ||
81 | mfhi v0 | ||
82 | LONG_S v0, GDB_FR_HI(sp) | ||
83 | mflo v0 | ||
84 | LONG_S v0, GDB_FR_LO(sp) | ||
85 | |||
86 | /* | ||
87 | * Now the integer registers | ||
88 | */ | ||
89 | |||
90 | LONG_S zero, GDB_FR_REG0(sp) /* I know... */ | ||
91 | LONG_S $1, GDB_FR_REG1(sp) | ||
92 | /* v0 already saved */ | ||
93 | LONG_S $3, GDB_FR_REG3(sp) | ||
94 | LONG_S $4, GDB_FR_REG4(sp) | ||
95 | LONG_S $5, GDB_FR_REG5(sp) | ||
96 | LONG_S $6, GDB_FR_REG6(sp) | ||
97 | LONG_S $7, GDB_FR_REG7(sp) | ||
98 | LONG_S $8, GDB_FR_REG8(sp) | ||
99 | LONG_S $9, GDB_FR_REG9(sp) | ||
100 | LONG_S $10, GDB_FR_REG10(sp) | ||
101 | LONG_S $11, GDB_FR_REG11(sp) | ||
102 | LONG_S $12, GDB_FR_REG12(sp) | ||
103 | LONG_S $13, GDB_FR_REG13(sp) | ||
104 | LONG_S $14, GDB_FR_REG14(sp) | ||
105 | LONG_S $15, GDB_FR_REG15(sp) | ||
106 | LONG_S $16, GDB_FR_REG16(sp) | ||
107 | LONG_S $17, GDB_FR_REG17(sp) | ||
108 | LONG_S $18, GDB_FR_REG18(sp) | ||
109 | LONG_S $19, GDB_FR_REG19(sp) | ||
110 | LONG_S $20, GDB_FR_REG20(sp) | ||
111 | LONG_S $21, GDB_FR_REG21(sp) | ||
112 | LONG_S $22, GDB_FR_REG22(sp) | ||
113 | LONG_S $23, GDB_FR_REG23(sp) | ||
114 | LONG_S $24, GDB_FR_REG24(sp) | ||
115 | LONG_S $25, GDB_FR_REG25(sp) | ||
116 | LONG_S $26, GDB_FR_REG26(sp) | ||
117 | LONG_S $27, GDB_FR_REG27(sp) | ||
118 | LONG_S $28, GDB_FR_REG28(sp) | ||
119 | /* sp already saved */ | ||
120 | LONG_S $30, GDB_FR_REG30(sp) | ||
121 | LONG_S $31, GDB_FR_REG31(sp) | ||
122 | |||
123 | CLI /* disable interrupts */ | ||
124 | TRACE_IRQS_OFF | ||
125 | |||
126 | /* | ||
127 | * Followed by the floating point registers | ||
128 | */ | ||
129 | mfc0 v0, CP0_STATUS /* FPU enabled? */ | ||
130 | srl v0, v0, 16 | ||
131 | andi v0, v0, (ST0_CU1 >> 16) | ||
132 | |||
133 | beqz v0,2f /* disabled, skip */ | ||
134 | nop | ||
135 | |||
136 | SDC1 $0, GDB_FR_FPR0(sp) | ||
137 | SDC1 $1, GDB_FR_FPR1(sp) | ||
138 | SDC1 $2, GDB_FR_FPR2(sp) | ||
139 | SDC1 $3, GDB_FR_FPR3(sp) | ||
140 | SDC1 $4, GDB_FR_FPR4(sp) | ||
141 | SDC1 $5, GDB_FR_FPR5(sp) | ||
142 | SDC1 $6, GDB_FR_FPR6(sp) | ||
143 | SDC1 $7, GDB_FR_FPR7(sp) | ||
144 | SDC1 $8, GDB_FR_FPR8(sp) | ||
145 | SDC1 $9, GDB_FR_FPR9(sp) | ||
146 | SDC1 $10, GDB_FR_FPR10(sp) | ||
147 | SDC1 $11, GDB_FR_FPR11(sp) | ||
148 | SDC1 $12, GDB_FR_FPR12(sp) | ||
149 | SDC1 $13, GDB_FR_FPR13(sp) | ||
150 | SDC1 $14, GDB_FR_FPR14(sp) | ||
151 | SDC1 $15, GDB_FR_FPR15(sp) | ||
152 | SDC1 $16, GDB_FR_FPR16(sp) | ||
153 | SDC1 $17, GDB_FR_FPR17(sp) | ||
154 | SDC1 $18, GDB_FR_FPR18(sp) | ||
155 | SDC1 $19, GDB_FR_FPR19(sp) | ||
156 | SDC1 $20, GDB_FR_FPR20(sp) | ||
157 | SDC1 $21, GDB_FR_FPR21(sp) | ||
158 | SDC1 $22, GDB_FR_FPR22(sp) | ||
159 | SDC1 $23, GDB_FR_FPR23(sp) | ||
160 | SDC1 $24, GDB_FR_FPR24(sp) | ||
161 | SDC1 $25, GDB_FR_FPR25(sp) | ||
162 | SDC1 $26, GDB_FR_FPR26(sp) | ||
163 | SDC1 $27, GDB_FR_FPR27(sp) | ||
164 | SDC1 $28, GDB_FR_FPR28(sp) | ||
165 | SDC1 $29, GDB_FR_FPR29(sp) | ||
166 | SDC1 $30, GDB_FR_FPR30(sp) | ||
167 | SDC1 $31, GDB_FR_FPR31(sp) | ||
168 | |||
169 | /* | ||
170 | * FPU control registers | ||
171 | */ | ||
172 | |||
173 | cfc1 v0, CP1_STATUS | ||
174 | LONG_S v0, GDB_FR_FSR(sp) | ||
175 | cfc1 v0, CP1_REVISION | ||
176 | LONG_S v0, GDB_FR_FIR(sp) | ||
177 | |||
178 | /* | ||
179 | * Current stack frame ptr | ||
180 | */ | ||
181 | |||
182 | 2: | ||
183 | LONG_S sp, GDB_FR_FRP(sp) | ||
184 | |||
185 | /* | ||
186 | * CP0 registers (R4000/R4400 unused registers skipped) | ||
187 | */ | ||
188 | |||
189 | mfc0 v0, CP0_INDEX | ||
190 | LONG_S v0, GDB_FR_CP0_INDEX(sp) | ||
191 | mfc0 v0, CP0_RANDOM | ||
192 | LONG_S v0, GDB_FR_CP0_RANDOM(sp) | ||
193 | DMFC0 v0, CP0_ENTRYLO0 | ||
194 | LONG_S v0, GDB_FR_CP0_ENTRYLO0(sp) | ||
195 | DMFC0 v0, CP0_ENTRYLO1 | ||
196 | LONG_S v0, GDB_FR_CP0_ENTRYLO1(sp) | ||
197 | DMFC0 v0, CP0_CONTEXT | ||
198 | LONG_S v0, GDB_FR_CP0_CONTEXT(sp) | ||
199 | mfc0 v0, CP0_PAGEMASK | ||
200 | LONG_S v0, GDB_FR_CP0_PAGEMASK(sp) | ||
201 | mfc0 v0, CP0_WIRED | ||
202 | LONG_S v0, GDB_FR_CP0_WIRED(sp) | ||
203 | DMFC0 v0, CP0_ENTRYHI | ||
204 | LONG_S v0, GDB_FR_CP0_ENTRYHI(sp) | ||
205 | mfc0 v0, CP0_PRID | ||
206 | LONG_S v0, GDB_FR_CP0_PRID(sp) | ||
207 | |||
208 | .set at | ||
209 | |||
210 | /* | ||
211 | * Continue with the higher level handler | ||
212 | */ | ||
213 | |||
214 | move a0,sp | ||
215 | |||
216 | jal handle_exception | ||
217 | nop | ||
218 | |||
219 | /* | ||
220 | * Restore all writable registers, in reverse order | ||
221 | */ | ||
222 | |||
223 | .set noat | ||
224 | |||
225 | LONG_L v0, GDB_FR_CP0_ENTRYHI(sp) | ||
226 | LONG_L v1, GDB_FR_CP0_WIRED(sp) | ||
227 | DMTC0 v0, CP0_ENTRYHI | ||
228 | mtc0 v1, CP0_WIRED | ||
229 | LONG_L v0, GDB_FR_CP0_PAGEMASK(sp) | ||
230 | LONG_L v1, GDB_FR_CP0_ENTRYLO1(sp) | ||
231 | mtc0 v0, CP0_PAGEMASK | ||
232 | DMTC0 v1, CP0_ENTRYLO1 | ||
233 | LONG_L v0, GDB_FR_CP0_ENTRYLO0(sp) | ||
234 | LONG_L v1, GDB_FR_CP0_INDEX(sp) | ||
235 | DMTC0 v0, CP0_ENTRYLO0 | ||
236 | LONG_L v0, GDB_FR_CP0_CONTEXT(sp) | ||
237 | mtc0 v1, CP0_INDEX | ||
238 | DMTC0 v0, CP0_CONTEXT | ||
239 | |||
240 | |||
241 | /* | ||
242 | * Next, the floating point registers | ||
243 | */ | ||
244 | mfc0 v0, CP0_STATUS /* check if the FPU is enabled */ | ||
245 | srl v0, v0, 16 | ||
246 | andi v0, v0, (ST0_CU1 >> 16) | ||
247 | |||
248 | beqz v0, 3f /* disabled, skip */ | ||
249 | nop | ||
250 | |||
251 | LDC1 $31, GDB_FR_FPR31(sp) | ||
252 | LDC1 $30, GDB_FR_FPR30(sp) | ||
253 | LDC1 $29, GDB_FR_FPR29(sp) | ||
254 | LDC1 $28, GDB_FR_FPR28(sp) | ||
255 | LDC1 $27, GDB_FR_FPR27(sp) | ||
256 | LDC1 $26, GDB_FR_FPR26(sp) | ||
257 | LDC1 $25, GDB_FR_FPR25(sp) | ||
258 | LDC1 $24, GDB_FR_FPR24(sp) | ||
259 | LDC1 $23, GDB_FR_FPR23(sp) | ||
260 | LDC1 $22, GDB_FR_FPR22(sp) | ||
261 | LDC1 $21, GDB_FR_FPR21(sp) | ||
262 | LDC1 $20, GDB_FR_FPR20(sp) | ||
263 | LDC1 $19, GDB_FR_FPR19(sp) | ||
264 | LDC1 $18, GDB_FR_FPR18(sp) | ||
265 | LDC1 $17, GDB_FR_FPR17(sp) | ||
266 | LDC1 $16, GDB_FR_FPR16(sp) | ||
267 | LDC1 $15, GDB_FR_FPR15(sp) | ||
268 | LDC1 $14, GDB_FR_FPR14(sp) | ||
269 | LDC1 $13, GDB_FR_FPR13(sp) | ||
270 | LDC1 $12, GDB_FR_FPR12(sp) | ||
271 | LDC1 $11, GDB_FR_FPR11(sp) | ||
272 | LDC1 $10, GDB_FR_FPR10(sp) | ||
273 | LDC1 $9, GDB_FR_FPR9(sp) | ||
274 | LDC1 $8, GDB_FR_FPR8(sp) | ||
275 | LDC1 $7, GDB_FR_FPR7(sp) | ||
276 | LDC1 $6, GDB_FR_FPR6(sp) | ||
277 | LDC1 $5, GDB_FR_FPR5(sp) | ||
278 | LDC1 $4, GDB_FR_FPR4(sp) | ||
279 | LDC1 $3, GDB_FR_FPR3(sp) | ||
280 | LDC1 $2, GDB_FR_FPR2(sp) | ||
281 | LDC1 $1, GDB_FR_FPR1(sp) | ||
282 | LDC1 $0, GDB_FR_FPR0(sp) | ||
283 | |||
284 | /* | ||
285 | * Now the CP0 and integer registers | ||
286 | */ | ||
287 | |||
288 | 3: | ||
289 | #ifdef CONFIG_MIPS_MT_SMTC | ||
290 | /* Read-modify write of Status must be atomic */ | ||
291 | mfc0 t2, CP0_TCSTATUS | ||
292 | ori t1, t2, TCSTATUS_IXMT | ||
293 | mtc0 t1, CP0_TCSTATUS | ||
294 | andi t2, t2, TCSTATUS_IXMT | ||
295 | _ehb | ||
296 | DMT 9 # dmt t1 | ||
297 | jal mips_ihb | ||
298 | nop | ||
299 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
300 | mfc0 t0, CP0_STATUS | ||
301 | ori t0, 0x1f | ||
302 | xori t0, 0x1f | ||
303 | mtc0 t0, CP0_STATUS | ||
304 | #ifdef CONFIG_MIPS_MT_SMTC | ||
305 | andi t1, t1, VPECONTROL_TE | ||
306 | beqz t1, 9f | ||
307 | nop | ||
308 | EMT # emt | ||
309 | 9: | ||
310 | mfc0 t1, CP0_TCSTATUS | ||
311 | xori t1, t1, TCSTATUS_IXMT | ||
312 | or t1, t1, t2 | ||
313 | mtc0 t1, CP0_TCSTATUS | ||
314 | _ehb | ||
315 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
316 | LONG_L v0, GDB_FR_STATUS(sp) | ||
317 | LONG_L v1, GDB_FR_EPC(sp) | ||
318 | mtc0 v0, CP0_STATUS | ||
319 | DMTC0 v1, CP0_EPC | ||
320 | LONG_L v0, GDB_FR_HI(sp) | ||
321 | LONG_L v1, GDB_FR_LO(sp) | ||
322 | mthi v0 | ||
323 | mtlo v1 | ||
324 | LONG_L $31, GDB_FR_REG31(sp) | ||
325 | LONG_L $30, GDB_FR_REG30(sp) | ||
326 | LONG_L $28, GDB_FR_REG28(sp) | ||
327 | LONG_L $27, GDB_FR_REG27(sp) | ||
328 | LONG_L $26, GDB_FR_REG26(sp) | ||
329 | LONG_L $25, GDB_FR_REG25(sp) | ||
330 | LONG_L $24, GDB_FR_REG24(sp) | ||
331 | LONG_L $23, GDB_FR_REG23(sp) | ||
332 | LONG_L $22, GDB_FR_REG22(sp) | ||
333 | LONG_L $21, GDB_FR_REG21(sp) | ||
334 | LONG_L $20, GDB_FR_REG20(sp) | ||
335 | LONG_L $19, GDB_FR_REG19(sp) | ||
336 | LONG_L $18, GDB_FR_REG18(sp) | ||
337 | LONG_L $17, GDB_FR_REG17(sp) | ||
338 | LONG_L $16, GDB_FR_REG16(sp) | ||
339 | LONG_L $15, GDB_FR_REG15(sp) | ||
340 | LONG_L $14, GDB_FR_REG14(sp) | ||
341 | LONG_L $13, GDB_FR_REG13(sp) | ||
342 | LONG_L $12, GDB_FR_REG12(sp) | ||
343 | LONG_L $11, GDB_FR_REG11(sp) | ||
344 | LONG_L $10, GDB_FR_REG10(sp) | ||
345 | LONG_L $9, GDB_FR_REG9(sp) | ||
346 | LONG_L $8, GDB_FR_REG8(sp) | ||
347 | LONG_L $7, GDB_FR_REG7(sp) | ||
348 | LONG_L $6, GDB_FR_REG6(sp) | ||
349 | LONG_L $5, GDB_FR_REG5(sp) | ||
350 | LONG_L $4, GDB_FR_REG4(sp) | ||
351 | LONG_L $3, GDB_FR_REG3(sp) | ||
352 | LONG_L $2, GDB_FR_REG2(sp) | ||
353 | LONG_L $1, GDB_FR_REG1(sp) | ||
354 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
355 | LONG_L k0, GDB_FR_EPC(sp) | ||
356 | LONG_L $29, GDB_FR_REG29(sp) /* Deallocate stack */ | ||
357 | jr k0 | ||
358 | rfe | ||
359 | #else | ||
360 | LONG_L sp, GDB_FR_REG29(sp) /* Deallocate stack */ | ||
361 | |||
362 | .set mips3 | ||
363 | eret | ||
364 | .set mips0 | ||
365 | #endif | ||
366 | .set at | ||
367 | .set reorder | ||
368 | END(trap_low) | ||
369 | |||
370 | LEAF(kgdb_read_byte) | ||
371 | 4: lb t0, (a0) | ||
372 | sb t0, (a1) | ||
373 | li v0, 0 | ||
374 | jr ra | ||
375 | .section __ex_table,"a" | ||
376 | PTR 4b, kgdbfault | ||
377 | .previous | ||
378 | END(kgdb_read_byte) | ||
379 | |||
380 | LEAF(kgdb_write_byte) | ||
381 | 5: sb a0, (a1) | ||
382 | li v0, 0 | ||
383 | jr ra | ||
384 | .section __ex_table,"a" | ||
385 | PTR 5b, kgdbfault | ||
386 | .previous | ||
387 | END(kgdb_write_byte) | ||
388 | |||
389 | .type kgdbfault@function | ||
390 | .ent kgdbfault | ||
391 | |||
392 | kgdbfault: li v0, -EFAULT | ||
393 | jr ra | ||
394 | .end kgdbfault | ||
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c deleted file mode 100644 index 25f4eab8ea9c..000000000000 --- a/arch/mips/kernel/gdb-stub.c +++ /dev/null | |||
@@ -1,1155 +0,0 @@ | |||
1 | /* | ||
2 | * arch/mips/kernel/gdb-stub.c | ||
3 | * | ||
4 | * Originally written by Glenn Engel, Lake Stevens Instrument Division | ||
5 | * | ||
6 | * Contributed by HP Systems | ||
7 | * | ||
8 | * Modified for SPARC by Stu Grossman, Cygnus Support. | ||
9 | * | ||
10 | * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse | ||
11 | * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> | ||
12 | * | ||
13 | * Copyright (C) 1995 Andreas Busse | ||
14 | * | ||
15 | * Copyright (C) 2003 MontaVista Software Inc. | ||
16 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * To enable debugger support, two things need to happen. One, a | ||
21 | * call to set_debug_traps() is necessary in order to allow any breakpoints | ||
22 | * or error conditions to be properly intercepted and reported to gdb. | ||
23 | * Two, a breakpoint needs to be generated to begin communication. This | ||
24 | * is most easily accomplished by a call to breakpoint(). Breakpoint() | ||
25 | * simulates a breakpoint by executing a BREAK instruction. | ||
26 | * | ||
27 | * | ||
28 | * The following gdb commands are supported: | ||
29 | * | ||
30 | * command function Return value | ||
31 | * | ||
32 | * g return the value of the CPU registers hex data or ENN | ||
33 | * G set the value of the CPU registers OK or ENN | ||
34 | * | ||
35 | * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN | ||
36 | * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN | ||
37 | * | ||
38 | * c Resume at current address SNN ( signal NN) | ||
39 | * cAA..AA Continue at address AA..AA SNN | ||
40 | * | ||
41 | * s Step one instruction SNN | ||
42 | * sAA..AA Step one instruction from AA..AA SNN | ||
43 | * | ||
44 | * k kill | ||
45 | * | ||
46 | * ? What was the last sigval ? SNN (signal NN) | ||
47 | * | ||
48 | * bBB..BB Set baud rate to BB..BB OK or BNN, then sets | ||
49 | * baud rate | ||
50 | * | ||
51 | * All commands and responses are sent with a packet which includes a | ||
52 | * checksum. A packet consists of | ||
53 | * | ||
54 | * $<packet info>#<checksum>. | ||
55 | * | ||
56 | * where | ||
57 | * <packet info> :: <characters representing the command or response> | ||
58 | * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> | ||
59 | * | ||
60 | * When a packet is received, it is first acknowledged with either '+' or '-'. | ||
61 | * '+' indicates a successful transfer. '-' indicates a failed transfer. | ||
62 | * | ||
63 | * Example: | ||
64 | * | ||
65 | * Host: Reply: | ||
66 | * $m0,10#2a +$00010203040506070809101112131415#42 | ||
67 | * | ||
68 | * | ||
69 | * ============== | ||
70 | * MORE EXAMPLES: | ||
71 | * ============== | ||
72 | * | ||
73 | * For reference -- the following are the steps that one | ||
74 | * company took (RidgeRun Inc) to get remote gdb debugging | ||
75 | * going. In this scenario the host machine was a PC and the | ||
76 | * target platform was a Galileo EVB64120A MIPS evaluation | ||
77 | * board. | ||
78 | * | ||
79 | * Step 1: | ||
80 | * First download gdb-5.0.tar.gz from the internet. | ||
81 | * and then build/install the package. | ||
82 | * | ||
83 | * Example: | ||
84 | * $ tar zxf gdb-5.0.tar.gz | ||
85 | * $ cd gdb-5.0 | ||
86 | * $ ./configure --target=mips-linux-elf | ||
87 | * $ make | ||
88 | * $ install | ||
89 | * $ which mips-linux-elf-gdb | ||
90 | * /usr/local/bin/mips-linux-elf-gdb | ||
91 | * | ||
92 | * Step 2: | ||
93 | * Configure linux for remote debugging and build it. | ||
94 | * | ||
95 | * Example: | ||
96 | * $ cd ~/linux | ||
97 | * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging> | ||
98 | * $ make | ||
99 | * | ||
100 | * Step 3: | ||
101 | * Download the kernel to the remote target and start | ||
102 | * the kernel running. It will promptly halt and wait | ||
103 | * for the host gdb session to connect. It does this | ||
104 | * since the "Kernel Hacking" option has defined | ||
105 | * CONFIG_KGDB which in turn enables your calls | ||
106 | * to: | ||
107 | * set_debug_traps(); | ||
108 | * breakpoint(); | ||
109 | * | ||
110 | * Step 4: | ||
111 | * Start the gdb session on the host. | ||
112 | * | ||
113 | * Example: | ||
114 | * $ mips-linux-elf-gdb vmlinux | ||
115 | * (gdb) set remotebaud 115200 | ||
116 | * (gdb) target remote /dev/ttyS1 | ||
117 | * ...at this point you are connected to | ||
118 | * the remote target and can use gdb | ||
119 | * in the normal fasion. Setting | ||
120 | * breakpoints, single stepping, | ||
121 | * printing variables, etc. | ||
122 | */ | ||
123 | #include <linux/string.h> | ||
124 | #include <linux/kernel.h> | ||
125 | #include <linux/signal.h> | ||
126 | #include <linux/sched.h> | ||
127 | #include <linux/mm.h> | ||
128 | #include <linux/console.h> | ||
129 | #include <linux/init.h> | ||
130 | #include <linux/smp.h> | ||
131 | #include <linux/spinlock.h> | ||
132 | #include <linux/slab.h> | ||
133 | #include <linux/reboot.h> | ||
134 | |||
135 | #include <asm/asm.h> | ||
136 | #include <asm/cacheflush.h> | ||
137 | #include <asm/mipsregs.h> | ||
138 | #include <asm/pgtable.h> | ||
139 | #include <asm/system.h> | ||
140 | #include <asm/gdb-stub.h> | ||
141 | #include <asm/inst.h> | ||
142 | |||
143 | /* | ||
144 | * external low-level support routines | ||
145 | */ | ||
146 | |||
147 | extern int putDebugChar(char c); /* write a single character */ | ||
148 | extern char getDebugChar(void); /* read and return a single char */ | ||
149 | extern void trap_low(void); | ||
150 | |||
151 | /* | ||
152 | * breakpoint and test functions | ||
153 | */ | ||
154 | extern void breakpoint(void); | ||
155 | extern void breakinst(void); | ||
156 | extern void async_breakpoint(void); | ||
157 | extern void async_breakinst(void); | ||
158 | extern void adel(void); | ||
159 | |||
160 | /* | ||
161 | * local prototypes | ||
162 | */ | ||
163 | |||
164 | static void getpacket(char *buffer); | ||
165 | static void putpacket(char *buffer); | ||
166 | static int computeSignal(int tt); | ||
167 | static int hex(unsigned char ch); | ||
168 | static int hexToInt(char **ptr, int *intValue); | ||
169 | static int hexToLong(char **ptr, long *longValue); | ||
170 | static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); | ||
171 | void handle_exception(struct gdb_regs *regs); | ||
172 | |||
173 | int kgdb_enabled; | ||
174 | |||
175 | /* | ||
176 | * spin locks for smp case | ||
177 | */ | ||
178 | static DEFINE_SPINLOCK(kgdb_lock); | ||
179 | static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { | ||
180 | [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED, | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * BUFMAX defines the maximum number of characters in inbound/outbound buffers | ||
185 | * at least NUMREGBYTES*2 are needed for register packets | ||
186 | */ | ||
187 | #define BUFMAX 2048 | ||
188 | |||
189 | static char input_buffer[BUFMAX]; | ||
190 | static char output_buffer[BUFMAX]; | ||
191 | static int initialized; /* !0 means we've been initialized */ | ||
192 | static int kgdb_started; | ||
193 | static const char hexchars[]="0123456789abcdef"; | ||
194 | |||
195 | /* Used to prevent crashes in memory access. Note that they'll crash anyway if | ||
196 | we haven't set up fault handlers yet... */ | ||
197 | int kgdb_read_byte(unsigned char *address, unsigned char *dest); | ||
198 | int kgdb_write_byte(unsigned char val, unsigned char *dest); | ||
199 | |||
200 | /* | ||
201 | * Convert ch from a hex digit to an int | ||
202 | */ | ||
203 | static int hex(unsigned char ch) | ||
204 | { | ||
205 | if (ch >= 'a' && ch <= 'f') | ||
206 | return ch-'a'+10; | ||
207 | if (ch >= '0' && ch <= '9') | ||
208 | return ch-'0'; | ||
209 | if (ch >= 'A' && ch <= 'F') | ||
210 | return ch-'A'+10; | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * scan for the sequence $<data>#<checksum> | ||
216 | */ | ||
217 | static void getpacket(char *buffer) | ||
218 | { | ||
219 | unsigned char checksum; | ||
220 | unsigned char xmitcsum; | ||
221 | int i; | ||
222 | int count; | ||
223 | unsigned char ch; | ||
224 | |||
225 | do { | ||
226 | /* | ||
227 | * wait around for the start character, | ||
228 | * ignore all other characters | ||
229 | */ | ||
230 | while ((ch = (getDebugChar() & 0x7f)) != '$') ; | ||
231 | |||
232 | checksum = 0; | ||
233 | xmitcsum = -1; | ||
234 | count = 0; | ||
235 | |||
236 | /* | ||
237 | * now, read until a # or end of buffer is found | ||
238 | */ | ||
239 | while (count < BUFMAX) { | ||
240 | ch = getDebugChar(); | ||
241 | if (ch == '#') | ||
242 | break; | ||
243 | checksum = checksum + ch; | ||
244 | buffer[count] = ch; | ||
245 | count = count + 1; | ||
246 | } | ||
247 | |||
248 | if (count >= BUFMAX) | ||
249 | continue; | ||
250 | |||
251 | buffer[count] = 0; | ||
252 | |||
253 | if (ch == '#') { | ||
254 | xmitcsum = hex(getDebugChar() & 0x7f) << 4; | ||
255 | xmitcsum |= hex(getDebugChar() & 0x7f); | ||
256 | |||
257 | if (checksum != xmitcsum) | ||
258 | putDebugChar('-'); /* failed checksum */ | ||
259 | else { | ||
260 | putDebugChar('+'); /* successful transfer */ | ||
261 | |||
262 | /* | ||
263 | * if a sequence char is present, | ||
264 | * reply the sequence ID | ||
265 | */ | ||
266 | if (buffer[2] == ':') { | ||
267 | putDebugChar(buffer[0]); | ||
268 | putDebugChar(buffer[1]); | ||
269 | |||
270 | /* | ||
271 | * remove sequence chars from buffer | ||
272 | */ | ||
273 | count = strlen(buffer); | ||
274 | for (i=3; i <= count; i++) | ||
275 | buffer[i-3] = buffer[i]; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | while (checksum != xmitcsum); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * send the packet in buffer. | ||
285 | */ | ||
286 | static void putpacket(char *buffer) | ||
287 | { | ||
288 | unsigned char checksum; | ||
289 | int count; | ||
290 | unsigned char ch; | ||
291 | |||
292 | /* | ||
293 | * $<packet info>#<checksum>. | ||
294 | */ | ||
295 | |||
296 | do { | ||
297 | putDebugChar('$'); | ||
298 | checksum = 0; | ||
299 | count = 0; | ||
300 | |||
301 | while ((ch = buffer[count]) != 0) { | ||
302 | if (!(putDebugChar(ch))) | ||
303 | return; | ||
304 | checksum += ch; | ||
305 | count += 1; | ||
306 | } | ||
307 | |||
308 | putDebugChar('#'); | ||
309 | putDebugChar(hexchars[checksum >> 4]); | ||
310 | putDebugChar(hexchars[checksum & 0xf]); | ||
311 | |||
312 | } | ||
313 | while ((getDebugChar() & 0x7f) != '+'); | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * Convert the memory pointed to by mem into hex, placing result in buf. | ||
319 | * Return a pointer to the last char put in buf (null), in case of mem fault, | ||
320 | * return 0. | ||
321 | * may_fault is non-zero if we are reading from arbitrary memory, but is currently | ||
322 | * not used. | ||
323 | */ | ||
324 | static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) | ||
325 | { | ||
326 | unsigned char ch; | ||
327 | |||
328 | while (count-- > 0) { | ||
329 | if (kgdb_read_byte(mem++, &ch) != 0) | ||
330 | return 0; | ||
331 | *buf++ = hexchars[ch >> 4]; | ||
332 | *buf++ = hexchars[ch & 0xf]; | ||
333 | } | ||
334 | |||
335 | *buf = 0; | ||
336 | |||
337 | return buf; | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * convert the hex array pointed to by buf into binary to be placed in mem | ||
342 | * return a pointer to the character AFTER the last byte written | ||
343 | * may_fault is non-zero if we are reading from arbitrary memory, but is currently | ||
344 | * not used. | ||
345 | */ | ||
346 | static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault) | ||
347 | { | ||
348 | int i; | ||
349 | unsigned char ch; | ||
350 | |||
351 | for (i=0; i<count; i++) | ||
352 | { | ||
353 | if (binary) { | ||
354 | ch = *buf++; | ||
355 | if (ch == 0x7d) | ||
356 | ch = 0x20 ^ *buf++; | ||
357 | } | ||
358 | else { | ||
359 | ch = hex(*buf++) << 4; | ||
360 | ch |= hex(*buf++); | ||
361 | } | ||
362 | if (kgdb_write_byte(ch, mem++) != 0) | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | return mem; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * This table contains the mapping between SPARC hardware trap types, and | ||
371 | * signals, which are primarily what GDB understands. It also indicates | ||
372 | * which hardware traps we need to commandeer when initializing the stub. | ||
373 | */ | ||
374 | static struct hard_trap_info { | ||
375 | unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ | ||
376 | unsigned char signo; /* Signal that we map this trap into */ | ||
377 | } hard_trap_info[] = { | ||
378 | { 6, SIGBUS }, /* instruction bus error */ | ||
379 | { 7, SIGBUS }, /* data bus error */ | ||
380 | { 9, SIGTRAP }, /* break */ | ||
381 | { 10, SIGILL }, /* reserved instruction */ | ||
382 | /* { 11, SIGILL }, */ /* CPU unusable */ | ||
383 | { 12, SIGFPE }, /* overflow */ | ||
384 | { 13, SIGTRAP }, /* trap */ | ||
385 | { 14, SIGSEGV }, /* virtual instruction cache coherency */ | ||
386 | { 15, SIGFPE }, /* floating point exception */ | ||
387 | { 23, SIGSEGV }, /* watch */ | ||
388 | { 31, SIGSEGV }, /* virtual data cache coherency */ | ||
389 | { 0, 0} /* Must be last */ | ||
390 | }; | ||
391 | |||
392 | /* Save the normal trap handlers for user-mode traps. */ | ||
393 | void *saved_vectors[32]; | ||
394 | |||
395 | /* | ||
396 | * Set up exception handlers for tracing and breakpoints | ||
397 | */ | ||
398 | void set_debug_traps(void) | ||
399 | { | ||
400 | struct hard_trap_info *ht; | ||
401 | unsigned long flags; | ||
402 | unsigned char c; | ||
403 | |||
404 | local_irq_save(flags); | ||
405 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
406 | saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); | ||
407 | |||
408 | putDebugChar('+'); /* 'hello world' */ | ||
409 | /* | ||
410 | * In case GDB is started before us, ack any packets | ||
411 | * (presumably "$?#xx") sitting there. | ||
412 | */ | ||
413 | while((c = getDebugChar()) != '$'); | ||
414 | while((c = getDebugChar()) != '#'); | ||
415 | c = getDebugChar(); /* eat first csum byte */ | ||
416 | c = getDebugChar(); /* eat second csum byte */ | ||
417 | putDebugChar('+'); /* ack it */ | ||
418 | |||
419 | initialized = 1; | ||
420 | local_irq_restore(flags); | ||
421 | } | ||
422 | |||
423 | void restore_debug_traps(void) | ||
424 | { | ||
425 | struct hard_trap_info *ht; | ||
426 | unsigned long flags; | ||
427 | |||
428 | local_irq_save(flags); | ||
429 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
430 | set_except_vector(ht->tt, saved_vectors[ht->tt]); | ||
431 | local_irq_restore(flags); | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * Convert the MIPS hardware trap type code to a Unix signal number. | ||
436 | */ | ||
437 | static int computeSignal(int tt) | ||
438 | { | ||
439 | struct hard_trap_info *ht; | ||
440 | |||
441 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
442 | if (ht->tt == tt) | ||
443 | return ht->signo; | ||
444 | |||
445 | return SIGHUP; /* default for things we don't know about */ | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * While we find nice hex chars, build an int. | ||
450 | * Return number of chars processed. | ||
451 | */ | ||
452 | static int hexToInt(char **ptr, int *intValue) | ||
453 | { | ||
454 | int numChars = 0; | ||
455 | int hexValue; | ||
456 | |||
457 | *intValue = 0; | ||
458 | |||
459 | while (**ptr) { | ||
460 | hexValue = hex(**ptr); | ||
461 | if (hexValue < 0) | ||
462 | break; | ||
463 | |||
464 | *intValue = (*intValue << 4) | hexValue; | ||
465 | numChars ++; | ||
466 | |||
467 | (*ptr)++; | ||
468 | } | ||
469 | |||
470 | return (numChars); | ||
471 | } | ||
472 | |||
473 | static int hexToLong(char **ptr, long *longValue) | ||
474 | { | ||
475 | int numChars = 0; | ||
476 | int hexValue; | ||
477 | |||
478 | *longValue = 0; | ||
479 | |||
480 | while (**ptr) { | ||
481 | hexValue = hex(**ptr); | ||
482 | if (hexValue < 0) | ||
483 | break; | ||
484 | |||
485 | *longValue = (*longValue << 4) | hexValue; | ||
486 | numChars ++; | ||
487 | |||
488 | (*ptr)++; | ||
489 | } | ||
490 | |||
491 | return numChars; | ||
492 | } | ||
493 | |||
494 | |||
495 | #if 0 | ||
496 | /* | ||
497 | * Print registers (on target console) | ||
498 | * Used only to debug the stub... | ||
499 | */ | ||
500 | void show_gdbregs(struct gdb_regs * regs) | ||
501 | { | ||
502 | /* | ||
503 | * Saved main processor registers | ||
504 | */ | ||
505 | printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
506 | regs->reg0, regs->reg1, regs->reg2, regs->reg3, | ||
507 | regs->reg4, regs->reg5, regs->reg6, regs->reg7); | ||
508 | printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
509 | regs->reg8, regs->reg9, regs->reg10, regs->reg11, | ||
510 | regs->reg12, regs->reg13, regs->reg14, regs->reg15); | ||
511 | printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
512 | regs->reg16, regs->reg17, regs->reg18, regs->reg19, | ||
513 | regs->reg20, regs->reg21, regs->reg22, regs->reg23); | ||
514 | printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
515 | regs->reg24, regs->reg25, regs->reg26, regs->reg27, | ||
516 | regs->reg28, regs->reg29, regs->reg30, regs->reg31); | ||
517 | |||
518 | /* | ||
519 | * Saved cp0 registers | ||
520 | */ | ||
521 | printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", | ||
522 | regs->cp0_epc, regs->cp0_status, regs->cp0_cause); | ||
523 | } | ||
524 | #endif /* dead code */ | ||
525 | |||
526 | /* | ||
527 | * We single-step by setting breakpoints. When an exception | ||
528 | * is handled, we need to restore the instructions hoisted | ||
529 | * when the breakpoints were set. | ||
530 | * | ||
531 | * This is where we save the original instructions. | ||
532 | */ | ||
533 | static struct gdb_bp_save { | ||
534 | unsigned long addr; | ||
535 | unsigned int val; | ||
536 | } step_bp[2]; | ||
537 | |||
538 | #define BP 0x0000000d /* break opcode */ | ||
539 | |||
540 | /* | ||
541 | * Set breakpoint instructions for single stepping. | ||
542 | */ | ||
543 | static void single_step(struct gdb_regs *regs) | ||
544 | { | ||
545 | union mips_instruction insn; | ||
546 | unsigned long targ; | ||
547 | int is_branch, is_cond, i; | ||
548 | |||
549 | targ = regs->cp0_epc; | ||
550 | insn.word = *(unsigned int *)targ; | ||
551 | is_branch = is_cond = 0; | ||
552 | |||
553 | switch (insn.i_format.opcode) { | ||
554 | /* | ||
555 | * jr and jalr are in r_format format. | ||
556 | */ | ||
557 | case spec_op: | ||
558 | switch (insn.r_format.func) { | ||
559 | case jalr_op: | ||
560 | case jr_op: | ||
561 | targ = *(®s->reg0 + insn.r_format.rs); | ||
562 | is_branch = 1; | ||
563 | break; | ||
564 | } | ||
565 | break; | ||
566 | |||
567 | /* | ||
568 | * This group contains: | ||
569 | * bltz_op, bgez_op, bltzl_op, bgezl_op, | ||
570 | * bltzal_op, bgezal_op, bltzall_op, bgezall_op. | ||
571 | */ | ||
572 | case bcond_op: | ||
573 | is_branch = is_cond = 1; | ||
574 | targ += 4 + (insn.i_format.simmediate << 2); | ||
575 | break; | ||
576 | |||
577 | /* | ||
578 | * These are unconditional and in j_format. | ||
579 | */ | ||
580 | case jal_op: | ||
581 | case j_op: | ||
582 | is_branch = 1; | ||
583 | targ += 4; | ||
584 | targ >>= 28; | ||
585 | targ <<= 28; | ||
586 | targ |= (insn.j_format.target << 2); | ||
587 | break; | ||
588 | |||
589 | /* | ||
590 | * These are conditional. | ||
591 | */ | ||
592 | case beq_op: | ||
593 | case beql_op: | ||
594 | case bne_op: | ||
595 | case bnel_op: | ||
596 | case blez_op: | ||
597 | case blezl_op: | ||
598 | case bgtz_op: | ||
599 | case bgtzl_op: | ||
600 | case cop0_op: | ||
601 | case cop1_op: | ||
602 | case cop2_op: | ||
603 | case cop1x_op: | ||
604 | is_branch = is_cond = 1; | ||
605 | targ += 4 + (insn.i_format.simmediate << 2); | ||
606 | break; | ||
607 | } | ||
608 | |||
609 | if (is_branch) { | ||
610 | i = 0; | ||
611 | if (is_cond && targ != (regs->cp0_epc + 8)) { | ||
612 | step_bp[i].addr = regs->cp0_epc + 8; | ||
613 | step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8); | ||
614 | *(unsigned *)(regs->cp0_epc + 8) = BP; | ||
615 | } | ||
616 | step_bp[i].addr = targ; | ||
617 | step_bp[i].val = *(unsigned *)targ; | ||
618 | *(unsigned *)targ = BP; | ||
619 | } else { | ||
620 | step_bp[0].addr = regs->cp0_epc + 4; | ||
621 | step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4); | ||
622 | *(unsigned *)(regs->cp0_epc + 4) = BP; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | /* | ||
627 | * If asynchronously interrupted by gdb, then we need to set a breakpoint | ||
628 | * at the interrupted instruction so that we wind up stopped with a | ||
629 | * reasonable stack frame. | ||
630 | */ | ||
631 | static struct gdb_bp_save async_bp; | ||
632 | |||
633 | /* | ||
634 | * Swap the interrupted EPC with our asynchronous breakpoint routine. | ||
635 | * This is safer than stuffing the breakpoint in-place, since no cache | ||
636 | * flushes (or resulting smp_call_functions) are required. The | ||
637 | * assumption is that only one CPU will be handling asynchronous bp's, | ||
638 | * and only one can be active at a time. | ||
639 | */ | ||
640 | extern spinlock_t smp_call_lock; | ||
641 | |||
642 | void set_async_breakpoint(unsigned long *epc) | ||
643 | { | ||
644 | /* skip breaking into userland */ | ||
645 | if ((*epc & 0x80000000) == 0) | ||
646 | return; | ||
647 | |||
648 | #ifdef CONFIG_SMP | ||
649 | /* avoid deadlock if someone is make IPC */ | ||
650 | if (spin_is_locked(&smp_call_lock)) | ||
651 | return; | ||
652 | #endif | ||
653 | |||
654 | async_bp.addr = *epc; | ||
655 | *epc = (unsigned long)async_breakpoint; | ||
656 | } | ||
657 | |||
658 | #ifdef CONFIG_SMP | ||
659 | static void kgdb_wait(void *arg) | ||
660 | { | ||
661 | unsigned flags; | ||
662 | int cpu = smp_processor_id(); | ||
663 | |||
664 | local_irq_save(flags); | ||
665 | |||
666 | __raw_spin_lock(&kgdb_cpulock[cpu]); | ||
667 | __raw_spin_unlock(&kgdb_cpulock[cpu]); | ||
668 | |||
669 | local_irq_restore(flags); | ||
670 | } | ||
671 | #endif | ||
672 | |||
673 | /* | ||
674 | * GDB stub needs to call kgdb_wait on all processor with interrupts | ||
675 | * disabled, so it uses it's own special variant. | ||
676 | */ | ||
677 | static int kgdb_smp_call_kgdb_wait(void) | ||
678 | { | ||
679 | #ifdef CONFIG_SMP | ||
680 | cpumask_t mask = cpu_online_map; | ||
681 | struct call_data_struct data; | ||
682 | int cpu = smp_processor_id(); | ||
683 | int cpus; | ||
684 | |||
685 | /* | ||
686 | * Can die spectacularly if this CPU isn't yet marked online | ||
687 | */ | ||
688 | BUG_ON(!cpu_online(cpu)); | ||
689 | |||
690 | cpu_clear(cpu, mask); | ||
691 | cpus = cpus_weight(mask); | ||
692 | if (!cpus) | ||
693 | return 0; | ||
694 | |||
695 | if (spin_is_locked(&smp_call_lock)) { | ||
696 | /* | ||
697 | * Some other processor is trying to make us do something | ||
698 | * but we're not going to respond... give up | ||
699 | */ | ||
700 | return -1; | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * We will continue here, accepting the fact that | ||
705 | * the kernel may deadlock if another CPU attempts | ||
706 | * to call smp_call_function now... | ||
707 | */ | ||
708 | |||
709 | data.func = kgdb_wait; | ||
710 | data.info = NULL; | ||
711 | atomic_set(&data.started, 0); | ||
712 | data.wait = 0; | ||
713 | |||
714 | spin_lock(&smp_call_lock); | ||
715 | call_data = &data; | ||
716 | mb(); | ||
717 | |||
718 | core_send_ipi_mask(mask, SMP_CALL_FUNCTION); | ||
719 | |||
720 | /* Wait for response */ | ||
721 | /* FIXME: lock-up detection, backtrace on lock-up */ | ||
722 | while (atomic_read(&data.started) != cpus) | ||
723 | barrier(); | ||
724 | |||
725 | call_data = NULL; | ||
726 | spin_unlock(&smp_call_lock); | ||
727 | #endif | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * This function does all command processing for interfacing to gdb. It | ||
734 | * returns 1 if you should skip the instruction at the trap address, 0 | ||
735 | * otherwise. | ||
736 | */ | ||
737 | void handle_exception(struct gdb_regs *regs) | ||
738 | { | ||
739 | int trap; /* Trap type */ | ||
740 | int sigval; | ||
741 | long addr; | ||
742 | int length; | ||
743 | char *ptr; | ||
744 | unsigned long *stack; | ||
745 | int i; | ||
746 | int bflag = 0; | ||
747 | |||
748 | kgdb_started = 1; | ||
749 | |||
750 | /* | ||
751 | * acquire the big kgdb spinlock | ||
752 | */ | ||
753 | if (!spin_trylock(&kgdb_lock)) { | ||
754 | /* | ||
755 | * some other CPU has the lock, we should go back to | ||
756 | * receive the gdb_wait IPC | ||
757 | */ | ||
758 | return; | ||
759 | } | ||
760 | |||
761 | /* | ||
762 | * If we're in async_breakpoint(), restore the real EPC from | ||
763 | * the breakpoint. | ||
764 | */ | ||
765 | if (regs->cp0_epc == (unsigned long)async_breakinst) { | ||
766 | regs->cp0_epc = async_bp.addr; | ||
767 | async_bp.addr = 0; | ||
768 | } | ||
769 | |||
770 | /* | ||
771 | * acquire the CPU spinlocks | ||
772 | */ | ||
773 | for_each_online_cpu(i) | ||
774 | if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0) | ||
775 | panic("kgdb: couldn't get cpulock %d\n", i); | ||
776 | |||
777 | /* | ||
778 | * force other cpus to enter kgdb | ||
779 | */ | ||
780 | kgdb_smp_call_kgdb_wait(); | ||
781 | |||
782 | /* | ||
783 | * If we're in breakpoint() increment the PC | ||
784 | */ | ||
785 | trap = (regs->cp0_cause & 0x7c) >> 2; | ||
786 | if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst) | ||
787 | regs->cp0_epc += 4; | ||
788 | |||
789 | /* | ||
790 | * If we were single_stepping, restore the opcodes hoisted | ||
791 | * for the breakpoint[s]. | ||
792 | */ | ||
793 | if (step_bp[0].addr) { | ||
794 | *(unsigned *)step_bp[0].addr = step_bp[0].val; | ||
795 | step_bp[0].addr = 0; | ||
796 | |||
797 | if (step_bp[1].addr) { | ||
798 | *(unsigned *)step_bp[1].addr = step_bp[1].val; | ||
799 | step_bp[1].addr = 0; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | stack = (long *)regs->reg29; /* stack ptr */ | ||
804 | sigval = computeSignal(trap); | ||
805 | |||
806 | /* | ||
807 | * reply to host that an exception has occurred | ||
808 | */ | ||
809 | ptr = output_buffer; | ||
810 | |||
811 | /* | ||
812 | * Send trap type (converted to signal) | ||
813 | */ | ||
814 | *ptr++ = 'T'; | ||
815 | *ptr++ = hexchars[sigval >> 4]; | ||
816 | *ptr++ = hexchars[sigval & 0xf]; | ||
817 | |||
818 | /* | ||
819 | * Send Error PC | ||
820 | */ | ||
821 | *ptr++ = hexchars[REG_EPC >> 4]; | ||
822 | *ptr++ = hexchars[REG_EPC & 0xf]; | ||
823 | *ptr++ = ':'; | ||
824 | ptr = mem2hex((char *)®s->cp0_epc, ptr, sizeof(long), 0); | ||
825 | *ptr++ = ';'; | ||
826 | |||
827 | /* | ||
828 | * Send frame pointer | ||
829 | */ | ||
830 | *ptr++ = hexchars[REG_FP >> 4]; | ||
831 | *ptr++ = hexchars[REG_FP & 0xf]; | ||
832 | *ptr++ = ':'; | ||
833 | ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0); | ||
834 | *ptr++ = ';'; | ||
835 | |||
836 | /* | ||
837 | * Send stack pointer | ||
838 | */ | ||
839 | *ptr++ = hexchars[REG_SP >> 4]; | ||
840 | *ptr++ = hexchars[REG_SP & 0xf]; | ||
841 | *ptr++ = ':'; | ||
842 | ptr = mem2hex((char *)®s->reg29, ptr, sizeof(long), 0); | ||
843 | *ptr++ = ';'; | ||
844 | |||
845 | *ptr++ = 0; | ||
846 | putpacket(output_buffer); /* send it off... */ | ||
847 | |||
848 | /* | ||
849 | * Wait for input from remote GDB | ||
850 | */ | ||
851 | while (1) { | ||
852 | output_buffer[0] = 0; | ||
853 | getpacket(input_buffer); | ||
854 | |||
855 | switch (input_buffer[0]) | ||
856 | { | ||
857 | case '?': | ||
858 | output_buffer[0] = 'S'; | ||
859 | output_buffer[1] = hexchars[sigval >> 4]; | ||
860 | output_buffer[2] = hexchars[sigval & 0xf]; | ||
861 | output_buffer[3] = 0; | ||
862 | break; | ||
863 | |||
864 | /* | ||
865 | * Detach debugger; let CPU run | ||
866 | */ | ||
867 | case 'D': | ||
868 | putpacket(output_buffer); | ||
869 | goto finish_kgdb; | ||
870 | break; | ||
871 | |||
872 | case 'd': | ||
873 | /* toggle debug flag */ | ||
874 | break; | ||
875 | |||
876 | /* | ||
877 | * Return the value of the CPU registers | ||
878 | */ | ||
879 | case 'g': | ||
880 | ptr = output_buffer; | ||
881 | ptr = mem2hex((char *)®s->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */ | ||
882 | ptr = mem2hex((char *)®s->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */ | ||
883 | ptr = mem2hex((char *)®s->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */ | ||
884 | ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */ | ||
885 | ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */ | ||
886 | ptr = mem2hex((char *)®s->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */ | ||
887 | break; | ||
888 | |||
889 | /* | ||
890 | * set the value of the CPU registers - return OK | ||
891 | */ | ||
892 | case 'G': | ||
893 | { | ||
894 | ptr = &input_buffer[1]; | ||
895 | hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0, 0); | ||
896 | ptr += 32*(2*sizeof(long)); | ||
897 | hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0); | ||
898 | ptr += 6*(2*sizeof(long)); | ||
899 | hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0); | ||
900 | ptr += 32*(2*sizeof(long)); | ||
901 | hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0); | ||
902 | ptr += 2*(2*sizeof(long)); | ||
903 | hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0); | ||
904 | ptr += 2*(2*sizeof(long)); | ||
905 | hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0, 0); | ||
906 | strcpy(output_buffer, "OK"); | ||
907 | } | ||
908 | break; | ||
909 | |||
910 | /* | ||
911 | * mAA..AA,LLLL Read LLLL bytes at address AA..AA | ||
912 | */ | ||
913 | case 'm': | ||
914 | ptr = &input_buffer[1]; | ||
915 | |||
916 | if (hexToLong(&ptr, &addr) | ||
917 | && *ptr++ == ',' | ||
918 | && hexToInt(&ptr, &length)) { | ||
919 | if (mem2hex((char *)addr, output_buffer, length, 1)) | ||
920 | break; | ||
921 | strcpy(output_buffer, "E03"); | ||
922 | } else | ||
923 | strcpy(output_buffer, "E01"); | ||
924 | break; | ||
925 | |||
926 | /* | ||
927 | * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA | ||
928 | */ | ||
929 | case 'X': | ||
930 | bflag = 1; | ||
931 | /* fall through */ | ||
932 | |||
933 | /* | ||
934 | * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK | ||
935 | */ | ||
936 | case 'M': | ||
937 | ptr = &input_buffer[1]; | ||
938 | |||
939 | if (hexToLong(&ptr, &addr) | ||
940 | && *ptr++ == ',' | ||
941 | && hexToInt(&ptr, &length) | ||
942 | && *ptr++ == ':') { | ||
943 | if (hex2mem(ptr, (char *)addr, length, bflag, 1)) | ||
944 | strcpy(output_buffer, "OK"); | ||
945 | else | ||
946 | strcpy(output_buffer, "E03"); | ||
947 | } | ||
948 | else | ||
949 | strcpy(output_buffer, "E02"); | ||
950 | break; | ||
951 | |||
952 | /* | ||
953 | * cAA..AA Continue at address AA..AA(optional) | ||
954 | */ | ||
955 | case 'c': | ||
956 | /* try to read optional parameter, pc unchanged if no parm */ | ||
957 | |||
958 | ptr = &input_buffer[1]; | ||
959 | if (hexToLong(&ptr, &addr)) | ||
960 | regs->cp0_epc = addr; | ||
961 | |||
962 | goto exit_kgdb_exception; | ||
963 | break; | ||
964 | |||
965 | /* | ||
966 | * kill the program; let us try to restart the machine | ||
967 | * Reset the whole machine. | ||
968 | */ | ||
969 | case 'k': | ||
970 | case 'r': | ||
971 | machine_restart("kgdb restarts machine"); | ||
972 | break; | ||
973 | |||
974 | /* | ||
975 | * Step to next instruction | ||
976 | */ | ||
977 | case 's': | ||
978 | /* | ||
979 | * There is no single step insn in the MIPS ISA, so we | ||
980 | * use breakpoints and continue, instead. | ||
981 | */ | ||
982 | single_step(regs); | ||
983 | goto exit_kgdb_exception; | ||
984 | /* NOTREACHED */ | ||
985 | break; | ||
986 | |||
987 | /* | ||
988 | * Set baud rate (bBB) | ||
989 | * FIXME: Needs to be written | ||
990 | */ | ||
991 | case 'b': | ||
992 | { | ||
993 | #if 0 | ||
994 | int baudrate; | ||
995 | extern void set_timer_3(); | ||
996 | |||
997 | ptr = &input_buffer[1]; | ||
998 | if (!hexToInt(&ptr, &baudrate)) | ||
999 | { | ||
1000 | strcpy(output_buffer, "B01"); | ||
1001 | break; | ||
1002 | } | ||
1003 | |||
1004 | /* Convert baud rate to uart clock divider */ | ||
1005 | |||
1006 | switch (baudrate) | ||
1007 | { | ||
1008 | case 38400: | ||
1009 | baudrate = 16; | ||
1010 | break; | ||
1011 | case 19200: | ||
1012 | baudrate = 33; | ||
1013 | break; | ||
1014 | case 9600: | ||
1015 | baudrate = 65; | ||
1016 | break; | ||
1017 | default: | ||
1018 | baudrate = 0; | ||
1019 | strcpy(output_buffer, "B02"); | ||
1020 | goto x1; | ||
1021 | } | ||
1022 | |||
1023 | if (baudrate) { | ||
1024 | putpacket("OK"); /* Ack before changing speed */ | ||
1025 | set_timer_3(baudrate); /* Set it */ | ||
1026 | } | ||
1027 | #endif | ||
1028 | } | ||
1029 | break; | ||
1030 | |||
1031 | } /* switch */ | ||
1032 | |||
1033 | /* | ||
1034 | * reply to the request | ||
1035 | */ | ||
1036 | |||
1037 | putpacket(output_buffer); | ||
1038 | |||
1039 | } /* while */ | ||
1040 | |||
1041 | return; | ||
1042 | |||
1043 | finish_kgdb: | ||
1044 | restore_debug_traps(); | ||
1045 | |||
1046 | exit_kgdb_exception: | ||
1047 | /* release locks so other CPUs can go */ | ||
1048 | for_each_online_cpu(i) | ||
1049 | __raw_spin_unlock(&kgdb_cpulock[i]); | ||
1050 | spin_unlock(&kgdb_lock); | ||
1051 | |||
1052 | __flush_cache_all(); | ||
1053 | return; | ||
1054 | } | ||
1055 | |||
1056 | /* | ||
1057 | * This function will generate a breakpoint exception. It is used at the | ||
1058 | * beginning of a program to sync up with a debugger and can be used | ||
1059 | * otherwise as a quick means to stop program execution and "break" into | ||
1060 | * the debugger. | ||
1061 | */ | ||
1062 | void breakpoint(void) | ||
1063 | { | ||
1064 | if (!initialized) | ||
1065 | return; | ||
1066 | |||
1067 | __asm__ __volatile__( | ||
1068 | ".globl breakinst\n\t" | ||
1069 | ".set\tnoreorder\n\t" | ||
1070 | "nop\n" | ||
1071 | "breakinst:\tbreak\n\t" | ||
1072 | "nop\n\t" | ||
1073 | ".set\treorder" | ||
1074 | ); | ||
1075 | } | ||
1076 | |||
1077 | /* Nothing but the break; don't pollute any registers */ | ||
1078 | void async_breakpoint(void) | ||
1079 | { | ||
1080 | __asm__ __volatile__( | ||
1081 | ".globl async_breakinst\n\t" | ||
1082 | ".set\tnoreorder\n\t" | ||
1083 | "nop\n" | ||
1084 | "async_breakinst:\tbreak\n\t" | ||
1085 | "nop\n\t" | ||
1086 | ".set\treorder" | ||
1087 | ); | ||
1088 | } | ||
1089 | |||
1090 | void adel(void) | ||
1091 | { | ||
1092 | __asm__ __volatile__( | ||
1093 | ".globl\tadel\n\t" | ||
1094 | "lui\t$8,0x8000\n\t" | ||
1095 | "lw\t$9,1($8)\n\t" | ||
1096 | ); | ||
1097 | } | ||
1098 | |||
1099 | /* | ||
1100 | * malloc is needed by gdb client in "call func()", even a private one | ||
1101 | * will make gdb happy | ||
1102 | */ | ||
1103 | static void __used *malloc(size_t size) | ||
1104 | { | ||
1105 | return kmalloc(size, GFP_ATOMIC); | ||
1106 | } | ||
1107 | |||
1108 | static void __used free(void *where) | ||
1109 | { | ||
1110 | kfree(where); | ||
1111 | } | ||
1112 | |||
1113 | #ifdef CONFIG_GDB_CONSOLE | ||
1114 | |||
1115 | void gdb_putsn(const char *str, int l) | ||
1116 | { | ||
1117 | char outbuf[18]; | ||
1118 | |||
1119 | if (!kgdb_started) | ||
1120 | return; | ||
1121 | |||
1122 | outbuf[0]='O'; | ||
1123 | |||
1124 | while(l) { | ||
1125 | int i = (l>8)?8:l; | ||
1126 | mem2hex((char *)str, &outbuf[1], i, 0); | ||
1127 | outbuf[(i*2)+1]=0; | ||
1128 | putpacket(outbuf); | ||
1129 | str += i; | ||
1130 | l -= i; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | static void gdb_console_write(struct console *con, const char *s, unsigned n) | ||
1135 | { | ||
1136 | gdb_putsn(s, n); | ||
1137 | } | ||
1138 | |||
1139 | static struct console gdb_console = { | ||
1140 | .name = "gdb", | ||
1141 | .write = gdb_console_write, | ||
1142 | .flags = CON_PRINTBUFFER, | ||
1143 | .index = -1 | ||
1144 | }; | ||
1145 | |||
1146 | static int __init register_gdb_console(void) | ||
1147 | { | ||
1148 | register_console(&gdb_console); | ||
1149 | |||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | console_initcall(register_gdb_console); | ||
1154 | |||
1155 | #endif | ||
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 6045b9a51a35..8acba0880d9f 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c | |||
@@ -126,19 +126,6 @@ asmlinkage void spurious_interrupt(void) | |||
126 | atomic_inc(&irq_err_count); | 126 | atomic_inc(&irq_err_count); |
127 | } | 127 | } |
128 | 128 | ||
129 | #ifdef CONFIG_KGDB | ||
130 | extern void breakpoint(void); | ||
131 | extern void set_debug_traps(void); | ||
132 | |||
133 | static int kgdb_flag = 1; | ||
134 | static int __init nokgdb(char *str) | ||
135 | { | ||
136 | kgdb_flag = 0; | ||
137 | return 1; | ||
138 | } | ||
139 | __setup("nokgdb", nokgdb); | ||
140 | #endif | ||
141 | |||
142 | void __init init_IRQ(void) | 129 | void __init init_IRQ(void) |
143 | { | 130 | { |
144 | int i; | 131 | int i; |
@@ -147,12 +134,4 @@ void __init init_IRQ(void) | |||
147 | set_irq_noprobe(i); | 134 | set_irq_noprobe(i); |
148 | 135 | ||
149 | arch_init_irq(); | 136 | arch_init_irq(); |
150 | |||
151 | #ifdef CONFIG_KGDB | ||
152 | if (kgdb_flag) { | ||
153 | printk("Wait for gdb client connection ...\n"); | ||
154 | set_debug_traps(); | ||
155 | breakpoint(); | ||
156 | } | ||
157 | #endif | ||
158 | } | 137 | } |