Пример #1
0
int foo(int i, int iZero, int iMinusOne)
{
    NOREF(iZero);

    /* allocate a buffer which we fill up to the end. */
    size_t cb = (i % 1555) + 32;
    g_cbFoo = cb;
    char  *pv = (char *)alloca(cb);
    RTStrPrintf(pv, cb, "i=%d%*s\n", i, cb, "");
#ifdef VMM_R0_SWITCH_STACK
    g_cbFooUsed = VMM_STACK_SIZE - ((uintptr_t)pv - (uintptr_t)g_Jmp.pvSavedStack);
    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < (intptr_t)VMM_STACK_SIZE - 128, ("%#x - (%p - %p) -> %#x; cb=%#x i=%d\n", VMM_STACK_SIZE, pv, g_Jmp.pvSavedStack, g_cbFooUsed, cb, i), -15);
#elif defined(RT_ARCH_AMD64)
    g_cbFooUsed = (uintptr_t)g_Jmp.rsp - (uintptr_t)pv;
    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.rsp, pv, g_cbFooUsed, cb, i), -15);
#elif defined(RT_ARCH_X86)
    g_cbFooUsed = (uintptr_t)g_Jmp.esp - (uintptr_t)pv;
    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < (intptr_t)VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.esp, pv, g_cbFooUsed, cb, i), -15);
#endif

    /* Do long jmps every 7th time */
    if ((i % 7) == 0)
    {
        g_cJmps++;
        int rc = vmmR0CallRing3LongJmp(&g_Jmp, 42);
        if (!rc)
            return i + 10000;
        return -1;
    }
    NOREF(iMinusOne);
    return i;
}
Пример #2
0
/**
 * Calls the ring-3 host code.
 *
 * @returns VBox status code of the ring-3 call.
 * @retval  VERR_VMM_RING3_CALL_DISABLED if called at the wrong time. This must
 *          be passed up the stack, or if that isn't possible then VMMRZCallRing3
 *          needs to change it into an assertion.
 *
 *
 * @param   pVM             The cross context VM structure.
 * @param   pVCpu           The cross context virtual CPU structure of the calling EMT.
 * @param   enmOperation    The operation.
 * @param   uArg            The argument to the operation.
 */
VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation, uint64_t uArg)
{
    VMCPU_ASSERT_EMT(pVCpu);

    /*
     * Check if calling ring-3 has been disabled and only let let fatal calls thru.
     */
    if (RT_UNLIKELY(    pVCpu->vmm.s.cCallRing3Disabled != 0
                    &&  enmOperation != VMMCALLRING3_VM_R0_ASSERTION))
    {
#ifndef IN_RING0
        /*
         * In most cases, it's sufficient to return a status code which
         * will then be propagated up the code usually encountering several
         * AssertRC invocations along the way. Hitting one of those is more
         * helpful than stopping here.
         *
         * However, some doesn't check the status code because they are called
         * from void functions, and for these we'll turn this into a ring-0
         * assertion host call.
         */
        if (enmOperation != VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS)
            return VERR_VMM_RING3_CALL_DISABLED;
#endif
#ifdef IN_RC
        RTStrPrintf(g_szRTAssertMsg1, sizeof(pVM->vmm.s.szRing0AssertMsg1),
                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x\n", enmOperation, uArg, pVCpu->idCpu);
#endif
        RTStrPrintf(pVM->vmm.s.szRing0AssertMsg1, sizeof(pVM->vmm.s.szRing0AssertMsg1),
                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x\n", enmOperation, uArg, pVCpu->idCpu);
        enmOperation = VMMCALLRING3_VM_R0_ASSERTION;
    }

    /*
     * The normal path.
     */
/** @todo profile this! */
    pVCpu->vmm.s.enmCallRing3Operation = enmOperation;
    pVCpu->vmm.s.u64CallRing3Arg = uArg;
    pVCpu->vmm.s.rcCallRing3 = VERR_VMM_RING3_CALL_NO_RC;
#ifdef IN_RC
    pVM->vmm.s.pfnRCToHost(VINF_VMM_CALL_HOST);
#else
    int rc;
    if (pVCpu->vmm.s.pfnCallRing3CallbackR0)
    {
        rc = pVCpu->vmm.s.pfnCallRing3CallbackR0(pVCpu, enmOperation, pVCpu->vmm.s.pvCallRing3CallbackUserR0);
        if (RT_FAILURE(rc))
            return rc;
    }
    rc = vmmR0CallRing3LongJmp(&pVCpu->vmm.s.CallRing3JmpBufR0, VINF_VMM_CALL_HOST);
    if (RT_FAILURE(rc))
        return rc;
#endif
    return pVCpu->vmm.s.rcCallRing3;
}