diff options
Diffstat (limited to 'arch/sh/kernel/kgdb_stub.c')
-rw-r--r-- | arch/sh/kernel/kgdb_stub.c | 490 |
1 files changed, 57 insertions, 433 deletions
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c index d8927d85492e..a5323364cbca 100644 --- a/arch/sh/kernel/kgdb_stub.c +++ b/arch/sh/kernel/kgdb_stub.c | |||
@@ -6,11 +6,11 @@ | |||
6 | * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>, | 6 | * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>, |
7 | * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>, | 7 | * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>, |
8 | * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>. | 8 | * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>. |
9 | * | 9 | * |
10 | * This version by Henry Bell <henry.bell@st.com> | 10 | * This version by Henry Bell <henry.bell@st.com> |
11 | * Minor modifications by Jeremy Siegel <jsiegel@mvista.com> | 11 | * Minor modifications by Jeremy Siegel <jsiegel@mvista.com> |
12 | * | 12 | * |
13 | * Contains low-level support for remote debug using GDB. | 13 | * Contains low-level support for remote debug using GDB. |
14 | * | 14 | * |
15 | * To enable debugger support, two things need to happen. A call to | 15 | * To enable debugger support, two things need to happen. A call to |
16 | * set_debug_traps() is necessary in order to allow any breakpoints | 16 | * set_debug_traps() is necessary in order to allow any breakpoints |
@@ -48,7 +48,7 @@ | |||
48 | * k kill (Detach GDB) | 48 | * k kill (Detach GDB) |
49 | * | 49 | * |
50 | * d Toggle debug flag | 50 | * d Toggle debug flag |
51 | * D Detach GDB | 51 | * D Detach GDB |
52 | * | 52 | * |
53 | * Hct Set thread t for operations, OK or ENN | 53 | * Hct Set thread t for operations, OK or ENN |
54 | * c = 'c' (step, cont), c = 'g' (other | 54 | * c = 'c' (step, cont), c = 'g' (other |
@@ -58,7 +58,7 @@ | |||
58 | * qfThreadInfo Get list of current threads (first) m<id> | 58 | * qfThreadInfo Get list of current threads (first) m<id> |
59 | * qsThreadInfo " " " " " (subsequent) | 59 | * qsThreadInfo " " " " " (subsequent) |
60 | * qOffsets Get section offsets Text=x;Data=y;Bss=z | 60 | * qOffsets Get section offsets Text=x;Data=y;Bss=z |
61 | * | 61 | * |
62 | * TXX Find if thread XX is alive OK or ENN | 62 | * TXX Find if thread XX is alive OK or ENN |
63 | * ? What was the last sigval ? SNN (signal NN) | 63 | * ? What was the last sigval ? SNN (signal NN) |
64 | * O Output to GDB console | 64 | * O Output to GDB console |
@@ -74,7 +74,7 @@ | |||
74 | * '$' or '#'. If <data> starts with two characters followed by | 74 | * '$' or '#'. If <data> starts with two characters followed by |
75 | * ':', then the existing stubs interpret this as a sequence number. | 75 | * ':', then the existing stubs interpret this as a sequence number. |
76 | * | 76 | * |
77 | * CSUM1 and CSUM2 are ascii hex representation of an 8-bit | 77 | * CSUM1 and CSUM2 are ascii hex representation of an 8-bit |
78 | * checksum of <data>, the most significant nibble is sent first. | 78 | * checksum of <data>, the most significant nibble is sent first. |
79 | * the hex digits 0-9,a-f are used. | 79 | * the hex digits 0-9,a-f are used. |
80 | * | 80 | * |
@@ -86,8 +86,8 @@ | |||
86 | * Responses can be run-length encoded to save space. A '*' means that | 86 | * Responses can be run-length encoded to save space. A '*' means that |
87 | * the next character is an ASCII encoding giving a repeat count which | 87 | * the next character is an ASCII encoding giving a repeat count which |
88 | * stands for that many repititions of the character preceding the '*'. | 88 | * stands for that many repititions of the character preceding the '*'. |
89 | * The encoding is n+29, yielding a printable character where n >=3 | 89 | * The encoding is n+29, yielding a printable character where n >=3 |
90 | * (which is where RLE starts to win). Don't use an n > 126. | 90 | * (which is where RLE starts to win). Don't use an n > 126. |
91 | * | 91 | * |
92 | * So "0* " means the same as "0000". | 92 | * So "0* " means the same as "0000". |
93 | */ | 93 | */ |
@@ -100,12 +100,10 @@ | |||
100 | #include <linux/delay.h> | 100 | #include <linux/delay.h> |
101 | #include <linux/linkage.h> | 101 | #include <linux/linkage.h> |
102 | #include <linux/init.h> | 102 | #include <linux/init.h> |
103 | |||
104 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
105 | #include <linux/console.h> | 103 | #include <linux/console.h> |
106 | #endif | 104 | #include <linux/sysrq.h> |
107 | |||
108 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <asm/cacheflush.h> | ||
109 | #include <asm/current.h> | 107 | #include <asm/current.h> |
110 | #include <asm/signal.h> | 108 | #include <asm/signal.h> |
111 | #include <asm/pgtable.h> | 109 | #include <asm/pgtable.h> |
@@ -153,7 +151,6 @@ char kgdb_in_gdb_mode; | |||
153 | char in_nmi; /* Set during NMI to prevent reentry */ | 151 | char in_nmi; /* Set during NMI to prevent reentry */ |
154 | int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ | 152 | int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ |
155 | int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */ | 153 | int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */ |
156 | int kgdb_halt; | ||
157 | 154 | ||
158 | /* Exposed for user access */ | 155 | /* Exposed for user access */ |
159 | struct task_struct *kgdb_current; | 156 | struct task_struct *kgdb_current; |
@@ -246,14 +243,6 @@ static char out_buffer[OUTBUFMAX]; | |||
246 | 243 | ||
247 | static void kgdb_to_gdb(const char *s); | 244 | static void kgdb_to_gdb(const char *s); |
248 | 245 | ||
249 | #ifdef CONFIG_KGDB_THREAD | ||
250 | static struct task_struct *trapped_thread; | ||
251 | static struct task_struct *current_thread; | ||
252 | typedef unsigned char threadref[8]; | ||
253 | #define BUF_THREAD_ID_SIZE 16 | ||
254 | #endif | ||
255 | |||
256 | |||
257 | /* Convert ch to hex */ | 246 | /* Convert ch to hex */ |
258 | static int hex(const char ch) | 247 | static int hex(const char ch) |
259 | { | 248 | { |
@@ -328,7 +317,7 @@ static int hex_to_int(char **ptr, int *int_value) | |||
328 | } | 317 | } |
329 | 318 | ||
330 | /* Copy the binary array pointed to by buf into mem. Fix $, #, | 319 | /* Copy the binary array pointed to by buf into mem. Fix $, #, |
331 | and 0x7d escaped with 0x7d. Return a pointer to the character | 320 | and 0x7d escaped with 0x7d. Return a pointer to the character |
332 | after the last byte written. */ | 321 | after the last byte written. */ |
333 | static char *ebin_to_mem(const char *buf, char *mem, int count) | 322 | static char *ebin_to_mem(const char *buf, char *mem, int count) |
334 | { | 323 | { |
@@ -349,66 +338,6 @@ static char *pack_hex_byte(char *pkt, int byte) | |||
349 | return pkt; | 338 | return pkt; |
350 | } | 339 | } |
351 | 340 | ||
352 | #ifdef CONFIG_KGDB_THREAD | ||
353 | |||
354 | /* Pack a thread ID */ | ||
355 | static char *pack_threadid(char *pkt, threadref * id) | ||
356 | { | ||
357 | char *limit; | ||
358 | unsigned char *altid; | ||
359 | |||
360 | altid = (unsigned char *) id; | ||
361 | |||
362 | limit = pkt + BUF_THREAD_ID_SIZE; | ||
363 | while (pkt < limit) | ||
364 | pkt = pack_hex_byte(pkt, *altid++); | ||
365 | return pkt; | ||
366 | } | ||
367 | |||
368 | /* Convert an integer into our threadref */ | ||
369 | static void int_to_threadref(threadref * id, const int value) | ||
370 | { | ||
371 | unsigned char *scan = (unsigned char *) id; | ||
372 | int i = 4; | ||
373 | |||
374 | while (i--) | ||
375 | *scan++ = 0; | ||
376 | |||
377 | *scan++ = (value >> 24) & 0xff; | ||
378 | *scan++ = (value >> 16) & 0xff; | ||
379 | *scan++ = (value >> 8) & 0xff; | ||
380 | *scan++ = (value & 0xff); | ||
381 | } | ||
382 | |||
383 | /* Return a task structure ptr for a particular pid */ | ||
384 | static struct task_struct *get_thread(int pid) | ||
385 | { | ||
386 | struct task_struct *thread; | ||
387 | |||
388 | /* Use PID_MAX w/gdb for pid 0 */ | ||
389 | if (pid == PID_MAX) pid = 0; | ||
390 | |||
391 | /* First check via PID */ | ||
392 | thread = find_task_by_pid(pid); | ||
393 | |||
394 | if (thread) | ||
395 | return thread; | ||
396 | |||
397 | /* Start at the start */ | ||
398 | thread = init_tasks[0]; | ||
399 | |||
400 | /* Walk along the linked list of tasks */ | ||
401 | do { | ||
402 | if (thread->pid == pid) | ||
403 | return thread; | ||
404 | thread = thread->next_task; | ||
405 | } while (thread != init_tasks[0]); | ||
406 | |||
407 | return NULL; | ||
408 | } | ||
409 | |||
410 | #endif /* CONFIG_KGDB_THREAD */ | ||
411 | |||
412 | /* Scan for the start char '$', read the packet and check the checksum */ | 341 | /* Scan for the start char '$', read the packet and check the checksum */ |
413 | static void get_packet(char *buffer, int buflen) | 342 | static void get_packet(char *buffer, int buflen) |
414 | { | 343 | { |
@@ -452,7 +381,7 @@ static void get_packet(char *buffer, int buflen) | |||
452 | /* Ack successful transfer */ | 381 | /* Ack successful transfer */ |
453 | put_debug_char('+'); | 382 | put_debug_char('+'); |
454 | 383 | ||
455 | /* If a sequence char is present, reply | 384 | /* If a sequence char is present, reply |
456 | the sequence ID */ | 385 | the sequence ID */ |
457 | if (buffer[2] == ':') { | 386 | if (buffer[2] == ':') { |
458 | put_debug_char(buffer[0]); | 387 | put_debug_char(buffer[0]); |
@@ -611,74 +540,6 @@ static void gdb_regs_to_kgdb_regs(const int *gdb_regs, | |||
611 | regs->vbr = gdb_regs[VBR]; | 540 | regs->vbr = gdb_regs[VBR]; |
612 | } | 541 | } |
613 | 542 | ||
614 | #ifdef CONFIG_KGDB_THREAD | ||
615 | /* Make a local copy of registers from the specified thread */ | ||
616 | asmlinkage void ret_from_fork(void); | ||
617 | static void thread_regs_to_gdb_regs(const struct task_struct *thread, | ||
618 | int *gdb_regs) | ||
619 | { | ||
620 | int regno; | ||
621 | int *tregs; | ||
622 | |||
623 | /* Initialize to zero */ | ||
624 | for (regno = 0; regno < MAXREG; regno++) | ||
625 | gdb_regs[regno] = 0; | ||
626 | |||
627 | /* Just making sure... */ | ||
628 | if (thread == NULL) | ||
629 | return; | ||
630 | |||
631 | /* A new fork has pt_regs on the stack from a fork() call */ | ||
632 | if (thread->thread.pc == (unsigned long)ret_from_fork) { | ||
633 | |||
634 | int vbr_val; | ||
635 | struct pt_regs *kregs; | ||
636 | kregs = (struct pt_regs*)thread->thread.sp; | ||
637 | |||
638 | gdb_regs[R0] = kregs->regs[R0]; | ||
639 | gdb_regs[R1] = kregs->regs[R1]; | ||
640 | gdb_regs[R2] = kregs->regs[R2]; | ||
641 | gdb_regs[R3] = kregs->regs[R3]; | ||
642 | gdb_regs[R4] = kregs->regs[R4]; | ||
643 | gdb_regs[R5] = kregs->regs[R5]; | ||
644 | gdb_regs[R6] = kregs->regs[R6]; | ||
645 | gdb_regs[R7] = kregs->regs[R7]; | ||
646 | gdb_regs[R8] = kregs->regs[R8]; | ||
647 | gdb_regs[R9] = kregs->regs[R9]; | ||
648 | gdb_regs[R10] = kregs->regs[R10]; | ||
649 | gdb_regs[R11] = kregs->regs[R11]; | ||
650 | gdb_regs[R12] = kregs->regs[R12]; | ||
651 | gdb_regs[R13] = kregs->regs[R13]; | ||
652 | gdb_regs[R14] = kregs->regs[R14]; | ||
653 | gdb_regs[R15] = kregs->regs[R15]; | ||
654 | gdb_regs[PC] = kregs->pc; | ||
655 | gdb_regs[PR] = kregs->pr; | ||
656 | gdb_regs[GBR] = kregs->gbr; | ||
657 | gdb_regs[MACH] = kregs->mach; | ||
658 | gdb_regs[MACL] = kregs->macl; | ||
659 | gdb_regs[SR] = kregs->sr; | ||
660 | |||
661 | asm("stc vbr, %0":"=r"(vbr_val)); | ||
662 | gdb_regs[VBR] = vbr_val; | ||
663 | return; | ||
664 | } | ||
665 | |||
666 | /* Otherwise, we have only some registers from switch_to() */ | ||
667 | tregs = (int *)thread->thread.sp; | ||
668 | gdb_regs[R15] = (int)tregs; | ||
669 | gdb_regs[R14] = *tregs++; | ||
670 | gdb_regs[R13] = *tregs++; | ||
671 | gdb_regs[R12] = *tregs++; | ||
672 | gdb_regs[R11] = *tregs++; | ||
673 | gdb_regs[R10] = *tregs++; | ||
674 | gdb_regs[R9] = *tregs++; | ||
675 | gdb_regs[R8] = *tregs++; | ||
676 | gdb_regs[PR] = *tregs++; | ||
677 | gdb_regs[GBR] = *tregs++; | ||
678 | gdb_regs[PC] = thread->thread.pc; | ||
679 | } | ||
680 | #endif /* CONFIG_KGDB_THREAD */ | ||
681 | |||
682 | /* Calculate the new address for after a step */ | 543 | /* Calculate the new address for after a step */ |
683 | static short *get_step_address(void) | 544 | static short *get_step_address(void) |
684 | { | 545 | { |
@@ -759,7 +620,7 @@ static short *get_step_address(void) | |||
759 | return (short *) addr; | 620 | return (short *) addr; |
760 | } | 621 | } |
761 | 622 | ||
762 | /* Set up a single-step. Replace the instruction immediately after the | 623 | /* Set up a single-step. Replace the instruction immediately after the |
763 | current instruction (i.e. next in the expected flow of control) with a | 624 | current instruction (i.e. next in the expected flow of control) with a |
764 | trap instruction, so that returning will cause only a single instruction | 625 | trap instruction, so that returning will cause only a single instruction |
765 | to be executed. Note that this model is slightly broken for instructions | 626 | to be executed. Note that this model is slightly broken for instructions |
@@ -797,37 +658,11 @@ static void undo_single_step(void) | |||
797 | /* Send a signal message */ | 658 | /* Send a signal message */ |
798 | static void send_signal_msg(const int signum) | 659 | static void send_signal_msg(const int signum) |
799 | { | 660 | { |
800 | #ifndef CONFIG_KGDB_THREAD | ||
801 | out_buffer[0] = 'S'; | 661 | out_buffer[0] = 'S'; |
802 | out_buffer[1] = highhex(signum); | 662 | out_buffer[1] = highhex(signum); |
803 | out_buffer[2] = lowhex(signum); | 663 | out_buffer[2] = lowhex(signum); |
804 | out_buffer[3] = 0; | 664 | out_buffer[3] = 0; |
805 | put_packet(out_buffer); | 665 | put_packet(out_buffer); |
806 | #else /* CONFIG_KGDB_THREAD */ | ||
807 | int threadid; | ||
808 | threadref thref; | ||
809 | char *out = out_buffer; | ||
810 | const char *tstring = "thread"; | ||
811 | |||
812 | *out++ = 'T'; | ||
813 | *out++ = highhex(signum); | ||
814 | *out++ = lowhex(signum); | ||
815 | |||
816 | while (*tstring) { | ||
817 | *out++ = *tstring++; | ||
818 | } | ||
819 | *out++ = ':'; | ||
820 | |||
821 | threadid = trapped_thread->pid; | ||
822 | if (threadid == 0) threadid = PID_MAX; | ||
823 | int_to_threadref(&thref, threadid); | ||
824 | pack_threadid(out, &thref); | ||
825 | out += BUF_THREAD_ID_SIZE; | ||
826 | *out++ = ';'; | ||
827 | |||
828 | *out = 0; | ||
829 | put_packet(out_buffer); | ||
830 | #endif /* CONFIG_KGDB_THREAD */ | ||
831 | } | 666 | } |
832 | 667 | ||
833 | /* Reply that all was well */ | 668 | /* Reply that all was well */ |
@@ -962,15 +797,7 @@ static void step_with_sig_msg(void) | |||
962 | /* Send register contents */ | 797 | /* Send register contents */ |
963 | static void send_regs_msg(void) | 798 | static void send_regs_msg(void) |
964 | { | 799 | { |
965 | #ifdef CONFIG_KGDB_THREAD | ||
966 | if (!current_thread) | ||
967 | kgdb_regs_to_gdb_regs(&trap_registers, registers); | ||
968 | else | ||
969 | thread_regs_to_gdb_regs(current_thread, registers); | ||
970 | #else | ||
971 | kgdb_regs_to_gdb_regs(&trap_registers, registers); | 800 | kgdb_regs_to_gdb_regs(&trap_registers, registers); |
972 | #endif | ||
973 | |||
974 | mem_to_hex((char *) registers, out_buffer, NUMREGBYTES); | 801 | mem_to_hex((char *) registers, out_buffer, NUMREGBYTES); |
975 | put_packet(out_buffer); | 802 | put_packet(out_buffer); |
976 | } | 803 | } |
@@ -978,201 +805,13 @@ static void send_regs_msg(void) | |||
978 | /* Set register contents - currently can't set other thread's registers */ | 805 | /* Set register contents - currently can't set other thread's registers */ |
979 | static void set_regs_msg(void) | 806 | static void set_regs_msg(void) |
980 | { | 807 | { |
981 | #ifdef CONFIG_KGDB_THREAD | 808 | kgdb_regs_to_gdb_regs(&trap_registers, registers); |
982 | if (!current_thread) { | 809 | hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES); |
983 | #endif | 810 | gdb_regs_to_kgdb_regs(registers, &trap_registers); |
984 | kgdb_regs_to_gdb_regs(&trap_registers, registers); | 811 | send_ok_msg(); |
985 | hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES); | ||
986 | gdb_regs_to_kgdb_regs(registers, &trap_registers); | ||
987 | send_ok_msg(); | ||
988 | #ifdef CONFIG_KGDB_THREAD | ||
989 | } else | ||
990 | send_err_msg(); | ||
991 | #endif | ||
992 | } | ||
993 | |||
994 | |||
995 | #ifdef CONFIG_KGDB_THREAD | ||
996 | |||
997 | /* Set the status for a thread */ | ||
998 | void set_thread_msg(void) | ||
999 | { | ||
1000 | int threadid; | ||
1001 | struct task_struct *thread = NULL; | ||
1002 | char *ptr; | ||
1003 | |||
1004 | switch (in_buffer[1]) { | ||
1005 | |||
1006 | /* To select which thread for gG etc messages, i.e. supported */ | ||
1007 | case 'g': | ||
1008 | |||
1009 | ptr = &in_buffer[2]; | ||
1010 | hex_to_int(&ptr, &threadid); | ||
1011 | thread = get_thread(threadid); | ||
1012 | |||
1013 | /* If we haven't found it */ | ||
1014 | if (!thread) { | ||
1015 | send_err_msg(); | ||
1016 | break; | ||
1017 | } | ||
1018 | |||
1019 | /* Set current_thread (or not) */ | ||
1020 | if (thread == trapped_thread) | ||
1021 | current_thread = NULL; | ||
1022 | else | ||
1023 | current_thread = thread; | ||
1024 | send_ok_msg(); | ||
1025 | break; | ||
1026 | |||
1027 | /* To select which thread for cCsS messages, i.e. unsupported */ | ||
1028 | case 'c': | ||
1029 | send_ok_msg(); | ||
1030 | break; | ||
1031 | |||
1032 | default: | ||
1033 | send_empty_msg(); | ||
1034 | break; | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | /* Is a thread alive? */ | ||
1039 | static void thread_status_msg(void) | ||
1040 | { | ||
1041 | char *ptr; | ||
1042 | int threadid; | ||
1043 | struct task_struct *thread = NULL; | ||
1044 | |||
1045 | ptr = &in_buffer[1]; | ||
1046 | hex_to_int(&ptr, &threadid); | ||
1047 | thread = get_thread(threadid); | ||
1048 | if (thread) | ||
1049 | send_ok_msg(); | ||
1050 | else | ||
1051 | send_err_msg(); | ||
1052 | } | ||
1053 | /* Send the current thread ID */ | ||
1054 | static void thread_id_msg(void) | ||
1055 | { | ||
1056 | int threadid; | ||
1057 | threadref thref; | ||
1058 | |||
1059 | out_buffer[0] = 'Q'; | ||
1060 | out_buffer[1] = 'C'; | ||
1061 | |||
1062 | if (current_thread) | ||
1063 | threadid = current_thread->pid; | ||
1064 | else if (trapped_thread) | ||
1065 | threadid = trapped_thread->pid; | ||
1066 | else /* Impossible, but just in case! */ | ||
1067 | { | ||
1068 | send_err_msg(); | ||
1069 | return; | ||
1070 | } | ||
1071 | |||
1072 | /* Translate pid 0 to PID_MAX for gdb */ | ||
1073 | if (threadid == 0) threadid = PID_MAX; | ||
1074 | |||
1075 | int_to_threadref(&thref, threadid); | ||
1076 | pack_threadid(out_buffer + 2, &thref); | ||
1077 | out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0'; | ||
1078 | put_packet(out_buffer); | ||
1079 | } | ||
1080 | |||
1081 | /* Send thread info */ | ||
1082 | static void thread_info_msg(void) | ||
1083 | { | ||
1084 | struct task_struct *thread = NULL; | ||
1085 | int threadid; | ||
1086 | char *pos; | ||
1087 | threadref thref; | ||
1088 | |||
1089 | /* Start with 'm' */ | ||
1090 | out_buffer[0] = 'm'; | ||
1091 | pos = &out_buffer[1]; | ||
1092 | |||
1093 | /* For all possible thread IDs - this will overrun if > 44 threads! */ | ||
1094 | /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */ | ||
1095 | for (threadid = 1; threadid <= PID_MAX; threadid++) { | ||
1096 | |||
1097 | read_lock(&tasklist_lock); | ||
1098 | thread = get_thread(threadid); | ||
1099 | read_unlock(&tasklist_lock); | ||
1100 | |||
1101 | /* If it's a valid thread */ | ||
1102 | if (thread) { | ||
1103 | int_to_threadref(&thref, threadid); | ||
1104 | pack_threadid(pos, &thref); | ||
1105 | pos += BUF_THREAD_ID_SIZE; | ||
1106 | *pos++ = ','; | ||
1107 | } | ||
1108 | } | ||
1109 | *--pos = 0; /* Lose final comma */ | ||
1110 | put_packet(out_buffer); | ||
1111 | |||
1112 | } | ||
1113 | |||
1114 | /* Return printable info for gdb's 'info threads' command */ | ||
1115 | static void thread_extra_info_msg(void) | ||
1116 | { | ||
1117 | int threadid; | ||
1118 | struct task_struct *thread = NULL; | ||
1119 | char buffer[20], *ptr; | ||
1120 | int i; | ||
1121 | |||
1122 | /* Extract thread ID */ | ||
1123 | ptr = &in_buffer[17]; | ||
1124 | hex_to_int(&ptr, &threadid); | ||
1125 | thread = get_thread(threadid); | ||
1126 | |||
1127 | /* If we don't recognise it, say so */ | ||
1128 | if (thread == NULL) | ||
1129 | strcpy(buffer, "(unknown)"); | ||
1130 | else | ||
1131 | strcpy(buffer, thread->comm); | ||
1132 | |||
1133 | /* Construct packet */ | ||
1134 | for (i = 0, ptr = out_buffer; buffer[i]; i++) | ||
1135 | ptr = pack_hex_byte(ptr, buffer[i]); | ||
1136 | |||
1137 | if (thread->thread.pc == (unsigned long)ret_from_fork) { | ||
1138 | strcpy(buffer, "<new fork>"); | ||
1139 | for (i = 0; buffer[i]; i++) | ||
1140 | ptr = pack_hex_byte(ptr, buffer[i]); | ||
1141 | } | ||
1142 | |||
1143 | *ptr = '\0'; | ||
1144 | put_packet(out_buffer); | ||
1145 | } | ||
1146 | |||
1147 | /* Handle all qFooBarBaz messages - have to use an if statement as | ||
1148 | opposed to a switch because q messages can have > 1 char id. */ | ||
1149 | static void query_msg(void) | ||
1150 | { | ||
1151 | const char *q_start = &in_buffer[1]; | ||
1152 | |||
1153 | /* qC = return current thread ID */ | ||
1154 | if (strncmp(q_start, "C", 1) == 0) | ||
1155 | thread_id_msg(); | ||
1156 | |||
1157 | /* qfThreadInfo = query all threads (first) */ | ||
1158 | else if (strncmp(q_start, "fThreadInfo", 11) == 0) | ||
1159 | thread_info_msg(); | ||
1160 | |||
1161 | /* qsThreadInfo = query all threads (subsequent). We know we have sent | ||
1162 | them all after the qfThreadInfo message, so there are no to send */ | ||
1163 | else if (strncmp(q_start, "sThreadInfo", 11) == 0) | ||
1164 | put_packet("l"); /* el = last */ | ||
1165 | |||
1166 | /* qThreadExtraInfo = supply printable information per thread */ | ||
1167 | else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0) | ||
1168 | thread_extra_info_msg(); | ||
1169 | |||
1170 | /* Unsupported - empty message as per spec */ | ||
1171 | else | ||
1172 | send_empty_msg(); | ||
1173 | } | 812 | } |
1174 | #endif /* CONFIG_KGDB_THREAD */ | ||
1175 | 813 | ||
814 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
1176 | /* | 815 | /* |
1177 | * Bring up the ports.. | 816 | * Bring up the ports.. |
1178 | */ | 817 | */ |
@@ -1185,6 +824,9 @@ static int kgdb_serial_setup(void) | |||
1185 | 824 | ||
1186 | return 0; | 825 | return 0; |
1187 | } | 826 | } |
827 | #else | ||
828 | #define kgdb_serial_setup() 0 | ||
829 | #endif | ||
1188 | 830 | ||
1189 | /* The command loop, read and act on requests */ | 831 | /* The command loop, read and act on requests */ |
1190 | static void kgdb_command_loop(const int excep_code, const int trapa_value) | 832 | static void kgdb_command_loop(const int excep_code, const int trapa_value) |
@@ -1193,7 +835,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1193 | 835 | ||
1194 | if (excep_code == NMI_VEC) { | 836 | if (excep_code == NMI_VEC) { |
1195 | #ifndef CONFIG_KGDB_NMI | 837 | #ifndef CONFIG_KGDB_NMI |
1196 | KGDB_PRINTK("Ignoring unexpected NMI?\n"); | 838 | printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n"); |
1197 | return; | 839 | return; |
1198 | #else /* CONFIG_KGDB_NMI */ | 840 | #else /* CONFIG_KGDB_NMI */ |
1199 | if (!kgdb_enabled) { | 841 | if (!kgdb_enabled) { |
@@ -1207,19 +849,10 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1207 | if (!kgdb_enabled) | 849 | if (!kgdb_enabled) |
1208 | return; | 850 | return; |
1209 | 851 | ||
1210 | #ifdef CONFIG_KGDB_THREAD | ||
1211 | /* Until GDB specifies a thread */ | ||
1212 | current_thread = NULL; | ||
1213 | trapped_thread = current; | ||
1214 | #endif | ||
1215 | |||
1216 | /* Enter GDB mode (e.g. after detach) */ | 852 | /* Enter GDB mode (e.g. after detach) */ |
1217 | if (!kgdb_in_gdb_mode) { | 853 | if (!kgdb_in_gdb_mode) { |
1218 | /* Do serial setup, notify user, issue preemptive ack */ | 854 | /* Do serial setup, notify user, issue preemptive ack */ |
1219 | kgdb_serial_setup(); | 855 | printk(KERN_NOTICE "KGDB: Waiting for GDB\n"); |
1220 | KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n", | ||
1221 | (kgdb_porttype ? kgdb_porttype->name : ""), | ||
1222 | kgdb_portnum, kgdb_baud); | ||
1223 | kgdb_in_gdb_mode = 1; | 856 | kgdb_in_gdb_mode = 1; |
1224 | put_debug_char('+'); | 857 | put_debug_char('+'); |
1225 | } | 858 | } |
@@ -1233,21 +866,18 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1233 | will later be replaced by its original one. Do NOT do this for | 866 | will later be replaced by its original one. Do NOT do this for |
1234 | trap 0xff, since that indicates a compiled-in breakpoint which | 867 | trap 0xff, since that indicates a compiled-in breakpoint which |
1235 | will not be replaced (and we would retake the trap forever) */ | 868 | will not be replaced (and we would retake the trap forever) */ |
1236 | if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) { | 869 | if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2))) |
1237 | trap_registers.pc -= 2; | 870 | trap_registers.pc -= 2; |
1238 | } | ||
1239 | 871 | ||
1240 | /* Undo any stepping we may have done */ | 872 | /* Undo any stepping we may have done */ |
1241 | undo_single_step(); | 873 | undo_single_step(); |
1242 | 874 | ||
1243 | while (1) { | 875 | while (1) { |
1244 | |||
1245 | out_buffer[0] = 0; | 876 | out_buffer[0] = 0; |
1246 | get_packet(in_buffer, BUFMAX); | 877 | get_packet(in_buffer, BUFMAX); |
1247 | 878 | ||
1248 | /* Examine first char of buffer to see what we need to do */ | 879 | /* Examine first char of buffer to see what we need to do */ |
1249 | switch (in_buffer[0]) { | 880 | switch (in_buffer[0]) { |
1250 | |||
1251 | case '?': /* Send which signal we've received */ | 881 | case '?': /* Send which signal we've received */ |
1252 | send_signal_msg(sigval); | 882 | send_signal_msg(sigval); |
1253 | break; | 883 | break; |
@@ -1291,21 +921,6 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1291 | step_msg(); | 921 | step_msg(); |
1292 | return; | 922 | return; |
1293 | 923 | ||
1294 | #ifdef CONFIG_KGDB_THREAD | ||
1295 | |||
1296 | case 'H': /* Task related */ | ||
1297 | set_thread_msg(); | ||
1298 | break; | ||
1299 | |||
1300 | case 'T': /* Query thread status */ | ||
1301 | thread_status_msg(); | ||
1302 | break; | ||
1303 | |||
1304 | case 'q': /* Handle query - currently thread-related */ | ||
1305 | query_msg(); | ||
1306 | break; | ||
1307 | #endif | ||
1308 | |||
1309 | case 'k': /* 'Kill the program' with a kernel ? */ | 924 | case 'k': /* 'Kill the program' with a kernel ? */ |
1310 | break; | 925 | break; |
1311 | 926 | ||
@@ -1323,11 +938,8 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1323 | } | 938 | } |
1324 | 939 | ||
1325 | /* There has been an exception, most likely a breakpoint. */ | 940 | /* There has been an exception, most likely a breakpoint. */ |
1326 | asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | 941 | static void handle_exception(struct pt_regs *regs) |
1327 | unsigned long r6, unsigned long r7, | ||
1328 | struct pt_regs __regs) | ||
1329 | { | 942 | { |
1330 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
1331 | int excep_code, vbr_val; | 943 | int excep_code, vbr_val; |
1332 | int count; | 944 | int count; |
1333 | int trapa_value = ctrl_inl(TRA); | 945 | int trapa_value = ctrl_inl(TRA); |
@@ -1355,7 +967,7 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | |||
1355 | kgdb_trapa_val = trapa_value; | 967 | kgdb_trapa_val = trapa_value; |
1356 | 968 | ||
1357 | /* Act on the exception */ | 969 | /* Act on the exception */ |
1358 | kgdb_command_loop(excep_code >> 5, trapa_value); | 970 | kgdb_command_loop(excep_code, trapa_value); |
1359 | 971 | ||
1360 | kgdb_current = NULL; | 972 | kgdb_current = NULL; |
1361 | 973 | ||
@@ -1373,14 +985,12 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | |||
1373 | asm("ldc %0, vbr": :"r"(vbr_val)); | 985 | asm("ldc %0, vbr": :"r"(vbr_val)); |
1374 | } | 986 | } |
1375 | 987 | ||
1376 | /* Trigger a breakpoint by function */ | 988 | asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, |
1377 | void breakpoint(void) | 989 | unsigned long r6, unsigned long r7, |
990 | struct pt_regs __regs) | ||
1378 | { | 991 | { |
1379 | if (!kgdb_enabled) { | 992 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
1380 | kgdb_enabled = 1; | 993 | handle_exception(regs); |
1381 | kgdb_init(); | ||
1382 | } | ||
1383 | BREAKPOINT(); | ||
1384 | } | 994 | } |
1385 | 995 | ||
1386 | /* Initialise the KGDB data structures and serial configuration */ | 996 | /* Initialise the KGDB data structures and serial configuration */ |
@@ -1395,24 +1005,16 @@ int kgdb_init(void) | |||
1395 | kgdb_in_gdb_mode = 0; | 1005 | kgdb_in_gdb_mode = 0; |
1396 | 1006 | ||
1397 | if (kgdb_serial_setup() != 0) { | 1007 | if (kgdb_serial_setup() != 0) { |
1398 | KGDB_PRINTK("serial setup error\n"); | 1008 | printk(KERN_NOTICE "KGDB: serial setup error\n"); |
1399 | return -1; | 1009 | return -1; |
1400 | } | 1010 | } |
1401 | 1011 | ||
1402 | /* Init ptr to exception handler */ | 1012 | /* Init ptr to exception handler */ |
1403 | kgdb_debug_hook = kgdb_handle_exception; | 1013 | kgdb_debug_hook = handle_exception; |
1404 | kgdb_bus_err_hook = kgdb_handle_bus_error; | 1014 | kgdb_bus_err_hook = kgdb_handle_bus_error; |
1405 | 1015 | ||
1406 | /* Enter kgdb now if requested, or just report init done */ | 1016 | /* Enter kgdb now if requested, or just report init done */ |
1407 | if (kgdb_halt) { | 1017 | printk(KERN_NOTICE "KGDB: stub is initialized.\n"); |
1408 | kgdb_in_gdb_mode = 1; | ||
1409 | put_debug_char('+'); | ||
1410 | breakpoint(); | ||
1411 | } | ||
1412 | else | ||
1413 | { | ||
1414 | KGDB_PRINTK("stub is initialized.\n"); | ||
1415 | } | ||
1416 | 1018 | ||
1417 | return 0; | 1019 | return 0; |
1418 | } | 1020 | } |
@@ -1437,7 +1039,7 @@ static void kgdb_msg_write(const char *s, unsigned count) | |||
1437 | 1039 | ||
1438 | /* Calculate how many this time */ | 1040 | /* Calculate how many this time */ |
1439 | wcount = (count > MAXOUT) ? MAXOUT : count; | 1041 | wcount = (count > MAXOUT) ? MAXOUT : count; |
1440 | 1042 | ||
1441 | /* Pack in hex chars */ | 1043 | /* Pack in hex chars */ |
1442 | for (i = 0; i < wcount; i++) | 1044 | for (i = 0; i < wcount; i++) |
1443 | bufptr = pack_hex_byte(bufptr, s[i]); | 1045 | bufptr = pack_hex_byte(bufptr, s[i]); |
@@ -1467,3 +1069,25 @@ void kgdb_console_write(struct console *co, const char *s, unsigned count) | |||
1467 | kgdb_msg_write(s, count); | 1069 | kgdb_msg_write(s, count); |
1468 | } | 1070 | } |
1469 | #endif | 1071 | #endif |
1072 | |||
1073 | #ifdef CONFIG_KGDB_SYSRQ | ||
1074 | static void sysrq_handle_gdb(int key, struct tty_struct *tty) | ||
1075 | { | ||
1076 | printk("Entering GDB stub\n"); | ||
1077 | breakpoint(); | ||
1078 | } | ||
1079 | |||
1080 | static struct sysrq_key_op sysrq_gdb_op = { | ||
1081 | .handler = sysrq_handle_gdb, | ||
1082 | .help_msg = "Gdb", | ||
1083 | .action_msg = "GDB", | ||
1084 | }; | ||
1085 | |||
1086 | static int gdb_register_sysrq(void) | ||
1087 | { | ||
1088 | printk("Registering GDB sysrq handler\n"); | ||
1089 | register_sysrq_key('g', &sysrq_gdb_op); | ||
1090 | return 0; | ||
1091 | } | ||
1092 | module_init(gdb_register_sysrq); | ||
1093 | #endif | ||