Kthread stack poisoning
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 6 Jun 2011 21:10:11 +0000 (14:10 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:04 +0000 (17:36 -0700)
This has a bunch of asserts to check when sleeping or restarting a
kthread to make sure that we aren't using an active kernel stack.

The option will eventually go away or change when we have kthread
structs at the top of stacks.

For now, this will probably fail on sparc and riscv, so don't turn it on
for them.  Its not a big deal, since this is meant to debug heavy
kthreading.

Makeconfig
Makelocal.template
kern/arch/i686/trap.c
kern/src/kthread.c
kern/src/smp.c

index 56383f1..64c811c 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_RESET_STACKS:=              -D__CONFIG_RESET_STACKS__
 CONFIG_PCI_VERBOSE:=               -D__CONFIG_PCI_VERBOSE__
 CONFIG_ETH_AUDIO:=                 -D__CONFIG_ETH_AUDIO__
 CONFIG_KB_CORE0_ONLY:=             -D__CONFIG_KB_CORE0_ONLY__
+CONFIG_KTHREAD_POISON:=            -D__CONFIG_KTHREAD_POISON__
 
 # Userspace configuration parameters
 # By default, each of these options will be turned off
index 84020fb..ae9ea59 100644 (file)
@@ -31,6 +31,7 @@
 #KERN_CFLAGS += $(CONFIG_ETH_AUDIO)
 # Avoid KB input on buggy nehalems (brho's machine)
 #KERN_CFLAGS += $(CONFIG_KB_CORE0_ONLY)
+#KERN_CFLAGS += $(CONFIG_KTHREAD_POISON)
 
 #KERN_CFLAGS += -DDEVELOPER_NAME=waterman
 #KERN_CFLAGS += -DDEVELOPER_NAME=brho
index 7f376d4..d5f567c 100644 (file)
@@ -170,6 +170,11 @@ void idt_init(void)
        uintptr_t stacktop_kva = (uintptr_t)ppn2kva(PTE2PPN(*pte)) + PGSIZE;
        ts.ts_esp0 = stacktop_kva;
        ts.ts_ss0 = SINIT(GD_KD);
+#ifdef __CONFIG_KTHREAD_POISON__
+       /* TODO: KTHR-STACK */
+       uintptr_t *poison = (uintptr_t*)ROUNDDOWN(stacktop_kva - 1, PGSIZE);
+       *poison = 0xdeadbeef;
+#endif /* __CONFIG_KTHREAD_POISON__ */
 
        // Initialize the TSS field of the gdt.
        SEG16ROINIT(gdt[GD_TSS >> 3],STS_T32A, (uint32_t)(&ts),sizeof(taskstate_t),0);
index 8cbfca7..2207d30 100644 (file)
@@ -58,12 +58,27 @@ void sleep_on(struct semaphore *sem)
                kthread = kmem_cache_alloc(kthread_kcache, 0);
                assert(kthread);
                assert(!kpage_alloc(&page));    /* decref'd when the kthread is freed */
+#ifdef __CONFIG_KTHREAD_POISON__
+               /* TODO: KTHR-STACK don't poison like this */
+               *(uintptr_t*)page2kva(page) = 0;
+#endif /* __CONFIG_KTHREAD_POISON__ */
                new_stacktop = (uintptr_t)page2kva(page) + PGSIZE;
        }
        /* This is the stacktop we are currently on and wish to save */
        kthread->stacktop = get_stack_top();
        /* Set the core's new default stack */
        set_stack_top(new_stacktop);
+#ifdef __CONFIG_KTHREAD_POISON__
+       /* Mark the new stack as in-use, and unmark the current kthread */
+       /* TODO: KTHR-STACK don't poison like this */
+       uintptr_t *new_stack_poison, *kth_stack_poison;
+       new_stack_poison = (uintptr_t*)ROUNDDOWN(new_stacktop - 1, PGSIZE);
+       assert(!*new_stack_poison);
+       *new_stack_poison = 0xdeadbeef;
+       kth_stack_poison = (uintptr_t*)ROUNDDOWN(kthread->stacktop - 1, PGSIZE);
+       assert(*kth_stack_poison == 0xdeadbeef);
+       *kth_stack_poison = 0;
+#endif /* __CONFIG_KTHREAD_POISON__ */
        /* The kthread needs to stay in the process context (if there is one), but
         * we want the core (which could be a vcore) to stay in the context too.  If
         * we want to leave, we'll need to do that in smp_idle() or elsewhere in the
@@ -110,6 +125,12 @@ unwind_sleep_prep:
        pcpui->spare = kthread;
        /* save the "freshly alloc'd" stack/page, not the one we came in on */
        kthread->stacktop = new_stacktop;
+#ifdef __CONFIG_KTHREAD_POISON__
+       /* TODO: KTHR-STACK don't unpoison like this */
+       /* switch back to old stack in use, new one not */
+       *new_stack_poison = 0;
+       *kth_stack_poison = 0xdeadbeef;
+#endif /* __CONFIG_KTHREAD_POISON__ */
 block_return_path:
        printd("[kernel] Returning from being 'blocked'! at %llu\n", read_tsc());
 block_return_path_np:
@@ -141,6 +162,17 @@ void restart_kthread(struct kthread *kthread)
        current_stacktop = get_stack_top();
        /* When a kthread runs, its stack is the default kernel stack */
        set_stack_top(kthread->stacktop);
+#ifdef __CONFIG_KTHREAD_POISON__
+       /* TODO: KTHR-STACK */
+       /* Assert and switch to cur stack not in use, kthr stack in use */
+       uintptr_t *cur_stack_poison, *kth_stack_poison;
+       cur_stack_poison = (uintptr_t*)ROUNDDOWN(current_stacktop - 1, PGSIZE);
+       assert(*cur_stack_poison == 0xdeadbeef);
+       *cur_stack_poison = 0;
+       kth_stack_poison = (uintptr_t*)ROUNDDOWN(kthread->stacktop - 1, PGSIZE);
+       assert(!*kth_stack_poison);
+       *kth_stack_poison = 0xdeadbeef;
+#endif /* __CONFIG_KTHREAD_POISON__ */
        /* Set the spare stuff (current kthread, current (not kthread) stacktop) */
        pcpui->spare = kthread;
        kthread->stacktop = current_stacktop;
@@ -166,8 +198,21 @@ void restart_kthread(struct kthread *kthread)
  * particularly smart yet, but when we do, we can put it here. */
 void kthread_runnable(struct kthread *kthread)
 {
+       uint32_t dst = core_id();
+       #if 0
+       /* turn this block on if you want to test migrating non-core0 kthreads */
+       switch (dst) {
+               case 0:
+                       break;
+               case 7:
+                       dst = 2;
+                       break;
+               default:
+                       dst++;
+       }
+       #endif
        /* For lack of anything better, send it to ourselves. (TODO: KSCHED) */
-       send_kernel_message(core_id(), __launch_kthread, (void*)kthread, 0, 0,
+       send_kernel_message(dst, __launch_kthread, (void*)kthread, 0, 0,
                            KMSG_ROUTINE);
 }
 
index dc4e86f..66bb502 100644 (file)
@@ -94,4 +94,11 @@ void smp_percpu_init(void)
        STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
        /* Initialize the per-core timer chain */
        init_timer_chain(&per_cpu_info[coreid].tchain, set_pcpu_alarm_interrupt);
+
+#ifdef __CONFIG_KTHREAD_POISON__
+/* TODO: KTHR-STACK */
+uintptr_t *poison = (uintptr_t*)ROUNDDOWN(get_stack_top() - 1, PGSIZE);
+*poison = 0xdeadbeef;
+#endif /* __CONFIG_KTHREAD_POISON__ */
+
 }