Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 1 | /* |
| 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 Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 27 | #include "../common/secure_entries.hpp" |
Anton Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 28 | #include "mpc_sie_drv.h" |
| 29 | #include "trustzone.h" |
Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 30 | |
| 31 | #include "inference_process.hpp" |
| 32 | |
| 33 | // System includes |
| 34 | #include <arm_cmse.h> |
| 35 | #include <inttypes.h> |
| 36 | #include <stdio.h> |
| 37 | |
| 38 | using namespace std; |
| 39 | |
| 40 | funcptr_ns nonsecure_result_checker = 0; |
| 41 | |
| 42 | /**************************************************************************** |
| 43 | * InferenceJob |
| 44 | ****************************************************************************/ |
| 45 | |
| 46 | #define TENSOR_ARENA_SIZE 0xa0000 |
Jonny Svärd | f521be9 | 2021-03-01 14:35:49 +0100 | [diff] [blame] | 47 | __attribute__((section(".bss.tensor_arena"), aligned(16))) uint8_t TFLuTensorArena[TENSOR_ARENA_SIZE]; |
Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 48 | |
| 49 | InferenceProcess::InferenceProcess inferenceProcess(TFLuTensorArena, TENSOR_ARENA_SIZE); |
| 50 | |
| 51 | /**************************************************************************** |
| 52 | * Functions |
| 53 | ****************************************************************************/ |
| 54 | |
| 55 | namespace { |
| 56 | |
Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 57 | #include "input.h" |
Anton Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 58 | #include "model.h" |
Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 59 | #include "output.h" |
| 60 | |
| 61 | } // namespace |
| 62 | |
| 63 | #define N_MEM_RANGES (2) |
| 64 | static 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) |
| 131 | static 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 Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 139 | 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 Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 143 | |
| 144 | /* Non secure range */ |
Anton Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 145 | 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 Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 149 | |
| 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) |
| 201 | void 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 Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 214 | uint32_t BLKSZ = 1 << (((xtgu->cfg) & 0xf) + 5); |
Per Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 215 | |
| 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 | |
| 251 | int 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 | |
| 282 | void 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 | |
| 324 | int 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 | |
| 347 | uint8_t outputData[1001] __attribute__((aligned(4), section("output_data_sec"))); |
| 348 | |
| 349 | int 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 Moberg | 908a07c | 2021-04-08 09:50:57 +0200 | [diff] [blame] | 359 | 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 Åstrand | 79929ff | 2021-01-26 14:42:43 +0100 | [diff] [blame] | 367 | |
| 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 | |
| 375 | extern "C" int __attribute__((cmse_nonsecure_entry)) run_secure_inference(void) { |
| 376 | return run_inference(); |
| 377 | } |
| 378 | |
| 379 | extern "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 | |
| 386 | extern "C" void __attribute__((cmse_nonsecure_entry)) set_result_function(funcptr_ns callback_fn) { |
| 387 | nonsecure_result_checker = callback_fn; |
| 388 | } |