Example #1
0
/* Switch the context from the source box to the destination one, using the
 * stack pointers provided as input. */
void context_switch_in(TContextSwitchType context_type, uint8_t dst_id, uint32_t src_sp, uint32_t dst_sp)
{
    uint8_t src_id;

    /* Source box: Gather information from the current state. */
    src_id = g_active_box;

    /* The source/destination box IDs can be the same (for example, in IRQs). */
    if (src_id != dst_id) {
        /* Update the context pointer to the one of the destination box. */
        *(__uvisor_config.uvisor_box_context) = (uint32_t *) g_context_current_states[dst_id].bss;

        /* Update the ID of the currently active box. */
        g_active_box = dst_id;
        UvisorBoxIndex * index = (UvisorBoxIndex *) *(__uvisor_config.uvisor_box_context);
        index->box_id_self = dst_id;

        /* Switch MPU configurations. */
        /* This function halts if it finds an error. */
        vmpu_switch(src_id, dst_id);
    }

    /* Push the state of the source box and set the stack pointer for the
     * destination box.
     * This is only needed if the context switch is tied to a function. Unbound
     * context switches require the host OS to set the correct stack pointer
     * before handling execution to the unprivileged code, and for the same
     * reason do not require state-keeping.  */
    /* This function halts if it finds an error. */
    if (context_type == CONTEXT_SWITCH_FUNCTION_GATEWAY ||
        context_type == CONTEXT_SWITCH_FUNCTION_ISR     ||
        context_type == CONTEXT_SWITCH_FUNCTION_DEBUG) {
        context_state_push(context_type, src_id, src_sp);
        __set_PSP(dst_sp);
    }
}
Example #2
0
/* Switch the context from the source box to the destination one, using the
 * stack pointers provided as input. */
void context_switch_in(TContextSwitchType context_type, uint8_t dst_id, uint32_t src_sp, uint32_t dst_sp)
{
    /* The source box is the currently active box. */
    uint8_t src_id = g_active_box;
    if (!vmpu_is_box_id_valid(src_id)) {
        /* Note: We accept that the source box ID is invalid if this is the very
         *       first context switch. */
        if (context_type == CONTEXT_SWITCH_UNBOUND_FIRST) {
            src_id = dst_id;
        } else {
            HALT_ERROR(SANITY_CHECK_FAILED, "Context switch: The source box ID is out of range (%u).\r\n", src_id);
        }
    }
    if (!vmpu_is_box_id_valid(dst_id)) {
        HALT_ERROR(SANITY_CHECK_FAILED, "Context switch: The destination box ID is out of range (%u).\r\n", dst_id);
    }

    /* The source/destination box IDs can be the same (for example, in IRQs). */
    if (src_id != dst_id || context_type == CONTEXT_SWITCH_UNBOUND_FIRST) {
        /* Store outgoing newlib reent pointer. */
        UvisorBoxIndex * index = (UvisorBoxIndex *) g_context_current_states[src_id].bss;
        index->bss.address_of.newlib_reent = (uint32_t) *(__uvisor_config.newlib_impure_ptr);

        /* Update the context pointer to the one of the destination box. */
        index = (UvisorBoxIndex *) g_context_current_states[dst_id].bss;
        *(__uvisor_config.uvisor_box_context) = (uint32_t *) index;

        /* Update the ID of the currently active box. */
        g_active_box = dst_id;
        index->box_id_self = dst_id;

#if defined(ARCH_CORE_ARMv8M)
        /* Switch vIRQ configurations. */
        virq_switch(src_id, dst_id);
#endif /* defined(ARCH_CORE_ARMv8M) */

        /* Switch MPU configurations. */
        /* This function halts if it finds an error. */
        vmpu_switch(src_id, dst_id);

        /* Restore incoming newlib reent pointer. */
        *(__uvisor_config.newlib_impure_ptr) = (uint32_t *) index->bss.address_of.newlib_reent;
    }

    /* Push the state of the source box and set the stack pointer for the
     * destination box.
     * This is only needed if the context switch is tied to a function. Unbound
     * context switches require the host OS to set the correct stack pointer
     * before handling execution to the unprivileged code, and for the same
     * reason do not require state-keeping.  */
    /* This function halts if it finds an error. */
    if (context_type == CONTEXT_SWITCH_FUNCTION_GATEWAY ||
        context_type == CONTEXT_SWITCH_FUNCTION_ISR     ||
        context_type == CONTEXT_SWITCH_FUNCTION_DEBUG) {
        context_state_push(context_type, src_id, src_sp);
#if defined(ARCH_CORE_ARMv8M)
        /* FIXME: Set the right LR value depending on which NS SP is actually used. */
        __TZ_set_MSP_NS(dst_sp);
        __TZ_set_PSP_NS(dst_sp);
#else
        __set_PSP(dst_sp);
#endif
    }
}