VirtualBox

Changeset 45943 in vbox


Ignore:
Timestamp:
May 8, 2013 9:30:28 AM (12 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0: Fix overly-delayed update of PGM's view of CR3. More longjmp fun.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r45937 r45943  
    51245124            {
    51255125                CPUMSetGuestCR3(pVCpu, uVal);
    5126                 /* Set the force flag to inform PGM about it when necessary. It is cleared by PGMUpdateCR3().*/
    5127                 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
     5126                if (VMMRZCallRing3IsEnabled(pVCpu))
     5127                    PGMUpdateCR3(pVCpu, uVal);
     5128                else
     5129                {
     5130                    /* Set the force flag to inform PGM about it when necessary. It is cleared by PGMUpdateCR3().*/
     5131                    VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
     5132                }
    51285133            }
    51295134
     
    51355140                rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);        AssertRCReturn(rc, rc);
    51365141                rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);        AssertRCReturn(rc, rc);
    5137                 /* Set the force flag to inform PGM about it when necessary. It is cleared by PGMGstUpdatePaePdpes(). */
    5138                 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
     5142
     5143                if (VMMRZCallRing3IsEnabled(pVCpu))
     5144                    PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
     5145                else
     5146                {
     5147                    /* Set the force flag to inform PGM about it when necessary. It is cleared by PGMGstUpdatePaePdpes(). */
     5148                    VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
     5149                }
    51395150            }
    51405151        }
     
    51425153        pVCpu->hm.s.vmx.fUpdatedGuestState |= HMVMX_UPDATED_GUEST_CR3;
    51435154    }
     5155
     5156    /*
     5157     * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
     5158     * -> VMMRZCallRing3Disable() -> hmR0VmxSaveGuestState() -> Set VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
     5159     * -> continue with VM-exit handling -> hmR0VmxSaveGuestControlRegs() and here we are.
     5160     *
     5161     * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again.
     5162     * We cover for it here.
     5163     */
     5164    if (VMMRZCallRing3IsEnabled(pVCpu))
     5165    {
     5166        if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
     5167            PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
     5168
     5169        if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
     5170            PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
     5171
     5172        Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
     5173        Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
     5174    }
     5175
    51445176    return rc;
    51455177}
     
    53895421        return VINF_SUCCESS;
    53905422
    5391     VMMRZCallRing3Disable(pVCpu);
    5392     Assert(VMMR0IsLogFlushDisabled(pVCpu));
     5423    /* Though we can longjmp to ring-3 due to log-flushes here and get recalled again on the ring-3 callback path,
     5424       there is no real need to. */
     5425    if (VMMRZCallRing3IsEnabled(pVCpu))
     5426        VMMR0LogFlushDisable(pVCpu);
     5427    else
     5428        Assert(VMMR0IsLogFlushDisabled(pVCpu));
    53935429    LogFunc(("\n"));
    53945430
     
    54295465              ("Missed guest state bits while saving state; residue %RX32\n", pVCpu->hm.s.vmx.fUpdatedGuestState));
    54305466
    5431     VMMRZCallRing3Enable(pVCpu);
     5467    if (VMMRZCallRing3IsEnabled(pVCpu))
     5468        VMMR0LogFlushEnable(pVCpu);
     5469
    54325470    return rc;
    54335471}
     
    54745512            rc = PGMUpdateCR3(pVCpu, pMixedCtx->cr3);
    54755513            Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3);
     5514            Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
    54765515        }
    54775516        if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
     
    54795518            rc = PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
    54805519            AssertRC(rc);
     5520            Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
    54815521        }
    54825522
     
    67626802        /*
    67636803         * If the TPR was raised by the guest, it wouldn't cause a VM-exit immediately. Instead we sync the TPR lazily whenever
    6764          * we eventually get a VM-exit for any reason. This maybe expensive as PDMApicSetTPR() can longjmp to ring-3; also why
    6765          * we do it outside of hmR0VmxSaveGuestState() which must never cause longjmps.
     6804         * we eventually get a VM-exit for any reason. This maybe expensive as PDMApicSetTPR() can longjmp to ring-3 and which is
     6805         * why it's done here as it's easier and no less efficient to deal with it here than making hmR0VmxSaveGuestState()
     6806         * cope with longjmps safely (see VMCPU_FF_HM_UPDATE_CR3 handling).
    67666807         */
    67676808        if (   (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
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