diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-04-17 14:05:37 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 14:05:37 -0400 |
commit | 82da3ff89dc2a1842cff9b0d4cbc345cb90b59e1 (patch) | |
tree | f802b14eeaab231a940b9e974641b007f5815818 | |
parent | f2d937f3bf00665ccf048b3b6616ef95859b0945 (diff) |
x86: kgdb support
simplified and streamlined kgdb support on x86, both 32-bit and 64-bit,
based on patch from:
Subject: kgdb: core-lite
From: Jason Wessel <jason.wessel@windriver.com>
[ and countless other authors - see the patch for details. ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/kgdb.c | 417 | ||||
-rw-r--r-- | include/asm-x86/kgdb.h | 81 |
4 files changed, 500 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6c70fed0f9a0..5c4c8d7a46cc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -23,6 +23,7 @@ config X86 | |||
23 | select HAVE_KPROBES | 23 | select HAVE_KPROBES |
24 | select HAVE_KRETPROBES | 24 | select HAVE_KRETPROBES |
25 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) | 25 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) |
26 | select HAVE_ARCH_KGDB | ||
26 | 27 | ||
27 | 28 | ||
28 | config GENERIC_LOCKBREAK | 29 | config GENERIC_LOCKBREAK |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4eb5ce841106..4a4260c7f672 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -66,6 +66,7 @@ obj-$(CONFIG_MODULES) += module_$(BITS).o | |||
66 | obj-$(CONFIG_ACPI_SRAT) += srat_32.o | 66 | obj-$(CONFIG_ACPI_SRAT) += srat_32.o |
67 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 67 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
68 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | 68 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o |
69 | obj-$(CONFIG_KGDB) += kgdb.o | ||
69 | obj-$(CONFIG_VM86) += vm86_32.o | 70 | obj-$(CONFIG_VM86) += vm86_32.o |
70 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 71 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
71 | 72 | ||
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c new file mode 100644 index 000000000000..37194d6374d8 --- /dev/null +++ b/arch/x86/kernel/kgdb.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2, or (at your option) any | ||
5 | * later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, but | ||
8 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
10 | * General Public License for more details. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Copyright (C) 2004 Amit S. Kale <amitkale@linsyssoft.com> | ||
16 | * Copyright (C) 2000-2001 VERITAS Software Corporation. | ||
17 | * Copyright (C) 2002 Andi Kleen, SuSE Labs | ||
18 | * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd. | ||
19 | * Copyright (C) 2007 MontaVista Software, Inc. | ||
20 | * Copyright (C) 2007-2008 Jason Wessel, Wind River Systems, Inc. | ||
21 | */ | ||
22 | /**************************************************************************** | ||
23 | * Contributor: Lake Stevens Instrument Division$ | ||
24 | * Written by: Glenn Engel $ | ||
25 | * Updated by: Amit Kale<akale@veritas.com> | ||
26 | * Updated by: Tom Rini <trini@kernel.crashing.org> | ||
27 | * Updated by: Jason Wessel <jason.wessel@windriver.com> | ||
28 | * Modified for 386 by Jim Kingdon, Cygnus Support. | ||
29 | * Origianl kgdb, compatibility with 2.1.xx kernel by | ||
30 | * David Grothe <dave@gcom.com> | ||
31 | * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com> | ||
32 | * X86_64 changes from Andi Kleen's patch merged by Jim Houston | ||
33 | */ | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/kdebug.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/ptrace.h> | ||
39 | #include <linux/sched.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/kgdb.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/smp.h> | ||
44 | |||
45 | #include <asm/apicdef.h> | ||
46 | #include <asm/system.h> | ||
47 | |||
48 | #ifdef CONFIG_X86_32 | ||
49 | # include <mach_ipi.h> | ||
50 | #else | ||
51 | # include <asm/mach_apic.h> | ||
52 | #endif | ||
53 | |||
54 | /* | ||
55 | * Put the error code here just in case the user cares: | ||
56 | */ | ||
57 | static int gdb_x86errcode; | ||
58 | |||
59 | /* | ||
60 | * Likewise, the vector number here (since GDB only gets the signal | ||
61 | * number through the usual means, and that's not very specific): | ||
62 | */ | ||
63 | static int gdb_x86vector = -1; | ||
64 | |||
65 | /** | ||
66 | * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs | ||
67 | * @gdb_regs: A pointer to hold the registers in the order GDB wants. | ||
68 | * @regs: The &struct pt_regs of the current process. | ||
69 | * | ||
70 | * Convert the pt_regs in @regs into the format for registers that | ||
71 | * GDB expects, stored in @gdb_regs. | ||
72 | */ | ||
73 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
74 | { | ||
75 | gdb_regs[GDB_AX] = regs->ax; | ||
76 | gdb_regs[GDB_BX] = regs->bx; | ||
77 | gdb_regs[GDB_CX] = regs->cx; | ||
78 | gdb_regs[GDB_DX] = regs->dx; | ||
79 | gdb_regs[GDB_SI] = regs->si; | ||
80 | gdb_regs[GDB_DI] = regs->di; | ||
81 | gdb_regs[GDB_BP] = regs->bp; | ||
82 | gdb_regs[GDB_PS] = regs->flags; | ||
83 | gdb_regs[GDB_PC] = regs->ip; | ||
84 | #ifdef CONFIG_X86_32 | ||
85 | gdb_regs[GDB_DS] = regs->ds; | ||
86 | gdb_regs[GDB_ES] = regs->es; | ||
87 | gdb_regs[GDB_CS] = regs->cs; | ||
88 | gdb_regs[GDB_SS] = __KERNEL_DS; | ||
89 | gdb_regs[GDB_FS] = 0xFFFF; | ||
90 | gdb_regs[GDB_GS] = 0xFFFF; | ||
91 | #else | ||
92 | gdb_regs[GDB_R8] = regs->r8; | ||
93 | gdb_regs[GDB_R9] = regs->r9; | ||
94 | gdb_regs[GDB_R10] = regs->r10; | ||
95 | gdb_regs[GDB_R11] = regs->r11; | ||
96 | gdb_regs[GDB_R12] = regs->r12; | ||
97 | gdb_regs[GDB_R13] = regs->r13; | ||
98 | gdb_regs[GDB_R14] = regs->r14; | ||
99 | gdb_regs[GDB_R15] = regs->r15; | ||
100 | #endif | ||
101 | gdb_regs[GDB_SP] = regs->sp; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs | ||
106 | * @gdb_regs: A pointer to hold the registers in the order GDB wants. | ||
107 | * @p: The &struct task_struct of the desired process. | ||
108 | * | ||
109 | * Convert the register values of the sleeping process in @p to | ||
110 | * the format that GDB expects. | ||
111 | * This function is called when kgdb does not have access to the | ||
112 | * &struct pt_regs and therefore it should fill the gdb registers | ||
113 | * @gdb_regs with what has been saved in &struct thread_struct | ||
114 | * thread field during switch_to. | ||
115 | */ | ||
116 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
117 | { | ||
118 | gdb_regs[GDB_AX] = 0; | ||
119 | gdb_regs[GDB_BX] = 0; | ||
120 | gdb_regs[GDB_CX] = 0; | ||
121 | gdb_regs[GDB_DX] = 0; | ||
122 | gdb_regs[GDB_SI] = 0; | ||
123 | gdb_regs[GDB_DI] = 0; | ||
124 | gdb_regs[GDB_BP] = *(unsigned long *)p->thread.sp; | ||
125 | #ifdef CONFIG_X86_32 | ||
126 | gdb_regs[GDB_DS] = __KERNEL_DS; | ||
127 | gdb_regs[GDB_ES] = __KERNEL_DS; | ||
128 | gdb_regs[GDB_PS] = 0; | ||
129 | gdb_regs[GDB_CS] = __KERNEL_CS; | ||
130 | gdb_regs[GDB_PC] = p->thread.ip; | ||
131 | gdb_regs[GDB_SS] = __KERNEL_DS; | ||
132 | gdb_regs[GDB_FS] = 0xFFFF; | ||
133 | gdb_regs[GDB_GS] = 0xFFFF; | ||
134 | #else | ||
135 | gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); | ||
136 | gdb_regs[GDB_PC] = 0; | ||
137 | gdb_regs[GDB_R8] = 0; | ||
138 | gdb_regs[GDB_R9] = 0; | ||
139 | gdb_regs[GDB_R10] = 0; | ||
140 | gdb_regs[GDB_R11] = 0; | ||
141 | gdb_regs[GDB_R12] = 0; | ||
142 | gdb_regs[GDB_R13] = 0; | ||
143 | gdb_regs[GDB_R14] = 0; | ||
144 | gdb_regs[GDB_R15] = 0; | ||
145 | #endif | ||
146 | gdb_regs[GDB_SP] = p->thread.sp; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs. | ||
151 | * @gdb_regs: A pointer to hold the registers we've received from GDB. | ||
152 | * @regs: A pointer to a &struct pt_regs to hold these values in. | ||
153 | * | ||
154 | * Convert the GDB regs in @gdb_regs into the pt_regs, and store them | ||
155 | * in @regs. | ||
156 | */ | ||
157 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
158 | { | ||
159 | regs->ax = gdb_regs[GDB_AX]; | ||
160 | regs->bx = gdb_regs[GDB_BX]; | ||
161 | regs->cx = gdb_regs[GDB_CX]; | ||
162 | regs->dx = gdb_regs[GDB_DX]; | ||
163 | regs->si = gdb_regs[GDB_SI]; | ||
164 | regs->di = gdb_regs[GDB_DI]; | ||
165 | regs->bp = gdb_regs[GDB_BP]; | ||
166 | regs->flags = gdb_regs[GDB_PS]; | ||
167 | regs->ip = gdb_regs[GDB_PC]; | ||
168 | #ifdef CONFIG_X86_32 | ||
169 | regs->ds = gdb_regs[GDB_DS]; | ||
170 | regs->es = gdb_regs[GDB_ES]; | ||
171 | regs->cs = gdb_regs[GDB_CS]; | ||
172 | #else | ||
173 | regs->r8 = gdb_regs[GDB_R8]; | ||
174 | regs->r9 = gdb_regs[GDB_R9]; | ||
175 | regs->r10 = gdb_regs[GDB_R10]; | ||
176 | regs->r11 = gdb_regs[GDB_R11]; | ||
177 | regs->r12 = gdb_regs[GDB_R12]; | ||
178 | regs->r13 = gdb_regs[GDB_R13]; | ||
179 | regs->r14 = gdb_regs[GDB_R14]; | ||
180 | regs->r15 = gdb_regs[GDB_R15]; | ||
181 | #endif | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * kgdb_post_primary_code - Save error vector/code numbers. | ||
186 | * @regs: Original pt_regs. | ||
187 | * @e_vector: Original error vector. | ||
188 | * @err_code: Original error code. | ||
189 | * | ||
190 | * This is needed on architectures which support SMP and KGDB. | ||
191 | * This function is called after all the slave cpus have been put | ||
192 | * to a know spin state and the primary CPU has control over KGDB. | ||
193 | */ | ||
194 | void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code) | ||
195 | { | ||
196 | /* primary processor is completely in the debugger */ | ||
197 | gdb_x86vector = e_vector; | ||
198 | gdb_x86errcode = err_code; | ||
199 | } | ||
200 | |||
201 | #ifdef CONFIG_SMP | ||
202 | /** | ||
203 | * kgdb_roundup_cpus - Get other CPUs into a holding pattern | ||
204 | * @flags: Current IRQ state | ||
205 | * | ||
206 | * On SMP systems, we need to get the attention of the other CPUs | ||
207 | * and get them be in a known state. This should do what is needed | ||
208 | * to get the other CPUs to call kgdb_wait(). Note that on some arches, | ||
209 | * the NMI approach is not used for rounding up all the CPUs. For example, | ||
210 | * in case of MIPS, smp_call_function() is used to roundup CPUs. In | ||
211 | * this case, we have to make sure that interrupts are enabled before | ||
212 | * calling smp_call_function(). The argument to this function is | ||
213 | * the flags that will be used when restoring the interrupts. There is | ||
214 | * local_irq_save() call before kgdb_roundup_cpus(). | ||
215 | * | ||
216 | * On non-SMP systems, this is not called. | ||
217 | */ | ||
218 | void kgdb_roundup_cpus(unsigned long flags) | ||
219 | { | ||
220 | send_IPI_allbutself(APIC_DM_NMI); | ||
221 | } | ||
222 | #endif | ||
223 | |||
224 | /** | ||
225 | * kgdb_arch_handle_exception - Handle architecture specific GDB packets. | ||
226 | * @vector: The error vector of the exception that happened. | ||
227 | * @signo: The signal number of the exception that happened. | ||
228 | * @err_code: The error code of the exception that happened. | ||
229 | * @remcom_in_buffer: The buffer of the packet we have read. | ||
230 | * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into. | ||
231 | * @regs: The &struct pt_regs of the current process. | ||
232 | * | ||
233 | * This function MUST handle the 'c' and 's' command packets, | ||
234 | * as well packets to set / remove a hardware breakpoint, if used. | ||
235 | * If there are additional packets which the hardware needs to handle, | ||
236 | * they are handled here. The code should return -1 if it wants to | ||
237 | * process more packets, and a %0 or %1 if it wants to exit from the | ||
238 | * kgdb callback. | ||
239 | */ | ||
240 | int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | ||
241 | char *remcomInBuffer, char *remcomOutBuffer, | ||
242 | struct pt_regs *linux_regs) | ||
243 | { | ||
244 | unsigned long addr; | ||
245 | char *ptr; | ||
246 | int newPC; | ||
247 | |||
248 | switch (remcomInBuffer[0]) { | ||
249 | case 'c': | ||
250 | case 's': | ||
251 | /* try to read optional parameter, pc unchanged if no parm */ | ||
252 | ptr = &remcomInBuffer[1]; | ||
253 | if (kgdb_hex2long(&ptr, &addr)) | ||
254 | linux_regs->ip = addr; | ||
255 | newPC = linux_regs->ip; | ||
256 | |||
257 | /* clear the trace bit */ | ||
258 | linux_regs->flags &= ~TF_MASK; | ||
259 | atomic_set(&kgdb_cpu_doing_single_step, -1); | ||
260 | |||
261 | /* set the trace bit if we're stepping */ | ||
262 | if (remcomInBuffer[0] == 's') { | ||
263 | linux_regs->flags |= TF_MASK; | ||
264 | kgdb_single_step = 1; | ||
265 | if (kgdb_contthread) { | ||
266 | atomic_set(&kgdb_cpu_doing_single_step, | ||
267 | raw_smp_processor_id()); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | /* this means that we do not want to exit from the handler: */ | ||
275 | return -1; | ||
276 | } | ||
277 | |||
278 | static inline int | ||
279 | single_step_cont(struct pt_regs *regs, struct die_args *args) | ||
280 | { | ||
281 | /* | ||
282 | * Single step exception from kernel space to user space so | ||
283 | * eat the exception and continue the process: | ||
284 | */ | ||
285 | printk(KERN_ERR "KGDB: trap/step from kernel to user space, " | ||
286 | "resuming...\n"); | ||
287 | kgdb_arch_handle_exception(args->trapnr, args->signr, | ||
288 | args->err, "c", "", regs); | ||
289 | |||
290 | return NOTIFY_STOP; | ||
291 | } | ||
292 | |||
293 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
294 | { | ||
295 | struct pt_regs *regs = args->regs; | ||
296 | |||
297 | switch (cmd) { | ||
298 | case DIE_NMI: | ||
299 | if (atomic_read(&kgdb_active) != -1) { | ||
300 | /* KGDB CPU roundup */ | ||
301 | kgdb_nmicallback(raw_smp_processor_id(), regs); | ||
302 | return NOTIFY_STOP; | ||
303 | } | ||
304 | return NOTIFY_DONE; | ||
305 | |||
306 | case DIE_NMI_IPI: | ||
307 | if (atomic_read(&kgdb_active) != -1) { | ||
308 | /* KGDB CPU roundup: */ | ||
309 | if (kgdb_nmicallback(raw_smp_processor_id(), regs)) | ||
310 | return NOTIFY_DONE; | ||
311 | return NOTIFY_STOP; | ||
312 | } | ||
313 | return NOTIFY_DONE; | ||
314 | |||
315 | case DIE_NMIWATCHDOG: | ||
316 | if (atomic_read(&kgdb_active) != -1) { | ||
317 | /* KGDB CPU roundup: */ | ||
318 | kgdb_nmicallback(raw_smp_processor_id(), regs); | ||
319 | return NOTIFY_STOP; | ||
320 | } | ||
321 | /* Enter debugger: */ | ||
322 | break; | ||
323 | |||
324 | case DIE_DEBUG: | ||
325 | if (atomic_read(&kgdb_cpu_doing_single_step) == | ||
326 | raw_smp_processor_id() && | ||
327 | user_mode(regs)) | ||
328 | return single_step_cont(regs, args); | ||
329 | /* fall through */ | ||
330 | default: | ||
331 | if (user_mode(regs)) | ||
332 | return NOTIFY_DONE; | ||
333 | } | ||
334 | |||
335 | if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs)) | ||
336 | return NOTIFY_DONE; | ||
337 | |||
338 | return NOTIFY_STOP; | ||
339 | } | ||
340 | |||
341 | static int | ||
342 | kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) | ||
343 | { | ||
344 | unsigned long flags; | ||
345 | int ret; | ||
346 | |||
347 | local_irq_save(flags); | ||
348 | ret = __kgdb_notify(ptr, cmd); | ||
349 | local_irq_restore(flags); | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | static struct notifier_block kgdb_notifier = { | ||
355 | .notifier_call = kgdb_notify, | ||
356 | |||
357 | /* | ||
358 | * Lowest-prio notifier priority, we want to be notified last: | ||
359 | */ | ||
360 | .priority = -INT_MAX, | ||
361 | }; | ||
362 | |||
363 | /** | ||
364 | * kgdb_arch_init - Perform any architecture specific initalization. | ||
365 | * | ||
366 | * This function will handle the initalization of any architecture | ||
367 | * specific callbacks. | ||
368 | */ | ||
369 | int kgdb_arch_init(void) | ||
370 | { | ||
371 | return register_die_notifier(&kgdb_notifier); | ||
372 | } | ||
373 | |||
374 | /** | ||
375 | * kgdb_arch_exit - Perform any architecture specific uninitalization. | ||
376 | * | ||
377 | * This function will handle the uninitalization of any architecture | ||
378 | * specific callbacks, for dynamic registration and unregistration. | ||
379 | */ | ||
380 | void kgdb_arch_exit(void) | ||
381 | { | ||
382 | unregister_die_notifier(&kgdb_notifier); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * | ||
387 | * kgdb_skipexception - Bail out of KGDB when we've been triggered. | ||
388 | * @exception: Exception vector number | ||
389 | * @regs: Current &struct pt_regs. | ||
390 | * | ||
391 | * On some architectures we need to skip a breakpoint exception when | ||
392 | * it occurs after a breakpoint has been removed. | ||
393 | * | ||
394 | * Skip an int3 exception when it occurs after a breakpoint has been | ||
395 | * removed. Backtrack eip by 1 since the int3 would have caused it to | ||
396 | * increment by 1. | ||
397 | */ | ||
398 | int kgdb_skipexception(int exception, struct pt_regs *regs) | ||
399 | { | ||
400 | if (exception == 3 && kgdb_isremovedbreak(regs->ip - 1)) { | ||
401 | regs->ip -= 1; | ||
402 | return 1; | ||
403 | } | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs) | ||
408 | { | ||
409 | if (exception == 3) | ||
410 | return instruction_pointer(regs) - 1; | ||
411 | return instruction_pointer(regs); | ||
412 | } | ||
413 | |||
414 | struct kgdb_arch arch_kgdb_ops = { | ||
415 | /* Breakpoint instruction: */ | ||
416 | .gdb_bpt_instr = { 0xcc }, | ||
417 | }; | ||
diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h new file mode 100644 index 000000000000..484c47554f3b --- /dev/null +++ b/include/asm-x86/kgdb.h | |||
@@ -0,0 +1,81 @@ | |||
1 | #ifndef _ASM_KGDB_H_ | ||
2 | #define _ASM_KGDB_H_ | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2001-2004 Amit S. Kale | ||
6 | * Copyright (C) 2008 Wind River Systems, Inc. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * BUFMAX defines the maximum number of characters in inbound/outbound | ||
11 | * buffers at least NUMREGBYTES*2 are needed for register packets | ||
12 | * Longer buffer is needed to list all threads | ||
13 | */ | ||
14 | #define BUFMAX 1024 | ||
15 | |||
16 | /* | ||
17 | * Note that this register image is in a different order than | ||
18 | * the register image that Linux produces at interrupt time. | ||
19 | * | ||
20 | * Linux's register image is defined by struct pt_regs in ptrace.h. | ||
21 | * Just why GDB uses a different order is a historical mystery. | ||
22 | */ | ||
23 | #ifdef CONFIG_X86_32 | ||
24 | enum regnames { | ||
25 | GDB_AX, /* 0 */ | ||
26 | GDB_CX, /* 1 */ | ||
27 | GDB_DX, /* 2 */ | ||
28 | GDB_BX, /* 3 */ | ||
29 | GDB_SP, /* 4 */ | ||
30 | GDB_BP, /* 5 */ | ||
31 | GDB_SI, /* 6 */ | ||
32 | GDB_DI, /* 7 */ | ||
33 | GDB_PC, /* 8 also known as eip */ | ||
34 | GDB_PS, /* 9 also known as eflags */ | ||
35 | GDB_CS, /* 10 */ | ||
36 | GDB_SS, /* 11 */ | ||
37 | GDB_DS, /* 12 */ | ||
38 | GDB_ES, /* 13 */ | ||
39 | GDB_FS, /* 14 */ | ||
40 | GDB_GS, /* 15 */ | ||
41 | }; | ||
42 | #else /* ! CONFIG_X86_32 */ | ||
43 | enum regnames { | ||
44 | GDB_AX, /* 0 */ | ||
45 | GDB_DX, /* 1 */ | ||
46 | GDB_CX, /* 2 */ | ||
47 | GDB_BX, /* 3 */ | ||
48 | GDB_SI, /* 4 */ | ||
49 | GDB_DI, /* 5 */ | ||
50 | GDB_BP, /* 6 */ | ||
51 | GDB_SP, /* 7 */ | ||
52 | GDB_R8, /* 8 */ | ||
53 | GDB_R9, /* 9 */ | ||
54 | GDB_R10, /* 10 */ | ||
55 | GDB_R11, /* 11 */ | ||
56 | GDB_R12, /* 12 */ | ||
57 | GDB_R13, /* 13 */ | ||
58 | GDB_R14, /* 14 */ | ||
59 | GDB_R15, /* 15 */ | ||
60 | GDB_PC, /* 16 */ | ||
61 | GDB_PS, /* 17 */ | ||
62 | }; | ||
63 | #endif /* CONFIG_X86_32 */ | ||
64 | |||
65 | /* | ||
66 | * Number of bytes of registers: | ||
67 | */ | ||
68 | #ifdef CONFIG_X86_32 | ||
69 | # define NUMREGBYTES 64 | ||
70 | #else | ||
71 | # define NUMREGBYTES ((GDB_PS+1)*8) | ||
72 | #endif | ||
73 | |||
74 | static inline void arch_kgdb_breakpoint(void) | ||
75 | { | ||
76 | asm(" int $3"); | ||
77 | } | ||
78 | #define BREAK_INSTR_SIZE 1 | ||
79 | #define CACHE_FLUSH_IS_SAFE 1 | ||
80 | |||
81 | #endif /* _ASM_KGDB_H_ */ | ||