void vmpu_mem_init(void) { /* enable read access to unsecure flash regions * - allow execution * - give read access to ENET DMA bus master */ vmpu_mpu_set_static_acl(1, FLASH_ORIGIN, (uint32_t) __uvisor_config.secure_end - FLASH_ORIGIN, UVISOR_TACL_SREAD | UVISOR_TACL_SEXECUTE | UVISOR_TACL_UREAD | UVISOR_TACL_UEXECUTE | UVISOR_TACL_USER, 0x4UL << 18); /* rest of SRAM, accessible to mbed * - non-executable for uvisor * - five read/write access to ENET DMA bus master */ vmpu_mpu_set_static_acl(2, (uint32_t) __uvisor_config.page_end, (uint32_t) __uvisor_config.sram_end - (uint32_t) __uvisor_config.page_end, UVISOR_TACL_SREAD | UVISOR_TACL_SWRITE | UVISOR_TACL_UREAD | UVISOR_TACL_UWRITE | UVISOR_TACL_UEXECUTE | UVISOR_TACL_USER, 0x6UL << 18); }
void vmpu_arch_init_hw(void) { /* Enable the public Flash. */ vmpu_mpu_set_static_acl( 0, FLASH_ORIGIN, ((uint32_t) __uvisor_config.secure_end) - FLASH_ORIGIN, UVISOR_TACLDEF_SECURE_CONST | UVISOR_TACL_EXECUTE, 0 ); /* Enable the public SRAM: * * We use one region for this, which start at SRAM origin (which is always * aligned) and has a power-of-two size that is equal or _larger_ than * SRAM. This means the region may end _behind_ the end of SRAM! * * At the beginning of SRAM uVisor places its private BSS section and * behind that the page heap. In order to use only one region, we require * the end of the page heap to align with 1/8th of the region size, so that * we can use the subregion mask. * The page heap reduces the memory wastage to less than one page size, by * "growing" the page heap downwards from the subregion alignment towards * the uVisor bss. * * Note: The correct alignment needs to be done in the host linkerscript. * Use `ALIGN( (1 << LOG2CEIL(LENGTH(SRAM)) / 8 )` for GNU linker. * * 2^n <-- region end * ... * .---------. <-- uvisor_config.sram_end * | box 0 | * | public | * | memory | * +---------+ <-- uvisor_config.page_end: n/8th of _region_ size (not SRAM size) * | page | * | heap | * +---------+ <-- aligned to page size * | wastage | <-- wasted SRAM is less than 1 page size * +---------+ <-- uvisor_config.page_start * | uVisor | * | bss | * '---------' <-- uvisor_config.sram_start, region start * * Example: The region size of a 96kB SRAM will be 128kB, and the page heap * end will have to be aligned to 16kB, _not_ 12kB (= 96kB / 8). * * Note: In case the uVisor bss section is moved to another memory region * (tightly-coupled memory for example), the page heap remains and * the same considerations apply. Therefore the uVisor bss section * location has no impact on this. */ /* Calculate the region size by rounding up the SRAM size to the next power-of-two. */ const uint32_t total_size = (1 << vmpu_region_bits((uint32_t) __uvisor_config.public_sram_end - (uint32_t) __uvisor_config.public_sram_start)); /* The alignment is 1/8th of the region size = rounded up SRAM size. */ const uint32_t subregions_size = total_size / 8; const uint32_t protected_size = (uint32_t) __uvisor_config.page_end - (uint32_t) __uvisor_config.public_sram_start; /* The protected size must be aligned to the subregion size. */ if (protected_size % subregions_size != 0) { HALT_ERROR(SANITY_CHECK_FAILED, "The __uvisor_page_end symbol (0x%08X) is not aligned to an MPU subregion boundary.", (uint32_t) __uvisor_config.page_end); } /* Note: It's called the subregion _disable_ mask, so setting one bit in it _disables_ the * permissions in this subregion. Totally not confusing, amiright!? */ const uint8_t subregions_disable_mask = (uint8_t) ((1UL << (protected_size / subregions_size)) - 1UL); /* Unlock the upper SRAM subregion only. */ /* Note: We allow code execution for backwards compatibility. Both the user * and superuser flags are set since the ARMv7-M MPU cannot * distinguish between the two. */ vmpu_mpu_set_static_acl( 1, (uint32_t) __uvisor_config.public_sram_start, total_size, UVISOR_TACLDEF_DATA | UVISOR_TACL_EXECUTE, subregions_disable_mask ); /* On page heap alignments: * * Individual pages in the page heap are protected by subregions. A page of * size 2^N must have its start address aligned to 2^N. However, for page * sizes > 1/8th region size, the start address is not guaranteed to be * aligned to 2^N. * * Example: 2^N = page size, 2^(N-1) = 1/8th SRAM (32kB page size in a 128kB SRAM). * * | | * +-----------+ <-- uvisor_config.page_end: 0x30000 = 3/8th * 128kB is aligned to 16kB. * | 32kB page | * +-----------+ <-- page start address: 0x30000 - 32kB = 0x10000 is not aligned to 32kB!! * | | * * Due to these contradicting alignment requirements, it is not possible to * have a page size larger than 1/8th region size. */ if (subregions_size < *__uvisor_config.page_size) { HALT_ERROR(SANITY_CHECK_FAILED, "The page size (%ukB) must not be larger than 1/8th of SRAM (%ukB).", *__uvisor_config.page_size / 1024, subregions_size / 1024); } }