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