VirtualBox

Changeset 93831 in vbox


Ignore:
Timestamp:
Feb 17, 2022 4:58:36 PM (3 years ago)
Author:
vboxsync
Message:

VMM/{VMXAllTemplate.cpp.h,NEMR3Native-darwin}: Add code to allow for single stepping and sharing the guest's DRx state with th hypervisor debugger (hardware breakpoints, etc.), bugref:9044

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

Legend:

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

    r93748 r93831  
    85938593            VMMRZCallRing3Enable(pVCpu);
    85948594#else
    8595             /** @todo */
     8595            CPUMR3NemActivateGuestDebugState(pVCpu);
     8596            Assert(CPUMIsGuestDebugStateActive(pVCpu));
     8597            Assert(!CPUMIsHyperDebugStateActive(pVCpu));
    85968598#endif
    85978599
     
    1070010702    pDbgState->fCpe1Extra       &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1;
    1070110703    pDbgState->fCpe1Unwanted    &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0;
    10702 #ifndef IN_NEM_DARWIN /** @todo */
     10704#ifndef IN_NEM_DARWIN
    1070310705    if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
    1070410706    {
    1070510707        pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
     10708        pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
     10709    }
     10710#else
     10711    if (pVCpu->nem.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
     10712    {
     10713        pVCpu->nem.s.fDebugWantRdTscExit ^= true;
    1070610714        pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
    1070710715    }
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp

    r93826 r93831  
    14691469
    14701470/**
     1471 * Exports the guest debug registers into the guest-state applying any hypervisor
     1472 * debug related states (hardware breakpoints from the debugger, etc.).
     1473 *
     1474 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
     1475 *
     1476 * @returns VBox status code.
     1477 * @param   pVCpu           The cross context virtual CPU structure.
     1478 * @param   pVmxTransient   The VMX-transient structure.
     1479 */
     1480static int nemR3DarwinExportDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
     1481{
     1482    PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
     1483
     1484#ifdef VBOX_STRICT
     1485    /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
     1486    if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
     1487    {
     1488        /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
     1489        Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
     1490        Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
     1491    }
     1492#endif
     1493
     1494    bool     fSteppingDB      = false;
     1495    bool     fInterceptMovDRx = false;
     1496    uint32_t uProcCtls        = pVmcsInfo->u32ProcCtls;
     1497    if (pVCpu->nem.s.fSingleInstruction)
     1498    {
     1499        /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
     1500        if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
     1501        {
     1502            uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
     1503            Assert(fSteppingDB == false);
     1504        }
     1505        else
     1506        {
     1507            pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
     1508            pVCpu->nem.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
     1509            pVCpu->nem.s.fClearTrapFlag = true;
     1510            fSteppingDB = true;
     1511        }
     1512    }
     1513
     1514    uint64_t u64GuestDr7;
     1515    if (   fSteppingDB
     1516        || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
     1517    {
     1518        /*
     1519         * Use the combined guest and host DRx values found in the hypervisor register set
     1520         * because the hypervisor debugger has breakpoints active or someone is single stepping
     1521         * on the host side without a monitor trap flag.
     1522         *
     1523         * Note! DBGF expects a clean DR6 state before executing guest code.
     1524         */
     1525        if (!CPUMIsHyperDebugStateActive(pVCpu))
     1526        {
     1527            /*
     1528             * Make sure the hypervisor values are up to date.
     1529             */
     1530            CPUMRecalcHyperDRx(pVCpu, UINT8_MAX /* no loading, please */);
     1531
     1532            CPUMR3NemActivateHyperDebugState(pVCpu);
     1533
     1534            Assert(CPUMIsHyperDebugStateActive(pVCpu));
     1535            Assert(!CPUMIsGuestDebugStateActive(pVCpu));
     1536        }
     1537
     1538        /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
     1539        u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
     1540        pVCpu->nem.s.fUsingHyperDR7 = true;
     1541        fInterceptMovDRx = true;
     1542    }
     1543    else
     1544    {
     1545        /*
     1546         * If the guest has enabled debug registers, we need to load them prior to
     1547         * executing guest code so they'll trigger at the right time.
     1548         */
     1549        HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
     1550        if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
     1551        {
     1552            if (!CPUMIsGuestDebugStateActive(pVCpu))
     1553            {
     1554                CPUMR3NemActivateGuestDebugState(pVCpu);
     1555
     1556                Assert(CPUMIsGuestDebugStateActive(pVCpu));
     1557                Assert(!CPUMIsHyperDebugStateActive(pVCpu));
     1558            }
     1559            Assert(!fInterceptMovDRx);
     1560        }
     1561        else if (!CPUMIsGuestDebugStateActive(pVCpu))
     1562        {
     1563            /*
     1564             * If no debugging enabled, we'll lazy load DR0-3.  Unlike on AMD-V, we
     1565             * must intercept #DB in order to maintain a correct DR6 guest value, and
     1566             * because we need to intercept it to prevent nested #DBs from hanging the
     1567             * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
     1568             */
     1569            fInterceptMovDRx = true;
     1570        }
     1571
     1572        /* Update DR7 with the actual guest value. */
     1573        u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
     1574        pVCpu->nem.s.fUsingHyperDR7 = false;
     1575    }
     1576
     1577    if (fInterceptMovDRx)
     1578        uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
     1579    else
     1580        uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
     1581
     1582    /*
     1583     * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
     1584     * monitor-trap flag and update our cache.
     1585     */
     1586    if (uProcCtls != pVmcsInfo->u32ProcCtls)
     1587    {
     1588        int rc = nemR3DarwinWriteVmcs32(pVCpu, VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
     1589        AssertRC(rc);
     1590        pVmcsInfo->u32ProcCtls = uProcCtls;
     1591    }
     1592
     1593    /*
     1594     * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
     1595     * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
     1596     *
     1597     * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
     1598     */
     1599    if (fSteppingDB)
     1600    {
     1601        Assert(pVCpu->nem.s.fSingleInstruction);
     1602        Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
     1603
     1604        uint32_t fIntrState = 0;
     1605        int rc = nemR3DarwinReadVmcs32(pVCpu, VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
     1606        AssertRC(rc);
     1607
     1608        if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
     1609        {
     1610            fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
     1611            rc = nemR3DarwinWriteVmcs32(pVCpu, VMX_VMCS32_GUEST_INT_STATE, fIntrState);
     1612            AssertRC(rc);
     1613        }
     1614    }
     1615
     1616    /*
     1617     * Store status of the shared guest/host debug state at the time of VM-entry.
     1618     */
     1619    pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
     1620    pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
     1621
     1622    return VINF_SUCCESS;
     1623}
     1624
     1625
     1626/**
    14711627 * Converts the given CPUM externalized bitmask to the appropriate HM changed bitmask.
    14721628 *
     
    16611817    }
    16621818
     1819    rc = nemR3DarwinExportDebugState(pVCpu, pVmxTransient);
     1820    AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
     1821
    16631822    vmxHCExportGuestXcptIntercepts(pVCpu, pVmxTransient);
    16641823    vmxHCExportGuestRip(pVCpu);
     
    16901849    if (fWhat & CPUMCTX_EXTRN_DR0_DR3)
    16911850    {
    1692         WRITE_GREG(HV_X86_DR0, pVCpu->cpum.GstCtx.dr[0]); // CPUMGetHyperDR0(pVCpu));
    1693         WRITE_GREG(HV_X86_DR1, pVCpu->cpum.GstCtx.dr[1]); // CPUMGetHyperDR1(pVCpu));
    1694         WRITE_GREG(HV_X86_DR2, pVCpu->cpum.GstCtx.dr[2]); // CPUMGetHyperDR2(pVCpu));
    1695         WRITE_GREG(HV_X86_DR3, pVCpu->cpum.GstCtx.dr[3]); // CPUMGetHyperDR3(pVCpu));
     1851        WRITE_GREG(HV_X86_DR0, CPUMGetHyperDR0(pVCpu));
     1852        WRITE_GREG(HV_X86_DR1, CPUMGetHyperDR1(pVCpu));
     1853        WRITE_GREG(HV_X86_DR2, CPUMGetHyperDR2(pVCpu));
     1854        WRITE_GREG(HV_X86_DR3, CPUMGetHyperDR3(pVCpu));
    16961855        ASMAtomicUoAndU64(&pVCpu->nem.s.fCtxChanged, ~HM_CHANGED_GUEST_DR0_DR3);
    16971856    }
    16981857    if (fWhat & CPUMCTX_EXTRN_DR6)
    16991858    {
    1700         WRITE_GREG(HV_X86_DR6, pVCpu->cpum.GstCtx.dr[6]); // CPUMGetHyperDR6(pVCpu));
     1859        WRITE_GREG(HV_X86_DR6, CPUMGetHyperDR6(pVCpu));
    17011860        ASMAtomicUoAndU64(&pVCpu->nem.s.fCtxChanged, ~HM_CHANGED_GUEST_DR6);
    17021861    }
    17031862    if (fWhat & CPUMCTX_EXTRN_DR7)
    17041863    {
    1705         WRITE_GREG(HV_X86_DR7, pVCpu->cpum.GstCtx.dr[7]); // CPUMGetHyperDR7(pVCpu));
     1864        WRITE_GREG(HV_X86_DR7, CPUMGetHyperDR7(pVCpu));
    17061865        ASMAtomicUoAndU64(&pVCpu->nem.s.fCtxChanged, ~HM_CHANGED_GUEST_DR7);
    17071866    }
     
    32053364
    32063365/**
     3366 * Prepares the VM to run the guest.
     3367 *
     3368 * @returns Strict VBox status code.
     3369 * @param   pVM                 The cross context VM structure.
     3370 * @param   pVCpu               The cross context virtual CPU structure.
     3371 * @param   pVmxTransient       The VMX transient state.
     3372 * @param   fSingleStepping     Flag whether we run in single stepping mode.
     3373 */
     3374static VBOXSTRICTRC nemR3DarwinPreRunGuest(PVM pVM, PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fSingleStepping)
     3375{
     3376    /*
     3377     * Check and process force flag actions, some of which might require us to go back to ring-3.
     3378     */
     3379    VBOXSTRICTRC rcStrict = vmxHCCheckForceFlags(pVCpu, false /*fIsNestedGuest*/, fSingleStepping);
     3380    if (rcStrict == VINF_SUCCESS)
     3381    { /*likely */ }
     3382    else
     3383        return rcStrict;
     3384
     3385    /*
     3386     * Do not execute in HV if the A20 isn't enabled.
     3387     */
     3388    if (PGMPhysIsA20Enabled(pVCpu))
     3389    { /* likely */ }
     3390    else
     3391    {
     3392        LogFlow(("NEM/%u: breaking: A20 disabled\n", pVCpu->idCpu));
     3393        return VINF_EM_RESCHEDULE_REM;
     3394    }
     3395
     3396    /*
     3397     * Evaluate events to be injected into the guest.
     3398     *
     3399     * Events in TRPM can be injected without inspecting the guest state.
     3400     * If any new events (interrupts/NMI) are pending currently, we try to set up the
     3401     * guest to cause a VM-exit the next time they are ready to receive the event.
     3402     */
     3403    if (TRPMHasTrap(pVCpu))
     3404        vmxHCTrpmTrapToPendingEvent(pVCpu);
     3405
     3406    uint32_t fIntrState;
     3407    rcStrict = vmxHCEvaluatePendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, &fIntrState);
     3408
     3409    /*
     3410     * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
     3411     * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
     3412     * also result in triple-faulting the VM.
     3413     *
     3414     * With nested-guests, the above does not apply since unrestricted guest execution is a
     3415     * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
     3416     */
     3417    rcStrict = vmxHCInjectPendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, fIntrState, fSingleStepping);
     3418    if (RT_LIKELY(rcStrict == VINF_SUCCESS))
     3419    { /* likely */ }
     3420    else
     3421        return rcStrict;
     3422
     3423    int rc = nemR3DarwinExportGuestState(pVM, pVCpu, pVmxTransient);
     3424    AssertRCReturn(rc, rc);
     3425
     3426    LogFlowFunc(("Running vCPU\n"));
     3427    pVCpu->nem.s.Event.fPending = false;
     3428    return VINF_SUCCESS;
     3429}
     3430
     3431
     3432/**
    32073433 * The normal runloop (no debugging features enabled).
    32083434 *
     
    32303456    uint64_t       offDeltaIgnored;
    32313457    uint64_t const nsNextTimerEvt = TMTimerPollGIP(pVM, pVCpu, &offDeltaIgnored); NOREF(nsNextTimerEvt);
    3232 
    3233     const bool      fSingleStepping = DBGFIsStepping(pVCpu);
    32343458    VBOXSTRICTRC    rcStrict        = VINF_SUCCESS;
    32353459    for (unsigned iLoop = 0;; iLoop++)
    32363460    {
    3237         /*
    3238          * Check and process force flag actions, some of which might require us to go back to ring-3.
    3239          */
    3240         rcStrict = vmxHCCheckForceFlags(pVCpu, false /*fIsNestedGuest*/, fSingleStepping);
    3241         if (rcStrict == VINF_SUCCESS)
    3242         { /*likely */ }
    3243         else
    3244         {
    3245             if (rcStrict == VINF_EM_RAW_TO_R3)
    3246                 rcStrict = VINF_SUCCESS;
     3461        rcStrict = nemR3DarwinPreRunGuest(pVM, pVCpu, &VmxTransient, false /* fSingleStepping */);
     3462        if (rcStrict != VINF_SUCCESS)
    32473463            break;
    3248         }
    3249 
    3250         /*
    3251          * Do not execute in HV if the A20 isn't enabled.
    3252          */
    3253         if (PGMPhysIsA20Enabled(pVCpu))
    3254         { /* likely */ }
    3255         else
    3256         {
    3257             rcStrict = VINF_EM_RESCHEDULE_REM;
    3258             LogFlow(("NEM/%u: breaking: A20 disabled\n", pVCpu->idCpu));
    3259             break;
    3260         }
    3261 
    3262         /*
    3263          * Evaluate events to be injected into the guest.
    3264          *
    3265          * Events in TRPM can be injected without inspecting the guest state.
    3266          * If any new events (interrupts/NMI) are pending currently, we try to set up the
    3267          * guest to cause a VM-exit the next time they are ready to receive the event.
    3268          */
    3269         if (TRPMHasTrap(pVCpu))
    3270             vmxHCTrpmTrapToPendingEvent(pVCpu);
    3271 
    3272         uint32_t fIntrState;
    3273         rcStrict = vmxHCEvaluatePendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, &fIntrState);
    3274 
    3275         /*
    3276          * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
    3277          * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
    3278          * also result in triple-faulting the VM.
    3279          *
    3280          * With nested-guests, the above does not apply since unrestricted guest execution is a
    3281          * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
    3282          */
    3283         rcStrict = vmxHCInjectPendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, fIntrState, fSingleStepping);
    3284         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    3285         { /* likely */ }
    3286         else
    3287         {
    3288             AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fSingleStepping),
    3289                       ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    3290             break;
    3291         }
    3292 
    3293         int rc = nemR3DarwinExportGuestState(pVM, pVCpu, &VmxTransient);
    3294         AssertRCReturn(rc, rc);
    3295 
    3296         LogFlowFunc(("Running vCPU\n"));
    3297         pVCpu->nem.s.Event.fPending = false;
    32983464
    32993465        hv_return_t hrc = nemR3DarwinRunGuest(pVM, pVCpu, &VmxTransient);
     
    33123478                break;
    33133479            }
    3314             //Assert(!pVCpu->cpum.GstCtx.fExtrn);
    33153480        }
    33163481        else
     
    34783643    VmxTransient.pVmcsInfo = &pVCpu->nem.s.VmcsInfo;
    34793644
     3645    bool const fSavedSingleInstruction = pVCpu->nem.s.fSingleInstruction;
     3646    pVCpu->nem.s.fSingleInstruction    = pVCpu->nem.s.fSingleInstruction || DBGFIsStepping(pVCpu);
     3647    pVCpu->nem.s.fDebugWantRdTscExit   = false;
     3648    pVCpu->nem.s.fUsingDebugLoop       = true;
     3649
    34803650    /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps.  */
    34813651    VMXRUNDBGSTATE DbgState;
     
    34903660    uint64_t       offDeltaIgnored;
    34913661    uint64_t const nsNextTimerEvt = TMTimerPollGIP(pVM, pVCpu, &offDeltaIgnored); NOREF(nsNextTimerEvt);
    3492 
    3493     const bool      fSingleStepping = DBGFIsStepping(pVCpu);
    34943662    VBOXSTRICTRC    rcStrict        = VINF_SUCCESS;
    34953663    for (unsigned iLoop = 0;; iLoop++)
    34963664    {
     3665        bool fStepping = pVCpu->nem.s.fSingleInstruction;
     3666
    34973667        /* Set up VM-execution controls the next two can respond to. */
    34983668        vmxHCPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
    34993669
    3500         /*
    3501          * Check and process force flag actions, some of which might require us to go back to ring-3.
    3502          */
    3503         rcStrict = vmxHCCheckForceFlags(pVCpu, false /*fIsNestedGuest*/, fSingleStepping);
    3504         if (rcStrict == VINF_SUCCESS)
    3505         { /*likely */ }
    3506         else
    3507         {
    3508             if (rcStrict == VINF_EM_RAW_TO_R3)
    3509                 rcStrict = VINF_SUCCESS;
     3670        rcStrict = nemR3DarwinPreRunGuest(pVM, pVCpu, &VmxTransient, fStepping);
     3671        if (rcStrict != VINF_SUCCESS)
    35103672            break;
    3511         }
    3512 
    3513         /*
    3514          * Do not execute in HV if the A20 isn't enabled.
    3515          */
    3516         if (PGMPhysIsA20Enabled(pVCpu))
    3517         { /* likely */ }
    3518         else
    3519         {
    3520             rcStrict = VINF_EM_RESCHEDULE_REM;
    3521             LogFlow(("NEM/%u: breaking: A20 disabled\n", pVCpu->idCpu));
    3522             break;
    3523         }
    3524 
    3525         /*
    3526          * Evaluate events to be injected into the guest.
    3527          *
    3528          * Events in TRPM can be injected without inspecting the guest state.
    3529          * If any new events (interrupts/NMI) are pending currently, we try to set up the
    3530          * guest to cause a VM-exit the next time they are ready to receive the event.
    3531          */
    3532         if (TRPMHasTrap(pVCpu))
    3533             vmxHCTrpmTrapToPendingEvent(pVCpu);
    3534 
    3535         uint32_t fIntrState;
    3536         rcStrict = vmxHCEvaluatePendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, &fIntrState);
    3537 
    3538         /*
    3539          * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
    3540          * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
    3541          * also result in triple-faulting the VM.
    3542          *
    3543          * With nested-guests, the above does not apply since unrestricted guest execution is a
    3544          * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
    3545          */
    3546         rcStrict = vmxHCInjectPendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, false /*fIsNestedGuest*/, fIntrState, fSingleStepping);
    3547         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    3548         { /* likely */ }
    3549         else
    3550         {
    3551             AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fSingleStepping),
    3552                       ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    3553             break;
    3554         }
    3555 
    3556         int rc = nemR3DarwinExportGuestState(pVM, pVCpu, &VmxTransient);
    3557         AssertRCReturn(rc, rc);
    3558 
    3559         LogFlowFunc(("Running vCPU\n"));
    3560         pVCpu->nem.s.Event.fPending = false;
    3561 
    3562         /* Override any obnoxious code in the above two calls. */
     3673
     3674        /* Override any obnoxious code in the above call. */
    35633675        vmxHCPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
    35643676
     
    35783690                break;
    35793691            }
    3580             //Assert(!pVCpu->cpum.GstCtx.fExtrn);
     3692
     3693            /*
     3694             * Stepping: Did the RIP change, if so, consider it a single step.
     3695             * Otherwise, make sure one of the TFs gets set.
     3696             */
     3697            if (fStepping)
     3698            {
     3699                int rc = vmxHCImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
     3700                AssertRC(rc);
     3701                if (   pVCpu->cpum.GstCtx.rip    != DbgState.uRipStart
     3702                    || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
     3703                {
     3704                    rcStrict = VINF_EM_DBG_STEPPED;
     3705                    break;
     3706                }
     3707                ASMAtomicUoOrU64(&pVCpu->nem.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
     3708            }
    35813709        }
    35823710        else
     
    35873715        }
    35883716    } /* the run loop */
     3717
     3718    /*
     3719     * Clear the X86_EFL_TF if necessary.
     3720     */
     3721    if (pVCpu->nem.s.fClearTrapFlag)
     3722    {
     3723        int rc = vmxHCImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
     3724        AssertRC(rc);
     3725        pVCpu->nem.s.fClearTrapFlag = false;
     3726        pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
     3727    }
     3728
     3729    pVCpu->nem.s.fUsingDebugLoop     = false;
     3730    pVCpu->nem.s.fDebugWantRdTscExit = false;
     3731    pVCpu->nem.s.fSingleInstruction  = fSavedSingleInstruction;
    35893732
    35903733    /* Restore all controls applied by vmxHCPreRunGuestDebugStateApply above. */
     
    36233766    else
    36243767        rcStrict = nemR3DarwinRunGuestDebug(pVM, pVCpu);
     3768
     3769    if (rcStrict == VINF_EM_RAW_TO_R3)
     3770        rcStrict = VINF_SUCCESS;
    36253771
    36263772    /*
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r93787 r93831  
    335335    /** Whether we're executing a single instruction. */
    336336    bool                        fSingleInstruction : 1;
     337    /** Set if we using the debug loop and wish to intercept RDTSC. */
     338    bool                        fDebugWantRdTscExit : 1;
     339    /** Whether we are currently executing in the debug loop.
     340     *  Mainly for assertions. */
     341    bool                        fUsingDebugLoop : 1;
     342    /** Set if we need to clear the trap flag because of single stepping. */
     343    bool                        fClearTrapFlag : 1;
     344    /** Whether we're using the hyper DR7 or guest DR7. */
     345    bool                        fUsingHyperDR7 : 1;
    337346
    338347#if defined(RT_OS_LINUX)
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