blob: acef4d6943a7ec14454e5e450a02cc1b52707df3 [file] [log] [blame]
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +00001/*
Antonio de Angelis04bf6592018-02-26 11:57:36 +00002 * Copyright (c) 2017 - 2018, 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
13#include "cmsis.h"
14#include "tfm_api.h"
15#include "cmsis_os2.h"
16
17#include "tfm_integ_test.h"
18#include "test/framework/integ_test.h"
19
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"
28#include "tfm_ns_svc.h"
29
30#define TRY_SFN(fn, ...) \
31 do { \
32 enum tfm_status_e res = (enum tfm_status_e) fn(__VA_ARGS__); \
33 switch(res) { \
34 case TFM_SUCCESS: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000035 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") successful!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000036 break; \
Mate Toth-Pal7de74b52018-02-23 15:46:47 +010037 case TFM_PARTITION_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000038 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") pended!"); \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000039 break; \
Mate Toth-Pal7de74b52018-02-23 15:46:47 +010040 case TFM_ERROR_PARTITION_ALREADY_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000041 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
42 "already pended!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000043 break; \
44 case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000045 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
46 "S domain locked!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000047 break; \
48 case TFM_ERROR_NS_THREAD_MODE_CALL: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000049 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
50 "NS thread mode!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000051 break; \
52 default: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000053 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
54 "generic!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000055 } \
56 } while(0)
57/**
58 * \brief SVC_SECURE_DECREMENT_NS_LOCK_1
59 *
60 */
61void svc_secure_decrement_ns_lock_1(void)
62{
63 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
64}
65
66/**
67 * \brief SVC_SECURE_DECREMENT_NS_LOCK_2
68 *
69 */
70void svc_secure_decrement_ns_lock_2(void)
71{
72 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
73}
74/**
75 * \brief Test definition for the RTX - TFM integration tests
76 * scenarios
77 */
78enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000079 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
80 access TFM */
81 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
82 gets delayed */
83 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
84 priority task waiting on lower priority task
85 undefinitely if NS lock is configured without priority
86 inheritance */
87 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
88 lock mechanism */
89 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
90 overcome the NS lock but finds TFM core locked by
91 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000092 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
93 timeout to acquire the NS lock. The timeout will
94 expire only if TFM Core is built with the
95 de-prioritization disabled (i.e. TFM_API_SVCCLEAR
96 defined) */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000097};
98
99static const osThreadAttr_t tattr_seq = {
100 .name = "seq_task",
101 .stack_size = 1024U,
102 .attr_bits = osThreadJoinable,
103 .tz_module = 1,
104};
105static const osThreadAttr_t tattr_mid = {
106 .name = "mid_task",
107 .stack_size = 512U,
108 .attr_bits = osThreadJoinable,
109 .tz_module = 0,
110 .priority = osPriorityAboveNormal
111};
112static const osThreadAttr_t tattr_pri = {
113 .name = "pri_task",
114 .stack_size = 1024U,
115 .attr_bits = osThreadJoinable,
116 .tz_module = 1,
117 .priority = osPriorityHigh
118};
119
120/**
121 * \brief Mutex id, NS lock
122 */
123static osMutexId_t mutex_id;
124
125/**
126 * \brief Mutex properties, NS lock
127 */
128static const osMutexAttr_t mattr_ns_lock = {
129 .name = "ns_lock",
130 //.attr_bits = osMutexPrioInherit
131};
132
133/**
134 * \brief SVC dispatcher
135 */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000136__attribute__((always_inline)) __STATIC_INLINE
137void svc_dispatch(enum tfm_svc_num svc_num)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000138{
139 switch (svc_num) {
140 case SVC_SECURE_DECREMENT_NS_LOCK_1:
141 SVC(SVC_SECURE_DECREMENT_NS_LOCK_1);
142 break;
143 case SVC_SECURE_DECREMENT_NS_LOCK_2:
144 SVC(SVC_SECURE_DECREMENT_NS_LOCK_2);
145 break;
146 default:
147 break;
148 }
149}
150
151/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000152 * \brief TFM NS lock options
153 *
154 * \details Options used while acquiring the NS lock
155 */
156struct tfm_ns_lock_options
157{
158 bool use_ns_lock;
159 uint32_t timeout;
160};
161
162/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000163 * \brief tfm_service_request
164 *
165 * \details This function is used to request a TFM
166 * service in handler mode, using SVC.
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000167 * Optionally uses the NS lock and specifies
168 * a timeout for obtaining the NS lock
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000169 */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000170static void tfm_service_request(enum tfm_svc_num svc_num,
171 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000172{
173 osStatus_t result;
174
175 char buffer[80];
176
177#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000178 do { \
179 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
180 LOG_MSG(buffer); \
181 } \
182 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000183
184 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
185
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000186 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000187 result = osMutexAcquire(mutex_id,0);
188 if (result == osOK) {
189 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000190 /* Add a delay here just to let the pri_task try to
191 * acquire the NS lock before seq_task enters secure world
192 */
193 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
194 osDelay(100U);
195 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000196 svc_dispatch(svc_num);
197 LOG_MSG_THREAD("NS Lock: releasing...");
198 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000199 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000200
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000201 if (ns_lock_options_p->timeout == osWaitForever) {
202 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
203 } else {
204 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
205 }
206
207 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
208 if (result == osOK) {
209 LOG_MSG_THREAD("NS Lock: acquired");
210 svc_dispatch(svc_num);
211 LOG_MSG_THREAD("NS Lock: releasing...");
212 osMutexRelease(mutex_id);
213 } else if (result == osErrorTimeout) {
214 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
215 } else {
216 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
217 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000218 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000219 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000220 /* Add a delay here to let the seq_task (which always uses the NS lock)
221 * enter secure world before the pri_task (which can try to overcome the
222 * NS lock in test scenario 5)
223 */
224 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
225 osDelay(100U);
226 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000227 svc_dispatch(svc_num);
228 }
229}
230
231/**
232 * \brief Non-blocking test thread
233 *
234 */
235__attribute__((noreturn))
236static void mid_task(void *argument)
237{
238 osThreadId_t thread_id_pri;
239 osThreadState_t thread_pri_state;
240 uint32_t idx;
241
242 thread_id_pri = *((osThreadId_t *)argument);
243
244 /* go to sleep */
245 osDelay(100U);
246
247 thread_pri_state = osThreadGetState(thread_id_pri);
248
249 if (thread_pri_state == osThreadBlocked) {
250 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000251 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000252 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000253 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000254 LOG_MSG("Running [mid_task]");
255 }
256
257 /* Do non TFM related, non blocking, operations */
258 for (idx=0; idx<0x3ffffff; idx++) {
259 }
260
261 LOG_MSG("Exiting [mid_task]");
262
263 osThreadExit();
264}
265
266/**
267 * \brief Priority test thread
268 *
269 */
270__attribute__((noreturn))
271static void pri_task(void *argument)
272{
273 /* go to sleep */
274 osDelay(100U);
275
276 /* After wake up, try to get hold of the NS lock */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000277 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2,
278 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000279
280 osThreadExit();
281}
282
283/**
284 * \brief Sequential test thread
285 *
286 */
287__attribute__((noreturn))
288static void seq_task(void *argument)
289{
290 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000291 enum test_type test_type;
292
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000293 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
294 struct tfm_ns_lock_options ns_lock_opt =
295 {.use_ns_lock=true, .timeout=osWaitForever};
296 struct tfm_ns_lock_options ns_lock_opt_pri =
297 {.use_ns_lock=true, .timeout=osWaitForever};
298
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000299 test_type = *((enum test_type *)argument);
300
301 if (test_type == TEST_TYPE_1) {
302 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000303 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000304 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000305 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000306 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000307 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000308 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000309 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000310 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000311 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000312 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000313 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000314 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000315 ns_lock_opt_pri.use_ns_lock = false;
316 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
317 } else if (test_type == TEST_TYPE_6) {
318 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
319 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
320 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000321 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000322 LOG_MSG("Scenario not supported");
323 osThreadExit();
324 }
325
326 /* Try to acquire the NS lock */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000327 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000328
329 if (test_type == TEST_TYPE_1) {
330 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000331 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000332 osThreadJoin(thread_id);
333 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000334 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000335 osThreadJoin(thread_id);
336 osThreadJoin(thread_id_mid);
337 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000338 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000339 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000340 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000341 osThreadJoin(thread_id);
342 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000343 } else if (test_type == TEST_TYPE_6) {
344 osThreadJoin(thread_id);
345 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000346 }
347
348 osThreadExit();
349}
350
351/**
352 * \brief Execute the interactive tets cases
353 *
354 */
355void execute_ns_interactive_tests(void)
356{
357 uint8_t idx;
358
359 osThreadId_t thread_id;
360
361 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000362 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000363 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000364
365 /* Create the NS lock -- shared among testing scenarios */
366 mutex_id = osMutexNew(&mattr_ns_lock);
367
368 /* Loop in the test list */
369 for (idx=0; idx<sizeof(test_type); idx++) {
370 /* Spawn the main thread */
371 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
372
373 /* Wait for it to finish before moving to the next scenario */
374 osThreadJoin(thread_id);
375 }
376}
377#endif /* CORE_TEST_INTERACTIVE */
378
Ben Davis6d7256b2018-04-18 14:16:53 +0100379#if defined(TEST_FRAMEWORK_NS) || defined(TEST_FRAMEWORK_S)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000380/**
381 * \brief Services test thread
382 *
383 */
384__attribute__((noreturn))
385void test_app(void *argument)
386{
387 UNUSED_VARIABLE(argument);
Ben Davis6d7256b2018-04-18 14:16:53 +0100388
389#ifdef TEST_FRAMEWORK_S
390 /* FIXME: The non-secure audit log test currently relies on the fact that
391 * the audit log secure test is run first. However the Non-secure tests
392 * represent simpler and more common test cases which would make more sense
393 * to be run first. Therefore if this dependency is removed the execution
394 * order of these test classes should be reversed. */
395 tfm_secure_client_run_tests();
396#endif
397#ifdef TEST_FRAMEWORK_NS
398 tfm_non_secure_client_run_tests();
399#endif
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000400 /* End of test */
401 for (;;) {
402 }
403}
Ben Davis6d7256b2018-04-18 14:16:53 +0100404#endif /* TEST_FRAMEWORK_NS OR TEST_FRAMEWORK_S */