コード例 #1
0
ファイル: dispatch.c プロジェクト: BarrelfishOS/barrelfish
/**
 * \brief Switch context to 'dcb'.
 *
 * Switch to the dispatcher pointed to by 'dcb'. Sets 'dcb_current'.
 *
 * \param dcb        Pointer to dispatcher to which to switch context.
 */
void
context_switch(struct dcb *dcb) {
    struct dispatcher_shared_generic *disp =
        get_dispatcher_shared_generic(dcb->disp);

    assert(dcb != NULL);
    assert(dcb->vspace != 0);

    // VM guests do not have a user space dispatcher
    if (!dcb->is_vm_guest) {
        assert(dcb->disp != 0);
    }

    paging_context_switch(dcb->vspace);
    context_switch_counter++;

    /* Write the CONTEXTID register, so that the debugger can tell dispatchers
     * apart.  We use the physical address of the dispatcher control block.
     * Note that the low 10 bits of dcb are zero, and the lower 8 bits of the
     * register hold the ASID, which we're not yet using. */
    cp15_write_contextidr(((uint32_t)dcb) & ~MASK(8));

    if (!dcb->is_vm_guest) {
        assert(dcb->disp_cte.cap.type == ObjType_Frame);

        /*
         * The name of the function is somewhat misleading. we need an unused
         * user register that always stores the pointer to the current
         * dispatcher. most ABIs define a register for thread-local storage,
         * and we have been abusing that on x64 for the dispatcher pointer
         * --arch_set_thread_ register sets this pointer.  Obviously this
         * needs to change to support thread-local storage using a standard
         * ABI, so we will have to figure out how to get to the dispatcher
         * from something like a thread-local variable.  The reason that this
         * is in the switch path and not in resume/execute is that on x86_64
         * loading the thread register (fs) is stupidly expensive, so we avoid
         * doing it unless we switch contexts -- presumably that could be a
         * local optimisation in the x86_64 dispatch paths rather than the
         * generic context_switch path/
         */
        arch_set_thread_register(disp->udisp);
    }
}
コード例 #2
0
ファイル: dispatch.c プロジェクト: MichaelFQuigley/barrelfish
/**
 * \brief Switch context to 'dcb'.
 *
 * Switch to the dispatcher pointed to by 'dcb'. Sets 'dcb_current'.
 *
 * \param dcb        Pointer to dispatcher to which to switch context.
 */
void
context_switch(struct dcb *dcb) {
    struct dispatcher_shared_generic *disp =
        get_dispatcher_shared_generic(dcb->disp);

    assert(dcb != NULL);
    assert(dcb->vspace != 0);

    // VM guests do not have a user space dispatcher
    if (!dcb->is_vm_guest) {
        assert(dcb->disp != 0);
    }

    paging_context_switch(dcb->vspace);
    context_switch_counter++;

    if (!dcb->is_vm_guest) {
        assert(dcb->disp_cte.cap.type == ObjType_Frame);

        /*
         * The name of the function is somewhat misleading. we need an unused
         * user register that always stores the pointer to the current
         * dispatcher. most ABIs define a register for thread-local storage,
         * and we have been abusing that on x64 for the dispatcher pointer
         * --arch_set_thread_ register sets this pointer.  Obviously this
         * needs to change to support thread-local storage using a standard
         * ABI, so we will have to figure out how to get to the dispatcher
         * from something like a thread-local variable.  The reason that this
         * is in the switch path and not in resume/execute is that on x86_64
         * loading the thread register (fs) is stupidly expensive, so we avoid
         * doing it unless we switch contexts -- presumably that could be a
         * local optimisation in the x86_64 dispatch paths rather than the
         * generic context_switch path/
         */
        arch_set_thread_register(disp->udisp);
    }
}