blob: b2777dadd3951605144e8e18f6c52333d21281b9 [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"
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +020016#include "tfm_nspm_api.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000017
18#include "tfm_integ_test.h"
Tamas Banc2074a72018-08-14 10:23:12 +010019#include "test/framework/test_framework_integ_test.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000020
Ben Davis6d7256b2018-04-18 14:16:53 +010021#ifdef TEST_FRAMEWORK_S
22#include \
23 "test/test_services/tfm_secure_client_service/tfm_secure_client_service_api.h"
24#endif
25
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000026#ifdef CORE_TEST_INTERACTIVE
27#include "test/test_services/tfm_core_test/core_test_defs.h"
28#include "test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h"
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000029
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; \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000037 case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000038 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
39 "S domain locked!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000040 break; \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000041 default: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000042 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
43 "generic!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000044 } \
45 } while(0)
46/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020047 * \brief secure_decrement_ns_lock_1
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000048 *
49 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020050void secure_decrement_ns_lock_1(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000051{
52 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
53}
54
55/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020056 * \brief secure_decrement_ns_lock_2
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000057 *
58 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020059void secure_decrement_ns_lock_2(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000060{
61 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
62}
63/**
64 * \brief Test definition for the RTX - TFM integration tests
65 * scenarios
66 */
67enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000068 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
69 access TFM */
70 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
71 gets delayed */
72 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
73 priority task waiting on lower priority task
74 undefinitely if NS lock is configured without priority
75 inheritance */
76 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
77 lock mechanism */
78 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
79 overcome the NS lock but finds TFM core locked by
80 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000081 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
82 timeout to acquire the NS lock. The timeout will
83 expire only if TFM Core is built with the
Miklos Balintace4c3f2018-07-30 12:31:15 +020084 de-prioritization disabled */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000085};
86
87static const osThreadAttr_t tattr_seq = {
88 .name = "seq_task",
89 .stack_size = 1024U,
90 .attr_bits = osThreadJoinable,
91 .tz_module = 1,
92};
93static const osThreadAttr_t tattr_mid = {
94 .name = "mid_task",
95 .stack_size = 512U,
96 .attr_bits = osThreadJoinable,
97 .tz_module = 0,
98 .priority = osPriorityAboveNormal
99};
100static const osThreadAttr_t tattr_pri = {
101 .name = "pri_task",
102 .stack_size = 1024U,
103 .attr_bits = osThreadJoinable,
104 .tz_module = 1,
105 .priority = osPriorityHigh
106};
107
108/**
109 * \brief Mutex id, NS lock
110 */
111static osMutexId_t mutex_id;
112
113/**
114 * \brief Mutex properties, NS lock
115 */
116static const osMutexAttr_t mattr_ns_lock = {
117 .name = "ns_lock",
118 //.attr_bits = osMutexPrioInherit
119};
120
121/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000122 * \brief TFM NS lock options
123 *
124 * \details Options used while acquiring the NS lock
125 */
126struct tfm_ns_lock_options
127{
128 bool use_ns_lock;
129 uint32_t timeout;
130};
131
132/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000133 * \brief tfm_service_request
134 *
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200135 * \details This function is used to request a TFM service in thread mode.
136 * Optionally uses the NS lock and specifies a timeout for obtaining
137 * the NS lock.
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000138 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200139static void tfm_service_request(void(*fn)(void),
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000140 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000141{
142 osStatus_t result;
143
144 char buffer[80];
145
146#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000147 do { \
148 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
149 LOG_MSG(buffer); \
150 } \
151 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000152
153 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
154
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000155 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000156 result = osMutexAcquire(mutex_id,0);
157 if (result == osOK) {
158 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000159 /* Add a delay here just to let the pri_task try to
160 * acquire the NS lock before seq_task enters secure world
161 */
162 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
163 osDelay(100U);
164 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200165 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000166 LOG_MSG_THREAD("NS Lock: releasing...");
167 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000168 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000169
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000170 if (ns_lock_options_p->timeout == osWaitForever) {
171 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
172 } else {
173 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
174 }
175
176 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
177 if (result == osOK) {
178 LOG_MSG_THREAD("NS Lock: acquired");
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200179 fn();
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000180 LOG_MSG_THREAD("NS Lock: releasing...");
181 osMutexRelease(mutex_id);
182 } else if (result == osErrorTimeout) {
183 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
184 } else {
185 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
186 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000187 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000188 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000189 /* Add a delay here to let the seq_task (which always uses the NS lock)
190 * enter secure world before the pri_task (which can try to overcome the
191 * NS lock in test scenario 5)
192 */
193 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
194 osDelay(100U);
195 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200196 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000197 }
198}
199
200/**
201 * \brief Non-blocking test thread
202 *
203 */
204__attribute__((noreturn))
205static void mid_task(void *argument)
206{
207 osThreadId_t thread_id_pri;
208 osThreadState_t thread_pri_state;
209 uint32_t idx;
210
Mate Toth-Pal53136092018-09-19 09:34:01 +0200211#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200212 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200213#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200214
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000215 thread_id_pri = *((osThreadId_t *)argument);
216
217 /* go to sleep */
218 osDelay(100U);
219
220 thread_pri_state = osThreadGetState(thread_id_pri);
221
222 if (thread_pri_state == osThreadBlocked) {
223 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000224 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000225 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000226 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000227 LOG_MSG("Running [mid_task]");
228 }
229
230 /* Do non TFM related, non blocking, operations */
231 for (idx=0; idx<0x3ffffff; idx++) {
232 }
233
234 LOG_MSG("Exiting [mid_task]");
235
236 osThreadExit();
237}
238
239/**
240 * \brief Priority test thread
241 *
242 */
243__attribute__((noreturn))
244static void pri_task(void *argument)
245{
Mate Toth-Pal53136092018-09-19 09:34:01 +0200246#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200247 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200248#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200249
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000250 /* go to sleep */
251 osDelay(100U);
252
253 /* After wake up, try to get hold of the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200254 tfm_service_request(secure_decrement_ns_lock_2,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000255 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000256
257 osThreadExit();
258}
259
260/**
261 * \brief Sequential test thread
262 *
263 */
264__attribute__((noreturn))
265static void seq_task(void *argument)
266{
267 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000268 enum test_type test_type;
269
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000270 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
271 struct tfm_ns_lock_options ns_lock_opt =
272 {.use_ns_lock=true, .timeout=osWaitForever};
273 struct tfm_ns_lock_options ns_lock_opt_pri =
274 {.use_ns_lock=true, .timeout=osWaitForever};
275
Mate Toth-Pal53136092018-09-19 09:34:01 +0200276#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200277 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200278#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200279
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000280 test_type = *((enum test_type *)argument);
281
282 if (test_type == TEST_TYPE_1) {
283 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000284 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000285 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000286 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000287 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000288 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000289 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000290 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000291 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000292 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000293 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000294 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000295 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000296 ns_lock_opt_pri.use_ns_lock = false;
297 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
298 } else if (test_type == TEST_TYPE_6) {
299 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
300 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
301 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000302 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000303 LOG_MSG("Scenario not supported");
304 osThreadExit();
305 }
306
307 /* Try to acquire the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200308 tfm_service_request(secure_decrement_ns_lock_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000309
310 if (test_type == TEST_TYPE_1) {
311 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000312 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000313 osThreadJoin(thread_id);
314 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000315 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000316 osThreadJoin(thread_id);
317 osThreadJoin(thread_id_mid);
318 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000319 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000320 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000321 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000322 osThreadJoin(thread_id);
323 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000324 } else if (test_type == TEST_TYPE_6) {
325 osThreadJoin(thread_id);
326 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000327 }
328
329 osThreadExit();
330}
331
332/**
333 * \brief Execute the interactive tets cases
334 *
335 */
336void execute_ns_interactive_tests(void)
337{
338 uint8_t idx;
339
340 osThreadId_t thread_id;
341
342 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000343 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000344 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000345
346 /* Create the NS lock -- shared among testing scenarios */
347 mutex_id = osMutexNew(&mattr_ns_lock);
348
349 /* Loop in the test list */
350 for (idx=0; idx<sizeof(test_type); idx++) {
351 /* Spawn the main thread */
352 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
353
354 /* Wait for it to finish before moving to the next scenario */
355 osThreadJoin(thread_id);
356 }
357}
358#endif /* CORE_TEST_INTERACTIVE */
359
Ben Davis6d7256b2018-04-18 14:16:53 +0100360#if defined(TEST_FRAMEWORK_NS) || defined(TEST_FRAMEWORK_S)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000361/**
362 * \brief Services test thread
363 *
364 */
365__attribute__((noreturn))
366void test_app(void *argument)
367{
368 UNUSED_VARIABLE(argument);
Ben Davis6d7256b2018-04-18 14:16:53 +0100369
370#ifdef TEST_FRAMEWORK_S
371 /* FIXME: The non-secure audit log test currently relies on the fact that
372 * the audit log secure test is run first. However the Non-secure tests
373 * represent simpler and more common test cases which would make more sense
374 * to be run first. Therefore if this dependency is removed the execution
375 * order of these test classes should be reversed. */
376 tfm_secure_client_run_tests();
377#endif
378#ifdef TEST_FRAMEWORK_NS
379 tfm_non_secure_client_run_tests();
380#endif
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000381 /* End of test */
382 for (;;) {
383 }
384}
Ben Davis6d7256b2018-04-18 14:16:53 +0100385#endif /* TEST_FRAMEWORK_NS OR TEST_FRAMEWORK_S */