VirtualBox

Changeset 80587 in vbox


Ignore:
Timestamp:
Sep 4, 2019 5:44:20 PM (5 years ago)
Author:
vboxsync
Message:

VMM/HM: bugref:9546 Fix registering of the longjmp callback to be soon after enabling VT-x/AMD-V on the CPU. This gives us proper behavior when ring-0 assertions happen prior to VMXR0RunGuestCode/SVMR0RunGuestCode so we can relinquish hardware resources on the way out.

Location:
trunk/src/VBox/VMM/VMMR0
Files:
6 edited

Legend:

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

    r80333 r80587  
    8787    /** @name Ring-0 method table for AMD-V and VT-x specific operations.
    8888     * @{ */
    89     DECLR0CALLBACKMEMBER(int,  pfnEnterSession, (PVMCPUCC pVCpu));
    90     DECLR0CALLBACKMEMBER(void, pfnThreadCtxCallback, (RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit));
    91     DECLR0CALLBACKMEMBER(int,  pfnExportHostState, (PVMCPUCC pVCpu));
     89    DECLR0CALLBACKMEMBER(int,          pfnEnterSession, (PVMCPUCC pVCpu));
     90    DECLR0CALLBACKMEMBER(void,         pfnThreadCtxCallback, (RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit));
     91    DECLR0CALLBACKMEMBER(int,          pfnCallRing3Callback, (PVMCPUCC pVCpu, VMMCALLRING3 enmOperation));
     92    DECLR0CALLBACKMEMBER(int,          pfnExportHostState, (PVMCPUCC pVCpu));
    9293    DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnRunGuestCode, (PVMCPUCC pVCpu));
    93     DECLR0CALLBACKMEMBER(int,  pfnEnableCpu, (PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
    94                                               bool fEnabledByHost, PCSUPHWVIRTMSRS pHwvirtMsrs));
    95     DECLR0CALLBACKMEMBER(int,  pfnDisableCpu, (void *pvCpuPage, RTHCPHYS HCPhysCpuPage));
    96     DECLR0CALLBACKMEMBER(int,  pfnInitVM, (PVMCC pVM));
    97     DECLR0CALLBACKMEMBER(int,  pfnTermVM, (PVMCC pVM));
    98     DECLR0CALLBACKMEMBER(int,  pfnSetupVM, (PVMCC pVM));
     94    DECLR0CALLBACKMEMBER(int,          pfnEnableCpu, (PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
     95                                                      bool fEnabledByHost, PCSUPHWVIRTMSRS pHwvirtMsrs));
     96    DECLR0CALLBACKMEMBER(int,          pfnDisableCpu, (void *pvCpuPage, RTHCPHYS HCPhysCpuPage));
     97    DECLR0CALLBACKMEMBER(int,          pfnInitVM, (PVMCC pVM));
     98    DECLR0CALLBACKMEMBER(int,          pfnTermVM, (PVMCC pVM));
     99    DECLR0CALLBACKMEMBER(int,          pfnSetupVM, (PVMCC pVM));
    99100    /** @} */
    100101
     
    269270}
    270271
     272static DECLCALLBACK(int) hmR0DummyCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
     273{
     274    RT_NOREF2(pVCpu, enmOperation);
     275    return VINF_SUCCESS;
     276}
     277
    271278static DECLCALLBACK(VBOXSTRICTRC) hmR0DummyRunGuestCode(PVMCPUCC pVCpu)
    272279{
     
    466473            g_HmR0.pfnEnterSession      = VMXR0Enter;
    467474            g_HmR0.pfnThreadCtxCallback = VMXR0ThreadCtxCallback;
     475            g_HmR0.pfnCallRing3Callback = VMXR0CallRing3Callback;
    468476            g_HmR0.pfnExportHostState   = VMXR0ExportHostState;
    469477            g_HmR0.pfnRunGuestCode      = VMXR0RunGuestCode;
     
    518526    g_HmR0.pfnEnterSession      = SVMR0Enter;
    519527    g_HmR0.pfnThreadCtxCallback = SVMR0ThreadCtxCallback;
     528    g_HmR0.pfnCallRing3Callback = SVMR0CallRing3Callback;
    520529    g_HmR0.pfnExportHostState   = SVMR0ExportHostState;
    521530    g_HmR0.pfnRunGuestCode      = SVMR0RunGuestCode;
     
    588597    g_HmR0.pfnEnterSession      = hmR0DummyEnter;
    589598    g_HmR0.pfnThreadCtxCallback = hmR0DummyThreadCtxCallback;
     599    g_HmR0.pfnCallRing3Callback = hmR0DummyCallRing3Callback;
    590600    g_HmR0.pfnExportHostState   = hmR0DummyExportHostState;
    591601    g_HmR0.pfnRunGuestCode      = hmR0DummyRunGuestCode;
     
    13391349
    13401350/**
     1351 * Notification callback before performing a longjump to ring-3.
     1352 *
     1353 * @returns VBox status code.
     1354 * @param   pVCpu           The cross context virtual CPU structure.
     1355 * @param   enmOperation    The operation causing the ring-3 longjump.
     1356 * @param   pvUser          User argument, currently unused, NULL.
     1357 */
     1358static DECLCALLBACK(int) hmR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
     1359{
     1360    RT_NOREF(pvUser);
     1361    Assert(pVCpu);
     1362    Assert(g_HmR0.pfnCallRing3Callback);
     1363    return g_HmR0.pfnCallRing3Callback(pVCpu, enmOperation);
     1364}
     1365
     1366
     1367/**
    13411368 * Turns on HM on the CPU if necessary and initializes the bare minimum state
    13421369 * required for entering HM context.
     
    13591386    if (!pHostCpu->fConfigured)
    13601387        rc = hmR0EnableCpu(pVCpu->CTX_SUFF(pVM), idCpu);
     1388
     1389    /* Register a callback to fire prior to performing a longjmp to ring-3 so HM can disable VT-x/AMD-V if needed. */
     1390    VMMRZCallRing3SetNotification(pVCpu, hmR0CallRing3Callback, NULL /* pvUser */);
    13611391
    13621392    /* Reload host-state (back from ring-3/migrated CPUs) and shared guest/host bits. */
     
    14561486    pVCpu->hm.s.idEnteredCpu = NIL_RTCPUID;
    14571487
     1488    /* De-register the longjmp-to-ring 3 callback now that we have reliquished hardware resources. */
     1489    VMMRZCallRing3RemoveNotification(pVCpu);
    14581490    return VINF_SUCCESS;
    14591491}
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r80454 r80587  
    28882888     *
    28892889     * Consider this scenario: #VMEXIT -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp
    2890      * -> hmR0SvmCallRing3Callback() -> VMMRZCallRing3Disable() -> hmR0SvmImportGuestState()
     2890     * -> SVMR0CallRing3Callback() -> VMMRZCallRing3Disable() -> hmR0SvmImportGuestState()
    28912891     * -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp -> continue with #VMEXIT
    28922892     * handling -> hmR0SvmImportGuestState() and here we are.
     
    29452945    /*
    29462946     * !!! IMPORTANT !!!
    2947      * If you modify code here, make sure to check whether hmR0SvmCallRing3Callback() needs to be updated too.
     2947     * If you modify code here, make sure to check whether SVMR0CallRing3Callback() needs to be updated too.
    29482948     */
    29492949
     
    30083008    /*
    30093009     * !!! IMPORTANT !!!
    3010      * If you modify code here, make sure to check whether hmR0SvmCallRing3Callback() needs to be updated too.
     3010     * If you modify code here, make sure to check whether SVMR0CallRing3Callback() needs to be updated too.
    30113011     */
    30123012
     
    30443044 * @param   pVCpu           The cross context virtual CPU structure.
    30453045 * @param   enmOperation    The operation causing the ring-3 longjump.
    3046  * @param   pvUser          The user argument, NULL (currently unused).
    3047  */
    3048 static DECLCALLBACK(int) hmR0SvmCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
    3049 {
    3050     RT_NOREF_PV(pvUser);
    3051 
     3046 */
     3047VMMR0DECL(int) SVMR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
     3048{
    30523049    if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
    30533050    {
     
    31293126    hmR0SvmLeaveSession(pVCpu);
    31303127    STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
     3128
     3129    /* Thread-context hooks are unregistered at this point!!! */
     3130    /* Ring-3 callback notifications are unregistered at this point!!! */
    31313131
    31323132    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
     
    31553155
    31563156    STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
    3157 
    3158     /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
    3159     VMMRZCallRing3RemoveNotification(pVCpu);
    31603157    VMMRZCallRing3Enable(pVCpu);
    31613158
     
    47894786         * better than a kernel panic. This also disables flushing of the R0-logger instance.
    47904787         */
    4791         VMMRZCallRing3Disable(pVCpu);
    4792         VMMRZCallRing3RemoveNotification(pVCpu);
    47934788        hmR0SvmPreRunGuestCommitted(pVCpu, &SvmTransient);
    47944789
     
    49544949VMMR0DECL(VBOXSTRICTRC) SVMR0RunGuestCode(PVMCPUCC pVCpu)
    49554950{
     4951    AssertPtr(pVCpu);
     4952    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
    49564953    Assert(VMMRZCallRing3IsEnabled(pVCpu));
     4954    Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
    49574955    HMSVM_ASSERT_PREEMPT_SAFE(pVCpu);
    4958     VMMRZCallRing3SetNotification(pVCpu, hmR0SvmCallRing3Callback, NULL /* pvUser */);
    49594956
    49604957    uint32_t cLoops = 0;
    49614958    int      rc;
    49624959#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    4963     if (!CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx))
     4960    if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
    49644961#endif
    49654962    {
     
    49964993    /* Prepare to return to ring-3. This will remove longjmp notifications. */
    49974994    rc = hmR0SvmExitToRing3(pVCpu, rc);
     4995    Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
    49984996    Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
    49994997    return rc;
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.h

    r80274 r80587  
    4141VMMR0DECL(int)          SVMR0Enter(PVMCPUCC pVCpu);
    4242VMMR0DECL(void)         SVMR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit);
     43VMMR0DECL(int)          SVMR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation);
    4344VMMR0DECL(int)          SVMR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvPageCpu, RTHCPHYS HCPhysCpuPage,
    4445                                       bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs);
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r80580 r80587  
    72527252{
    72537253    int      rc   = VINF_SUCCESS;
    7254     PVMCC      pVM  = pVCpu->CTX_SUFF(pVM);
     7254    PVMCC    pVM  = pVCpu->CTX_SUFF(pVM);
    72557255    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
    72567256    uint32_t u32Val;
     
    75557555     * Honor any pending CR3 updates.
    75567556     *
    7557      * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
     7557     * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
    75587558     * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
    75597559     * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
     
    78737873    /*
    78747874     * !!! IMPORTANT !!!
    7875      * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
     7875     * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
    78767876     */
    78777877
     
    80018001    /*
    80028002     * !!! IMPORTANT !!!
    8003      * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
     8003     * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
    80048004     */
    80058005
     
    80108010    VMMR0ThreadCtxHookDisable(pVCpu);
    80118011
    8012     /* Leave HM context. This takes care of local init (term). */
     8012    /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
    80138013    int rc = HMR0LeaveCpu(pVCpu);
    8014 
    80158014    HM_RESTORE_PREEMPT();
    80168015    return rc;
     
    81238122
    81248123    /* Thread-context hooks are unregistered at this point!!! */
     8124    /* Ring-3 callback notifications are unregistered at this point!!! */
    81258125
    81268126    /* Sync recompiler state. */
     
    81508150
    81518151    STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
    8152 
    8153     /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
    8154     VMMRZCallRing3RemoveNotification(pVCpu);
    81558152    VMMRZCallRing3Enable(pVCpu);
    8156 
    81578153    return rc;
    81588154}
     
    81668162 * @param   pVCpu           The cross context virtual CPU structure.
    81678163 * @param   enmOperation    The operation causing the ring-3 longjump.
    8168  * @param   pvUser          User argument, currently unused, NULL.
    8169  */
    8170 static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
    8171 {
    8172     RT_NOREF(pvUser);
     8164 */
     8165VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
     8166{
    81738167    if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
    81748168    {
     
    81808174        VMMRZCallRing3RemoveNotification(pVCpu);
    81818175        VMMRZCallRing3Disable(pVCpu);
    8182         RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    8183         RTThreadPreemptDisable(&PreemptState);
     8176        HM_DISABLE_PREEMPT(pVCpu);
    81848177
    81858178        PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
     
    82088201        /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
    82098202        VMMR0ThreadCtxHookDisable(pVCpu);
     8203
     8204        /* Leave HM context. This takes care of local init (term). */
    82108205        HMR0LeaveCpu(pVCpu);
    8211         RTThreadPreemptRestore(&PreemptState);
     8206        HM_RESTORE_PREEMPT();
    82128207        return VINF_SUCCESS;
    82138208    }
    82148209
    82158210    Assert(pVCpu);
    8216     Assert(pvUser);
    82178211    Assert(VMMRZCallRing3IsEnabled(pVCpu));
    82188212    HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
     
    1236312357    HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
    1236412358
    12365     VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
    12366 
    1236712359    VBOXSTRICTRC rcStrict;
    1236812360    uint32_t     cLoops = 0;
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.h

    r80274 r80587  
    3333VMMR0DECL(int)          VMXR0Enter(PVMCPUCC pVCpu);
    3434VMMR0DECL(void)         VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit);
     35VMMR0DECL(int)          VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation);
    3536VMMR0DECL(int)          VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys,
    3637                                       bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs);
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r80531 r80587  
    10151015     * @bugref{7726#c19} explains the need for this trick:
    10161016     *
    1017      *      hmR0VmxCallRing3Callback/hmR0SvmCallRing3Callback &
     1017     *      VMXR0CallRing3Callback/SVMR0CallRing3Callback &
    10181018     *      hmR0VmxLeaveSession/hmR0SvmLeaveSession disables context hooks during
    10191019     *      longjmp & normal return to ring-3, which opens a window where we may be
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