bc307a884f11152887e7e833fa489f9273c5fca4
[platform/core/security/tef-optee_os.git] / core / arch / arm / pta / interrupt_tests.c
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <keep.h>
28 #include <kernel/interrupt.h>
29 #include <kernel/misc.h>
30 #include <kernel/pseudo_ta.h>
31 #include <kernel/tee_time.h>
32 #include <kernel/thread.h>
33 #include <platform_config.h>
34 #include <string.h>
35 #include <tee/tee_cryp_provider.h>
36 #include <trace.h>
37
38 #define TA_NAME         "interrupt_tests.ta"
39
40 #define INTERRUPT_TESTS_UUID \
41                 { 0x48d58475, 0x3d5e, 0x4202, \
42                 { 0xa7, 0x75, 0x97, 0x85, 0xd2, 0x0f, 0x78, 0xae } }
43
44 #define CMD_INTERRUPT_TESTS     0
45
46 #define SGI_NUM         16
47 #define PPI_NUM         32
48
49 #ifndef TEST_SGI_ID
50 #define TEST_SGI_ID     11
51 #endif
52 #ifndef TEST_PPI_ID
53 #define TEST_PPI_ID     29
54 #endif
55 #ifndef TEST_SPI_ID
56 #define TEST_SPI_ID     61
57 #endif
58 #ifndef TEST_TIMES
59 #define TEST_TIMES      3
60 #endif
61
62 /*
63  * Trusted Application Entry Points
64  */
65
66 static size_t test_sgi_value[CFG_TEE_CORE_NB_CORE];
67 static size_t test_spi_value[CFG_TEE_CORE_NB_CORE];
68 static size_t test_ppi_value[CFG_TEE_CORE_NB_CORE];
69 static size_t expect_sgi_value[CFG_TEE_CORE_NB_CORE];
70 static size_t expect_spi_value[CFG_TEE_CORE_NB_CORE];
71 static size_t expect_ppi_value[CFG_TEE_CORE_NB_CORE];
72
73 static enum itr_return __maybe_unused ihandler_ok(struct itr_handler *handler)
74 {
75         size_t core_num = get_core_pos();
76
77         assert(core_num < CFG_TEE_CORE_NB_CORE);
78
79         if (handler->it < SGI_NUM)
80                 test_sgi_value[core_num]++;
81         else if (handler->it < PPI_NUM)
82                 test_ppi_value[core_num]++;
83         else
84                 test_spi_value[core_num]++;
85
86         return ITRR_HANDLED;
87 }
88 KEEP_PAGER(ihandler_ok);
89
90 struct itr_handler sgi_handler = {
91         .it = TEST_SGI_ID,
92         .handler = ihandler_ok,
93 };
94
95 struct itr_handler spi_handler = {
96         .it = TEST_SPI_ID,
97         .handler = ihandler_ok,
98 };
99
100 struct itr_handler ppi_handler = {
101         .it = TEST_PPI_ID,
102         .handler = ihandler_ok,
103 };
104
105 static TEE_Result test_sgi(void)
106 {
107         TEE_Result res;
108         uint8_t i;
109         uint8_t j;
110         uint8_t num;
111         uint8_t cpu_mask;
112
113         itr_add(&sgi_handler);
114         itr_enable(TEST_SGI_ID);
115
116         for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++)
117                 expect_sgi_value[i]++;
118         itr_raise_sgi(TEST_SGI_ID,
119                      (uint8_t)(SHIFT_U32(1, CFG_TEE_CORE_NB_CORE) - 1));
120         tee_time_wait(200);
121         if (memcmp(test_sgi_value, expect_sgi_value, sizeof(test_sgi_value)))
122                 return TEE_ERROR_GENERIC;
123
124         for (i = 0; i < TEST_TIMES; i++) {
125                 res = crypto_ops.prng.read(&num, 1);
126                 if (res != TEE_SUCCESS)
127                         return TEE_ERROR_GENERIC;
128                 num = num % CFG_TEE_CORE_NB_CORE;
129                 cpu_mask = 0x0;
130                 for (j = 0; j < num; j++) {
131                         expect_sgi_value[j]++;
132                         cpu_mask |= (0x1 << j);
133                 }
134                 itr_raise_sgi(TEST_SGI_ID, cpu_mask);
135                 tee_time_wait(200);
136                 if (memcmp(test_sgi_value, expect_sgi_value,
137                     sizeof(test_sgi_value)))
138                         return TEE_ERROR_GENERIC;
139         }
140
141         return TEE_SUCCESS;
142 }
143
144 static TEE_Result test_spi(void)
145 {
146         TEE_Result res;
147         uint8_t i;
148         uint8_t num;
149
150         itr_add(&spi_handler);
151         itr_enable(TEST_SPI_ID);
152
153         for (i = 0; i < TEST_TIMES; i++) {
154                 res = crypto_ops.prng.read(&num, 1);
155                 if (res != TEE_SUCCESS)
156                         return TEE_ERROR_GENERIC;
157                 num = num % CFG_TEE_CORE_NB_CORE;
158                 expect_spi_value[num]++;
159                 itr_set_affinity(TEST_SPI_ID, 0x1 << num);
160                 itr_raise_pi(TEST_SPI_ID);
161                 tee_time_wait(200);
162                 if (memcmp(test_spi_value, expect_spi_value,
163                     sizeof(test_spi_value)))
164                         return TEE_ERROR_GENERIC;
165         }
166
167         return TEE_SUCCESS;
168 }
169
170 static TEE_Result test_ppi(void)
171 {
172         uint32_t exceptions;
173
174         itr_add(&ppi_handler);
175         itr_enable(TEST_PPI_ID);
176
177         exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
178         expect_ppi_value[get_core_pos()]++;
179         itr_raise_pi(TEST_PPI_ID);
180         thread_unmask_exceptions(exceptions);
181         tee_time_wait(200);
182         if (memcmp(test_ppi_value, expect_ppi_value, sizeof(test_ppi_value)))
183                 return TEE_ERROR_GENERIC;
184
185         return TEE_SUCCESS;
186 }
187
188 static TEE_Result interrupt_tests(uint32_t nParamTypes __unused,
189                         TEE_Param pParams[TEE_NUM_PARAMS]__unused)
190 {
191         TEE_Result res;
192
193         assert(crypto_ops.prng.read);
194
195         res = test_sgi();
196         if (res != TEE_SUCCESS)
197                 return res;
198
199         res = test_spi();
200         if (res != TEE_SUCCESS)
201                 return res;
202
203         res = test_ppi();
204         if (res != TEE_SUCCESS)
205                 return res;
206
207         return TEE_SUCCESS;
208 }
209
210 static TEE_Result invoke_command(void *psess __unused,
211                                  uint32_t cmd, uint32_t ptypes,
212                                  TEE_Param params[4])
213 {
214         TEE_Result res;
215         uint8_t i;
216
217         switch (cmd) {
218         case CMD_INTERRUPT_TESTS:
219                 res = interrupt_tests(ptypes, params);
220                 DMSG("test value: sgi spi ppi");
221                 for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++)
222                         DMSG("------------[%zu] [%zu] [%zu]",
223                             test_sgi_value[i], test_spi_value[i],
224                             test_ppi_value[i]);
225                 DMSG("expc value: sgi spi ppi");
226                 for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++)
227                         DMSG("------------[%zu] [%zu] [%zu]",
228                             expect_sgi_value[i], expect_spi_value[i],
229                             expect_ppi_value[i]);
230                 return res;
231         default:
232                 break;
233         }
234         return TEE_ERROR_BAD_PARAMETERS;
235 }
236
237 pseudo_ta_register(.uuid = INTERRUPT_TESTS_UUID, .name = TA_NAME,
238                    .flags = PTA_DEFAULT_FLAGS,
239                    .invoke_command_entry_point = invoke_command);