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