blob: 09e16381ac351eb476617a1b89ef0eb4cbbc1286 [file] [log] [blame]
Per Åstrand79929ff2021-01-26 14:42:43 +01001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/****************************************************************************
20 * Includes
21 ****************************************************************************/
22
23// Ethos-U
24#include "ethosu_driver.h"
25
26// Trustzone defines and MPC driver
Per Åstrand79929ff2021-01-26 14:42:43 +010027#include "../common/secure_entries.hpp"
Anton Moberg908a07c2021-04-08 09:50:57 +020028#include "mpc_sie_drv.h"
29#include "trustzone.h"
Per Åstrand79929ff2021-01-26 14:42:43 +010030
31#include "inference_process.hpp"
32
33// System includes
34#include <arm_cmse.h>
35#include <inttypes.h>
36#include <stdio.h>
37
38using namespace std;
39
40funcptr_ns nonsecure_result_checker = 0;
41
42/****************************************************************************
43 * InferenceJob
44 ****************************************************************************/
45
46#define TENSOR_ARENA_SIZE 0xa0000
Jonny Svärdf521be92021-03-01 14:35:49 +010047__attribute__((section(".bss.tensor_arena"), aligned(16))) uint8_t TFLuTensorArena[TENSOR_ARENA_SIZE];
Per Åstrand79929ff2021-01-26 14:42:43 +010048
49InferenceProcess::InferenceProcess inferenceProcess(TFLuTensorArena, TENSOR_ARENA_SIZE);
50
51/****************************************************************************
52 * Functions
53 ****************************************************************************/
54
55namespace {
56
Per Åstrand79929ff2021-01-26 14:42:43 +010057#include "input.h"
Anton Moberg908a07c2021-04-08 09:50:57 +020058#include "model.h"
Per Åstrand79929ff2021-01-26 14:42:43 +010059#include "output.h"
60
61} // namespace
62
63#define N_MEM_RANGES (2)
64static int setup_sram0_mpc(const uint32_t baseaddr_s, /* Secure base address */
65 const uint32_t len_s, /* Length (in bytes) of secure region */
66 const uint32_t baseaddr_ns, /* Non-secure base address */
67 const uint32_t len_ns) /* Length (in bytes) of non-secure region */
68{
69 const char *mem_name = "SRAM0";
70
71 /* Secure range */
72 const struct mpc_sie_memory_range_t mpc_range_s = {.base = SRAM0_BASE_S,
73 .limit = SRAM0_BASE_S + SRAM0_SIZE - 1,
74 .range_offset = 0,
75 .attr = MPC_SIE_SEC_ATTR_SECURE};
76
77 /* Non secure range */
78 const struct mpc_sie_memory_range_t mpc_range_ns = {.base = SRAM0_BASE_NS,
79 .limit = SRAM0_BASE_NS + SRAM0_SIZE - 1,
80 .range_offset = 0,
81 .attr = MPC_SIE_SEC_ATTR_NONSECURE};
82
83 /* Consolidated ranges */
84 const struct mpc_sie_memory_range_t *mpc_range_list[N_MEM_RANGES] = {&mpc_range_s, &mpc_range_ns};
85
86 /* MPC device configuration controller */
87 const struct mpc_sie_dev_cfg_t mpc_dev_cfg = {.base = SRAM0_MPC};
88
89 /* MPC device data */
90 struct mpc_sie_dev_data_t mpc_dev_data = {0};
91
92 /* MPC device itself */
93 struct mpc_sie_dev_t mpc_dev = {&mpc_dev_cfg, &mpc_dev_data};
94
95 enum mpc_sie_error_t ret = MPC_SIE_ERR_NONE;
96
97 printf("Configuring MPC for %s\n", mem_name);
98
99 /* Initialise this MPC device */
100 ret = mpc_sie_init(&mpc_dev, mpc_range_list, N_MEM_RANGES);
101 if (MPC_SIE_ERR_NONE != ret) {
102 printf("Error initialising MPC for %s\n", mem_name);
103 return 1;
104 }
105
106 /* Configure the non secure region */
107 ret = mpc_sie_config_region(&mpc_dev, baseaddr_ns, baseaddr_ns + len_ns - 1, MPC_SIE_SEC_ATTR_NONSECURE);
108 if (MPC_SIE_ERR_NONE != ret) {
109 printf("Error configuring non-secure region for %s (%d)\n", mem_name, ret);
110 return 1;
111 }
112
113 /* Configure the secure region */
114 ret = mpc_sie_config_region(&mpc_dev, baseaddr_s, baseaddr_s + len_s - 1, MPC_SIE_SEC_ATTR_SECURE);
115 if (MPC_SIE_ERR_NONE != ret) {
116 printf("Error configuring secure region for %s\n", mem_name);
117 return 1;
118 }
119
120 /* Lock down the configuration */
121 ret = mpc_sie_lock_down(&mpc_dev);
122 if (MPC_SIE_ERR_NONE != ret) {
123 printf("Error locking down MPC for %s\n", mem_name);
124 return 1;
125 }
126
127 return 0;
128}
129
130#define N_MEM_RANGES (2)
131static int setup_bram_mpc(const uint32_t baseaddr_s, /* Secure base address */
132 const uint32_t len_s, /* Length (in bytes) of secure region */
133 const uint32_t baseaddr_ns, /* Non-secure base address */
134 const uint32_t len_ns) /* Length (in bytes) of non-secure region */
135{
136 const char *mem_name = "BRAM";
137
138 /* Secure range */
Anton Moberg908a07c2021-04-08 09:50:57 +0200139 const struct mpc_sie_memory_range_t mpc_range_s = {.base = BRAM_BASE_S,
140 .limit = BRAM_BASE_S + BRAM_TOTAL_SIZE - 1,
141 .range_offset = 0,
142 .attr = MPC_SIE_SEC_ATTR_SECURE};
Per Åstrand79929ff2021-01-26 14:42:43 +0100143
144 /* Non secure range */
Anton Moberg908a07c2021-04-08 09:50:57 +0200145 const struct mpc_sie_memory_range_t mpc_range_ns = {.base = BRAM_BASE_NS,
146 .limit = BRAM_BASE_NS + BRAM_TOTAL_SIZE - 1,
147 .range_offset = 0,
148 .attr = MPC_SIE_SEC_ATTR_NONSECURE};
Per Åstrand79929ff2021-01-26 14:42:43 +0100149
150 /* Consolidated ranges */
151 const struct mpc_sie_memory_range_t *mpc_range_list[N_MEM_RANGES] = {&mpc_range_s, &mpc_range_ns};
152
153 /* MPC device configuration controller */
154 const struct mpc_sie_dev_cfg_t mpc_dev_cfg = {.base = BRAM_MPC};
155
156 /* MPC device data */
157 struct mpc_sie_dev_data_t mpc_dev_data = {0};
158
159 /* MPC device itself */
160 struct mpc_sie_dev_t mpc_dev = {&mpc_dev_cfg, &mpc_dev_data};
161
162 enum mpc_sie_error_t ret = MPC_SIE_ERR_NONE;
163
164 printf("Configuring MPC for %s\n", mem_name);
165
166 /* Initialise this MPC device */
167 ret = mpc_sie_init(&mpc_dev, mpc_range_list, N_MEM_RANGES);
168 if (MPC_SIE_ERR_NONE != ret) {
169 printf("Error initialising MPC for %s\n", mem_name);
170 return 1;
171 }
172
173 /* Configure the non secure region */
174 ret = mpc_sie_config_region(&mpc_dev, baseaddr_ns, baseaddr_ns + len_ns - 1, MPC_SIE_SEC_ATTR_NONSECURE);
175 if (MPC_SIE_ERR_NONE != ret) {
176 printf("Error configuring non-secure region for %s (%d)\n", mem_name, ret);
177 return 1;
178 }
179
180 /* Configure the secure region */
181 ret = mpc_sie_config_region(&mpc_dev, baseaddr_s, baseaddr_s + len_s - 1, MPC_SIE_SEC_ATTR_SECURE);
182 if (MPC_SIE_ERR_NONE != ret) {
183 printf("Error configuring secure region for %s (%d)\n", mem_name, ret);
184 return 1;
185 }
186
187 /* Lock down the configuration */
188 ret = mpc_sie_lock_down(&mpc_dev);
189 if (MPC_SIE_ERR_NONE != ret) {
190 printf("Error locking down MPC for %s (%d)\n", mem_name, ret);
191 return 1;
192 }
193
194 return 0;
195}
196
197/* Depending on the Cortex-M configuration the LUT for the xTGU has
198 * different size, set a maximum value to target all cases
199 */
200#define MAX_BLK_NBR (32)
201void setup_xtgu_ns(uint32_t xtgu_base, uint32_t xtcm_start, uint32_t xtcm_size) {
202 struct xtgu {
203 uint32_t ctrl;
204 uint32_t cfg;
205 uint32_t reserved[2];
206 uint32_t lut[];
207 } *xtgu = (struct xtgu *)xtgu_base;
208 uint32_t lut_bit_mask[MAX_BLK_NBR] = {0};
209
210 /* Mask of the base offset of the I-/DTCM memory */
211 xtcm_start &= 0x00ffffff;
212
213 /* Read out xTGU configuration */
Anton Moberg908a07c2021-04-08 09:50:57 +0200214 uint32_t BLKSZ = 1 << (((xtgu->cfg) & 0xf) + 5);
Per Åstrand79929ff2021-01-26 14:42:43 +0100215
216 if (xtcm_start % BLKSZ != 0)
217 printf("XTCM: start address %08x not on block size boundary\n", xtcm_start);
218
219 if ((xtcm_start + xtcm_size) % BLKSZ != 0)
220 printf("XTCM: limit address %08x not on block size boundary\n", xtcm_start + xtcm_size);
221
222 printf("setting up xTGU LUT for mem@%08x(%08x)\n", xtcm_start, xtcm_size);
223
224 uint32_t xtcm_end = xtcm_start + xtcm_size - 1;
225 uint32_t xtcm_address = xtcm_start;
226 uint32_t block_idx_start = (xtcm_address / BLKSZ) / 32;
227 uint32_t block_idx_end;
228
229 while (xtcm_address < xtcm_end) {
230 uint32_t block_nbr = xtcm_address / BLKSZ;
231 uint32_t block_idx = block_nbr / 32;
232 uint32_t block_bit = 1 << (block_nbr % 32);
233
234 if (block_idx >= MAX_BLK_NBR) {
235 printf("lut bit mask too small, aborting!\n");
236 exit(1);
237 }
238 lut_bit_mask[block_idx] |= block_bit;
239
240 xtcm_address += BLKSZ;
241 if (block_idx != block_idx_end)
242 block_idx_end = block_idx;
243 }
244
245 /* Commit the LUT to the xTGU */
246 for (uint32_t i = block_idx_start; i <= block_idx_end; i++) {
247 xtgu->lut[i] = lut_bit_mask[i];
248 }
249}
250
251int setup_secure_attributes(void) {
252 int res;
253 /* Setup ITGU and DTGU to give non-secure state access to ITCM and DTCM memory. */
254 /* NS Code */
255 setup_xtgu_ns(ITCM_ITGU, TZ_NS_ITCM_START, TZ_NS_ITCM_SIZE);
256
257 /* NS stack location in DTCM */
258 setup_xtgu_ns(DTCM_DTGU, TZ_NS_DTCM_START, TZ_NS_DTCM_SIZE);
259
260 res = setup_bram_mpc(TZ_S_BRAM_START, TZ_S_BRAM_SIZE, TZ_NS_BRAM_START, TZ_NS_BRAM_SIZE);
261 printf("BRAM MPC %s\n", res ? "Failed" : "OK");
262
263 /* The SRAM has an MPC for each SRAM bank. Configure the first one for non-secure accesses here. */
264 res = setup_sram0_mpc(TZ_S_SRAM_START, TZ_S_SRAM_SIZE, TZ_NS_SRAM_START, TZ_NS_SRAM_SIZE);
265 printf("SRAM MPC %s\n", res ? "Failed" : "OK");
266
267 /*
268 * The IDAU is default not non-secure callable. In order for the code ram and data ram to be
269 * non-secure callable the NSCCFG (at 0x50080014) has to be configured.
270 * The register description can be found here:
271 * https://developer.arm.com/documentation/101773/0000
272 * bit 0 : Sets NSC for 0x10000000-0x1fffffff
273 * bit 1 : Sets NSC for 0x30000000-0x3fffffff
274 */
275 uint32_t *NSCCFG = (uint32_t *)(0x50080014);
276 *NSCCFG = 0x1;
277 printf("NSCCFG set NSC for CODE SRAM 0x10000000-0x1fffffff\n");
278
279 return 0;
280}
281
282void boot_non_secure() {
283 /* Boot the non-secure world */
284 typedef void (*ns_func)(void) __attribute__((cmse_nonsecure_call));
285 ns_func NS_ResetHandler;
286
287 printf("Setting NS MSP : 0x%x\n", *(uint32_t *)TZ_NS_START_VECTOR);
288 /* Setup non-secure stack */
289 __TZ_set_MSP_NS(*(uint32_t *)TZ_NS_START_VECTOR);
290
291 /* Setup non-secure reset vector */
292 printf("Setting NS VTOR : 0x%x\n", TZ_NS_START_VECTOR);
293 SCB_NS->VTOR = TZ_NS_START_VECTOR;
294
295 /* Enable features */
296#if (defined(__FPU_USED) && (__FPU_USED == 1U)) || (defined(__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U))
297 SCB_NS->CPACR |= ((3U << 10U * 2U) | /* enable CP10 Full Access */
298 (3U << 11U * 2U)); /* enable CP11 Full Access */
299#endif
300
301#ifdef UNALIGNED_SUPPORT_DISABLE
302 SCB_NS->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
303#endif
304
305 // Enable Loop and branch info cache
306 SCB_NS->CCR |= SCB_CCR_LOB_Msk;
307 __ISB();
308
309 /* Call cmse_ function to mark function as transition to non-secure state. */
310 NS_ResetHandler = (ns_func)cmse_nsfptr_create(*(ns_func *)(TZ_NS_START_VECTOR + 4U));
311 printf("Setting NS_ResetHandler to: %p\n", NS_ResetHandler);
312
313 /* Now we've read the NS memory, setup our secure world compartment. */
314 setup_secure_attributes();
315
316 /* Enable SAU, we are ready to jump to non-secure. */
317 SAU->CTRL = 1;
318
319 printf("Leaving secure world.\n");
320 /* Leave secure state. */
321 NS_ResetHandler();
322}
323
324int main() {
325 int ret = -1;
326 printf("Secure main starting up.\n");
327 SCB->CCR |= SCB_CCR_BFHFNMIGN_Msk;
328
329 SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk |
330 SCB_SHCSR_SECUREFAULTENA_Msk; // enable Usage-/Bus-/MPU-/Secure Fault
331
332 boot_non_secure();
333
334 printf("We're back in secure world!\n");
335
336 if (nonsecure_result_checker != 0) {
337 ret = nonsecure_result_checker();
338 }
339
340 return ret;
341}
342
343/****************************************************************************
344 * Secure gateway functions to be callable from non-secure world
345 ****************************************************************************/
346
347uint8_t outputData[1001] __attribute__((aligned(4), section("output_data_sec")));
348
349int run_inference(void) {
350 vector<InferenceProcess::DataPtr> input;
351 input.push_back(InferenceProcess::DataPtr(inputData, sizeof(inputData)));
352
353 vector<InferenceProcess::DataPtr> output;
354 output.push_back(InferenceProcess::DataPtr(outputData, sizeof(outputData)));
355
356 vector<InferenceProcess::DataPtr> expected;
357 expected.push_back(InferenceProcess::DataPtr(expectedData, sizeof(expectedData)));
358
Anton Moberg908a07c2021-04-08 09:50:57 +0200359 InferenceProcess::InferenceJob job("secure",
360 InferenceProcess::DataPtr(networkModelData, sizeof(networkModelData)),
361 input,
362 output,
363 expected,
364 512,
365 std::vector<uint8_t>(4),
366 false);
Per Åstrand79929ff2021-01-26 14:42:43 +0100367
368 bool failed = inferenceProcess.runJob(job);
369 printf("Status of executing the job: ");
370 printf(failed ? "failed\n" : "success\n");
371
372 return failed;
373}
374
375extern "C" int __attribute__((cmse_nonsecure_entry)) run_secure_inference(void) {
376 return run_inference();
377}
378
379extern "C" void __attribute__((cmse_nonsecure_entry)) nonsecure_print(const char *p) {
380 // Printing from non-secure, create RED ouput
381 printf("\033[31;1m");
382 printf("NS: %s\n", p);
383 printf("\033[0m");
384}
385
386extern "C" void __attribute__((cmse_nonsecure_entry)) set_result_function(funcptr_ns callback_fn) {
387 nonsecure_result_checker = callback_fn;
388}