Arch independent per-cpu initialization
[akaros.git] / kern / src / smp.c
index e1ab2b1..dc4e86f 100644 (file)
@@ -31,18 +31,22 @@ atomic_t outstanding_calls = 0;
  * - Management cores (core 0 for now) call manager, which should never return.
  * - Worker cores halt and wake up when interrupted, do any work on their work
  *   queue, then halt again.
- *
- * TODO: think about resetting the stack pointer at the beginning for worker
- * cores. (keeps the stack from growing if we never go back to userspace).
  * TODO: think about unifying the manager into a workqueue function, so we don't
  * need to check mgmt_core in here.  it gets a little ugly, since there are
  * other places where we check for mgmt and might not smp_idle / call manager.
  */
-void smp_idle(void)
+static void __smp_idle(void)
 {
        int8_t state = 0;
-       per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
 
+       /* There was a process running here, and we should return to it */
+       if (pcpui->cur_tf) {                    /* aka, current_tf */
+               assert(pcpui->cur_proc);        /* aka, current */
+               proc_restartcore();
+               assert(0);
+       }
+       /* if we made it here, we truly want to idle */
        /* in the future, we may need to proactively leave process context here.
         * for now, it is possible to have a current loaded, even if we are idle
         * (and presumably about to execute a kmsg or fire up a vcore). */
@@ -65,3 +69,29 @@ void smp_idle(void)
        }
        assert(0);
 }
+
+void smp_idle(void)
+{
+       #ifdef __CONFIG_RESET_STACKS__
+       set_stack_pointer(get_stack_top());
+       #endif /* __CONFIG_RESET_STACKS__ */
+       __smp_idle();
+       assert(0);
+}
+
+/* Arch-independent per-cpu initialization.  This will call the arch dependent
+ * init first. */
+void smp_percpu_init(void)
+{
+       uint32_t coreid = core_id();
+       /* Do this first */
+       __arch_pcpu_init(coreid);
+       per_cpu_info[coreid].spare = 0;
+       /* Init relevant lists */
+       spinlock_init(&per_cpu_info[coreid].immed_amsg_lock);
+       STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
+       spinlock_init(&per_cpu_info[coreid].routine_amsg_lock);
+       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);
+}