blob: cd33b76f6f0d0d22fa6a39a5d7941dda1590c76c [file] [log] [blame]
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +00001/*
Kevin Peng10a9fea2019-01-28 09:43:45 +08002 * Copyright (c) 2017 - 2019, Arm Limited. All rights reserved.
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdio.h>
9#include <stdint.h>
10#include <string.h>
11#include <stdbool.h>
12
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000013#include "tfm_api.h"
14#include "cmsis_os2.h"
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +020015#include "tfm_nspm_api.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000016
17#include "tfm_integ_test.h"
Tamas Banc2074a72018-08-14 10:23:12 +010018#include "test/framework/test_framework_integ_test.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000019
Ben Davis6d7256b2018-04-18 14:16:53 +010020#ifdef TEST_FRAMEWORK_S
21#include \
22 "test/test_services/tfm_secure_client_service/tfm_secure_client_service_api.h"
23#endif
24
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000025#ifdef CORE_TEST_INTERACTIVE
26#include "test/test_services/tfm_core_test/core_test_defs.h"
27#include "test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000028
29#define TRY_SFN(fn, ...) \
30 do { \
31 enum tfm_status_e res = (enum tfm_status_e) fn(__VA_ARGS__); \
32 switch(res) { \
33 case TFM_SUCCESS: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000034 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") successful!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000035 break; \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000036 case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000037 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
38 "S domain locked!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000039 break; \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000040 default: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000041 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
42 "generic!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000043 } \
44 } while(0)
45/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020046 * \brief secure_decrement_ns_lock_1
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000047 *
48 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020049void secure_decrement_ns_lock_1(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000050{
51 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
52}
53
54/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020055 * \brief secure_decrement_ns_lock_2
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000056 *
57 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020058void secure_decrement_ns_lock_2(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000059{
60 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
61}
62/**
63 * \brief Test definition for the RTX - TFM integration tests
64 * scenarios
65 */
66enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000067 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
68 access TFM */
69 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
70 gets delayed */
71 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
72 priority task waiting on lower priority task
73 undefinitely if NS lock is configured without priority
74 inheritance */
75 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
76 lock mechanism */
77 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
78 overcome the NS lock but finds TFM core locked by
79 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000080 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
81 timeout to acquire the NS lock. The timeout will
82 expire only if TFM Core is built with the
Miklos Balintace4c3f2018-07-30 12:31:15 +020083 de-prioritization disabled */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000084};
85
86static const osThreadAttr_t tattr_seq = {
87 .name = "seq_task",
88 .stack_size = 1024U,
89 .attr_bits = osThreadJoinable,
90 .tz_module = 1,
91};
92static const osThreadAttr_t tattr_mid = {
93 .name = "mid_task",
94 .stack_size = 512U,
95 .attr_bits = osThreadJoinable,
96 .tz_module = 0,
97 .priority = osPriorityAboveNormal
98};
99static const osThreadAttr_t tattr_pri = {
100 .name = "pri_task",
101 .stack_size = 1024U,
102 .attr_bits = osThreadJoinable,
103 .tz_module = 1,
104 .priority = osPriorityHigh
105};
106
107/**
108 * \brief Mutex id, NS lock
109 */
110static osMutexId_t mutex_id;
111
112/**
113 * \brief Mutex properties, NS lock
114 */
115static const osMutexAttr_t mattr_ns_lock = {
116 .name = "ns_lock",
117 //.attr_bits = osMutexPrioInherit
118};
119
120/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000121 * \brief TFM NS lock options
122 *
123 * \details Options used while acquiring the NS lock
124 */
125struct tfm_ns_lock_options
126{
127 bool use_ns_lock;
128 uint32_t timeout;
129};
130
131/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000132 * \brief tfm_service_request
133 *
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200134 * \details This function is used to request a TFM service in thread mode.
135 * Optionally uses the NS lock and specifies a timeout for obtaining
136 * the NS lock.
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000137 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200138static void tfm_service_request(void(*fn)(void),
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000139 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000140{
141 osStatus_t result;
142
143 char buffer[80];
144
145#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000146 do { \
147 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
148 LOG_MSG(buffer); \
149 } \
150 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000151
152 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
153
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000154 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000155 result = osMutexAcquire(mutex_id,0);
156 if (result == osOK) {
157 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000158 /* Add a delay here just to let the pri_task try to
159 * acquire the NS lock before seq_task enters secure world
160 */
161 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
162 osDelay(100U);
163 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200164 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000165 LOG_MSG_THREAD("NS Lock: releasing...");
166 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000167 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000168
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000169 if (ns_lock_options_p->timeout == osWaitForever) {
170 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
171 } else {
172 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
173 }
174
175 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
176 if (result == osOK) {
177 LOG_MSG_THREAD("NS Lock: acquired");
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200178 fn();
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000179 LOG_MSG_THREAD("NS Lock: releasing...");
180 osMutexRelease(mutex_id);
181 } else if (result == osErrorTimeout) {
182 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
183 } else {
184 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
185 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000186 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000187 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000188 /* Add a delay here to let the seq_task (which always uses the NS lock)
189 * enter secure world before the pri_task (which can try to overcome the
190 * NS lock in test scenario 5)
191 */
192 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
193 osDelay(100U);
194 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200195 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000196 }
197}
198
199/**
200 * \brief Non-blocking test thread
201 *
202 */
203__attribute__((noreturn))
204static void mid_task(void *argument)
205{
206 osThreadId_t thread_id_pri;
207 osThreadState_t thread_pri_state;
208 uint32_t idx;
209
Mate Toth-Pal53136092018-09-19 09:34:01 +0200210#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200211 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200212#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200213
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000214 thread_id_pri = *((osThreadId_t *)argument);
215
216 /* go to sleep */
217 osDelay(100U);
218
219 thread_pri_state = osThreadGetState(thread_id_pri);
220
221 if (thread_pri_state == osThreadBlocked) {
222 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000223 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000224 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000225 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000226 LOG_MSG("Running [mid_task]");
227 }
228
229 /* Do non TFM related, non blocking, operations */
230 for (idx=0; idx<0x3ffffff; idx++) {
231 }
232
233 LOG_MSG("Exiting [mid_task]");
234
235 osThreadExit();
236}
237
238/**
239 * \brief Priority test thread
240 *
241 */
242__attribute__((noreturn))
243static void pri_task(void *argument)
244{
Mate Toth-Pal53136092018-09-19 09:34:01 +0200245#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200246 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200247#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200248
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000249 /* go to sleep */
250 osDelay(100U);
251
252 /* After wake up, try to get hold of the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200253 tfm_service_request(secure_decrement_ns_lock_2,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000254 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000255
256 osThreadExit();
257}
258
259/**
260 * \brief Sequential test thread
261 *
262 */
263__attribute__((noreturn))
264static void seq_task(void *argument)
265{
266 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000267 enum test_type test_type;
268
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000269 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
270 struct tfm_ns_lock_options ns_lock_opt =
271 {.use_ns_lock=true, .timeout=osWaitForever};
272 struct tfm_ns_lock_options ns_lock_opt_pri =
273 {.use_ns_lock=true, .timeout=osWaitForever};
274
Mate Toth-Pal53136092018-09-19 09:34:01 +0200275#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200276 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200277#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200278
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000279 test_type = *((enum test_type *)argument);
280
281 if (test_type == TEST_TYPE_1) {
282 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000283 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000284 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000285 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000286 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000287 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000288 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000289 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000290 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000291 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000292 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000293 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000294 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000295 ns_lock_opt_pri.use_ns_lock = false;
296 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
297 } else if (test_type == TEST_TYPE_6) {
298 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
299 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
300 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000301 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000302 LOG_MSG("Scenario not supported");
303 osThreadExit();
304 }
305
306 /* Try to acquire the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200307 tfm_service_request(secure_decrement_ns_lock_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000308
309 if (test_type == TEST_TYPE_1) {
310 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000311 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000312 osThreadJoin(thread_id);
313 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000314 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000315 osThreadJoin(thread_id);
316 osThreadJoin(thread_id_mid);
317 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000318 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000319 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000320 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000321 osThreadJoin(thread_id);
322 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000323 } else if (test_type == TEST_TYPE_6) {
324 osThreadJoin(thread_id);
325 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000326 }
327
328 osThreadExit();
329}
330
331/**
332 * \brief Execute the interactive tets cases
333 *
334 */
335void execute_ns_interactive_tests(void)
336{
337 uint8_t idx;
338
339 osThreadId_t thread_id;
340
341 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000342 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000343 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000344
345 /* Create the NS lock -- shared among testing scenarios */
346 mutex_id = osMutexNew(&mattr_ns_lock);
347
348 /* Loop in the test list */
349 for (idx=0; idx<sizeof(test_type); idx++) {
350 /* Spawn the main thread */
351 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
352
353 /* Wait for it to finish before moving to the next scenario */
354 osThreadJoin(thread_id);
355 }
356}
357#endif /* CORE_TEST_INTERACTIVE */
358
Ben Davis6d7256b2018-04-18 14:16:53 +0100359#if defined(TEST_FRAMEWORK_NS) || defined(TEST_FRAMEWORK_S)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000360/**
361 * \brief Services test thread
362 *
363 */
364__attribute__((noreturn))
365void test_app(void *argument)
366{
367 UNUSED_VARIABLE(argument);
Ben Davis6d7256b2018-04-18 14:16:53 +0100368
369#ifdef TEST_FRAMEWORK_S
370 /* FIXME: The non-secure audit log test currently relies on the fact that
371 * the audit log secure test is run first. However the Non-secure tests
372 * represent simpler and more common test cases which would make more sense
373 * to be run first. Therefore if this dependency is removed the execution
374 * order of these test classes should be reversed. */
375 tfm_secure_client_run_tests();
376#endif
377#ifdef TEST_FRAMEWORK_NS
378 tfm_non_secure_client_run_tests();
379#endif
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000380 /* End of test */
381 for (;;) {
382 }
383}
Ben Davis6d7256b2018-04-18 14:16:53 +0100384#endif /* TEST_FRAMEWORK_NS OR TEST_FRAMEWORK_S */