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