aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kgdb.c68
1 files changed, 50 insertions, 18 deletions
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index c0d45b2c4d79..eaa21fc9ad1d 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -56,12 +56,14 @@
56 56
57static int kgdb_break_asap; 57static int kgdb_break_asap;
58 58
59#define KGDB_MAX_THREAD_QUERY 17
59struct kgdb_state { 60struct kgdb_state {
60 int ex_vector; 61 int ex_vector;
61 int signo; 62 int signo;
62 int err_code; 63 int err_code;
63 int cpu; 64 int cpu;
64 int pass_exception; 65 int pass_exception;
66 unsigned long thr_query;
65 unsigned long threadid; 67 unsigned long threadid;
66 long kgdb_usethreadid; 68 long kgdb_usethreadid;
67 struct pt_regs *linux_regs; 69 struct pt_regs *linux_regs;
@@ -445,9 +447,14 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
445{ 447{
446 int hex_val; 448 int hex_val;
447 int num = 0; 449 int num = 0;
450 int negate = 0;
448 451
449 *long_val = 0; 452 *long_val = 0;
450 453
454 if (**ptr == '-') {
455 negate = 1;
456 (*ptr)++;
457 }
451 while (**ptr) { 458 while (**ptr) {
452 hex_val = hex(**ptr); 459 hex_val = hex(**ptr);
453 if (hex_val < 0) 460 if (hex_val < 0)
@@ -458,6 +465,9 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
458 (*ptr)++; 465 (*ptr)++;
459 } 466 }
460 467
468 if (negate)
469 *long_val = -*long_val;
470
461 return num; 471 return num;
462} 472}
463 473
@@ -527,10 +537,16 @@ static void int_to_threadref(unsigned char *id, int value)
527static struct task_struct *getthread(struct pt_regs *regs, int tid) 537static struct task_struct *getthread(struct pt_regs *regs, int tid)
528{ 538{
529 /* 539 /*
530 * Non-positive TIDs are remapped idle tasks: 540 * Non-positive TIDs are remapped to the cpu shadow information
531 */ 541 */
532 if (tid <= 0) 542 if (tid == 0 || tid == -1)
533 return idle_task(-tid); 543 tid = -atomic_read(&kgdb_active) - 2;
544 if (tid < 0) {
545 if (kgdb_info[-tid - 2].task)
546 return kgdb_info[-tid - 2].task;
547 else
548 return idle_task(-tid - 2);
549 }
534 550
535 /* 551 /*
536 * find_task_by_pid_ns() does not take the tasklist lock anymore 552 * find_task_by_pid_ns() does not take the tasklist lock anymore
@@ -737,14 +753,15 @@ setundefined:
737} 753}
738 754
739/* 755/*
740 * Remap normal tasks to their real PID, idle tasks to -1 ... -NR_CPUs: 756 * Remap normal tasks to their real PID,
757 * CPU shadow threads are mapped to -CPU - 2
741 */ 758 */
742static inline int shadow_pid(int realpid) 759static inline int shadow_pid(int realpid)
743{ 760{
744 if (realpid) 761 if (realpid)
745 return realpid; 762 return realpid;
746 763
747 return -1-raw_smp_processor_id(); 764 return -raw_smp_processor_id() - 2;
748} 765}
749 766
750static char gdbmsgbuf[BUFMAX + 1]; 767static char gdbmsgbuf[BUFMAX + 1];
@@ -838,7 +855,7 @@ static void gdb_cmd_getregs(struct kgdb_state *ks)
838 local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo; 855 local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo;
839 } else { 856 } else {
840 local_debuggerinfo = NULL; 857 local_debuggerinfo = NULL;
841 for (i = 0; i < NR_CPUS; i++) { 858 for_each_online_cpu(i) {
842 /* 859 /*
843 * Try to find the task on some other 860 * Try to find the task on some other
844 * or possibly this node if we do not 861 * or possibly this node if we do not
@@ -972,10 +989,13 @@ static int gdb_cmd_reboot(struct kgdb_state *ks)
972/* Handle the 'q' query packets */ 989/* Handle the 'q' query packets */
973static void gdb_cmd_query(struct kgdb_state *ks) 990static void gdb_cmd_query(struct kgdb_state *ks)
974{ 991{
975 struct task_struct *thread; 992 struct task_struct *g;
993 struct task_struct *p;
976 unsigned char thref[8]; 994 unsigned char thref[8];
977 char *ptr; 995 char *ptr;
978 int i; 996 int i;
997 int cpu;
998 int finished = 0;
979 999
980 switch (remcom_in_buffer[1]) { 1000 switch (remcom_in_buffer[1]) {
981 case 's': 1001 case 's':
@@ -985,22 +1005,34 @@ static void gdb_cmd_query(struct kgdb_state *ks)
985 break; 1005 break;
986 } 1006 }
987 1007
988 if (remcom_in_buffer[1] == 'f') 1008 i = 0;
989 ks->threadid = 1;
990
991 remcom_out_buffer[0] = 'm'; 1009 remcom_out_buffer[0] = 'm';
992 ptr = remcom_out_buffer + 1; 1010 ptr = remcom_out_buffer + 1;
993 1011 if (remcom_in_buffer[1] == 'f') {
994 for (i = 0; i < 17; ks->threadid++) { 1012 /* Each cpu is a shadow thread */
995 thread = getthread(ks->linux_regs, ks->threadid); 1013 for_each_online_cpu(cpu) {
996 if (thread) { 1014 ks->thr_query = 0;
997 int_to_threadref(thref, ks->threadid); 1015 int_to_threadref(thref, -cpu - 2);
998 pack_threadid(ptr, thref); 1016 pack_threadid(ptr, thref);
999 ptr += BUF_THREAD_ID_SIZE; 1017 ptr += BUF_THREAD_ID_SIZE;
1000 *(ptr++) = ','; 1018 *(ptr++) = ',';
1001 i++; 1019 i++;
1002 } 1020 }
1003 } 1021 }
1022
1023 do_each_thread(g, p) {
1024 if (i >= ks->thr_query && !finished) {
1025 int_to_threadref(thref, p->pid);
1026 pack_threadid(ptr, thref);
1027 ptr += BUF_THREAD_ID_SIZE;
1028 *(ptr++) = ',';
1029 ks->thr_query++;
1030 if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0)
1031 finished = 1;
1032 }
1033 i++;
1034 } while_each_thread(g, p);
1035
1004 *(--ptr) = '\0'; 1036 *(--ptr) = '\0';
1005 break; 1037 break;
1006 1038
@@ -1023,15 +1055,15 @@ static void gdb_cmd_query(struct kgdb_state *ks)
1023 error_packet(remcom_out_buffer, -EINVAL); 1055 error_packet(remcom_out_buffer, -EINVAL);
1024 break; 1056 break;
1025 } 1057 }
1026 if (ks->threadid > 0) { 1058 if ((int)ks->threadid > 0) {
1027 kgdb_mem2hex(getthread(ks->linux_regs, 1059 kgdb_mem2hex(getthread(ks->linux_regs,
1028 ks->threadid)->comm, 1060 ks->threadid)->comm,
1029 remcom_out_buffer, 16); 1061 remcom_out_buffer, 16);
1030 } else { 1062 } else {
1031 static char tmpstr[23 + BUF_THREAD_ID_SIZE]; 1063 static char tmpstr[23 + BUF_THREAD_ID_SIZE];
1032 1064
1033 sprintf(tmpstr, "Shadow task %d for pid 0", 1065 sprintf(tmpstr, "shadowCPU%d",
1034 (int)(-ks->threadid-1)); 1066 (int)(-ks->threadid - 2));
1035 kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); 1067 kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr));
1036 } 1068 }
1037 break; 1069 break;