Пример #1
0
/**
 * @callback_method_impl{PFNVMMEMTRENDEZVOUS,
 *      Worker for gimR3KvmEnableWallClock}
 */
static DECLCALLBACK(VBOXSTRICTRC) gimR3KvmEnableWallClockCallback(PVM pVM, PVMCPU pVCpu, void *pvData)
{
    Assert(pvData);
    PKVMWALLCLOCKINFO pWallClockInfo  = (PKVMWALLCLOCKINFO)pvData;
    RTGCPHYS          GCPhysWallClock = pWallClockInfo->GCPhysWallClock;

    /*
     * Read the wall-clock version (sequence) from the guest.
     */
    uint32_t uVersion;
    Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysWallClock));
    int rc = PGMPhysSimpleReadGCPhys(pVM, &uVersion, GCPhysWallClock, sizeof(uVersion));
    if (RT_FAILURE(rc))
    {
        LogRel(("GIM: KVM: Failed to read wall-clock struct. version at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
        return rc;
    }

    /*
     * Ensure the version is incrementally even.
     */
    if (!(uVersion & 1))
        ++uVersion;
    ++uVersion;

    /*
     * Update wall-clock guest struct. with UTC information.
     */
    RTTIMESPEC TimeSpec;
    int32_t    iSec;
    int32_t    iNano;
    TMR3UtcNow(pVM, &TimeSpec);
    RTTimeSpecGetSecondsAndNano(&TimeSpec, &iSec, &iNano);

    GIMKVMWALLCLOCK WallClock;
    RT_ZERO(WallClock);
    AssertCompile(sizeof(uVersion) == sizeof(WallClock.u32Version));
    WallClock.u32Version = uVersion;
    WallClock.u32Sec     = iSec;
    WallClock.u32Nano    = iNano;

    /*
     * Write out the wall-clock struct. to guest memory.
     */
    Assert(!(WallClock.u32Version & 1));
    rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysWallClock, &WallClock, sizeof(GIMKVMWALLCLOCK));
    if (RT_SUCCESS(rc))
    {
        LogRel(("GIM: KVM: Enabled wall-clock struct. at %#RGp - u32Sec=%u u32Nano=%u uVersion=%#RU32\n", GCPhysWallClock,
                WallClock.u32Sec, WallClock.u32Nano, WallClock.u32Version));
    }
    else
        LogRel(("GIM: KVM: Failed to write wall-clock struct. at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
    return rc;
}
Пример #2
0
/**
 * Writes guest memory.
 *
 * @returns VBox status code.
 *
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the target CPU context (for the address).
 * @param   pAddress    Where to start writing.
 * @param   pvBuf       The data to write.
 * @param   cbWrite     The number of bytes to write.
 */
static DECLCALLBACK(int) dbgfR3MemWrite(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbWrite)
{
    /*
     * 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;
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);

    /*
     * HMA is always special.
     */
    int rc;
    if (DBGFADDRESS_IS_HMA(pAddress))
    {
        /** @todo write to HMA. */
        rc = VERR_ACCESS_DENIED;
    }
    else
    {
        /*
         * Select PGM function by addressing mode.
         */
        PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
        PGMMODE enmMode = PGMGetGuestMode(pVCpu);
        if (    enmMode == PGMMODE_REAL
            ||  enmMode == PGMMODE_PROTECTED
            ||  DBGFADDRESS_IS_PHYS(pAddress) )
            rc = PGMPhysSimpleWriteGCPhys(pVM, pAddress->FlatPtr, pvBuf, cbWrite);
        else
        {
#if GC_ARCH_BITS > 32
            if (    (   pAddress->FlatPtr >= _4G
                     || pAddress->FlatPtr + cbWrite > _4G)
                &&  enmMode != PGMMODE_AMD64
                &&  enmMode != PGMMODE_AMD64_NX)
                return VERR_PAGE_TABLE_NOT_PRESENT;
#endif
            rc = PGMPhysSimpleWriteGCPtr(pVCpu, pAddress->FlatPtr, pvBuf, cbWrite);
        }
    }
    return rc;
}
Пример #3
0
/**
 * Enables the KVM VCPU system-time structure.
 *
 * @returns VBox status code.
 * @param   pVM                Pointer to the VM.
 * @param   pVCpu              Pointer to the VMCPU.
 *
 * @remarks Don't do any release assertions here, these can be triggered by
 *          guest R0 code.
 */
VMMR3_INT_DECL(int) gimR3KvmEnableSystemTime(PVM pVM, PVMCPU pVCpu)
{
    PGIMKVM    pKvm    = &pVM->gim.s.u.Kvm;
    PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;

    /*
     * Validate the mapping address first.
     */
    if (!PGMPhysIsGCPhysNormal(pVM, pKvmCpu->GCPhysSystemTime))
    {
        LogRel(("GIM: KVM: VCPU%3d: Invalid physical addr requested for mapping system-time struct. GCPhysSystemTime=%#RGp\n",
               pVCpu->idCpu, pKvmCpu->GCPhysSystemTime));
        return VERR_GIM_OPERATION_FAILED;
    }

    /*
     * Construct the system-time struct.
     */
    GIMKVMSYSTEMTIME SystemTime;
    RT_ZERO(SystemTime);
    SystemTime.u32Version  = pKvmCpu->u32SystemTimeVersion;
    SystemTime.u64NanoTS   = pKvmCpu->uVirtNanoTS;
    SystemTime.u64Tsc      = pKvmCpu->uTsc;
    SystemTime.fFlags      = pKvmCpu->fSystemTimeFlags | GIM_KVM_SYSTEM_TIME_FLAGS_TSC_STABLE;

    /*
     * How the guest calculates the system time (nanoseconds):
     *
     * tsc = rdtsc - SysTime.u64Tsc
     * if (SysTime.i8TscShift >= 0)
     *     tsc <<= i8TscShift;
     * else
     *     tsc >>= -i8TscShift;
     * time = ((tsc * SysTime.u32TscScale) >> 32) + SysTime.u64NanoTS
     */
    uint64_t u64TscFreq   = pKvm->cTscTicksPerSecond;
    SystemTime.i8TscShift = 0;
    while (u64TscFreq > 2 * RT_NS_1SEC_64)
    {
        u64TscFreq >>= 1;
        SystemTime.i8TscShift--;
    }
    uint32_t uTscFreqLo = (uint32_t)u64TscFreq;
    while (uTscFreqLo <= RT_NS_1SEC)
    {
        uTscFreqLo <<= 1;
        SystemTime.i8TscShift++;
    }
    SystemTime.u32TscScale = ASMDivU64ByU32RetU32(RT_NS_1SEC_64 << 32, uTscFreqLo);

    /*
     * Update guest memory with the system-time struct.
     */
    Assert(!(SystemTime.u32Version & UINT32_C(1)));
    int rc = PGMPhysSimpleWriteGCPhys(pVM, pKvmCpu->GCPhysSystemTime, &SystemTime, sizeof(GIMKVMSYSTEMTIME));
    if (RT_SUCCESS(rc))
    {
        LogRel(("GIM: KVM: VCPU%3d: Enabled system-time struct. at %#RGp - u32TscScale=%#RX32 i8TscShift=%d uVersion=%#RU32 "
                "fFlags=%#x uTsc=%#RX64 uVirtNanoTS=%#RX64\n", pVCpu->idCpu, pKvmCpu->GCPhysSystemTime, SystemTime.u32TscScale,
                SystemTime.i8TscShift, SystemTime.u32Version, SystemTime.fFlags, pKvmCpu->uTsc, pKvmCpu->uVirtNanoTS));
        TMR3CpuTickParavirtEnable(pVM);
    }
    else
        LogRel(("GIM: KVM: VCPU%3d: Failed to write system-time struct. at %#RGp. rc=%Rrc\n",
                pVCpu->idCpu, pKvmCpu->GCPhysSystemTime, rc));

    return rc;
}