VirtualBox

Changeset 55510 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Apr 29, 2015 10:13:15 AM (10 years ago)
Author:
vboxsync
Message:

VMM/GIM: EMT Rendezvous while updating global wall-clock struct.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp

    r55455 r55510  
    4747#define GIM_KVM_SAVED_STATE_VERSION         UINT32_C(1)
    4848
     49/**
     50 * VBox internal struct. to passback to EMT rendezvous callback while enabling
     51 * the KVM wall-clock.
     52 */
     53typedef struct KVMWALLCLOCKINFO
     54{
     55    /** Guest physical address of the wall-clock struct.  */
     56    RTGCPHYS GCPhysWallClock;
     57} KVMWALLCLOCKINFO;
     58/** Pointer to the wall-clock info. struct. */
     59typedef KVMWALLCLOCKINFO *PKVMWALLCLOCKINFO;
    4960
    5061/*******************************************************************************
     
    438449
    439450/**
     451 * @callback_method_impl{PFNVMMEMTRENDEZVOUS,
     452 *      Worker for gimR3KvmEnableWallClock}
     453 */
     454static DECLCALLBACK(VBOXSTRICTRC) gimR3KvmEnableWallClockCallback(PVM pVM, PVMCPU pVCpu, void *pvData)
     455{
     456    Assert(pvData);
     457    PKVMWALLCLOCKINFO pWallClockInfo  = (PKVMWALLCLOCKINFO)pvData;
     458    RTGCPHYS          GCPhysWallClock = pWallClockInfo->GCPhysWallClock;
     459
     460    /*
     461     * Read the wall-clock version (sequence) from the guest.
     462     */
     463    uint32_t uVersion;
     464    Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysWallClock));
     465    int rc = PGMPhysSimpleReadGCPhys(pVM, &uVersion, GCPhysWallClock, sizeof(uVersion));
     466    if (RT_FAILURE(rc))
     467    {
     468        LogRel(("GIM: KVM: Failed to read wall-clock struct. version at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
     469        return rc;
     470    }
     471
     472    /*
     473     * Ensure the version is incrementally even.
     474     */
     475    if (!(uVersion & 1))
     476        ++uVersion;
     477    ++uVersion;
     478
     479    /*
     480     * Update wall-clock guest struct. with UTC information.
     481     */
     482    RTTIMESPEC TimeSpec;
     483    int32_t    iSec;
     484    int32_t    iNano;
     485    TMR3UtcNow(pVM, &TimeSpec);
     486    RTTimeSpecGetSecondsAndNano(&TimeSpec, &iSec, &iNano);
     487
     488    GIMKVMWALLCLOCK WallClock;
     489    RT_ZERO(WallClock);
     490    AssertCompile(sizeof(uVersion) == sizeof(WallClock.u32Version));
     491    WallClock.u32Version = uVersion;
     492    WallClock.u32Sec     = iSec;
     493    WallClock.u32Nano    = iNano;
     494
     495    /*
     496     * Write out the wall-clock struct. to guest memory.
     497     */
     498    Assert(!(WallClock.u32Version & 1));
     499    rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysWallClock, &WallClock, sizeof(GIMKVMWALLCLOCK));
     500    if (RT_SUCCESS(rc))
     501    {
     502        LogRel(("GIM: KVM: Enabled wall-clock struct. at %#RGp - u32Sec=%u u32Nano=%u uVersion=%#RU32\n", GCPhysWallClock,
     503                WallClock.u32Sec, WallClock.u32Nano, WallClock.u32Version));
     504    }
     505    else
     506        LogRel(("GIM: KVM: Failed to write wall-clock struct. at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
     507    return rc;
     508}
     509
     510
     511/**
    440512 * Enables the KVM wall-clock structure.
     513 *
     514 * Since the wall-clock can be read by any VCPU but it is a global struct. in
     515 * guest-memory, we do an EMT rendezvous here to be on the safe side. The
     516 * alternative is to use an MMIO2 region and use the WallClock.u32Version field
     517 * for transactional update. However, this MSR is rarely written to (typically
     518 * once during bootup) it's currently not a performance issue.
    441519 *
    442520 * @returns VBox status code.
     
    448526 *          guest R0 code.
    449527 */
    450 VMMR3_INT_DECL(int) gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysWallClock, uint32_t uVersion)
    451 {
    452     RTTIMESPEC TimeSpec;
    453     int32_t    iSec;
    454     int32_t    iNano;
    455 
    456     TMR3UtcNow(pVM, &TimeSpec);
    457     RTTimeSpecGetSecondsAndNano(&TimeSpec, &iSec, &iNano);
    458 
    459     GIMKVMWALLCLOCK WallClock;
    460     RT_ZERO(WallClock);
    461     WallClock.u32Version = uVersion;
    462     WallClock.u32Sec     = iSec;
    463     WallClock.u32Nano    = iNano;
    464 
    465     Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysWallClock));
    466     Assert(!(WallClock.u32Version & UINT32_C(1)));
    467     int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysWallClock, &WallClock, sizeof(GIMKVMWALLCLOCK));
    468     if (RT_SUCCESS(rc))
    469     {
    470         LogRel(("GIM: KVM: Enabled wall-clock struct. at %#RGp - u32Sec=%u u32Nano=%u uVersion=%#RU32\n", GCPhysWallClock,
    471                 WallClock.u32Sec, WallClock.u32Nano, WallClock.u32Version));
    472     }
    473     else
    474         LogRel(("GIM: KVM: Failed to write wall-clock struct. at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
    475 
    476     return rc;
    477 }
    478 
     528VMMR3_INT_DECL(int) gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysWallClock)
     529{
     530    KVMWALLCLOCKINFO WallClockInfo;
     531    WallClockInfo.GCPhysWallClock = GCPhysWallClock;
     532    return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, gimR3KvmEnableWallClockCallback, &WallClockInfo);
     533}
     534
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette