blob: 4ddf082bb46cbdef1514bf231ac30588035efbb0 [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
20#ifdef CORE_TEST_INTERACTIVE
21#include "test/test_services/tfm_core_test/core_test_defs.h"
22#include "test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h"
23#include "tfm_ns_svc.h"
24
25#define TRY_SFN(fn, ...) \
26 do { \
27 enum tfm_status_e res = (enum tfm_status_e) fn(__VA_ARGS__); \
28 switch(res) { \
29 case TFM_SUCCESS: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000030 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") successful!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000031 break; \
32 case TFM_SERVICE_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000033 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") pended!"); \
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000034 break; \
35 case TFM_ERROR_SERVICE_ALREADY_PENDED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000036 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
37 "already pended!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000038 break; \
39 case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000040 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
41 "S domain locked!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000042 break; \
43 case TFM_ERROR_NS_THREAD_MODE_CALL: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000044 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
45 "NS thread mode!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000046 break; \
47 default: \
Antonio de Angelis04bf6592018-02-26 11:57:36 +000048 LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
49 "generic!");\
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000050 } \
51 } while(0)
52/**
53 * \brief SVC_SECURE_DECREMENT_NS_LOCK_1
54 *
55 */
56void svc_secure_decrement_ns_lock_1(void)
57{
58 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
59}
60
61/**
62 * \brief SVC_SECURE_DECREMENT_NS_LOCK_2
63 *
64 */
65void svc_secure_decrement_ns_lock_2(void)
66{
67 TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
68}
69/**
70 * \brief Test definition for the RTX - TFM integration tests
71 * scenarios
72 */
73enum test_type {
Antonio de Angelis04bf6592018-02-26 11:57:36 +000074 TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to
75 access TFM */
76 TEST_TYPE_2, /*!< Priority test: high priority tries to preempt TFM,
77 gets delayed */
78 TEST_TYPE_3, /*!< Priority inversion: classical scenario with high
79 priority task waiting on lower priority task
80 undefinitely if NS lock is configured without priority
81 inheritance */
82 TEST_TYPE_4, /*!< non-NS lock: like sequential, but doesn't use any NS
83 lock mechanism */
84 TEST_TYPE_5, /*!< non-NS lock, core locked: high priority tries to
85 overcome the NS lock but finds TFM core locked by
86 lower priority task and fails */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +000087 TEST_TYPE_6 /*!< Like TEST_TYPE_2, but the high priority task has now a
88 timeout to acquire the NS lock. The timeout will
89 expire only if TFM Core is built with the
90 de-prioritization disabled (i.e. TFM_API_SVCCLEAR
91 defined) */
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +000092};
93
94static const osThreadAttr_t tattr_seq = {
95 .name = "seq_task",
96 .stack_size = 1024U,
97 .attr_bits = osThreadJoinable,
98 .tz_module = 1,
99};
100static const osThreadAttr_t tattr_mid = {
101 .name = "mid_task",
102 .stack_size = 512U,
103 .attr_bits = osThreadJoinable,
104 .tz_module = 0,
105 .priority = osPriorityAboveNormal
106};
107static const osThreadAttr_t tattr_pri = {
108 .name = "pri_task",
109 .stack_size = 1024U,
110 .attr_bits = osThreadJoinable,
111 .tz_module = 1,
112 .priority = osPriorityHigh
113};
114
115/**
116 * \brief Mutex id, NS lock
117 */
118static osMutexId_t mutex_id;
119
120/**
121 * \brief Mutex properties, NS lock
122 */
123static const osMutexAttr_t mattr_ns_lock = {
124 .name = "ns_lock",
125 //.attr_bits = osMutexPrioInherit
126};
127
128/**
129 * \brief SVC dispatcher
130 */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000131__attribute__((always_inline)) __STATIC_INLINE
132void svc_dispatch(enum tfm_svc_num svc_num)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000133{
134 switch (svc_num) {
135 case SVC_SECURE_DECREMENT_NS_LOCK_1:
136 SVC(SVC_SECURE_DECREMENT_NS_LOCK_1);
137 break;
138 case SVC_SECURE_DECREMENT_NS_LOCK_2:
139 SVC(SVC_SECURE_DECREMENT_NS_LOCK_2);
140 break;
141 default:
142 break;
143 }
144}
145
146/**
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000147 * \brief TFM NS lock options
148 *
149 * \details Options used while acquiring the NS lock
150 */
151struct tfm_ns_lock_options
152{
153 bool use_ns_lock;
154 uint32_t timeout;
155};
156
157/**
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000158 * \brief tfm_service_request
159 *
160 * \details This function is used to request a TFM
161 * service in handler mode, using SVC.
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000162 * Optionally uses the NS lock and specifies
163 * a timeout for obtaining the NS lock
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000164 */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000165static void tfm_service_request(enum tfm_svc_num svc_num,
166 struct tfm_ns_lock_options *ns_lock_options_p)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000167{
168 osStatus_t result;
169
170 char buffer[80];
171
172#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000173 do { \
174 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
175 LOG_MSG(buffer); \
176 } \
177 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000178
179 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
180
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000181 if (ns_lock_options_p->use_ns_lock) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000182 result = osMutexAcquire(mutex_id,0);
183 if (result == osOK) {
184 LOG_MSG_THREAD("NS Lock: acquired");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000185 /* Add a delay here just to let the pri_task try to
186 * acquire the NS lock before seq_task enters secure world
187 */
188 if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
189 osDelay(100U);
190 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000191 svc_dispatch(svc_num);
192 LOG_MSG_THREAD("NS Lock: releasing...");
193 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000194 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000195
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000196 if (ns_lock_options_p->timeout == osWaitForever) {
197 LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
198 } else {
199 LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
200 }
201
202 result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
203 if (result == osOK) {
204 LOG_MSG_THREAD("NS Lock: acquired");
205 svc_dispatch(svc_num);
206 LOG_MSG_THREAD("NS Lock: releasing...");
207 osMutexRelease(mutex_id);
208 } else if (result == osErrorTimeout) {
209 LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
210 } else {
211 LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
212 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000213 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000214 } else {
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000215 /* Add a delay here to let the seq_task (which always uses the NS lock)
216 * enter secure world before the pri_task (which can try to overcome the
217 * NS lock in test scenario 5)
218 */
219 if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
220 osDelay(100U);
221 }
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000222 svc_dispatch(svc_num);
223 }
224}
225
226/**
227 * \brief Non-blocking test thread
228 *
229 */
230__attribute__((noreturn))
231static void mid_task(void *argument)
232{
233 osThreadId_t thread_id_pri;
234 osThreadState_t thread_pri_state;
235 uint32_t idx;
236
237 thread_id_pri = *((osThreadId_t *)argument);
238
239 /* go to sleep */
240 osDelay(100U);
241
242 thread_pri_state = osThreadGetState(thread_id_pri);
243
244 if (thread_pri_state == osThreadBlocked) {
245 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000246 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000247 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000248 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000249 LOG_MSG("Running [mid_task]");
250 }
251
252 /* Do non TFM related, non blocking, operations */
253 for (idx=0; idx<0x3ffffff; idx++) {
254 }
255
256 LOG_MSG("Exiting [mid_task]");
257
258 osThreadExit();
259}
260
261/**
262 * \brief Priority test thread
263 *
264 */
265__attribute__((noreturn))
266static void pri_task(void *argument)
267{
268 /* go to sleep */
269 osDelay(100U);
270
271 /* After wake up, try to get hold of the NS lock */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000272 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2,
273 (struct tfm_ns_lock_options *)argument);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000274
275 osThreadExit();
276}
277
278/**
279 * \brief Sequential test thread
280 *
281 */
282__attribute__((noreturn))
283static void seq_task(void *argument)
284{
285 osThreadId_t thread_id, thread_id_mid;
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000286 enum test_type test_type;
287
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000288 /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
289 struct tfm_ns_lock_options ns_lock_opt =
290 {.use_ns_lock=true, .timeout=osWaitForever};
291 struct tfm_ns_lock_options ns_lock_opt_pri =
292 {.use_ns_lock=true, .timeout=osWaitForever};
293
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000294 test_type = *((enum test_type *)argument);
295
296 if (test_type == TEST_TYPE_1) {
297 LOG_MSG("Scenario 1 - Sequential");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000298 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000299 LOG_MSG("Scenario 2 - Priority");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000300 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000301 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000302 LOG_MSG("Scenario 3 - Priority inversion");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000303 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000304 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000305 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000306 LOG_MSG("Scenario 4 - non-NS lock");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000307 ns_lock_opt.use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000308 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000309 LOG_MSG("Scenario 5 - non-NS lock, core locked");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000310 ns_lock_opt_pri.use_ns_lock = false;
311 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
312 } else if (test_type == TEST_TYPE_6) {
313 LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
314 ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
315 thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000316 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000317 LOG_MSG("Scenario not supported");
318 osThreadExit();
319 }
320
321 /* Try to acquire the NS lock */
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000322 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, &ns_lock_opt);
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000323
324 if (test_type == TEST_TYPE_1) {
325 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000326 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000327 osThreadJoin(thread_id);
328 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000329 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000330 osThreadJoin(thread_id);
331 osThreadJoin(thread_id_mid);
332 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000333 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000334 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000335 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000336 osThreadJoin(thread_id);
337 LOG_MSG("Scenario 5 - test finished\n");
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000338 } else if (test_type == TEST_TYPE_6) {
339 osThreadJoin(thread_id);
340 LOG_MSG("Scenario 6 - test finished\n");
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000341 }
342
343 osThreadExit();
344}
345
346/**
347 * \brief Execute the interactive tets cases
348 *
349 */
350void execute_ns_interactive_tests(void)
351{
352 uint8_t idx;
353
354 osThreadId_t thread_id;
355
356 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000357 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
Antonio de Angelis1ea2a132017-12-06 14:36:05 +0000358 TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000359
360 /* Create the NS lock -- shared among testing scenarios */
361 mutex_id = osMutexNew(&mattr_ns_lock);
362
363 /* Loop in the test list */
364 for (idx=0; idx<sizeof(test_type); idx++) {
365 /* Spawn the main thread */
366 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
367
368 /* Wait for it to finish before moving to the next scenario */
369 osThreadJoin(thread_id);
370 }
371}
372#endif /* CORE_TEST_INTERACTIVE */
373
374#ifdef TEST_FRAMEWORK_NS
375/**
376 * \brief Services test thread
377 *
378 */
379__attribute__((noreturn))
380void test_app(void *argument)
381{
382 UNUSED_VARIABLE(argument);
383 start_integ_test();
384 /* End of test */
385 for (;;) {
386 }
387}
388#endif /* TEST_FRAMEWORK_NS */