VirtualBox

Changeset 83372 in vbox for trunk


Ignore:
Timestamp:
Mar 23, 2020 2:52:24 PM (5 years ago)
Author:
vboxsync
Message:

GIM/KVM: Update system-time struct on demand. Fixes guests that rely on the struct being frequently updated, e.g. SLES 10 SP4 (see bugref:7270).

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp

    r82968 r83372  
    240240            bool fEnable = RT_BOOL(uRawValue & MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT);
    241241#ifndef IN_RING3
    242             NOREF(fEnable); NOREF(pKvmCpu);
    243242            gimR0KvmUpdateSystemTime(pVM, pVCpu);
    244             return VINF_CPUM_R3_MSR_WRITE;
     243            if (   fEnable
     244                && MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr)
     245                && MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(uRawValue) == pKvmCpu->GCPhysSystemTime)
     246            {
     247                /*
     248                 * Guest is asking for an update of the system-time struct. We only
     249                 * need to update the TSC and system time fields, the rest stays unchanged.
     250                 * We have to write the version twice in case another VCPU is reading the
     251                 * system-time struct concurrently. Making the version number odd indicates
     252                 * that the data is being updated.
     253                 */
     254                GIMKVMSYSTEMTIME SystemTime;
     255                SystemTime.u32Version  = ++pKvmCpu->u32SystemTimeVersion;
     256                SystemTime.u32Padding0 = 0;
     257                SystemTime.u64NanoTS   = pKvmCpu->uVirtNanoTS;
     258                SystemTime.u64Tsc      = pKvmCpu->uTsc;
     259                AssertCompile(RT_UOFFSETOF(GIMKVMSYSTEMTIME, u32TscScale) == 3 * sizeof(uint64_t));
     260                int rc2 = PGMPhysSimpleWriteGCPhys(pVM, pKvmCpu->GCPhysSystemTime, &SystemTime, RT_UOFFSETOF(GIMKVMSYSTEMTIME, u32TscScale));
     261                if (RT_FAILURE(rc2))
     262                    return rc2;
     263
     264                /* Make the version number even again to indicate the data is consistent. */
     265                ++pKvmCpu->u32SystemTimeVersion;
     266                rc2 = PGMPhysSimpleWriteGCPhys(pVM, pKvmCpu->GCPhysSystemTime, &pKvmCpu->u32SystemTimeVersion, sizeof(pKvmCpu->u32SystemTimeVersion));
     267                if (RT_FAILURE(rc2))
     268                    return rc2;
     269                return VINF_SUCCESS;
     270            }
     271            else
     272                return VINF_CPUM_R3_MSR_WRITE;
    245273#else /* IN_RING3 */
    246274            if (!fEnable)
     
    249277                pKvmCpu->u64SystemTimeMsr = uRawValue;
    250278                return VINF_SUCCESS;
    251             }
    252 
    253             /* Is the system-time struct. already enabled? If so, get flags that need preserving. */
    254             GIMKVMSYSTEMTIME SystemTime;
    255             RT_ZERO(SystemTime);
    256             if (   MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr)
    257                 && MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(uRawValue) == pKvmCpu->GCPhysSystemTime)
    258             {
    259                 int rc2 = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
    260                 if (RT_SUCCESS(rc2))
    261                     pKvmCpu->fSystemTimeFlags = (SystemTime.fFlags & GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED);
    262279            }
    263280
  • trunk/src/VBox/VMM/VMMR0/GIMR0Kvm.cpp

    r82968 r83372  
    5656    uint64_t uVirtNanoTS;
    5757    RTCCUINTREG fEFlags = ASMIntDisableFlags();
    58     uTsc        = TMCpuTickGetNoCheck(pVCpu) | UINT64_C(1);
    59     uVirtNanoTS = TMVirtualGetNoCheck(pVM)   | UINT64_C(1);
     58    uTsc        = TMCpuTickGetNoCheck(pVCpu);
     59    uVirtNanoTS = TMVirtualGetNoCheck(pVM);
    6060    ASMSetFlags(fEFlags);
    6161
     
    6868    {
    6969        PGIMKVMCPU pKvmCpu = &VMCC_GET_CPU(pVM, idCpu)->gim.s.u.KvmCpu;
    70         if (   !pKvmCpu->uTsc
    71             && !pKvmCpu->uVirtNanoTS)
    72         {
    73             pKvmCpu->uTsc        = uTsc;
    74             pKvmCpu->uVirtNanoTS = uVirtNanoTS;
    75         }
     70        pKvmCpu->uTsc        = uTsc;
     71        pKvmCpu->uVirtNanoTS = uVirtNanoTS;
    7672    }
    7773    RTSpinlockRelease(pKvm->hSpinlockR0);
  • trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp

    r82968 r83372  
    416416
    417417    /*
    418      * Update guest memory with the system-time struct.
     418     * Update guest memory with the system-time struct. Technically we are cheating
     419     * by only writing the struct once with the version incremented by two; in reality,
     420     * the system-time struct is enabled once by the boot CPU and not concurrently read
     421     * by other VCPUs at the same time.
    419422     */
    420423    Assert(!(SystemTime.u32Version & UINT32_C(1)));
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