blob: 5509af7ac0d8f1aa360b71a8496e5c0853753d35 [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 Angelisa54ed7e2017-11-29 13:37:58 +000087};
88
89static const osThreadAttr_t tattr_seq = {
90 .name = "seq_task",
91 .stack_size = 1024U,
92 .attr_bits = osThreadJoinable,
93 .tz_module = 1,
94};
95static const osThreadAttr_t tattr_mid = {
96 .name = "mid_task",
97 .stack_size = 512U,
98 .attr_bits = osThreadJoinable,
99 .tz_module = 0,
100 .priority = osPriorityAboveNormal
101};
102static const osThreadAttr_t tattr_pri = {
103 .name = "pri_task",
104 .stack_size = 1024U,
105 .attr_bits = osThreadJoinable,
106 .tz_module = 1,
107 .priority = osPriorityHigh
108};
109
110/**
111 * \brief Mutex id, NS lock
112 */
113static osMutexId_t mutex_id;
114
115/**
116 * \brief Mutex properties, NS lock
117 */
118static const osMutexAttr_t mattr_ns_lock = {
119 .name = "ns_lock",
120 //.attr_bits = osMutexPrioInherit
121};
122
123/**
124 * \brief SVC dispatcher
125 */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000126__attribute__((always_inline)) __STATIC_INLINE
127void svc_dispatch(enum tfm_svc_num svc_num)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000128{
129 switch (svc_num) {
130 case SVC_SECURE_DECREMENT_NS_LOCK_1:
131 SVC(SVC_SECURE_DECREMENT_NS_LOCK_1);
132 break;
133 case SVC_SECURE_DECREMENT_NS_LOCK_2:
134 SVC(SVC_SECURE_DECREMENT_NS_LOCK_2);
135 break;
136 default:
137 break;
138 }
139}
140
141/**
142 * \brief tfm_service_request
143 *
144 * \details This function is used to request a TFM
145 * service in handler mode, using SVC.
146 * Optionally uses the NS lock
147 */
148static void tfm_service_request(enum tfm_svc_num svc_num, bool use_ns_lock)
149{
150 osStatus_t result;
151
152 char buffer[80];
153
154#define LOG_MSG_THREAD(MSG_THREAD) \
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000155 do { \
156 sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
157 LOG_MSG(buffer); \
158 } \
159 while(0)
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000160
161 LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
162
163 if (use_ns_lock) {
164 result = osMutexAcquire(mutex_id,0);
165 if (result == osOK) {
166 LOG_MSG_THREAD("NS Lock: acquired");
167 svc_dispatch(svc_num);
168 LOG_MSG_THREAD("NS Lock: releasing...");
169 osMutexRelease(mutex_id);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000170 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000171 LOG_MSG_THREAD("Failed to acquire the NS lock");
172
173 osMutexAcquire(mutex_id,osWaitForever);
174 LOG_MSG_THREAD("NS Lock: acquired");
175 svc_dispatch(svc_num);
176 LOG_MSG_THREAD("NS Lock: releasing...");
177 osMutexRelease(mutex_id);
178 }
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000179 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000180 svc_dispatch(svc_num);
181 }
182}
183
184/**
185 * \brief Non-blocking test thread
186 *
187 */
188__attribute__((noreturn))
189static void mid_task(void *argument)
190{
191 osThreadId_t thread_id_pri;
192 osThreadState_t thread_pri_state;
193 uint32_t idx;
194
195 thread_id_pri = *((osThreadId_t *)argument);
196
197 /* go to sleep */
198 osDelay(100U);
199
200 thread_pri_state = osThreadGetState(thread_id_pri);
201
202 if (thread_pri_state == osThreadBlocked) {
203 LOG_MSG("Running [mid_task] while [pri_task] is blocked");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000204 } else if (thread_pri_state == osThreadTerminated) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000205 LOG_MSG("Running [mid_task] while [pri_task] is terminated");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000206 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000207 LOG_MSG("Running [mid_task]");
208 }
209
210 /* Do non TFM related, non blocking, operations */
211 for (idx=0; idx<0x3ffffff; idx++) {
212 }
213
214 LOG_MSG("Exiting [mid_task]");
215
216 osThreadExit();
217}
218
219/**
220 * \brief Priority test thread
221 *
222 */
223__attribute__((noreturn))
224static void pri_task(void *argument)
225{
226 /* go to sleep */
227 osDelay(100U);
228
229 /* After wake up, try to get hold of the NS lock */
230 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2, *((bool *)argument));
231
232 osThreadExit();
233}
234
235/**
236 * \brief Sequential test thread
237 *
238 */
239__attribute__((noreturn))
240static void seq_task(void *argument)
241{
242 osThreadId_t thread_id, thread_id_mid;
243 bool use_ns_lock, use_ns_lock_pri;
244 enum test_type test_type;
245
246 test_type = *((enum test_type *)argument);
247
248 if (test_type == TEST_TYPE_1) {
249 LOG_MSG("Scenario 1 - Sequential");
250 use_ns_lock = true;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000251 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000252 LOG_MSG("Scenario 2 - Priority");
253 use_ns_lock = true;
254 use_ns_lock_pri = true;
255 thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000256 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000257 LOG_MSG("Scenario 3 - Priority inversion");
258 use_ns_lock = true;
259 use_ns_lock_pri = true;
260 thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
261 thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000262 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000263 LOG_MSG("Scenario 4 - non-NS lock");
264 use_ns_lock = false;
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000265 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000266 LOG_MSG("Scenario 5 - non-NS lock, core locked");
267 use_ns_lock = true;
268 use_ns_lock_pri = false;
269 thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000270 } else {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000271 LOG_MSG("Scenario not supported");
272 osThreadExit();
273 }
274
275 /* Try to acquire the NS lock */
276 tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, use_ns_lock);
277
278 if (test_type == TEST_TYPE_1) {
279 LOG_MSG("Scenario 1 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000280 } else if (test_type == TEST_TYPE_2) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000281 osThreadJoin(thread_id);
282 LOG_MSG("Scenario 2 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000283 } else if (test_type == TEST_TYPE_3) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000284 osThreadJoin(thread_id);
285 osThreadJoin(thread_id_mid);
286 LOG_MSG("Scenario 3 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000287 } else if (test_type == TEST_TYPE_4) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000288 LOG_MSG("Scenario 4 - test finished\n");
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000289 } else if (test_type == TEST_TYPE_5) {
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000290 osThreadJoin(thread_id);
291 LOG_MSG("Scenario 5 - test finished\n");
292 }
293
294 osThreadExit();
295}
296
297/**
298 * \brief Execute the interactive tets cases
299 *
300 */
301void execute_ns_interactive_tests(void)
302{
303 uint8_t idx;
304
305 osThreadId_t thread_id;
306
307 /* Test type list */
Antonio de Angelis04bf6592018-02-26 11:57:36 +0000308 enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
309 TEST_TYPE_4, TEST_TYPE_5};
Antonio de Angelisa54ed7e2017-11-29 13:37:58 +0000310
311 /* Create the NS lock -- shared among testing scenarios */
312 mutex_id = osMutexNew(&mattr_ns_lock);
313
314 /* Loop in the test list */
315 for (idx=0; idx<sizeof(test_type); idx++) {
316 /* Spawn the main thread */
317 thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
318
319 /* Wait for it to finish before moving to the next scenario */
320 osThreadJoin(thread_id);
321 }
322}
323#endif /* CORE_TEST_INTERACTIVE */
324
325#ifdef TEST_FRAMEWORK_NS
326/**
327 * \brief Services test thread
328 *
329 */
330__attribute__((noreturn))
331void test_app(void *argument)
332{
333 UNUSED_VARIABLE(argument);
334 start_integ_test();
335 /* End of test */
336 for (;;) {
337 }
338}
339#endif /* TEST_FRAMEWORK_NS */