1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/tc_util.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/kernel.h>
10
11 #ifdef CONFIG_SMP
12 #error Cannot test MP API if SMP is using the CPUs
13 #endif
14
15 BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS > 1);
16
17 #define CPU_STACK_SIZE 1024
18
19 K_THREAD_STACK_ARRAY_DEFINE(cpu_stacks, CONFIG_MP_MAX_NUM_CPUS, CPU_STACK_SIZE);
20
21 int cpu_arg;
22
23 volatile int cpu_running[CONFIG_MP_MAX_NUM_CPUS];
24
25 /**
26 * @brief Tests for multi processing
27 *
28 * @defgroup kernel_mp_tests MP Tests
29 *
30 * @ingroup all_tests
31 *
32 * @{
33 * @}
34 */
cpu_fn(void * arg)35 FUNC_NORETURN void cpu_fn(void *arg)
36 {
37 zassert_true(arg == &cpu_arg, "mismatched arg");
38
39 int cpu_id = (*(int *)arg) / 12345;
40 int mod = (*(int *)arg) % 12345;
41
42 zassert_true(mod == 0, "wrong arg");
43
44 cpu_running[cpu_id] = 1;
45
46 while (1) {
47 }
48 }
49
50 /**
51 * @brief Test to verify CPU start
52 *
53 * @ingroup kernel_mp_tests
54 *
55 * @details
56 * Test Objective:
57 * - To verify kernel architecture layer shall provide a means to start non-boot
58 * CPUs on SMP systems.
59 * The way we verify it is to call it by give it parameters especially the
60 * target executing function, etc. Then check if the function is running or
61 * not.
62 *
63 * Testing techniques:
64 * - Interface testing, function and block box testing,
65 * dynamic analysis and testing
66 *
67 * Prerequisite Conditions:
68 * - CONFIG_MP_MAX_NUM_CPUS > 1
69 *
70 * Input Specifications:
71 * - CPU ID: the cpu want to start
72 * - Stack structure
73 * - Stack size
74 * - Target executing function
75 * - An argument that pass to the function
76 *
77 * Test Procedure:
78 * -# In main thread, given and set a global variable cpu_arg to 12345.
79 * -# Call arch_cpu_start() with parameters
80 * -# Enter a while loop and wait for cpu_running equals to 1.
81 * -# In target function, check if the address is &cpu_arg and its content
82 * equal to 12345.
83 * -# Set the global flag variable cpu_running to 1.
84 * -# In main thread, check if the cpu_running equals to 1.
85 *
86 * Expected Test Result:
87 * - The given function execute cpu is running and .
88 *
89 * Pass/Fail Criteria:
90 * - Successful if the check of step 4, 6 are all pass.
91 * - Failure if one of the check of step 4, 6 is failed.
92 *
93 * Assumptions and Constraints:
94 * - This test using for the platform that support MP or SMP, in our current
95 * scenario which own over two CPUs.
96 *
97 * @see arch_cpu_start()
98 */
ZTEST(multiprocessing,test_mp_start)99 ZTEST(multiprocessing, test_mp_start)
100 {
101 for (int i = 1; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
102 int wait_count;
103
104 TC_PRINT("Starting CPU #%d...\n", i);
105
106 cpu_arg = 12345 * i;
107
108 arch_cpu_start(i, cpu_stacks[i], CPU_STACK_SIZE, cpu_fn, &cpu_arg);
109
110 /* Wait for about 5 (500 * 10ms) seconds for CPU to start. */
111 wait_count = 500;
112 while (!cpu_running[i]) {
113 k_busy_wait(10 * USEC_PER_MSEC);
114
115 wait_count--;
116 if (wait_count < 0) {
117 break;
118 }
119 }
120
121 zassert_true(cpu_running[i], "cpu #%d didn't start", i);
122 }
123 }
124
125 ZTEST_SUITE(multiprocessing, NULL, NULL, NULL, NULL, NULL);
126