blob: 63ec8f3923a92244fb0ccc7db2dec566d3c05373 [file] [log] [blame]
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +00001/*
Mate Toth-Pal5c047152019-02-28 11:07:20 +01002 * 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"
Mate Toth-Pal5c047152019-02-28 11:07:20 +010027#include "tfm_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{
Mate Toth-Pal5c047152019-02-28 11:07:20 +010051 uint32_t testcase_id = CORE_TEST_ID_BLOCK;
52 psa_invec in_vec = {&testcase_id, sizeof(testcase_id)};
53
54 TRY_SFN(tfm_spm_core_test_sfn_veneer, &in_vec, 1, NULL, 0);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000055}
56
57/**
Mate Toth-Pal1379e152018-07-30 17:38:29 +020058 * \brief secure_decrement_ns_lock_2
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000059 *
60 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +020061void secure_decrement_ns_lock_2(void)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000062{
Mate Toth-Pal5c047152019-02-28 11:07:20 +010063 uint32_t testcase_id = CORE_TEST_ID_BLOCK;
64 psa_invec in_vec = {&testcase_id, sizeof(testcase_id)};
65
66 TRY_SFN(tfm_spm_core_test_sfn_veneer, &in_vec, 1, NULL, 0);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000067}
68/**
69 * \brief Test definition for the RTX - TFM integration tests
70 * scenarios
71 */
72enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000073 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
74 access TFM */
75 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
76 gets delayed */
77 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
78 priority task waiting on lower priority task
79 undefinitely if NS lock is configured without priority
80 inheritance */
81 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
82 lock mechanism */
83 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
84 overcome the NS lock but finds TFM core locked by
85 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000086 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
87 timeout to acquire the NS lock. The timeout will
88 expire only if TFM Core is built with the
Miklos Balintace4c3f2018-07-30 12:31:15 +020089 de-prioritization disabled */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000090};
91
92static const osThreadAttr_t tattr_seq = {
93 .name = "seq_task",
94 .stack_size = 1024U,
95 .attr_bits = osThreadJoinable,
96 .tz_module = 1,
97};
98static const osThreadAttr_t tattr_mid = {
99 .name = "mid_task",
100 .stack_size = 512U,
101 .attr_bits = osThreadJoinable,
102 .tz_module = 0,
103 .priority = osPriorityAboveNormal
104};
105static const osThreadAttr_t tattr_pri = {
106 .name = "pri_task",
107 .stack_size = 1024U,
108 .attr_bits = osThreadJoinable,
109 .tz_module = 1,
110 .priority = osPriorityHigh
111};
112
113/**
114 * \brief Mutex id, NS lock
115 */
116static osMutexId_t mutex_id;
117
118/**
119 * \brief Mutex properties, NS lock
120 */
121static const osMutexAttr_t mattr_ns_lock = {
122 .name = "ns_lock",
123 //.attr_bits = osMutexPrioInherit
124};
125
126/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000127 * \brief TFM NS lock options
128 *
129 * \details Options used while acquiring the NS lock
130 */
131struct tfm_ns_lock_options
132{
133 bool use_ns_lock;
134 uint32_t timeout;
135};
136
137/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000138 * \brief tfm_service_request
139 *
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200140 * \details This function is used to request a TFM service in thread mode.
141 * Optionally uses the NS lock and specifies a timeout for obtaining
142 * the NS lock.
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000143 */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200144static void tfm_service_request(void(*fn)(void),
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000145 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000146{
147 osStatus_t result;
148
149 char buffer[80];
150
151#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000152 do { \
153 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
154 LOG_MSG(buffer); \
155 } \
156 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000157
158 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
159
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000160 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000161 result = osMutexAcquire(mutex_id,0);
162 if (result == osOK) {
163 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000164 /* Add a delay here just to let the pri_task try to
165 * acquire the NS lock before seq_task enters secure world
166 */
167 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
168 osDelay(100U);
169 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200170 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000171 LOG_MSG_THREAD("NS Lock: releasing...");
172 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000173 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000174
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000175 if (ns_lock_options_p->timeout == osWaitForever) {
176 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
177 } else {
178 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
179 }
180
181 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
182 if (result == osOK) {
183 LOG_MSG_THREAD("NS Lock: acquired");
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200184 fn();
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000185 LOG_MSG_THREAD("NS Lock: releasing...");
186 osMutexRelease(mutex_id);
187 } else if (result == osErrorTimeout) {
188 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
189 } else {
190 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
191 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000192 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000193 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000194 /* Add a delay here to let the seq_task (which always uses the NS lock)
195 * enter secure world before the pri_task (which can try to overcome the
196 * NS lock in test scenario 5)
197 */
198 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
199 osDelay(100U);
200 }
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200201 fn();
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000202 }
203}
204
205/**
206 * \brief Non-blocking test thread
207 *
208 */
209__attribute__((noreturn))
210static void mid_task(void *argument)
211{
212 osThreadId_t thread_id_pri;
213 osThreadState_t thread_pri_state;
214 uint32_t idx;
215
Mate Toth-Pal53136092018-09-19 09:34:01 +0200216#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200217 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200218#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200219
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000220 thread_id_pri = *((osThreadId_t *)argument);
221
222 /* go to sleep */
223 osDelay(100U);
224
225 thread_pri_state = osThreadGetState(thread_id_pri);
226
227 if (thread_pri_state == osThreadBlocked) {
228 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000229 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000230 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000231 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000232 LOG_MSG("Running [mid_task]");
233 }
234
235 /* Do non TFM related, non blocking, operations */
236 for (idx=0; idx<0x3ffffff; idx++) {
237 }
238
239 LOG_MSG("Exiting [mid_task]");
240
241 osThreadExit();
242}
243
244/**
245 * \brief Priority test thread
246 *
247 */
248__attribute__((noreturn))
249static void pri_task(void *argument)
250{
Mate Toth-Pal53136092018-09-19 09:34:01 +0200251#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200252 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200253#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200254
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000255 /* go to sleep */
256 osDelay(100U);
257
258 /* After wake up, try to get hold of the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200259 tfm_service_request(secure_decrement_ns_lock_2,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000260 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000261
262 osThreadExit();
263}
264
265/**
266 * \brief Sequential test thread
267 *
268 */
269__attribute__((noreturn))
270static void seq_task(void *argument)
271{
272 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000273 enum test_type test_type;
274
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000275 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
276 struct tfm_ns_lock_options ns_lock_opt =
277 {.use_ns_lock=true, .timeout=osWaitForever};
278 struct tfm_ns_lock_options ns_lock_opt_pri =
279 {.use_ns_lock=true, .timeout=osWaitForever};
280
Mate Toth-Pal53136092018-09-19 09:34:01 +0200281#ifdef TFM_NS_CLIENT_IDENTIFICATION
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200282 tfm_nspm_register_client_id();
Mate Toth-Pal53136092018-09-19 09:34:01 +0200283#endif /* TFM_NS_CLIENT_IDENTIFICATION */
Mate Toth-Pal3956a8a2018-08-03 17:18:47 +0200284
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000285 test_type = *((enum test_type *)argument);
286
287 if (test_type == TEST_TYPE_1) {
288 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000289 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000290 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000291 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000292 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000293 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000294 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000295 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000296 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000297 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000298 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000299 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000300 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000301 ns_lock_opt_pri.use_ns_lock = false;
302 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
303 } else if (test_type == TEST_TYPE_6) {
304 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
305 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
306 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000307 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000308 LOG_MSG("Scenario not supported");
309 osThreadExit();
310 }
311
312 /* Try to acquire the NS lock */
Mate Toth-Pal1379e152018-07-30 17:38:29 +0200313 tfm_service_request(secure_decrement_ns_lock_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000314
315 if (test_type == TEST_TYPE_1) {
316 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000317 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000318 osThreadJoin(thread_id);
319 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000320 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000321 osThreadJoin(thread_id);
322 osThreadJoin(thread_id_mid);
323 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000324 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000325 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000326 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000327 osThreadJoin(thread_id);
328 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000329 } else if (test_type == TEST_TYPE_6) {
330 osThreadJoin(thread_id);
331 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000332 }
333
334 osThreadExit();
335}
336
337/**
338 * \brief Execute the interactive tets cases
339 *
340 */
341void execute_ns_interactive_tests(void)
342{
343 uint8_t idx;
344
345 osThreadId_t thread_id;
346
347 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000348 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000349 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000350
351 /* Create the NS lock -- shared among testing scenarios */
352 mutex_id = osMutexNew(&mattr_ns_lock);
353
354 /* Loop in the test list */
355 for (idx=0; idx<sizeof(test_type); idx++) {
356 /* Spawn the main thread */
357 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
358
359 /* Wait for it to finish before moving to the next scenario */
360 osThreadJoin(thread_id);
361 }
362}
363#endif /* CORE_TEST_INTERACTIVE */
364
Ben Davis6d7256b2018-04-18 14:16:53 +0100365#if defined(TEST_FRAMEWORK_NS) || defined(TEST_FRAMEWORK_S)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000366/**
367 * \brief Services test thread
368 *
369 */
370__attribute__((noreturn))
371void test_app(void *argument)
372{
373 UNUSED_VARIABLE(argument);
Ben Davis6d7256b2018-04-18 14:16:53 +0100374
375#ifdef TEST_FRAMEWORK_S
376 /* FIXME: The non-secure audit log test currently relies on the fact that
377 * the audit log secure test is run first. However the Non-secure tests
378 * represent simpler and more common test cases which would make more sense
379 * to be run first. Therefore if this dependency is removed the execution
380 * order of these test classes should be reversed. */
381 tfm_secure_client_run_tests();
382#endif
383#ifdef TEST_FRAMEWORK_NS
384 tfm_non_secure_client_run_tests();
385#endif
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000386 /* End of test */
387 for (;;) {
388 }
389}
Ben Davis6d7256b2018-04-18 14:16:53 +0100390#endif /* TEST_FRAMEWORK_NS OR TEST_FRAMEWORK_S */