commit 2af38d26b65b706ba19a2023681eda7430ad973f
parent 282fc014ab0b315a89563883334d9d164c4bf220
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 13 Jul 2015 18:19:13 -0700
lkdebug: provide "threads clear" to nuke thread state
Useful for calling after a target reset to ensure there's no stale
thread list data to confuse things before the kernel creates threads
in the new session.
Diffstat:
3 files changed, 44 insertions(+), 16 deletions(-)
diff --git a/tools/debugger-commands.c b/tools/debugger-commands.c
@@ -762,6 +762,15 @@ int do_maskints(int argc, param *argv) {
 }
 
 int do_threads(int argc, param *argv) {
+	if (argc == 1) {
+		if (strcmp(argv[0].s, "clear")) {
+			xprintf("usage: threads [clear]\n");
+			return -1;
+		}
+		swdp_core_halt();
+		clear_lk_threads();
+		return 0;
+	}
 	lkthread_t *t;
 	swdp_core_halt();
 	t = find_lk_threads(1);
diff --git a/tools/lkdebug.c b/tools/lkdebug.c
@@ -141,32 +141,46 @@ void free_lk_threads(lkthread_t *list) {
 	}
 }
 
-lkthread_t *find_lk_threads(int verbose) {
-	lkdebuginfo_t di;
-	lkthread_t *list = NULL;
-	lkthread_t *current = NULL;
-	lkthread_t *t;
+static int load_debuginfo(lkdebuginfo_t *di, int verbose) {
 	u32 x;
-	u32 rtp;
-	if (swdp_ahb_read(DI_OFF_MAGIC, &x)) goto fail;
+	if (swdp_ahb_read(DI_OFF_MAGIC, &x)) return -1;
 	if (x != DI_MAGIC) {
 		if (verbose) xprintf("debuginfo: bad magic\n");
-		goto fail;
+		return -1;
 	}
-	if (swdp_ahb_read(DI_OFF_PTR, &x)) goto fail;
-	if (x & 3) goto fail;
+	if (swdp_ahb_read(DI_OFF_PTR, &x)) return -1;
+	if (x & 3) return -1;
 	if (verbose) xprintf("debuginfo @ %08x\n", x);
-	if (swdp_ahb_read32(x, (void*) &di, sizeof(di) / 4)) goto fail;
+	if (swdp_ahb_read32(x, (void*) di, sizeof(lkdebuginfo_t) / 4)) return -1;
 	if (verbose) {
 		xprintf("di %08x %08x %08x %d %d %d %d %d %d\n",
-			di.version, di.thread_list_ptr, di.current_thread_ptr,
-			di.off_list_node, di.off_state, di.off_saved_sp,
-			di.off_was_preempted, di.off_name, di.off_waitq);
+			di->version, di->thread_list_ptr, di->current_thread_ptr,
+			di->off_list_node, di->off_state, di->off_saved_sp,
+			di->off_was_preempted, di->off_name, di->off_waitq);
 	}
-	if (di.version != 0x0100) {
+	if (di->version != 0x0100) {
 		if (verbose) xprintf("debuginfo: unsupported version\n");
-		goto fail;
+		return -1;
 	}
+	return 0;
+}
+
+void clear_lk_threads(void) {
+	lkdebuginfo_t di;
+	if (load_debuginfo(&di, 0)) return;
+	swdp_ahb_write(di.current_thread_ptr, 0xffffffff);
+	swdp_ahb_write(di.thread_list_ptr + 0, 0xffffffff);
+	swdp_ahb_write(di.thread_list_ptr + 4, 0xffffffff);
+}
+
+lkthread_t *find_lk_threads(int verbose) {
+	lkdebuginfo_t di;
+	lkthread_t *list = NULL;
+	lkthread_t *current = NULL;
+	lkthread_t *t;
+	u32 x;
+	u32 rtp;
+	if (load_debuginfo(&di, verbose)) goto fail;
 	if (swdp_ahb_read(di.current_thread_ptr, &x)) goto fail;
 	current = read_lk_thread(&di, x, 1);
 	if (current == NULL) goto fail;
diff --git a/tools/lkdebug.h b/tools/lkdebug.h
@@ -40,4 +40,9 @@ void free_lk_threads(lkthread_t *list);
 lkthread_t *find_lk_thread(lkthread_t *list, u32 tptr);
 void get_lk_thread_name(lkthread_t *t, char *out, size_t max);
 
+// Invalidate current thread and threadlist
+// Intended for use after target reset, etc.
+// Will corrupt a running image.
+void clear_lk_threads(void);
+
 #endif