Example #1
0
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);
}
Example #2
0
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);
    }
}