ia64/xen-unstable

view xen/arch/x86/cdb.c @ 5401:260c108b2c0b

bitkeeper revision 1.1703 (42a881c8OTeDO-DPkTSLEnBspOFEIA)

missing include that is need when compiling with debug

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
author vh249@airwolf.cl.cam.ac.uk
date Thu Jun 09 17:52:08 2005 +0000 (2005-06-09)
parents da199897c714
children b99098e3c2ed dd668f7527cb b2f4823b6ff0
line source
1 /* Simple hacked-up version of pdb for use in post-mortem debugging of
2 Xen and domain 0. This should be a little cleaner, hopefully. Note
3 that we can't share a serial line with PDB. */
4 /* We try to avoid assuming much about what the rest of the system is
5 doing. In particular, dynamic memory allocation is out of the
6 question. */
7 /* Resuming after we've stopped used to work, but more through luck
8 than any actual intention. It doesn't at the moment. */
9 #include <xen/lib.h>
10 #include <asm/uaccess.h>
11 #include <xen/spinlock.h>
12 #include <xen/serial.h>
13 #include <xen/irq.h>
14 #include <asm/debugger.h>
15 #include <xen/init.h>
16 #include <xen/smp.h>
17 #include <xen/console.h>
18 #include <asm/apic.h>
20 /* Printk isn't particularly safe just after we've trapped to the
21 debugger. so avoid it. */
22 #define dbg_printk(...)
24 static unsigned char opt_cdb[30] = "none";
25 string_param("cdb", opt_cdb);
27 struct xendbg_context {
28 int serhnd;
29 u8 reply_csum;
30 int currently_attached:1;
31 };
33 /* Like copy_from_user, but safe to call with interrupts disabled.
35 Trust me, and don't look behind the curtain. */
36 static unsigned
37 dbg_copy_from_user(void *dest, const void *src, unsigned len)
38 {
39 int __d0, __d1, __d2;
40 ASSERT(!local_irq_is_enabled());
41 __asm__ __volatile__(
42 "1: rep; movsb\n"
43 "2:\n"
44 ".section .fixup,\"ax\"\n"
45 "3: addl $4, %%esp\n"
46 " jmp 2b\n"
47 ".previous\n"
48 ".section __pre_ex_table,\"a\"\n"
49 " .align 4\n"
50 " .long 1b,3b\n"
51 ".previous\n"
52 ".section __ex_table,\"a\"\n"
53 " .align 4\n"
54 " .long 1b,2b\n"
55 ".previous\n"
56 : "=c"(__d2), "=D" (__d0), "=S" (__d1)
57 : "0"(len), "1"(dest), "2"(src)
58 : "memory");
59 ASSERT(!local_irq_is_enabled());
60 return __d2;
61 }
63 static void
64 xendbg_put_char(u8 data, struct xendbg_context *ctx)
65 {
66 ctx->reply_csum += data;
67 serial_putc(ctx->serhnd, data);
68 }
70 static int
71 hex_char_val(unsigned char c)
72 {
73 if (c >= '0' && c <= '9')
74 return c - '0';
75 else if (c >= 'a' && c <= 'f')
76 return c - 'a' + 10;
77 else if (c >= 'A' && c <= 'F')
78 return c - 'A' + 10;
79 else
80 BUG();
81 return -1;
82 }
84 /* Receive a command. Returns -1 on csum error, 0 otherwise. */
85 /* Does not acknowledge. */
86 static int
87 attempt_receive_packet(char *recv_buf, struct xendbg_context *ctx)
88 {
89 int count;
90 u8 csum;
91 u8 received_csum;
92 u8 ch;
94 /* Skip over everything up to the first '$' */
95 while ((ch = serial_getc(ctx->serhnd)) != '$')
96 ;
97 csum = 0;
98 for (count = 0; count < 4096; count++) {
99 ch = serial_getc(ctx->serhnd);
100 if (ch == '#')
101 break;
102 recv_buf[count] = ch;
103 csum += ch;
104 }
105 if (count == 4096) {
106 dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
107 return -1;
108 }
109 recv_buf[count] = 0;
110 received_csum = hex_char_val(serial_getc(ctx->serhnd)) * 16 +
111 hex_char_val(serial_getc(ctx->serhnd));
112 if (received_csum == csum) {
113 return 0;
114 } else {
115 return -1;
116 }
117 }
119 /* Send a string of bytes to the debugger. */
120 static void
121 xendbg_send(const char *buf, int count, struct xendbg_context *ctx)
122 {
123 int x;
124 for (x = 0; x < count; x++)
125 xendbg_put_char(buf[x], ctx);
126 }
128 /* Receive a command, discarding up to ten packets with csum
129 * errors. Acknowledges all received packets. */
130 static int
131 receive_command(char *recv_buf, struct xendbg_context *ctx)
132 {
133 int r;
134 int count;
136 count = 0;
137 do {
138 r = attempt_receive_packet(recv_buf, ctx);
139 if (r < 0)
140 xendbg_put_char('-', ctx);
141 else
142 xendbg_put_char('+', ctx);
143 count++;
144 } while (r < 0 && count < 10);
145 return r;
146 }
148 static void
149 xendbg_start_reply(struct xendbg_context *ctx)
150 {
151 xendbg_put_char('$', ctx);
152 ctx->reply_csum = 0;
153 }
155 /* Return 0 if the reply was successfully received, !0 otherwise. */
156 static int
157 xendbg_finish_reply(struct xendbg_context *ctx)
158 {
159 char ch;
160 char buf[3];
162 sprintf(buf, "%.02x\n", ctx->reply_csum);
164 xendbg_put_char('#', ctx);
165 xendbg_send(buf, 2, ctx);
167 ch = serial_getc(ctx->serhnd);
168 if (ch == '+')
169 return 0;
170 else
171 return 1;
172 }
174 /* Swap the order of the bytes in a work. */
175 static inline unsigned
176 bswab32(unsigned val)
177 {
178 return (((val >> 0) & 0xff) << 24) |
179 (((val >> 8) & 0xff) << 16) |
180 (((val >> 16) & 0xff) << 8) |
181 (((val >> 24) & 0xff) << 0);
182 }
184 static int
185 handle_memory_read_command(unsigned long addr, unsigned long length,
186 struct xendbg_context *ctx)
187 {
188 int x;
189 unsigned char val;
190 int r;
191 char buf[2];
193 dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
194 length);
195 xendbg_start_reply(ctx);
196 for (x = 0; x < length; x++) {
197 r = dbg_copy_from_user(&val, (void *)(addr + x), 1);
198 if (r != 0) {
199 dbg_printk("Error reading from %lx.\n", addr + x);
200 break;
201 }
202 sprintf(buf, "%.02x", val);
203 xendbg_send(buf, 2, ctx);
204 }
205 if (x == 0)
206 xendbg_send("E05", 3, ctx);
207 dbg_printk("Read done.\n");
208 return xendbg_finish_reply(ctx);
209 }
211 static int
212 xendbg_send_reply(const char *buf, struct xendbg_context *ctx)
213 {
214 xendbg_start_reply(ctx);
215 xendbg_send(buf, strlen(buf), ctx);
216 return xendbg_finish_reply(ctx);
217 }
219 static int
220 handle_register_read_command(struct cpu_user_regs *regs, struct xendbg_context *ctx)
221 {
222 char buf[121];
224 sprintf(buf,
225 "%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x",
226 bswab32(regs->eax),
227 bswab32(regs->ecx),
228 bswab32(regs->edx),
229 bswab32(regs->ebx),
230 bswab32(regs->esp),
231 bswab32(regs->ebp),
232 bswab32(regs->esi),
233 bswab32(regs->edi),
234 bswab32(regs->eip),
235 bswab32(regs->eflags),
236 bswab32(regs->cs),
237 bswab32(regs->ss),
238 bswab32(regs->ds),
239 bswab32(regs->es),
240 bswab32(regs->fs),
241 bswab32(regs->gs));
242 return xendbg_send_reply(buf, ctx);
243 }
245 static int
246 process_command(char *received_packet, struct cpu_user_regs *regs,
247 struct xendbg_context *ctx)
248 {
249 char *ptr;
250 unsigned long addr, length;
251 int retry;
252 int counter;
253 int resume = 0;
255 /* Repeat until gdb acks the reply */
256 counter = 0;
257 do {
258 switch (received_packet[0]) {
259 case 'g': /* Read registers */
260 retry = handle_register_read_command(regs, ctx);
261 ASSERT(!local_irq_is_enabled());
262 break;
263 case 'm': /* Read memory */
264 addr = simple_strtoul(received_packet + 1, &ptr, 16);
265 if (ptr == received_packet + 1 ||
266 ptr[0] != ',') {
267 xendbg_send_reply("E03", ctx);
268 return 0;
269 }
270 length = simple_strtoul(ptr + 1, &ptr, 16);
271 if (ptr[0] != 0) {
272 xendbg_send_reply("E04", ctx);
273 return 0;
274 }
275 retry =
276 handle_memory_read_command(addr,
277 length,
278 ctx);
279 ASSERT(!local_irq_is_enabled());
280 break;
281 case 'G': /* Write registers */
282 case 'M': /* Write memory */
283 retry = xendbg_send_reply("E02", ctx);
284 break;
285 case 'D':
286 resume = 1;
287 ctx->currently_attached = 0;
288 retry = xendbg_send_reply("", ctx);
289 break;
290 case 'c': /* Resume at current address */
291 ctx->currently_attached = 1;
292 resume = 1;
293 retry = 0;
294 break;
295 case 'Z': /* We need to claim to support these or gdb
296 won't let you continue the process. */
297 case 'z':
298 retry = xendbg_send_reply("OK", ctx);
299 break;
301 case 's': /* Single step */
302 case '?':
303 retry = xendbg_send_reply("S01", ctx);
304 break;
305 default:
306 retry = xendbg_send_reply("", ctx);
307 break;
308 }
309 counter++;
310 } while (retry == 1 && counter < 10);
311 if (retry) {
312 dbg_printk("WARNING: gdb disappeared when we were trying to send it a reply.\n");
313 return 1;
314 }
315 return resume;
316 }
318 static struct xendbg_context
319 xdb_ctx = {
320 serhnd : -1
321 };
323 int
324 __trap_to_cdb(struct cpu_user_regs *regs)
325 {
326 int resume = 0;
327 int r;
328 static atomic_t xendbg_running = ATOMIC_INIT(1);
329 static char recv_buf[4096];
330 unsigned flags;
332 if (xdb_ctx.serhnd < 0) {
333 dbg_printk("Debugger not ready yet.\n");
334 return 0;
335 }
337 /* We rely on our caller to ensure we're only on one processor
338 * at a time... We should probably panic here, but given that
339 * we're a debugger we should probably be a little tolerant of
340 * things going wrong. */
341 /* We don't want to use a spin lock here, because we're doing
342 two distinct things:
344 1 -- we don't want to run on more than one processor at a time,
345 and
346 2 -- we want to do something sensible if we re-enter ourselves.
348 Spin locks are good for 1, but useless for 2. */
349 if (!atomic_dec_and_test(&xendbg_running)) {
350 printk("WARNING WARNING WARNING: Avoiding recursive xendbg.\n");
351 atomic_inc(&xendbg_running);
352 return 0;
353 }
355 smp_send_stop();
357 /* Try to make things a little more stable by disabling
358 interrupts while we're here. */
359 local_irq_save(flags);
361 watchdog_disable();
362 console_start_sync();
364 /* Shouldn't really do this, but otherwise we stop for no
365 obvious reason, which is Bad */
366 printk("Waiting for GDB to attach to XenDBG\n");
368 /* If gdb is already attached, tell it we've stopped again. */
369 if (xdb_ctx.currently_attached) {
370 do {
371 r = xendbg_send_reply("S01", &xdb_ctx);
372 } while (r != 0);
373 }
375 while (resume == 0) {
376 ASSERT(!local_irq_is_enabled());
377 r = receive_command(recv_buf, &xdb_ctx);
378 ASSERT(!local_irq_is_enabled());
379 if (r < 0) {
380 dbg_printk("GDB disappeared, trying to resume Xen...\n");
381 resume = 1;
382 } else {
383 ASSERT(!local_irq_is_enabled());
384 resume = process_command(recv_buf, regs, &xdb_ctx);
385 ASSERT(!local_irq_is_enabled());
386 }
387 }
389 console_end_sync();
390 watchdog_enable();
391 atomic_inc(&xendbg_running);
393 local_irq_restore(flags);
395 return 0;
396 }
398 static int
399 initialize_xendbg(void)
400 {
401 if (!strcmp(opt_cdb, "none"))
402 return 0;
403 xdb_ctx.serhnd = serial_parse_handle(opt_cdb);
404 if (xdb_ctx.serhnd == -1)
405 panic("Can't parse %s as CDB serial info.\n", opt_cdb);
407 /* Acknowledge any spurious GDB packets. */
408 xendbg_put_char('+', &xdb_ctx);
410 printk("Xendbg initialised.\n");
411 return 0;
412 }
414 __initcall(initialize_xendbg);