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