Title: [8992] trunk: [!no_src_qa!]Fix bug[#6044] Update kgdb switch cpu patch against latest kernel.
Revision
8992
Author
sonicz
Date
2010-07-16 06:50:39 -0400 (Fri, 16 Jul 2010)

Log Message

[!no_src_qa!]Fix bug[#6044] Update kgdb switch cpu patch against latest kernel.

Modified Paths

Diff

Modified: trunk/include/linux/kgdb.h (8991 => 8992)


--- trunk/include/linux/kgdb.h	2010-07-15 13:25:06 UTC (rev 8991)
+++ trunk/include/linux/kgdb.h	2010-07-16 10:50:39 UTC (rev 8992)
@@ -106,6 +106,7 @@
 #endif
 
 #define KGDB_HW_BREAKPOINT	1
+#define KGDB_THR_PROC_SWAP	2
 
 /*
  * Functions each KGDB-supporting architecture must provide:
@@ -202,6 +203,19 @@
  */
 extern void kgdb_roundup_cpus(unsigned long flags);
 
+/**
+ *	kgdb_roundup_cpu - Get spcific CPU into a holding pattern
+ *	@cpu: Specific cpu id
+ *	@flags: Current IRQ state
+ *
+ *	On SMP systems, we need to switch cpu from current active one to
+ *	the other passive one. This get current active CPU into a known state
+ *	in kgdb_wait().
+ *
+ *	On non-SMP systems, this is not called.
+ */
+extern void kgdb_roundup_cpu(int cpu, unsigned long flags);
+
 /* Optional functions. */
 extern int kgdb_validate_break_address(unsigned long addr);
 extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);

Modified: trunk/kernel/kgdb.c (8991 => 8992)


--- trunk/kernel/kgdb.c	2010-07-15 13:25:06 UTC (rev 8991)
+++ trunk/kernel/kgdb.c	2010-07-16 10:50:39 UTC (rev 8992)
@@ -1048,7 +1048,7 @@
 }
 
 /* Handle the 'H' task query packets */
-static void gdb_cmd_task(struct kgdb_state *ks)
+static int gdb_cmd_task(struct kgdb_state *ks)
 {
 	struct task_struct *thread;
 	char *ptr;
@@ -1065,6 +1065,15 @@
 		kgdb_usethread = thread;
 		ks->kgdb_usethreadid = ks->threadid;
 		strcpy(remcom_out_buffer, "OK");
+#ifdef CONFIG_SMP
+		/* switch cpu only when it is not a thread query request */
+		if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+			!ks->thr_query && ks->kgdb_usethreadid < -1) {
+			kgdb_roundup_cpu(raw_smp_processor_id(), 0);
+			kgdb_contthread = kgdb_usethread;
+			return 1;
+		}
+#endif
 		break;
 	case 'c':
 		ptr = &remcom_in_buffer[2];
@@ -1082,6 +1091,8 @@
 		strcpy(remcom_out_buffer, "OK");
 		break;
 	}
+
+	return 0;
 }
 
 /* Handle the 'T' thread query packets */
@@ -1090,6 +1101,9 @@
 	char *ptr = &remcom_in_buffer[1];
 	struct task_struct *thread;
 
+	/* reset thread query count before thread operation */
+	ks->thr_query = 0;
+
 	kgdb_hex2long(&ptr, &ks->threadid);
 	thread = getthread(ks->linux_regs, ks->threadid);
 	if (thread)
@@ -1202,20 +1216,31 @@
 	memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
 
 	if (kgdb_connected) {
-		unsigned char thref[8];
-		char *ptr;
+		/* reply the thread switch request after finish swtiching cpu */
+		if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+			!kgdb_single_step && kgdb_contthread == current) {
+			remcom_out_buffer[0] = 'O';
+			remcom_out_buffer[1] = 'K';
+			remcom_out_buffer[2] = 0;
+			put_packet(remcom_out_buffer);
+		} else {
+			unsigned char thref[8];
+			char *ptr;
 
-		/* Reply to host that an exception has occurred */
-		ptr = remcom_out_buffer;
-		*ptr++ = 'T';
-		ptr = pack_hex_byte(ptr, ks->signo);
-		ptr += strlen(strcpy(ptr, "thread:"));
-		int_to_threadref(thref, shadow_pid(current->pid));
-		ptr = pack_threadid(ptr, thref);
-		*ptr++ = ';';
-		put_packet(remcom_out_buffer);
+			/* Reply to host that an exception has occurred */
+			ptr = remcom_out_buffer;
+			*ptr++ = 'T';
+			ptr = pack_hex_byte(ptr, ks->signo);
+			ptr += strlen(strcpy(ptr, "thread:"));
+			int_to_threadref(thref, shadow_pid(current->pid));
+			ptr = pack_threadid(ptr, thref);
+			*ptr++ = ';';
+			put_packet(remcom_out_buffer);
+		}
 	}
 
+	kgdb_single_step = 0;
+	kgdb_contthread = current;
 	kgdb_usethread = kgdb_info[ks->cpu].task;
 	ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
 	ks->pass_exception = 0;
@@ -1262,7 +1287,8 @@
 			gdb_cmd_query(ks);
 			break;
 		case 'H': /* task related */
-			gdb_cmd_task(ks);
+			if (gdb_cmd_task(ks))
+				return 0;
 			break;
 		case 'T': /* Query thread status */
 			gdb_cmd_thread(ks);
@@ -1302,6 +1328,7 @@
 			if (error >= 0 || remcom_in_buffer[0] == 'D' ||
 			    remcom_in_buffer[0] == 'k') {
 				error = 0;
+				kgdb_contthread = NULL;
 				goto kgdb_exit;
 			}
 
@@ -1451,13 +1478,17 @@
 	 * CPU in a spin state while the debugger is active
 	 */
 	if (!kgdb_single_step) {
-		for (i = 0; i < NR_CPUS; i++)
-			atomic_inc(&passive_cpu_wait[i]);
+		if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+			kgdb_contthread == current)
+			atomic_inc(&passive_cpu_wait[cpu]);
+		else
+			for (i = 0; i < NR_CPUS; i++)
+				atomic_inc(&passive_cpu_wait[i]);
 	}
 
 #ifdef CONFIG_SMP
 	/* Signal the other CPUs to enter kgdb_wait() */
-	if ((!kgdb_single_step) && kgdb_do_roundup)
+	if ((!kgdb_single_step) && kgdb_do_roundup && kgdb_contthread != current)
 		kgdb_roundup_cpus(flags);
 #endif
 
@@ -1475,8 +1506,6 @@
 	 */
 	kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
 	kgdb_deactivate_sw_breakpoints();
-	kgdb_single_step = 0;
-	kgdb_contthread = current;
 	exception_level = 0;
 	trace_on = tracing_is_on();
 	if (trace_on)
@@ -1492,15 +1521,22 @@
 	atomic_dec(&cpu_in_kgdb[ks->cpu]);
 
 	if (!kgdb_single_step) {
-		for (i = NR_CPUS-1; i >= 0; i--)
+		/* wake up next master cpu when do real cpu switch */
+		if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+			kgdb_contthread) {
+			i = -(ks->kgdb_usethreadid + 2);
 			atomic_dec(&passive_cpu_wait[i]);
-		/*
-		 * Wait till all the CPUs have quit
-		 * from the debugger.
-		 */
-		for_each_online_cpu(i) {
-			while (atomic_read(&cpu_in_kgdb[i]))
-				cpu_relax();
+		} else {
+			for (i = NR_CPUS-1; i >= 0; i--)
+				atomic_dec(&passive_cpu_wait[i]);
+			/*
+			 * Wait till all the CPUs have quit
+			 * from the debugger.
+			 */
+			for_each_online_cpu(i) {
+				while (atomic_read(&cpu_in_kgdb[i]))
+					cpu_relax();
+			}
 		}
 	}
 
@@ -1569,6 +1605,18 @@
 		kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
 		kgdb_cpu_enter(ks, regs);
 		kgdb_info[cpu].exception_state &= ~DCPU_IS_SLAVE;
+
+		/* Trap into kgdb as the active CPU if gdb asks to switch. */
+		if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+			kgdb_contthread == current) {
+#ifdef __ARCH_SYNC_CORE_ICACHE
+			resync_core_icache();
+#endif
+#ifdef __ARCH_SYNC_CORE_DCACHE
+			resync_core_dcache();
+#endif
+			kgdb_breakpoint();
+		}
 		return 0;
 	}
 #endif
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to