Esempio n. 1
0
/** @interface_method_impl{PDMAPICHLPR0,pfnSetInterruptFF} */
static DECLCALLBACK(void) pdmR0ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    PVM    pVM   = pDevIns->Internal.s.pVMR0;
    PVMCPU pVCpu = &pVM->aCpus[idCpu];

    AssertReturnVoid(idCpu < pVM->cCpus);

    LogFlow(("pdmR0ApicHlp_SetInterruptFF: CPU%d=caller=%p/%d: VM_FF_INTERRUPT %d -> 1 (CPU%d)\n",
             VMMGetCpuId(pVM), pDevIns, pDevIns->iInstance, VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC), idCpu));

    switch (enmType)
    {
        case PDMAPICIRQ_UPDATE_PENDING:
            VMCPU_FF_SET(pVCpu, VMCPU_FF_UPDATE_APIC);
            break;
        case PDMAPICIRQ_HARDWARE:
#ifdef VBOX_WITH_NEW_APIC
            VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
#endif
            VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
            break;
        case PDMAPICIRQ_NMI:
            VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
            break;
        case PDMAPICIRQ_SMI:
            VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
            break;
        case PDMAPICIRQ_EXTINT:
            VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
            break;
        default:
            AssertMsgFailed(("enmType=%d\n", enmType));
            break;
    }

    /* We need to wake up the target CPU. */
    if (
#ifdef VBOX_WITH_NEW_APIC
        /* We are already on EMT if enmType is PDMAPICIRQ_HARDWARE. Don't bother with poking! */
        enmType != PDMAPICIRQ_HARDWARE &&
#endif
        VMMGetCpuId(pVM) != idCpu)
    {
        switch (VMCPU_GET_STATE(pVCpu))
        {
            case VMCPUSTATE_STARTED_EXEC:
                GVMMR0SchedPokeEx(pVM, pVCpu->idCpu, false /* don't take the used lock */);
                break;

            case VMCPUSTATE_STARTED_HALTED:
                GVMMR0SchedWakeUpEx(pVM, pVCpu->idCpu, false /* don't take the used lock */);
                break;

            default:
                break; /* nothing to do in other states. */
        }
    }
}
Esempio n. 2
0
/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
static DECLCALLBACK(VMCPUID) pdmR0DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR0);
    LogFlow(("pdmR0DevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, idCpu));
    return idCpu;
}
/**
 * Wrapper around CPUMIsGuestIn64BitCode.
 *
 * @returns VINF_SUCCESS.
 * @param   pVM             Pointer to the VM.
 * @param   idCpu           The current CPU ID.
 * @param   pfIn64BitCode   Where to return the result.
 */
static DECLCALLBACK(int) dbgfR3CpuIn64BitCode(PVM pVM, VMCPUID idCpu, bool *pfIn64BitCode)
{
    Assert(idCpu == VMMGetCpuId(pVM));
    PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
    *pfIn64BitCode = CPUMIsGuestIn64BitCode(pVCpu);
    return VINF_SUCCESS;
}
/**
 * Wrapper around CPUMGetGuestMode.
 *
 * @returns VINF_SUCCESS.
 * @param   pVM         Pointer to the VM.
 * @param   idCpu       The current CPU ID.
 * @param   penmMode    Where to return the mode.
 */
static DECLCALLBACK(int) dbgfR3CpuGetMode(PVM pVM, VMCPUID idCpu, CPUMMODE *penmMode)
{
    Assert(idCpu == VMMGetCpuId(pVM));
    PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
    *penmMode = CPUMGetGuestMode(pVCpu);
    return VINF_SUCCESS;
}
Esempio n. 5
0
/**
 * Scan guest memory for an exact byte string.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the CPU context to search in.
 * @param   pAddress    Where to store the mixed address.
 * @param   puAlign     The alignment restriction imposed on the search result.
 * @param   pcbRange    The number of bytes to scan. Passed as a pointer because
 *                      it may be 64-bit.
 * @param   pabNeedle   What to search for - exact search.
 * @param   cbNeedle    Size of the search byte string.
 * @param   pHitAddress Where to put the address of the first hit.
 */
static DECLCALLBACK(int) dbgfR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, PCRTGCUINTPTR pcbRange,
                                       RTGCUINTPTR *puAlign, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
{
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    Assert(idCpu == VMMGetCpuId(pVM));

    /*
     * Validate the input we use, PGM does the rest.
     */
    RTGCUINTPTR cbRange = *pcbRange;
    if (!DBGFR3AddrIsValid(pUVM, pAddress))
        return VERR_INVALID_POINTER;
    if (!VALID_PTR(pHitAddress))
        return VERR_INVALID_POINTER;
    if (DBGFADDRESS_IS_HMA(pAddress))
        return VERR_INVALID_POINTER;

    /*
     * Select DBGF worker by addressing mode.
     */
    int     rc;
    PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
    PGMMODE enmMode = PGMGetGuestMode(pVCpu);
    if (    enmMode == PGMMODE_REAL
        ||  enmMode == PGMMODE_PROTECTED
        ||  DBGFADDRESS_IS_PHYS(pAddress)
        )
    {
        RTGCPHYS GCPhysAlign = *puAlign;
        if (GCPhysAlign != *puAlign)
            return VERR_OUT_OF_RANGE;
        RTGCPHYS PhysHit;
        rc = PGMR3DbgScanPhysical(pVM, pAddress->FlatPtr, cbRange, GCPhysAlign, pabNeedle, cbNeedle, &PhysHit);
        if (RT_SUCCESS(rc))
            DBGFR3AddrFromPhys(pUVM, pHitAddress, PhysHit);
    }
    else
    {
#if GC_ARCH_BITS > 32
        if (    (   pAddress->FlatPtr >= _4G
                 || pAddress->FlatPtr + cbRange > _4G)
            &&  enmMode != PGMMODE_AMD64
            &&  enmMode != PGMMODE_AMD64_NX)
            return VERR_DBGF_MEM_NOT_FOUND;
#endif
        RTGCUINTPTR GCPtrHit;
        rc = PGMR3DbgScanVirtual(pVM, pVCpu, pAddress->FlatPtr, cbRange, *puAlign, pabNeedle, cbNeedle, &GCPtrHit);
        if (RT_SUCCESS(rc))
            DBGFR3AddrFromFlat(pUVM, pHitAddress, GCPtrHit);
    }

    return rc;
}
Esempio n. 6
0
/**
 * Read guest memory.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the CPU context to read memory from.
 * @param   pAddress    Where to start reading.
 * @param   pvBuf       Where to store the data we've read.
 * @param   cbRead      The number of bytes to read.
 */
static DECLCALLBACK(int) dbgfR3MemRead(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
{
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    Assert(idCpu == VMMGetCpuId(pVM));

    /*
     * Validate the input we use, PGM does the rest.
     */
    if (!DBGFR3AddrIsValid(pUVM, pAddress))
        return VERR_INVALID_POINTER;
    if (!VALID_PTR(pvBuf))
        return VERR_INVALID_POINTER;

    /*
     * HMA is special
     */
    int rc;
    if (DBGFADDRESS_IS_HMA(pAddress))
    {
        if (DBGFADDRESS_IS_PHYS(pAddress))
            rc = VERR_INVALID_POINTER;
        else
            rc = MMR3HyperReadGCVirt(pVM, pvBuf, pAddress->FlatPtr, cbRead);
    }
    else
    {
        /*
         * Select DBGF worker by addressing mode.
         */
        PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
        PGMMODE enmMode = PGMGetGuestMode(pVCpu);
        if (    enmMode == PGMMODE_REAL
            ||  enmMode == PGMMODE_PROTECTED
            ||  DBGFADDRESS_IS_PHYS(pAddress) )
            rc = PGMPhysSimpleReadGCPhys(pVM, pvBuf, pAddress->FlatPtr, cbRead);
        else
        {
#if GC_ARCH_BITS > 32
            if (    (   pAddress->FlatPtr >= _4G
                     || pAddress->FlatPtr + cbRead > _4G)
                &&  enmMode != PGMMODE_AMD64
                &&  enmMode != PGMMODE_AMD64_NX)
                return VERR_PAGE_TABLE_NOT_PRESENT;
#endif
            rc = PGMPhysSimpleReadGCPtr(pVCpu, pvBuf, pAddress->FlatPtr, cbRead);
        }
    }
    return rc;
}
Esempio n. 7
0
/**
 * Called on the EMT for the VCpu.
 *
 * @returns VBox status code.
 *
 * @param   pVM             The VM handle.
 * @param   idCpu           The ID of the CPU context.
 * @param   pAddress        The address.
 * @param   fReadOnly       Whether returning a read-only page is fine or not.
 * @param   ppvR3Ptr        Where to return the address.
 */
static DECLCALLBACK(int) dbgfR3AddrToVolatileR3PtrOnVCpu(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
{
    Assert(idCpu == VMMGetCpuId(pVM));

    int rc;
    if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
    {
        rc = VERR_NOT_SUPPORTED; /** @todo create some dedicated errors for this stuff. */
        /** @todo this may assert, create a debug version of this which doesn't. */
        if (MMHyperIsInsideArea(pVM, pAddress->FlatPtr))
        {
            void *pv = MMHyperRCToCC(pVM, (RTRCPTR)pAddress->FlatPtr);
            if (pv)
            {
                *ppvR3Ptr = pv;
                rc = VINF_SUCCESS;
            }
        }
    }
    else
    {
        /*
         * This is a tad ugly, but it gets the job done.
         */
        PGMPAGEMAPLOCK Lock;
        if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
        {
            if (fReadOnly)
                rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
            else
                rc = PGMPhysGCPhys2CCPtr(pVM, pAddress->FlatPtr, ppvR3Ptr, &Lock);
        }
        else
        {
            PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
            if (fReadOnly)
                rc = PGMPhysGCPtr2CCPtrReadOnly(pVCpu, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
            else
                rc = PGMPhysGCPtr2CCPtr(pVCpu, pAddress->FlatPtr, ppvR3Ptr, &Lock);
        }
        if (RT_SUCCESS(rc))
            PGMPhysReleasePageMappingLock(pVM, &Lock);
    }
    return rc;
}
Esempio n. 8
0
/**
 * Executes the VMMDEV_TESTING_CMD_VALUE_REG command when the data is ready.
 *
 * @param   pDevIns             The PDM device instance.
 * @param   pThis               The instance VMMDev data.
 */
static void vmmdevTestingCmdExec_ValueReg(PPDMDEVINS pDevIns, VMMDevState *pThis)
{
    char *pszRegNm = strchr(pThis->TestingData.String.sz, ':');
    if (pszRegNm)
    {
        *pszRegNm++ = '\0';
        pszRegNm = RTStrStrip(pszRegNm);
    }
    char        *pszValueNm = RTStrStrip(pThis->TestingData.String.sz);
    size_t const cchValueNm = strlen(pszValueNm);
    if (cchValueNm && pszRegNm && *pszRegNm)
    {
        PUVM        pUVM  = PDMDevHlpGetUVM(pDevIns);
        PVM         pVM   = PDMDevHlpGetVM(pDevIns);
        VMCPUID     idCpu = VMMGetCpuId(pVM);
        uint64_t    u64Value;
        int rc2 = DBGFR3RegNmQueryU64(pUVM, idCpu, pszRegNm, &u64Value);
        if (RT_SUCCESS(rc2))
        {
            const char *pszWarn = rc2 == VINF_DBGF_TRUNCATED_REGISTER ? " truncated" : "";
#if 1 /*!RTTestValue format*/
            char szFormat[128], szValue[128];
            RTStrPrintf(szFormat, sizeof(szFormat), "%%VR{%s}", pszRegNm);
            rc2 = DBGFR3RegPrintf(pUVM, idCpu, szValue, sizeof(szValue), szFormat);
            if (RT_SUCCESS(rc2))
                VMMDEV_TESTING_OUTPUT(("testing: VALUE '%s'%*s: %16s {reg=%s}%s\n",
                                       pszValueNm,
                                       (ssize_t)cchValueNm - 12 > 48 ? 0 : 48 - ((ssize_t)cchValueNm - 12), "",
                                       szValue, pszRegNm, pszWarn));
            else
#endif
                VMMDEV_TESTING_OUTPUT(("testing: VALUE '%s'%*s: %'9llu (%#llx) [0] {reg=%s}%s\n",
                                       pszValueNm,
                                       (ssize_t)cchValueNm - 12 > 48 ? 0 : 48 - ((ssize_t)cchValueNm - 12), "",
                                       u64Value, u64Value, pszRegNm, pszWarn));
        }
        else
            VMMDEV_TESTING_OUTPUT(("testing: error querying register '%s' for value '%s': %Rrc\n",
                                   pszRegNm, pszValueNm, rc2));
    }
    else
        VMMDEV_TESTING_OUTPUT(("testing: malformed register value '%s'/'%s'\n", pszValueNm, pszRegNm));
}
Esempio n. 9
0
/** @interface_method_impl{PDMAPICHLPR0,pfnGetCpuId} */
static DECLCALLBACK(VMCPUID) pdmR0ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
{
    PDMDEV_ASSERT_DEVINS(pDevIns);
    return VMMGetCpuId(pDevIns->Internal.s.pVMR0);
}
Esempio n. 10
0
/**
 * Check all registered modules for changes.
 *
 * @returns VBox status code.
 * @param   pVM                 Pointer to the VM
 */
VMMR3DECL(int) PGMR3SharedModuleCheckAll(PVM pVM)
{
    /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */
    return VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pgmR3CheckSharedModulesHelper, 2, pVM, VMMGetCpuId(pVM));
}
Esempio n. 11
0
/**
 * This is called on each EMT and will beat TM.
 *
 * @returns VINF_SUCCESS, test failure is reported via RTTEST.
 * @param   pVM         Pointer to the VM.
 * @param   hTest       The test handle.
 */
DECLCALLBACK(int) tstTMWorker(PVM pVM, RTTEST hTest)
{
    VMCPUID idCpu = VMMGetCpuId(pVM);
    RTTestPrintfNl(hTest,  RTTESTLVL_ALWAYS,  "idCpu=%d STARTING\n", idCpu);

    /*
     * Create the test set.
     */
    int rc;
    PTMTIMER apTimers[5];
    for (size_t i = 0; i < RT_ELEMENTS(apTimers); i++)
    {
        rc = TMR3TimerCreateInternal(pVM, i & 1 ? TMCLOCK_VIRTUAL :  TMCLOCK_VIRTUAL_SYNC,
                                     tstTMDummyCallback, NULL, "test timer",  &apTimers[i]);
        RTTEST_CHECK_RET(hTest, RT_SUCCESS(rc), rc);
    }

    /*
     * The run loop.
     */
    unsigned        uPrevPct = 0;
    uint32_t const  cLoops   = 100000;
    for (uint32_t iLoop = 0; iLoop < cLoops; iLoop++)
    {
        size_t      cLeft = RT_ELEMENTS(apTimers);
        unsigned    i     = iLoop % RT_ELEMENTS(apTimers);
        while (cLeft-- > 0)
        {
            PTMTIMER pTimer = apTimers[i];

            if (    cLeft == RT_ELEMENTS(apTimers) / 2
                &&  TMTimerIsActive(pTimer))
            {
                rc = TMTimerStop(pTimer);
                RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerStop: %Rrc\n",  rc));
            }
            else
            {
                rc = TMTimerSetMicro(pTimer, 50 + cLeft);
                RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerSetMicro: %Rrc\n", rc));
            }

            /* next */
            i = (i + 1) % RT_ELEMENTS(apTimers);
        }

        if (i % 3)
            TMR3TimerQueuesDo(pVM);

        /* Progress report. */
        unsigned uPct = (unsigned)(100.0 * iLoop / cLoops);
        if (uPct != uPrevPct)
        {
            uPrevPct = uPct;
            if (!(uPct % 10))
                RTTestPrintfNl(hTest,  RTTESTLVL_ALWAYS,  "idCpu=%d - %3u%%\n", idCpu, uPct);
        }
    }

    RTTestPrintfNl(hTest,  RTTESTLVL_ALWAYS,  "idCpu=%d DONE\n", idCpu);
    return 0;
}