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 #include <ksched.h>
11 #include <zephyr/kernel_structs.h>
12 
13 #if CONFIG_MP_MAX_NUM_CPUS < 2
14 #error SMP test requires at least two CPUs!
15 #endif
16 
17 #define RUN_FACTOR (CONFIG_SMP_TEST_RUN_FACTOR / 100.0)
18 
19 #define T2_STACK_SIZE (2048 + CONFIG_TEST_EXTRA_STACK_SIZE)
20 #define STACK_SIZE (384 + CONFIG_TEST_EXTRA_STACK_SIZE)
21 #define DELAY_US 50000
22 #define TIMEOUT 1000
23 #define EQUAL_PRIORITY 1
24 #define TIME_SLICE_MS 500
25 #define THREAD_DELAY 1
26 #define SLEEP_MS_LONG ((int)(15000 * RUN_FACTOR))
27 
28 struct k_thread t2;
29 K_THREAD_STACK_DEFINE(t2_stack, T2_STACK_SIZE);
30 
31 volatile int t2_count;
32 volatile int sync_count = -1;
33 
34 static int main_thread_id;
35 static int child_thread_id;
36 volatile int rv;
37 
38 K_SEM_DEFINE(cpuid_sema, 0, 1);
39 K_SEM_DEFINE(sema, 0, 1);
40 static struct k_mutex smutex;
41 static struct k_sem smp_sem;
42 
43 #define MAX_NUM_THREADS CONFIG_MP_MAX_NUM_CPUS
44 
45 struct thread_info {
46 	k_tid_t tid;
47 	int executed;
48 	int priority;
49 	int cpu_id;
50 };
51 static ZTEST_BMEM volatile struct thread_info tinfo[MAX_NUM_THREADS];
52 static struct k_thread tthread[MAX_NUM_THREADS];
53 static K_THREAD_STACK_ARRAY_DEFINE(tstack, MAX_NUM_THREADS, STACK_SIZE);
54 
55 static volatile int thread_started[MAX_NUM_THREADS - 1];
56 
57 static struct k_poll_signal tsignal[MAX_NUM_THREADS];
58 static struct k_poll_event tevent[MAX_NUM_THREADS];
59 
curr_cpu(void)60 static int curr_cpu(void)
61 {
62 	unsigned int k = arch_irq_lock();
63 	int ret = arch_curr_cpu()->id;
64 
65 	arch_irq_unlock(k);
66 	return ret;
67 }
68 
69 /**
70  * @brief SMP
71  * @defgroup kernel_smp_tests SMP Tests
72  * @ingroup all_tests
73  * @{
74  * @}
75  */
76 
77 /**
78  * @defgroup kernel_smp_integration_tests SMP Integration Tests
79  * @ingroup kernel_smp_tests
80  * @{
81  * @}
82  */
83 
84 /**
85  * @defgroup kernel_smp_module_tests SMP Module Tests
86  * @ingroup kernel_smp_tests
87  * @{
88  * @}
89  */
90 
t2_fn(void * a,void * b,void * c)91 static void t2_fn(void *a, void *b, void *c)
92 {
93 	ARG_UNUSED(a);
94 	ARG_UNUSED(b);
95 	ARG_UNUSED(c);
96 
97 	t2_count = 0;
98 
99 	/* This thread simply increments a counter while spinning on
100 	 * the CPU.  The idea is that it will always be iterating
101 	 * faster than the other thread so long as it is fairly
102 	 * scheduled (and it's designed to NOT be fairly schedulable
103 	 * without a separate CPU!), so the main thread can always
104 	 * check its progress.
105 	 */
106 	while (1) {
107 		k_busy_wait(DELAY_US);
108 		t2_count++;
109 	}
110 }
111 
112 /**
113  * @brief Verify SMP with 2 cooperative threads
114  *
115  * @ingroup kernel_smp_tests
116  *
117  * @details Multi processing is verified by checking whether
118  * 2 cooperative threads run simultaneously at different cores
119  */
ZTEST(smp,test_smp_coop_threads)120 ZTEST(smp, test_smp_coop_threads)
121 {
122 	int i, ok = 1;
123 
124 	if (!IS_ENABLED(CONFIG_SCHED_IPI_SUPPORTED)) {
125 		/* The spawned thread enters an infinite loop, so it can't be
126 		 * successfully aborted via an IPI.  Just skip in that
127 		 * configuration.
128 		 */
129 		ztest_test_skip();
130 	}
131 
132 	k_tid_t tid = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, t2_fn,
133 				      NULL, NULL, NULL,
134 				      K_PRIO_COOP(2), 0, K_NO_WAIT);
135 
136 	/* Wait for the other thread (on a separate CPU) to actually
137 	 * start running.  We want synchrony to be as perfect as
138 	 * possible.
139 	 */
140 	t2_count = -1;
141 	while (t2_count == -1) {
142 	}
143 
144 	for (i = 0; i < 10; i++) {
145 		/* Wait slightly longer than the other thread so our
146 		 * count will always be lower
147 		 */
148 		k_busy_wait(DELAY_US + (DELAY_US / 8));
149 
150 		if (t2_count <= i) {
151 			ok = 0;
152 			break;
153 		}
154 	}
155 
156 	k_thread_abort(tid);
157 	k_thread_join(tid, K_FOREVER);
158 	zassert_true(ok, "SMP test failed");
159 }
160 
child_fn(void * p1,void * p2,void * p3)161 static void child_fn(void *p1, void *p2, void *p3)
162 {
163 	ARG_UNUSED(p2);
164 	ARG_UNUSED(p3);
165 	int parent_cpu_id = POINTER_TO_INT(p1);
166 
167 	zassert_true(parent_cpu_id != curr_cpu(),
168 		     "Parent isn't on other core");
169 
170 	sync_count++;
171 	k_sem_give(&cpuid_sema);
172 }
173 
174 /**
175  * @brief Verify CPU IDs of threads in SMP
176  *
177  * @ingroup kernel_smp_tests
178  *
179  * @details Verify whether thread running on other core is
180  * parent thread from child thread
181  */
ZTEST(smp,test_cpu_id_threads)182 ZTEST(smp, test_cpu_id_threads)
183 {
184 	/* Make sure idle thread runs on each core */
185 	k_sleep(K_MSEC(1000));
186 
187 	int parent_cpu_id = curr_cpu();
188 
189 	k_tid_t tid = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, child_fn,
190 				      INT_TO_POINTER(parent_cpu_id), NULL,
191 				      NULL, K_PRIO_PREEMPT(2), 0, K_NO_WAIT);
192 
193 	while (sync_count == -1) {
194 	}
195 	k_sem_take(&cpuid_sema, K_FOREVER);
196 
197 	k_thread_abort(tid);
198 	k_thread_join(tid, K_FOREVER);
199 }
200 
thread_entry_fn(void * p1,void * p2,void * p3)201 static void thread_entry_fn(void *p1, void *p2, void *p3)
202 {
203 	ARG_UNUSED(p2);
204 	ARG_UNUSED(p3);
205 	int thread_num = POINTER_TO_INT(p1);
206 	int count = 0;
207 
208 	tinfo[thread_num].executed  = 1;
209 	tinfo[thread_num].cpu_id = curr_cpu();
210 
211 	while (count++ < 5) {
212 		k_busy_wait(DELAY_US);
213 	}
214 }
215 
spin_for_threads_exit(void)216 static void spin_for_threads_exit(void)
217 {
218 	unsigned int num_threads = arch_num_cpus();
219 
220 	for (int i = 0; i < num_threads - 1; i++) {
221 		volatile uint8_t *p = &tinfo[i].tid->base.thread_state;
222 
223 		while (!(*p & _THREAD_DEAD)) {
224 		}
225 	}
226 	k_busy_wait(DELAY_US);
227 }
228 
spawn_threads(int prio,int thread_num,int equal_prio,k_thread_entry_t thread_entry,int delay)229 static void spawn_threads(int prio, int thread_num, int equal_prio,
230 			k_thread_entry_t thread_entry, int delay)
231 {
232 	int i;
233 
234 	/* Spawn threads of priority higher than
235 	 * the previously created thread
236 	 */
237 	for (i = 0; i < thread_num; i++) {
238 		if (equal_prio) {
239 			tinfo[i].priority = prio;
240 		} else {
241 			/* Increase priority for each thread */
242 			tinfo[i].priority = prio - 1;
243 			prio = tinfo[i].priority;
244 		}
245 		tinfo[i].tid = k_thread_create(&tthread[i], tstack[i],
246 					       STACK_SIZE, thread_entry,
247 					       INT_TO_POINTER(i), NULL, NULL,
248 					       tinfo[i].priority, 0,
249 					       K_MSEC(delay));
250 		if (delay) {
251 			/* Increase delay for each thread */
252 			delay = delay + 10;
253 		}
254 	}
255 }
256 
abort_threads(int num)257 static void abort_threads(int num)
258 {
259 	for (int i = 0; i < num; i++) {
260 		k_thread_abort(tinfo[i].tid);
261 	}
262 
263 	for (int i = 0; i < num; i++) {
264 		k_thread_join(tinfo[i].tid, K_FOREVER);
265 	}
266 }
267 
cleanup_resources(void)268 static void cleanup_resources(void)
269 {
270 	unsigned int num_threads = arch_num_cpus();
271 
272 	for (int i = 0; i < num_threads; i++) {
273 		tinfo[i].tid = 0;
274 		tinfo[i].executed = 0;
275 		tinfo[i].priority = 0;
276 	}
277 }
278 
thread_ab_entry(void * p1,void * p2,void * p3)279 static void __no_optimization thread_ab_entry(void *p1, void *p2, void *p3)
280 {
281 	ARG_UNUSED(p1);
282 	ARG_UNUSED(p2);
283 	ARG_UNUSED(p3);
284 
285 	while (true) {
286 	}
287 }
288 
289 #define SPAWN_AB_PRIO K_PRIO_COOP(10)
290 
291 /**
292  * @brief Verify the code path when we do context switch in k_thread_abort on SMP system
293  *
294  * @ingroup kernel_smp_tests
295  *
296  * @details test logic:
297  * - The ztest thread has cooperative priority.
298  * - From ztest thread we spawn N number of cooperative threads, where N = number of CPUs.
299  *   - The spawned cooperative are executing infinite loop (so they occupy CPU core until they are
300  *     aborted).
301  *   - We have (number of CPUs - 1) spawned threads run and executing infinite loop, as current CPU
302  *     is occupied by ztest cooperative thread. Due to that the last of spawned threads is ready but
303  *     not executing.
304  * - We abort spawned threads one-by-one from the ztest thread.
305  *   - At the first k_thread_abort call the ztest thread will be preempted by the remaining spawned
306  *     thread which has higher priority than ztest thread.
307  *     But... k_thread_abort call should has destroyed one of the spawned threads, so ztest thread
308  *     should have a CPU available to run on.
309  * - We expect that all spawned threads will be aborted successfully.
310  *
311  * This was the test case for zephyrproject-rtos/zephyr#58040 issue where this test caused system
312  * hang.
313  */
314 
ZTEST(smp,test_coop_switch_in_abort)315 ZTEST(smp, test_coop_switch_in_abort)
316 {
317 	k_tid_t tid[MAX_NUM_THREADS];
318 	unsigned int num_threads = arch_num_cpus();
319 	unsigned int i;
320 
321 	zassert_true(_current->base.prio < 0, "test case relies on ztest thread be cooperative");
322 	zassert_true(_current->base.prio > SPAWN_AB_PRIO,
323 		     "spawn test need to have higher priority than ztest thread");
324 
325 	/* Spawn N number of cooperative threads, where N = number of CPUs */
326 	for (i = 0; i < num_threads; i++) {
327 		tid[i] = k_thread_create(&tthread[i], tstack[i],
328 					 STACK_SIZE, thread_ab_entry,
329 					 NULL, NULL, NULL,
330 					 SPAWN_AB_PRIO, 0, K_NO_WAIT);
331 	}
332 
333 	/* Wait for some time to let spawned threads on other cores run and start executing infinite
334 	 * loop.
335 	 */
336 	k_busy_wait(DELAY_US * 4);
337 
338 	/* At this time we have (number of CPUs - 1) spawned threads run and executing infinite loop
339 	 * on other CPU cores, as current CPU is occupied by this ztest cooperative thread.
340 	 * Due to that the last of spawned threads is ready but not executing.
341 	 */
342 
343 	/* Abort all spawned threads one-by-one. At the first k_thread_abort call the context
344 	 * switch will happen and the last 'spawned' thread will start.
345 	 * We should successfully abort all threads.
346 	 */
347 	for (i = 0; i < num_threads; i++) {
348 		k_thread_abort(tid[i]);
349 	}
350 
351 	/* Cleanup */
352 	for (i = 0; i < num_threads; i++) {
353 		zassert_equal(k_thread_join(tid[i], K_FOREVER), 0);
354 	}
355 }
356 
357 /**
358  * @brief Test cooperative threads non-preemption
359  *
360  * @ingroup kernel_smp_tests
361  *
362  * @details Spawn cooperative threads equal to number of cores
363  * supported. Main thread will already be running on 1 core.
364  * Check if the last thread created preempts any threads
365  * already running.
366  */
ZTEST(smp,test_coop_resched_threads)367 ZTEST(smp, test_coop_resched_threads)
368 {
369 	unsigned int num_threads = arch_num_cpus();
370 
371 	/* Spawn threads equal to number of cores,
372 	 * since we don't give up current CPU, last thread
373 	 * will not get scheduled
374 	 */
375 	spawn_threads(K_PRIO_COOP(10), num_threads, !EQUAL_PRIORITY,
376 		      &thread_entry_fn, THREAD_DELAY);
377 
378 	/* Wait for some time to let other core's thread run */
379 	k_busy_wait(DELAY_US);
380 
381 
382 	/* Reassure that cooperative thread's are not preempted
383 	 * by checking last thread's execution
384 	 * status. We know that all threads got rescheduled on
385 	 * other cores except the last one
386 	 */
387 	for (int i = 0; i < num_threads - 1; i++) {
388 		zassert_true(tinfo[i].executed == 1,
389 			     "cooperative thread %d didn't run", i);
390 	}
391 	zassert_true(tinfo[num_threads - 1].executed == 0,
392 		     "cooperative thread is preempted");
393 
394 	/* Abort threads created */
395 	abort_threads(num_threads);
396 	cleanup_resources();
397 }
398 
399 /**
400  * @brief Test preemptness of preemptive thread
401  *
402  * @ingroup kernel_smp_tests
403  *
404  * @details Create preemptive thread and let it run
405  * on another core and verify if it gets preempted
406  * if another thread of higher priority is spawned
407  */
ZTEST(smp,test_preempt_resched_threads)408 ZTEST(smp, test_preempt_resched_threads)
409 {
410 	unsigned int num_threads = arch_num_cpus();
411 
412 	/* Spawn threads  equal to number of cores,
413 	 * lower priority thread should
414 	 * be preempted by higher ones
415 	 */
416 	spawn_threads(K_PRIO_PREEMPT(10), num_threads, !EQUAL_PRIORITY,
417 		      &thread_entry_fn, THREAD_DELAY);
418 
419 	spin_for_threads_exit();
420 
421 	for (int i = 0; i < num_threads; i++) {
422 		zassert_true(tinfo[i].executed == 1,
423 			     "preemptive thread %d didn't run", i);
424 	}
425 
426 	/* Abort threads created */
427 	abort_threads(num_threads);
428 	cleanup_resources();
429 }
430 
431 /**
432  * @brief Validate behavior of thread when it yields
433  *
434  * @ingroup kernel_smp_tests
435  *
436  * @details Spawn cooperative threads equal to number
437  * of cores, so last thread would be pending, call
438  * yield() from main thread. Now, all threads must be
439  * executed
440  */
ZTEST(smp,test_yield_threads)441 ZTEST(smp, test_yield_threads)
442 {
443 	unsigned int num_threads = arch_num_cpus();
444 
445 	/* Spawn threads equal to the number
446 	 * of cores, so the last thread would be
447 	 * pending.
448 	 */
449 	spawn_threads(K_PRIO_COOP(10), num_threads, !EQUAL_PRIORITY,
450 		      &thread_entry_fn, !THREAD_DELAY);
451 
452 	k_yield();
453 	k_busy_wait(DELAY_US);
454 
455 	for (int i = 0; i < num_threads; i++) {
456 		zassert_true(tinfo[i].executed == 1,
457 			     "thread %d did not execute", i);
458 
459 	}
460 
461 	abort_threads(num_threads);
462 	cleanup_resources();
463 }
464 
465 /**
466  * @brief Test behavior of thread when it sleeps
467  *
468  * @ingroup kernel_smp_tests
469  *
470  * @details Spawn cooperative thread and call
471  * sleep() from main thread. After timeout, all
472  * threads has to be scheduled.
473  */
ZTEST(smp,test_sleep_threads)474 ZTEST(smp, test_sleep_threads)
475 {
476 	unsigned int num_threads = arch_num_cpus();
477 
478 	spawn_threads(K_PRIO_COOP(10), num_threads, !EQUAL_PRIORITY,
479 		      &thread_entry_fn, !THREAD_DELAY);
480 
481 	k_msleep(TIMEOUT);
482 
483 	for (int i = 0; i < num_threads; i++) {
484 		zassert_true(tinfo[i].executed == 1,
485 			     "thread %d did not execute", i);
486 	}
487 
488 	abort_threads(num_threads);
489 	cleanup_resources();
490 }
491 
thread_wakeup_entry(void * p1,void * p2,void * p3)492 static void thread_wakeup_entry(void *p1, void *p2, void *p3)
493 {
494 	ARG_UNUSED(p2);
495 	ARG_UNUSED(p3);
496 	int thread_num = POINTER_TO_INT(p1);
497 
498 	thread_started[thread_num] = 1;
499 
500 	k_msleep(DELAY_US * 1000);
501 
502 	tinfo[thread_num].executed  = 1;
503 }
504 
wakeup_on_start_thread(int tnum)505 static void wakeup_on_start_thread(int tnum)
506 {
507 	int threads_started = 0, i;
508 
509 	/* For each thread, spin waiting for it to first flag that
510 	 * it's going to sleep, and then that it's actually blocked
511 	 */
512 	for (i = 0; i < tnum; i++) {
513 		while (thread_started[i] == 0) {
514 		}
515 		while (!z_is_thread_prevented_from_running(tinfo[i].tid)) {
516 		}
517 	}
518 
519 	for (i = 0; i < tnum; i++) {
520 		if (thread_started[i] == 1 && threads_started <= tnum) {
521 			threads_started++;
522 			k_wakeup(tinfo[i].tid);
523 		}
524 	}
525 	zassert_equal(threads_started, tnum,
526 		      "All threads haven't started");
527 }
528 
check_wokeup_threads(int tnum)529 static void check_wokeup_threads(int tnum)
530 {
531 	int threads_woke_up = 0, i;
532 
533 	/* k_wakeup() isn't synchronous, give the other CPU time to
534 	 * schedule them
535 	 */
536 	k_busy_wait(200000);
537 
538 	for (i = 0; i < tnum; i++) {
539 		if (tinfo[i].executed == 1 && threads_woke_up <= tnum) {
540 			threads_woke_up++;
541 		}
542 	}
543 	zassert_equal(threads_woke_up, tnum, "Threads did not wakeup");
544 }
545 
546 /**
547  * @brief Test behavior of wakeup() in SMP case
548  *
549  * @ingroup kernel_smp_tests
550  *
551  * @details Spawn number of threads equal to number of
552  * remaining cores and let them sleep for a while. Call
553  * wakeup() of those threads from parent thread and check
554  * if they are all running
555  */
ZTEST(smp,test_wakeup_threads)556 ZTEST(smp, test_wakeup_threads)
557 {
558 	unsigned int num_threads = arch_num_cpus();
559 
560 	/* Spawn threads to run on all remaining cores */
561 	spawn_threads(K_PRIO_COOP(10), num_threads - 1, !EQUAL_PRIORITY,
562 		      &thread_wakeup_entry, !THREAD_DELAY);
563 
564 	/* Check if all the threads have started, then call wakeup */
565 	wakeup_on_start_thread(num_threads - 1);
566 
567 	/* Count threads which are woken up */
568 	check_wokeup_threads(num_threads - 1);
569 
570 	/* Abort all threads and cleanup */
571 	abort_threads(num_threads - 1);
572 	cleanup_resources();
573 }
574 
575 /* a thread for testing get current cpu */
thread_get_cpu_entry(void * p1,void * p2,void * p3)576 static void thread_get_cpu_entry(void *p1, void *p2, void *p3)
577 {
578 	ARG_UNUSED(p1);
579 	ARG_UNUSED(p2);
580 	ARG_UNUSED(p3);
581 
582 	int bsp_id = *(int *)p1;
583 	int cpu_id = -1;
584 
585 	/* get current cpu number for running thread */
586 	_cpu_t *curr_cpu = arch_curr_cpu();
587 
588 	/**TESTPOINT: call arch_curr_cpu() to get cpu struct */
589 	zassert_true(curr_cpu != NULL,
590 			"test failed to get current cpu.");
591 
592 	cpu_id = curr_cpu->id;
593 
594 	zassert_true(bsp_id != cpu_id,
595 			"should not be the same with our BSP");
596 
597 	/* loop forever to ensure running on this CPU */
598 	while (1) {
599 		k_busy_wait(DELAY_US);
600 	}
601 }
602 
603 /**
604  * @brief Test get a pointer of CPU
605  *
606  * @ingroup kernel_smp_module_tests
607  *
608  * @details
609  * Test Objective:
610  * - To verify architecture layer provides a mechanism to return a pointer to the
611  *   current kernel CPU record of the running CPU.
612  *   We call arch_curr_cpu() and get its member, both in main and spawned thread
613  *   separately, and compare them. They shall be different in SMP environment.
614  *
615  * Testing techniques:
616  * - Interface testing, function and block box testing,
617  *   dynamic analysis and testing,
618  *
619  * Prerequisite Conditions:
620  * - CONFIG_SMP=y, and the HW platform must support SMP.
621  *
622  * Input Specifications:
623  * - N/A
624  *
625  * Test Procedure:
626  * -# In main thread, call arch_curr_cpu() to get it's member "id",then store it
627  *  into a variable thread_id.
628  * -# Spawn a thread t2, and pass the stored thread_id to it, then call
629  *  k_busy_wait() 50us to wait for thread run and won't be swapped out.
630  * -# In thread t2, call arch_curr_cpu() to get pointer of current cpu data. Then
631  *  check if it not NULL.
632  * -# Store the member id via accessing pointer of current cpu data to var cpu_id.
633  * -# Check if cpu_id is not equaled to bsp_id that we pass into thread.
634  * -# Call k_busy_wait() and loop forever.
635  * -# In main thread, terminate the thread t2 before exit.
636  *
637  * Expected Test Result:
638  * - The pointer of current cpu data that we got from function call is correct.
639  *
640  * Pass/Fail Criteria:
641  * - Successful if the check of step 3,5 are all passed.
642  * - Failure if one of the check of step 3,5 is failed.
643  *
644  * Assumptions and Constraints:
645  * - This test using for the platform that support SMP, in our current scenario
646  *   , only x86_64, arc and xtensa supported.
647  *
648  * @see arch_curr_cpu()
649  */
650 static int _cpu_id;
ZTEST(smp,test_get_cpu)651 ZTEST(smp, test_get_cpu)
652 {
653 	k_tid_t thread_id;
654 
655 	if (!IS_ENABLED(CONFIG_SCHED_IPI_SUPPORTED)) {
656 		/* The spawned thread enters an infinite loop, so it can't be
657 		 * successfully aborted via an IPI.  Just skip in that
658 		 * configuration.
659 		 */
660 		ztest_test_skip();
661 	}
662 
663 	/* get current cpu number */
664 	_cpu_id = arch_curr_cpu()->id;
665 
666 	thread_id = k_thread_create(&t2, t2_stack, T2_STACK_SIZE,
667 				      thread_get_cpu_entry,
668 				      &_cpu_id, NULL, NULL,
669 				      K_PRIO_COOP(2),
670 				      K_INHERIT_PERMS, K_NO_WAIT);
671 
672 	k_busy_wait(DELAY_US);
673 
674 	k_thread_abort(thread_id);
675 	k_thread_join(thread_id, K_FOREVER);
676 }
677 
678 #ifdef CONFIG_TRACE_SCHED_IPI
679 /* global variable for testing send IPI */
680 static volatile int sched_ipi_has_called;
681 
z_trace_sched_ipi(void)682 void z_trace_sched_ipi(void)
683 {
684 	sched_ipi_has_called++;
685 }
686 #endif
687 
688 /**
689  * @brief Test interprocessor interrupt
690  *
691  * @ingroup kernel_smp_integration_tests
692  *
693  * @details
694  * Test Objective:
695  * - To verify architecture layer provides a mechanism to issue an interprocessor
696  *   interrupt to all other CPUs in the system that calls the scheduler IPI.
697  *   We simply add a hook in z_sched_ipi(), in order to check if it has been
698  *   called once in another CPU except the caller, when arch_sched_broadcast_ipi()
699  *   is called.
700  *
701  * Testing techniques:
702  * - Interface testing, function and block box testing,
703  *   dynamic analysis and testing
704  *
705  * Prerequisite Conditions:
706  * - CONFIG_SMP=y, and the HW platform must support SMP.
707  * - CONFIG_TRACE_SCHED_IPI=y was set.
708  *
709  * Input Specifications:
710  * - N/A
711  *
712  * Test Procedure:
713  * -# In main thread, given a global variable sched_ipi_has_called equaled zero.
714  * -# Call arch_sched_broadcast_ipi() then sleep for 100ms.
715  * -# In z_sched_ipi() handler, increment the sched_ipi_has_called.
716  * -# In main thread, check the sched_ipi_has_called is not equaled to zero.
717  * -# Repeat step 1 to 4 for 3 times.
718  *
719  * Expected Test Result:
720  * - The pointer of current cpu data that we got from function call is correct.
721  *
722  * Pass/Fail Criteria:
723  * - Successful if the check of step 4 are all passed.
724  * - Failure if one of the check of step 4 is failed.
725  *
726  * Assumptions and Constraints:
727  * - This test using for the platform that support SMP, in our current scenario
728  *   , only x86_64 and arc supported.
729  *
730  * @see arch_sched_broadcast_ipi()
731  */
732 #ifdef CONFIG_SCHED_IPI_SUPPORTED
ZTEST(smp,test_smp_ipi)733 ZTEST(smp, test_smp_ipi)
734 {
735 #ifndef CONFIG_TRACE_SCHED_IPI
736 	ztest_test_skip();
737 #else
738 
739 	TC_PRINT("cpu num=%d", arch_num_cpus());
740 
741 	for (int i = 0; i < 3 ; i++) {
742 		/* issue a sched ipi to tell other CPU to run thread */
743 		sched_ipi_has_called = 0;
744 		arch_sched_broadcast_ipi();
745 
746 		/* Need to wait longer than we think, loaded CI
747 		 * systems need to wait for host scheduling to run the
748 		 * other CPU's thread.
749 		 */
750 		k_msleep(100);
751 
752 		/**TESTPOINT: check if enter our IPI interrupt handler */
753 		zassert_true(sched_ipi_has_called != 0,
754 				"did not receive IPI.(%d)",
755 				sched_ipi_has_called);
756 	}
757 #endif
758 }
759 #endif
760 
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * esf)761 void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf)
762 {
763 	static int trigger;
764 
765 	if (reason != K_ERR_KERNEL_OOPS) {
766 		printk("wrong error reason\n");
767 		TC_END_REPORT(TC_FAIL);
768 		k_fatal_halt(reason);
769 	}
770 
771 	if (trigger == 0) {
772 		child_thread_id = curr_cpu();
773 		trigger++;
774 	} else {
775 		main_thread_id = curr_cpu();
776 
777 		/* Verify the fatal was happened on different core */
778 		zassert_true(main_thread_id != child_thread_id,
779 					"fatal on the same core");
780 	}
781 }
782 
entry_oops(void * p1,void * p2,void * p3)783 void entry_oops(void *p1, void *p2, void *p3)
784 {
785 	k_oops();
786 	TC_ERROR("SHOULD NEVER SEE THIS\n");
787 }
788 
789 /**
790  * @brief Test fatal error can be triggered on different core
791 
792  * @details When CONFIG_SMP is enabled, on some multiprocessor
793  * platforms, exception can be triggered on different core at
794  * the same time.
795  *
796  * @ingroup kernel_common_tests
797  */
ZTEST(smp,test_fatal_on_smp)798 ZTEST(smp, test_fatal_on_smp)
799 {
800 	/* Creat a child thread and trigger a crash */
801 	k_thread_create(&t2, t2_stack, T2_STACK_SIZE, entry_oops,
802 				      NULL, NULL, NULL,
803 				      K_PRIO_PREEMPT(2), 0, K_NO_WAIT);
804 
805 	/* hold cpu and wait for thread trigger exception and being terminated */
806 	k_busy_wait(5 * DELAY_US);
807 
808 	/* Verify that child thread is no longer running. We can't simply use k_thread_join here
809 	 * as we don't want to introduce reschedule point here.
810 	 */
811 	zassert_true(z_is_thread_state_set(&t2, _THREAD_DEAD));
812 
813 	/* Manually trigger the crash in mainthread */
814 	entry_oops(NULL, NULL, NULL);
815 
816 	/* should not be here */
817 	ztest_test_fail();
818 }
819 
workq_handler(struct k_work * work)820 static void workq_handler(struct k_work *work)
821 {
822 	child_thread_id = curr_cpu();
823 }
824 
825 /**
826  * @brief Test system workq run on different core
827 
828  * @details When macro CONFIG_SMP is enabled, workq can be run
829  * on different core.
830  *
831  * @ingroup kernel_common_tests
832  */
ZTEST(smp,test_workq_on_smp)833 ZTEST(smp, test_workq_on_smp)
834 {
835 	static struct k_work work;
836 
837 	k_work_init(&work, workq_handler);
838 
839 	/* submit work item on system workq */
840 	k_work_submit(&work);
841 
842 	/* Wait for some time to let other core's thread run */
843 	k_busy_wait(DELAY_US);
844 
845 	/* check work have finished */
846 	zassert_equal(k_work_busy_get(&work), 0);
847 
848 	main_thread_id = curr_cpu();
849 
850 	/* Verify the ztest thread and system workq run on different core */
851 	zassert_true(main_thread_id != child_thread_id,
852 		"system workq run on the same core");
853 }
854 
t1_mutex_lock(void * p1,void * p2,void * p3)855 static void t1_mutex_lock(void *p1, void *p2, void *p3)
856 {
857 	ARG_UNUSED(p2);
858 	ARG_UNUSED(p3);
859 
860 	/* t1 will get mutex first */
861 	k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
862 
863 	k_msleep(2);
864 
865 	k_mutex_unlock((struct k_mutex *)p1);
866 }
867 
t2_mutex_lock(void * p1,void * p2,void * p3)868 static void t2_mutex_lock(void *p1, void *p2, void *p3)
869 {
870 	ARG_UNUSED(p2);
871 	ARG_UNUSED(p3);
872 
873 	zassert_equal(_current->base.global_lock_count, 0,
874 			"thread global lock cnt %d is incorrect",
875 			_current->base.global_lock_count);
876 
877 	k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
878 
879 	zassert_equal(_current->base.global_lock_count, 0,
880 			"thread global lock cnt %d is incorrect",
881 			_current->base.global_lock_count);
882 
883 	k_mutex_unlock((struct k_mutex *)p1);
884 
885 	/**TESTPOINT: z_smp_release_global_lock() has been call during
886 	 * context switch but global_lock_cnt has not been decrease
887 	 * because no irq_lock() was called.
888 	 */
889 	zassert_equal(_current->base.global_lock_count, 0,
890 			"thread global lock cnt %d is incorrect",
891 			_current->base.global_lock_count);
892 }
893 
894 /**
895  * @brief Test scenario that a thread release the global lock
896  *
897  * @ingroup kernel_smp_tests
898  *
899  * @details Validate the scenario that make the internal APIs of SMP
900  * z_smp_release_global_lock() to be called.
901  */
ZTEST(smp,test_smp_release_global_lock)902 ZTEST(smp, test_smp_release_global_lock)
903 {
904 	k_mutex_init(&smutex);
905 
906 	tinfo[0].tid =
907 	k_thread_create(&tthread[0], tstack[0], STACK_SIZE,
908 			t1_mutex_lock,
909 			&smutex, NULL, NULL,
910 			K_PRIO_PREEMPT(5),
911 			K_INHERIT_PERMS, K_NO_WAIT);
912 
913 	tinfo[1].tid =
914 	k_thread_create(&tthread[1], tstack[1], STACK_SIZE,
915 		t2_mutex_lock,
916 			&smutex, NULL, NULL,
917 			K_PRIO_PREEMPT(3),
918 			K_INHERIT_PERMS, K_MSEC(1));
919 
920 	/* Hold one of the cpu to ensure context switch as we wanted
921 	 * can happen in another cpu.
922 	 */
923 	k_busy_wait(20000);
924 
925 	k_thread_join(tinfo[1].tid, K_FOREVER);
926 	k_thread_join(tinfo[0].tid, K_FOREVER);
927 	cleanup_resources();
928 }
929 
930 #define LOOP_COUNT ((int)(20000 * RUN_FACTOR))
931 
932 enum sync_t {
933 	LOCK_IRQ,
934 	LOCK_SEM,
935 	LOCK_MUTEX
936 };
937 
938 static int global_cnt;
939 static struct k_mutex smp_mutex;
940 
941 static void (*sync_lock)(void *);
942 static void (*sync_unlock)(void *);
943 
sync_lock_dummy(void * k)944 static void sync_lock_dummy(void *k)
945 {
946 	/* no sync lock used */
947 }
948 
sync_lock_irq(void * k)949 static void sync_lock_irq(void *k)
950 {
951 	*((unsigned int *)k) = irq_lock();
952 }
953 
sync_unlock_irq(void * k)954 static void sync_unlock_irq(void *k)
955 {
956 	irq_unlock(*(unsigned int *)k);
957 }
958 
sync_lock_sem(void * k)959 static void sync_lock_sem(void *k)
960 {
961 	k_sem_take(&smp_sem, K_FOREVER);
962 }
963 
sync_unlock_sem(void * k)964 static void sync_unlock_sem(void *k)
965 {
966 	k_sem_give(&smp_sem);
967 }
968 
sync_lock_mutex(void * k)969 static void sync_lock_mutex(void *k)
970 {
971 	k_mutex_lock(&smp_mutex, K_FOREVER);
972 }
973 
sync_unlock_mutex(void * k)974 static void sync_unlock_mutex(void *k)
975 {
976 	k_mutex_unlock(&smp_mutex);
977 }
978 
sync_init(int lock_type)979 static void sync_init(int lock_type)
980 {
981 	switch (lock_type) {
982 	case LOCK_IRQ:
983 		sync_lock = sync_lock_irq;
984 		sync_unlock = sync_unlock_irq;
985 		break;
986 	case LOCK_SEM:
987 		sync_lock = sync_lock_sem;
988 		sync_unlock = sync_unlock_sem;
989 		k_sem_init(&smp_sem, 1, 3);
990 		break;
991 	case LOCK_MUTEX:
992 		sync_lock = sync_lock_mutex;
993 		sync_unlock = sync_unlock_mutex;
994 		k_mutex_init(&smp_mutex);
995 		break;
996 
997 	default:
998 		sync_lock = sync_unlock = sync_lock_dummy;
999 	}
1000 }
1001 
inc_global_cnt(void * a,void * b,void * c)1002 static void inc_global_cnt(void *a, void *b, void *c)
1003 {
1004 	int key;
1005 
1006 	for (int i = 0; i < LOOP_COUNT; i++) {
1007 
1008 		sync_lock(&key);
1009 
1010 		global_cnt++;
1011 		global_cnt--;
1012 		global_cnt++;
1013 
1014 		sync_unlock(&key);
1015 	}
1016 }
1017 
run_concurrency(void * p1,void * p2,void * p3)1018 static int run_concurrency(void *p1, void *p2, void *p3)
1019 {
1020 	ARG_UNUSED(p3);
1021 
1022 	int type = POINTER_TO_INT(p1);
1023 	k_thread_entry_t func = p2;
1024 	uint32_t start_t, end_t;
1025 
1026 	sync_init(type);
1027 	global_cnt = 0;
1028 	start_t = k_cycle_get_32();
1029 
1030 	tinfo[0].tid =
1031 	k_thread_create(&tthread[0], tstack[0], STACK_SIZE,
1032 			func,
1033 			NULL, NULL, NULL,
1034 			K_PRIO_PREEMPT(1),
1035 			K_INHERIT_PERMS, K_NO_WAIT);
1036 
1037 	tinfo[1].tid =
1038 	k_thread_create(&tthread[1], tstack[1], STACK_SIZE,
1039 			func,
1040 			NULL, NULL, NULL,
1041 			K_PRIO_PREEMPT(1),
1042 			K_INHERIT_PERMS, K_NO_WAIT);
1043 
1044 	k_tid_t tid =
1045 	k_thread_create(&t2, t2_stack, T2_STACK_SIZE,
1046 			func,
1047 			NULL, NULL, NULL,
1048 			K_PRIO_PREEMPT(1),
1049 			K_INHERIT_PERMS, K_NO_WAIT);
1050 
1051 	k_thread_join(tinfo[0].tid, K_FOREVER);
1052 	k_thread_join(tinfo[1].tid, K_FOREVER);
1053 	k_thread_join(tid, K_FOREVER);
1054 	cleanup_resources();
1055 
1056 	end_t =  k_cycle_get_32();
1057 
1058 	printk("type %d: cnt %d, spend %u ms\n", type, global_cnt,
1059 		k_cyc_to_ms_ceil32(end_t - start_t));
1060 
1061 	return global_cnt == (LOOP_COUNT * 3);
1062 }
1063 
1064 /**
1065  * @brief Test if the concurrency of SMP works or not
1066  *
1067  * @ingroup kernel_smp_tests
1068  *
1069  * @details Validate the global lock and unlock API of SMP are thread-safe.
1070  * We make 3 thread to increase the global count in different cpu and
1071  * they both do locking then unlocking for LOOP_COUNT times. It shall be no
1072  * deadlock happened and total global count shall be 3 * LOOP COUNT.
1073  *
1074  * We show the 4 kinds of scenario:
1075  * - No any lock used
1076  * - Use global irq lock
1077  * - Use semaphore
1078  * - Use mutex
1079  */
ZTEST(smp,test_inc_concurrency)1080 ZTEST(smp, test_inc_concurrency)
1081 {
1082 	/* increasing global var with irq lock */
1083 	zassert_true(run_concurrency(INT_TO_POINTER(LOCK_IRQ), inc_global_cnt, NULL),
1084 			"total count %d is wrong(i)", global_cnt);
1085 
1086 	/* increasing global var with irq lock */
1087 	zassert_true(run_concurrency(INT_TO_POINTER(LOCK_SEM), inc_global_cnt, NULL),
1088 			"total count %d is wrong(s)", global_cnt);
1089 
1090 	/* increasing global var with irq lock */
1091 	zassert_true(run_concurrency(INT_TO_POINTER(LOCK_MUTEX), inc_global_cnt, NULL),
1092 			"total count %d is wrong(M)", global_cnt);
1093 }
1094 
1095 /**
1096  * @brief Torture test for context switching code
1097  *
1098  * @ingroup kernel_smp_tests
1099  *
1100  * @details Leverage the polling API to stress test the context switching code.
1101  *          This test will hammer all the CPUs with thread swapping requests.
1102  */
process_events(void * arg0,void * arg1,void * arg2)1103 static void process_events(void *arg0, void *arg1, void *arg2)
1104 {
1105 	ARG_UNUSED(arg1);
1106 	ARG_UNUSED(arg2);
1107 
1108 	uintptr_t id = (uintptr_t) arg0;
1109 
1110 	while (1) {
1111 		k_poll(&tevent[id], 1, K_FOREVER);
1112 
1113 		if (tevent[id].signal->result != 0x55) {
1114 			ztest_test_fail();
1115 		}
1116 
1117 		tevent[id].signal->signaled = 0;
1118 		tevent[id].state = K_POLL_STATE_NOT_READY;
1119 
1120 		k_poll_signal_reset(&tsignal[id]);
1121 	}
1122 }
1123 
signal_raise(void * arg0,void * arg1,void * arg2)1124 static void signal_raise(void *arg0, void *arg1, void *arg2)
1125 {
1126 	unsigned int num_threads = arch_num_cpus();
1127 
1128 	while (1) {
1129 		for (uintptr_t i = 0; i < num_threads; i++) {
1130 			k_poll_signal_raise(&tsignal[i], 0x55);
1131 		}
1132 	}
1133 }
1134 
ZTEST(smp,test_smp_switch_torture)1135 ZTEST(smp, test_smp_switch_torture)
1136 {
1137 	unsigned int num_threads = arch_num_cpus();
1138 
1139 	if (CONFIG_SMP_TEST_RUN_FACTOR == 0) {
1140 		/* If CONFIG_SMP_TEST_RUN_FACTOR is zero,
1141 		 * the switch torture test is effectively
1142 		 * not doing anything as the k_sleep()
1143 		 * below is not going to sleep at all,
1144 		 * and all created threads are being
1145 		 * terminated (almost) immediately after
1146 		 * creation. So if run factor is zero,
1147 		 * mark the test as skipped.
1148 		 */
1149 		ztest_test_skip();
1150 	}
1151 
1152 	for (uintptr_t i = 0; i < num_threads; i++) {
1153 		k_poll_signal_init(&tsignal[i]);
1154 		k_poll_event_init(&tevent[i], K_POLL_TYPE_SIGNAL,
1155 				  K_POLL_MODE_NOTIFY_ONLY, &tsignal[i]);
1156 
1157 		k_thread_create(&tthread[i], tstack[i], STACK_SIZE,
1158 				process_events,
1159 				(void *) i, NULL, NULL, K_PRIO_PREEMPT(i + 1),
1160 				K_INHERIT_PERMS, K_NO_WAIT);
1161 	}
1162 
1163 	k_thread_create(&t2, t2_stack, T2_STACK_SIZE, signal_raise,
1164 			NULL, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT);
1165 
1166 	k_sleep(K_MSEC(SLEEP_MS_LONG));
1167 
1168 	k_thread_abort(&t2);
1169 	k_thread_join(&t2, K_FOREVER);
1170 	for (uintptr_t i = 0; i < num_threads; i++) {
1171 		k_thread_abort(&tthread[i]);
1172 		k_thread_join(&tthread[i], K_FOREVER);
1173 	}
1174 }
1175 
1176 /**
1177  * @brief Torture test for cpu affinity code
1178  *
1179  * @ingroup kernel_smp_tests
1180  *
1181  * @details Pin thread to a specific cpu. Once thread gets cpu, check
1182  *          the cpu id is correct and then thread will give up cpu.
1183  */
1184 #ifdef CONFIG_SCHED_CPU_MASK
check_affinity(void * arg0,void * arg1,void * arg2)1185 static void check_affinity(void *arg0, void *arg1, void *arg2)
1186 {
1187 	ARG_UNUSED(arg1);
1188 	ARG_UNUSED(arg2);
1189 
1190 	int affinity = POINTER_TO_INT(arg0);
1191 	int counter = 30;
1192 
1193 	while (counter != 0) {
1194 		zassert_equal(affinity, curr_cpu(), "Affinity test failed.");
1195 		counter--;
1196 		k_yield();
1197 	}
1198 }
1199 
ZTEST(smp,test_smp_affinity)1200 ZTEST(smp, test_smp_affinity)
1201 {
1202 	int num_threads = arch_num_cpus();
1203 
1204 	for (int i = 0; i < num_threads; ++i) {
1205 		k_thread_create(&tthread[i], tstack[i],
1206 					       STACK_SIZE, check_affinity,
1207 					       INT_TO_POINTER(i), NULL, NULL,
1208 					       0, 0, K_FOREVER);
1209 
1210 		k_thread_cpu_pin(&tthread[i], i);
1211 		k_thread_start(&tthread[i]);
1212 	}
1213 
1214 	for (int i = 0; i < num_threads; i++) {
1215 		k_thread_join(&tthread[i], K_FOREVER);
1216 	}
1217 }
1218 #endif
1219 
smp_tests_setup(void)1220 static void *smp_tests_setup(void)
1221 {
1222 	/* Sleep a bit to guarantee that both CPUs enter an idle
1223 	 * thread from which they can exit correctly to run the main
1224 	 * test.
1225 	 */
1226 	k_sleep(K_MSEC(10));
1227 
1228 	return NULL;
1229 }
1230 
1231 ZTEST_SUITE(smp, NULL, smp_tests_setup, NULL, NULL, NULL);
1232