blob: a72d0c46d2c85671a1a6f1378393c71bf5483862 [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"
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; \
Mate Toth-Pal7de74b52018-02-23 15:46:47 +010036 case TFM_PARTITION_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000037 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") pended!"); \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000038 break; \
Mate Toth-Pal7de74b52018-02-23 15:46:47 +010039 case TFM_ERROR_PARTITION_ALREADY_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000040 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
41 "already pended!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000042 break; \
43 case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000044 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
45 "S domain locked!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000046 break; \
47 case TFM_ERROR_NS_THREAD_MODE_CALL: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000048 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
49 "NS thread mode!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000050 break; \
51 default: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000052 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
53 "generic!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000054 } \
55 } while(0)
56/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020057 * \brief secure_decrement_ns_lock_1
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000058 *
59 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020060void secure_decrement_ns_lock_1(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000061{
62 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
63}
64
65/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020066 * \brief secure_decrement_ns_lock_2
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000067 *
68 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020069void secure_decrement_ns_lock_2(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000070{
71 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
72}
73/**
74 * \brief Test definition for the RTX - TFM integration tests
75 * scenarios
76 */
77enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000078 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
79 access TFM */
80 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
81 gets delayed */
82 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
83 priority task waiting on lower priority task
84 undefinitely if NS lock is configured without priority
85 inheritance */
86 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
87 lock mechanism */
88 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
89 overcome the NS lock but finds TFM core locked by
90 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000091 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
92 timeout to acquire the NS lock. The timeout will
93 expire only if TFM Core is built with the
Miklos Balintace4c3f2018-07-30 12:31:15 +020094 de-prioritization disabled */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000095};
96
97static const osThreadAttr_t tattr_seq = {
98 .name = "seq_task",
99 .stack_size = 1024U,
100 .attr_bits = osThreadJoinable,
101 .tz_module = 1,
102};
103static const osThreadAttr_t tattr_mid = {
104 .name = "mid_task",
105 .stack_size = 512U,
106 .attr_bits = osThreadJoinable,
107 .tz_module = 0,
108 .priority = osPriorityAboveNormal
109};
110static const osThreadAttr_t tattr_pri = {
111 .name = "pri_task",
112 .stack_size = 1024U,
113 .attr_bits = osThreadJoinable,
114 .tz_module = 1,
115 .priority = osPriorityHigh
116};
117
118/**
119 * \brief Mutex id, NS lock
120 */
121static osMutexId_t mutex_id;
122
123/**
124 * \brief Mutex properties, NS lock
125 */
126static const osMutexAttr_t mattr_ns_lock = {
127 .name = "ns_lock",
128 //.attr_bits = osMutexPrioInherit
129};
130
131/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000132 * \brief TFM NS lock options
133 *
134 * \details Options used while acquiring the NS lock
135 */
136struct tfm_ns_lock_options
137{
138 bool use_ns_lock;
139 uint32_t timeout;
140};
141
142/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000143 * \brief tfm_service_request
144 *
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200145 * \details This function is used to request a TFM service in thread mode.
146 * Optionally uses the NS lock and specifies a timeout for obtaining
147 * the NS lock.
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000148 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200149static void tfm_service_request(void(*fn)(void),
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000150 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000151{
152 osStatus_t result;
153
154 char buffer[80];
155
156#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000157 do { \
158 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
159 LOG_MSG(buffer); \
160 } \
161 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000162
163 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
164
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000165 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000166 result = osMutexAcquire(mutex_id,0);
167 if (result == osOK) {
168 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000169 /* Add a delay here just to let the pri_task try to
170 * acquire the NS lock before seq_task enters secure world
171 */
172 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
173 osDelay(100U);
174 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200175 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000176 LOG_MSG_THREAD("NS Lock: releasing...");
177 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000178 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000179
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000180 if (ns_lock_options_p->timeout == osWaitForever) {
181 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
182 } else {
183 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
184 }
185
186 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
187 if (result == osOK) {
188 LOG_MSG_THREAD("NS Lock: acquired");
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200189 fn();
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000190 LOG_MSG_THREAD("NS Lock: releasing...");
191 osMutexRelease(mutex_id);
192 } else if (result == osErrorTimeout) {
193 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
194 } else {
195 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
196 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000197 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000198 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000199 /* Add a delay here to let the seq_task (which always uses the NS lock)
200 * enter secure world before the pri_task (which can try to overcome the
201 * NS lock in test scenario 5)
202 */
203 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
204 osDelay(100U);
205 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200206 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000207 }
208}
209
210/**
211 * \brief Non-blocking test thread
212 *
213 */
214__attribute__((noreturn))
215static void mid_task(void *argument)
216{
217 osThreadId_t thread_id_pri;
218 osThreadState_t thread_pri_state;
219 uint32_t idx;
220
221 thread_id_pri = *((osThreadId_t *)argument);
222
223 /* go to sleep */
224 osDelay(100U);
225
226 thread_pri_state = osThreadGetState(thread_id_pri);
227
228 if (thread_pri_state == osThreadBlocked) {
229 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000230 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000231 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000232 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000233 LOG_MSG("Running [mid_task]");
234 }
235
236 /* Do non TFM related, non blocking, operations */
237 for (idx=0; idx<0x3ffffff; idx++) {
238 }
239
240 LOG_MSG("Exiting [mid_task]");
241
242 osThreadExit();
243}
244
245/**
246 * \brief Priority test thread
247 *
248 */
249__attribute__((noreturn))
250static void pri_task(void *argument)
251{
252 /* go to sleep */
253 osDelay(100U);
254
255 /* After wake up, try to get hold of the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200256 tfm_service_request(secure_decrement_ns_lock_2,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000257 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000258
259 osThreadExit();
260}
261
262/**
263 * \brief Sequential test thread
264 *
265 */
266__attribute__((noreturn))
267static void seq_task(void *argument)
268{
269 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000270 enum test_type test_type;
271
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000272 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
273 struct tfm_ns_lock_options ns_lock_opt =
274 {.use_ns_lock=true, .timeout=osWaitForever};
275 struct tfm_ns_lock_options ns_lock_opt_pri =
276 {.use_ns_lock=true, .timeout=osWaitForever};
277
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000278 test_type = *((enum test_type *)argument);
279
280 if (test_type == TEST_TYPE_1) {
281 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000282 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000283 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000284 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000285 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000286 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000287 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000288 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000289 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000290 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000291 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000292 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000293 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000294 ns_lock_opt_pri.use_ns_lock = false;
295 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
296 } else if (test_type == TEST_TYPE_6) {
297 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
298 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
299 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000300 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000301 LOG_MSG("Scenario not supported");
302 osThreadExit();
303 }
304
305 /* Try to acquire the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200306 tfm_service_request(secure_decrement_ns_lock_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000307
308 if (test_type == TEST_TYPE_1) {
309 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000310 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000311 osThreadJoin(thread_id);
312 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000313 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000314 osThreadJoin(thread_id);
315 osThreadJoin(thread_id_mid);
316 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000317 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000318 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000319 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000320 osThreadJoin(thread_id);
321 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000322 } else if (test_type == TEST_TYPE_6) {
323 osThreadJoin(thread_id);
324 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000325 }
326
327 osThreadExit();
328}
329
330/**
331 * \brief Execute the interactive tets cases
332 *
333 */
334void execute_ns_interactive_tests(void)
335{
336 uint8_t idx;
337
338 osThreadId_t thread_id;
339
340 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000341 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000342 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000343
344 /* Create the NS lock -- shared among testing scenarios */
345 mutex_id = osMutexNew(&mattr_ns_lock);
346
347 /* Loop in the test list */
348 for (idx=0; idx<sizeof(test_type); idx++) {
349 /* Spawn the main thread */
350 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
351
352 /* Wait for it to finish before moving to the next scenario */
353 osThreadJoin(thread_id);
354 }
355}
356#endif /* CORE_TEST_INTERACTIVE */
357
Ben Davis6d7256b2018-04-18 14:16:53 +0100358#if defined(TEST_FRAMEWORK_NS) || defined(TEST_FRAMEWORK_S)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000359/**
360 * \brief Services test thread
361 *
362 */
363__attribute__((noreturn))
364void test_app(void *argument)
365{
366 UNUSED_VARIABLE(argument);
Ben Davis6d7256b2018-04-18 14:16:53 +0100367
368#ifdef TEST_FRAMEWORK_S
369 /* FIXME: The non-secure audit log test currently relies on the fact that
370 * the audit log secure test is run first. However the Non-secure tests
371 * represent simpler and more common test cases which would make more sense
372 * to be run first. Therefore if this dependency is removed the execution
373 * order of these test classes should be reversed. */
374 tfm_secure_client_run_tests();
375#endif
376#ifdef TEST_FRAMEWORK_NS
377 tfm_non_secure_client_run_tests();
378#endif
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000379 /* End of test */
380 for (;;) {
381 }
382}
Ben Davis6d7256b2018-04-18 14:16:53 +0100383#endif /* TEST_FRAMEWORK_NS OR TEST_FRAMEWORK_S */