VirtualBox

Ignore:
Timestamp:
Apr 19, 2013 12:09:02 PM (12 years ago)
Author:
vboxsync
Message:

VMMR0/HMVMXR0: Simultaneous hyper and guest single-stepping support when there is no Monitor Trap Flag capability on the CPU.

File:
1 edited

Legend:

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

    r45637 r45639  
    30583058    if (DBGFIsStepping(pVCpu))
    30593059    {
    3060         /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF. */
     3060        /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
    30613061        if (pVM->hm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG)
    30623062        {
     
    30663066            Assert(fInterceptDB == false);
    30673067        }
    3068         else if (pCtx->eflags.Bits.u1TF)    /* If the guest is using its TF bit, we cannot single step in DBGF. */
    3069         {
    3070             Assert(fInterceptDB == false);
    3071             /** @todo can we somehow signal DBGF that it cannot single-step instead of
    3072              *        just continuing? */
    3073         }
    30743068        else
    30753069            fInterceptDB = true;
    30763070    }
    3077     else
    3078         Assert(fInterceptDB == false);      /* If we are not single stepping in DBGF, there is no need to intercept #DB. */
    3079 
    3080 
    3081     /*
    3082      * If the guest is using its DRx registers and the host DRx does not yet contain the guest DRx values,
    3083      * load the guest DRx registers into the host and don't cause VM-exits on guest's MOV DRx accesses.
    3084      * The same for the hypervisor DRx registers, priority is for the guest here.
    3085      */
    3086     if (pCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
     3071
     3072    if (CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
     3073    {
     3074        if (!CPUMIsHyperDebugStateActive(pVCpu))
     3075        {
     3076            rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
     3077            AssertRC(rc);
     3078        }
     3079        Assert(CPUMIsHyperDebugStateActive(pVCpu));
     3080        fInterceptMovDRx = true;
     3081    }
     3082    else if (pCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
    30873083    {
    30883084        if (!CPUMIsGuestDebugStateActive(pVCpu))
     
    30953091        Assert(fInterceptMovDRx == false);
    30963092    }
    3097     else if (CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
    3098     {
    3099         if (!CPUMIsHyperDebugStateActive(pVCpu))
    3100         {
    3101             rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
    3102             AssertRC(rc);
    3103         }
    3104         Assert(CPUMIsHyperDebugStateActive(pVCpu));
    3105         fInterceptMovDRx = true;
    3106     }
    31073093    else if (!CPUMIsGuestDebugStateActive(pVCpu))
    31083094    {
    3109         /* For the first time we would need to intercept MOV DRx accesses even when the guest debug state isn't active. */
     3095        /* For the first time we would need to intercept MOV DRx accesses even when the guest debug registers aren't loaded. */
    31103096        fInterceptMovDRx = true;
    31113097    }
     
    85268512            ASMSetDR6(pMixedCtx->dr[6]);
    85278513
     8514        rc = hmR0VmxSaveGuestDebugRegs(pVCpu, pMixedCtx);
     8515
    85288516        /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
    85298517        pMixedCtx->dr[7] &= ~X86_DR7_GD;
     
    85358523
    85368524        /* Resync DR7. */
    8537         rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_DR7, pMixedCtx->dr[7]);
    8538 
    8539         rc |= hmR0VmxReadExitIntrInfoVmcs(pVCpu, pVmxTransient);
    8540         rc |= hmR0VmxReadExitInstrLenVmcs(pVCpu, pVmxTransient);
    8541         rc |= hmR0VmxReadExitIntrErrorCodeVmcs(pVCpu, pVmxTransient);
     8525        rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_DR7, pMixedCtx->dr[7]);
    85428526        AssertRCReturn(rc,rc);
     8527    }
     8528
     8529    /*
     8530     * If the #DB exception was meant for the guest, reflect it to the guest upon VM-reentry. If our hypervisor is
     8531     * simultaneously single-stepping with the guest, return to the debugger but also reflect #DB to the guest upon VM-reentry.
     8532     */
     8533    if (   rc == VINF_EM_RAW_GUEST_TRAP
     8534        || rc == VINF_EM_DBG_STEPPED)
     8535    {
     8536        int rc2 = hmR0VmxReadExitIntrInfoVmcs(pVCpu, pVmxTransient);
     8537        rc2 |= hmR0VmxReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     8538        rc2 |= hmR0VmxReadExitIntrErrorCodeVmcs(pVCpu, pVmxTransient);
     8539        AssertRCReturn(rc2, rc2);
    85438540        hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    85448541                               pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    8545         return rc;
    8546     }
    8547     /* Return to ring 3 to deal with the debug exit code. */
     8542        if (rc == VINF_EM_RAW_GUEST_TRAP)
     8543            rc = VINF_SUCCESS;
     8544    }
    85488545    return rc;
    85498546}
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