[lib][sm] Create all sm threads on the main CPU

If we sleep during boot on the main CPU while holding the
vmm_lock mutex before sm_secondary_init calls thread_create
which blocks on that mutex, we hit a deadlock where all secondary
CPUs are blocked on vmm_lock while the NS OS gets stuck trying
to schedule those CPUs over the main one.

This fixes the deadlock by creating the threads on the main CPU.

Bug: 217580763
Change-Id: Ie3d24655c8ad7394f35c9e5f258c3e5bb1523296
diff --git a/lib/sm/sm.c b/lib/sm/sm.c
index 881563d..bfe64a1 100644
--- a/lib/sm/sm.c
+++ b/lib/sm/sm.c
@@ -68,7 +68,6 @@
 static thread_t* nsirqthreads[SMP_MAX_CPUS];
 static thread_t* nsidlethreads[SMP_MAX_CPUS];
 static thread_t* stdcallthread;
-static bool ns_threads_started;
 static bool irq_thread_ready[SMP_MAX_CPUS];
 struct sm_std_call_state stdcallstate = {
         .event = EVENT_INITIAL_VALUE(stdcallstate.event, 0, 0),
@@ -384,43 +383,9 @@
                    LK_INIT_FLAG_ALL_CPUS);
 #endif
 
-static void sm_secondary_init(uint level) {
-    char name[32];
-    int cpu = arch_curr_cpu_num();
-
-    event_init(&nsirqevent[cpu], false, EVENT_FLAG_AUTOUNSIGNAL);
-
-    snprintf(name, sizeof(name), "irq-ns-switch-%d", cpu);
-    nsirqthreads[cpu] = thread_create(name, sm_irq_loop, (void*)(uintptr_t)cpu,
-                                      HIGHEST_PRIORITY, DEFAULT_STACK_SIZE);
-    if (!nsirqthreads[cpu]) {
-        panic("failed to create irq NS switcher thread for cpu %d!\n", cpu);
-    }
-    thread_set_pinned_cpu(nsirqthreads[cpu], cpu);
-    thread_set_real_time(nsirqthreads[cpu]);
-
-    snprintf(name, sizeof(name), "idle-ns-switch-%d", cpu);
-    nsidlethreads[cpu] = thread_create(name, sm_wait_for_smcall, NULL,
-                                       LOWEST_PRIORITY + 1, DEFAULT_STACK_SIZE);
-    if (!nsidlethreads[cpu]) {
-        panic("failed to create idle NS switcher thread for cpu %d!\n", cpu);
-    }
-    thread_set_pinned_cpu(nsidlethreads[cpu], cpu);
-    thread_set_real_time(nsidlethreads[cpu]);
-
-    if (ns_threads_started) {
-        thread_resume(nsirqthreads[cpu]);
-        thread_resume(nsidlethreads[cpu]);
-    }
-}
-
-LK_INIT_HOOK_FLAGS(libsm_cpu,
-                   sm_secondary_init,
-                   LK_INIT_LEVEL_PLATFORM - 2,
-                   LK_INIT_FLAG_ALL_CPUS);
-
 static void sm_init(uint level) {
     status_t err;
+    char name[32];
 
     mutex_acquire(&boot_args_lock);
 
@@ -447,6 +412,31 @@
 
     mutex_release(&boot_args_lock);
 
+    for (int cpu = 0; cpu < SMP_MAX_CPUS; cpu++) {
+        event_init(&nsirqevent[cpu], false, EVENT_FLAG_AUTOUNSIGNAL);
+
+        snprintf(name, sizeof(name), "irq-ns-switch-%d", cpu);
+        nsirqthreads[cpu] =
+                thread_create(name, sm_irq_loop, (void*)(uintptr_t)cpu,
+                              HIGHEST_PRIORITY, DEFAULT_STACK_SIZE);
+        if (!nsirqthreads[cpu]) {
+            panic("failed to create irq NS switcher thread for cpu %d!\n", cpu);
+        }
+        thread_set_pinned_cpu(nsirqthreads[cpu], cpu);
+        thread_set_real_time(nsirqthreads[cpu]);
+
+        snprintf(name, sizeof(name), "idle-ns-switch-%d", cpu);
+        nsidlethreads[cpu] =
+                thread_create(name, sm_wait_for_smcall, NULL,
+                              LOWEST_PRIORITY + 1, DEFAULT_STACK_SIZE);
+        if (!nsidlethreads[cpu]) {
+            panic("failed to create idle NS switcher thread for cpu %d!\n",
+                  cpu);
+        }
+        thread_set_pinned_cpu(nsidlethreads[cpu], cpu);
+        thread_set_real_time(nsidlethreads[cpu]);
+    }
+
     stdcallthread = thread_create("sm-stdcall", sm_stdcall_loop, NULL,
                                   LOWEST_PRIORITY + 2, DEFAULT_STACK_SIZE);
     if (!stdcallthread) {
@@ -536,13 +526,12 @@
 static void resume_nsthreads(void) {
     int i;
 
-    ns_threads_started = true;
-    smp_wmb();
     for (i = 0; i < SMP_MAX_CPUS; i++) {
-        if (nsirqthreads[i])
-            thread_resume(nsirqthreads[i]);
-        if (nsidlethreads[i])
-            thread_resume(nsidlethreads[i]);
+        DEBUG_ASSERT(nsirqthreads[i]);
+        DEBUG_ASSERT(nsidlethreads[i]);
+
+        thread_resume(nsirqthreads[i]);
+        thread_resume(nsidlethreads[i]);
     }
 }