1 /* Copyright (c) 2022 Intel Corporation.
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <zephyr/kernel.h>
6 #include <zephyr/kernel/smp.h>
7 #include <zephyr/ztest.h>
8 #include "tests.h"
9 
10 /* Experimentally 10ms is enough time to get the second CPU to run on
11  * all known platforms.
12  */
13 #define CPU_START_DELAY 10000
14 
15 /* IPIs happen  much faster than CPU startup */
16 #define CPU_IPI_DELAY 250
17 
18 BUILD_ASSERT(CONFIG_SMP);
19 BUILD_ASSERT(CONFIG_SMP_BOOT_DELAY);
20 
21 #define STACKSZ 2048
22 char stack[STACKSZ];
23 
24 volatile bool mp_flag;
25 
26 struct k_thread cpu_thr;
27 K_THREAD_STACK_DEFINE(thr_stack, STACKSZ);
28 
thread_fn(void * a,void * b,void * c)29 static void thread_fn(void *a, void *b, void *c)
30 {
31 	int cpuid = (int) a;
32 
33 	zassert_true(cpuid == 0 || cpuid == arch_curr_cpu()->id,
34 		     "running on wrong cpu");
35 	mp_flag = true;
36 }
37 
38 /* Needless to say: since this is starting the SMP CPUs, it needs to
39  * be the first test run!
40  */
ZTEST(intel_adsp_boot,test_1st_smp_boot_delay)41 ZTEST(intel_adsp_boot, test_1st_smp_boot_delay)
42 {
43 	unsigned int num_cpus = arch_num_cpus();
44 
45 	if (arch_num_cpus() < 2) {
46 		ztest_test_skip();
47 	}
48 
49 	for (int i = 1; i < num_cpus; i++) {
50 		printk("Launch cpu%d\n", i);
51 		mp_flag = false;
52 		k_thread_create(&cpu_thr, thr_stack, K_THREAD_STACK_SIZEOF(thr_stack),
53 				thread_fn, (void *)i, NULL, NULL,
54 				0, 0, K_FOREVER);
55 		k_thread_cpu_mask_clear(&cpu_thr);
56 		k_thread_cpu_mask_enable(&cpu_thr, i);
57 		k_thread_start(&cpu_thr);
58 
59 		/* Make sure that thread has not run (because the cpu is halted) */
60 		k_busy_wait(CPU_START_DELAY);
61 		zassert_false(mp_flag, "cpu %d must not be running yet", i);
62 
63 		/* Start the second CPU */
64 		k_smp_cpu_start(i, NULL, NULL);
65 
66 		/* Verify the thread ran */
67 		k_busy_wait(CPU_START_DELAY);
68 		zassert_true(mp_flag, "cpu %d did not start", i);
69 
70 		k_thread_abort(&cpu_thr);
71 	}
72 }
73 
ZTEST(intel_adsp_boot,test_3rd_post_boot_ipi)74 ZTEST(intel_adsp_boot, test_3rd_post_boot_ipi)
75 {
76 	if (arch_num_cpus() < 2) {
77 		ztest_test_skip();
78 	}
79 
80 	/* Spawn the same thread to do the same thing, but this time
81 	 * expect that the thread is going to run synchronously on
82 	 * another CPU as soon as its created.  Intended to test
83 	 * whether IPIs were correctly set up on the runtime-launched
84 	 * CPU.
85 	 */
86 	mp_flag = false;
87 	k_thread_create(&cpu_thr, thr_stack, K_THREAD_STACK_SIZEOF(thr_stack),
88 			thread_fn, (void *)0, NULL, NULL,
89 			1, 0, K_NO_WAIT);
90 
91 	k_busy_wait(CPU_IPI_DELAY);
92 	zassert_true(mp_flag, "cpu did not start thread via IPI");
93 }
94