VirtualBox

Changeset 12578 in vbox for trunk/src


Ignore:
Timestamp:
Sep 18, 2008 2:58:57 PM (16 years ago)
Author:
vboxsync
Message:

Enable hardware breakpoint support for VT-x and AMD-V.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/CPUM.cpp

    r12542 r12578  
    709709
    710710    pCtx->dr6                       = X86_DR6_INIT_VAL;
    711     pCtx->dr7                       = 0x400;
     711    pCtx->dr7                       = X86_DR7_INIT_VAL;
    712712
    713713    pCtx->fpu.FTW                   = 0xff;         /* All tags are set, i.e. the regs are empty. */
  • trunk/src/VBox/VMM/HWACCM.cpp

    r12554 r12578  
    163163    STAM_REG(pVM, &pVM->hwaccm.s.StatTSCIntercept,          STAMTYPE_COUNTER, "/HWACCM/TSC/Intercept",     STAMUNIT_OCCURENCES,    "Nr of occurances");
    164164
    165     STAM_REG(pVM, &pVM->hwaccm.s.StatDR0Armed,              STAMTYPE_COUNTER, "/HWACCM/Debug/Armed/DR0",   STAMUNIT_OCCURENCES,    "Nr of occurances");
    166     STAM_REG(pVM, &pVM->hwaccm.s.StatDR1Armed,              STAMTYPE_COUNTER, "/HWACCM/Debug/Armed/DR1",   STAMUNIT_OCCURENCES,    "Nr of occurances");
    167     STAM_REG(pVM, &pVM->hwaccm.s.StatDR2Armed,              STAMTYPE_COUNTER, "/HWACCM/Debug/Armed/DR2",   STAMUNIT_OCCURENCES,    "Nr of occurances");
    168     STAM_REG(pVM, &pVM->hwaccm.s.StatDR3Armed,              STAMTYPE_COUNTER, "/HWACCM/Debug/Armed/DR3",   STAMUNIT_OCCURENCES,    "Nr of occurances");
     165    STAM_REG(pVM, &pVM->hwaccm.s.StatDRxArmed,              STAMTYPE_COUNTER, "/HWACCM/Debug/Armed",           STAMUNIT_OCCURENCES,    "Nr of occurances");
    169166    STAM_REG(pVM, &pVM->hwaccm.s.StatDRxContextSwitch,      STAMTYPE_COUNTER, "/HWACCM/Debug/ContextSwitch",   STAMUNIT_OCCURENCES,    "Nr of occurances");
    170167
  • trunk/src/VBox/VMM/HWACCMInternal.h

    r12566 r12578  
    112112 */
    113113#ifdef VBOX_STRICT
    114 #define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_DE) | RT_BIT(X86_XCPT_DB) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF) | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NP) | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) | RT_BIT(X86_XCPT_MF)
     114#define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_DE) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF) | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NP) | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) | RT_BIT(X86_XCPT_MF)
    115115#define HWACCM_SVM_TRAP_MASK                HWACCM_VMX_TRAP_MASK
    116116#else
    117 #define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_DB) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF)
     117#define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF)
    118118#define HWACCM_SVM_TRAP_MASK                RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF)
    119119#endif
     
    285285        uint32_t                    ulLastInstrError;
    286286
     287        /** Current trap mask. */
     288        uint32_t                    u32TrapMask;
     289
    287290        struct
    288291        {
     
    377380    /** Currenty shadow paging mode. */
    378381    PGMMODE                 enmShadowMode;
    379 
    380 
    381 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    382     struct
    383     {
    384         /* Saved host debug registers. */
    385         uint64_t                dr0, dr1, dr2, dr3, dr6, dr7;
    386         bool                    fHostDR7Saved;
    387         bool                    fHostDebugRegsSaved;
    388     } savedhoststate;
    389 #endif
    390382
    391383#ifdef VBOX_STRICT
     
    450442
    451443    STAMCOUNTER             StatExitReasonNPF;
    452     STAMCOUNTER             StatDR0Armed;
    453     STAMCOUNTER             StatDR1Armed;
    454     STAMCOUNTER             StatDR2Armed;
    455     STAMCOUNTER             StatDR3Armed;
     444    STAMCOUNTER             StatDRxArmed;
    456445    STAMCOUNTER             StatDRxContextSwitch;
    457446
     
    484473/* Dummy callback handlers. */
    485474HWACCMR0DECL(int) HWACCMR0DummyEnter(PVM pVM, PHWACCM_CPUINFO pCpu);
    486 HWACCMR0DECL(int) HWACCMR0DummyLeave(PVM pVM);
     475HWACCMR0DECL(int) HWACCMR0DummyLeave(PVM pVM, CPUMCTX *pCtx);
    487476HWACCMR0DECL(int) HWACCMR0DummyEnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
    488477HWACCMR0DECL(int) HWACCMR0DummyDisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r11704 r12578  
    18061806
    18071807
     1808
     1809/**
     1810 * Checks if the guest debug state is active
     1811 *
     1812 * @returns boolean
     1813 * @param   pVM         VM handle.
     1814 */
     1815CPUMDECL(bool) CPUMIsGuestDebugStateActive(PVM pVM)
     1816{
     1817    return (pVM->cpum.s.fUseFlags & CPUM_USE_DEBUG_REGS) != 0;
     1818}
     1819
     1820/**
     1821 * Mark the guest's debug state as inactive
     1822 *
     1823 * @returns boolean
     1824 * @param   pVM         VM handle.
     1825 */
     1826CPUMDECL(void) CPUMDeactivateGuestDebugtate(PVM pVM)
     1827{
     1828    pVM->cpum.s.fUseFlags &= ~CPUM_USE_DEBUG_REGS;
     1829}
     1830
     1831
    18081832/**
    18091833 * Checks if the hidden selector registers are valid
  • trunk/src/VBox/VMM/VMMR0/CPUMR0.cpp

    r12227 r12578  
    167167#ifndef CPUM_CAN_HANDLE_NM_TRAPS_IN_KERNEL_MODE
    168168    uint64_t oldMsrEFERHost;
    169         uint32_t oldCR0 = ASMGetCR0();
     169    uint32_t oldCR0 = ASMGetCR0();
    170170
    171171    /* Clear MSR_K6_EFER_FFXSR or else we'll be unable to save/restore the XMM state with fxsave/fxrstor. */
     
    194194    ASMSetCR0(oldCR0);
    195195#else
    196     /* Save the FPU control word and MXCSR, so we can restore the properly afterwards.
     196    /* Save the FPU control word and MXCSR, so we can restore the state properly afterwards.
    197197     * We don't want the guest to be able to trigger floating point/SSE exceptions on the host.
    198198     */
     
    272272    return VINF_SUCCESS;
    273273}
     274
     275
     276/**
     277 * Save guest debug state
     278 *
     279 * @returns VBox status code.
     280 * @param   pVM         VM handle.
     281 * @param   pCtx        CPU context
     282 * @param   fDR6        Include DR6 or not
     283 */
     284CPUMR0DECL(int) CPUMR0SaveGuestDebugState(PVM pVM, PCPUMCTX pCtx, bool fDR6)
     285{
     286    Assert(pVM->cpum.s.fUseFlags & CPUM_USE_DEBUG_REGS);
     287
     288    /* Save the guest's debug state. The caller is responsible for DR7. */
     289    pCtx->dr0 = ASMGetDR0();
     290    pCtx->dr1 = ASMGetDR1();
     291    pCtx->dr2 = ASMGetDR2();
     292    pCtx->dr3 = ASMGetDR3();
     293    if (fDR6)
     294        pCtx->dr6 = ASMGetDR6();
     295
     296    /* Restore the host's debug state. DR0-3, DR6 and only then DR7! */
     297    ASMSetDR0(pVM->cpum.s.Host.dr0);
     298    ASMSetDR1(pVM->cpum.s.Host.dr1);
     299    ASMSetDR2(pVM->cpum.s.Host.dr2);
     300    ASMSetDR3(pVM->cpum.s.Host.dr3);
     301    ASMSetDR6(pVM->cpum.s.Host.dr6);
     302    ASMSetDR7(pVM->cpum.s.Host.dr7);
     303
     304    pVM->cpum.s.fUseFlags &= ~CPUM_USE_DEBUG_REGS;
     305    return VINF_SUCCESS;
     306}
     307
     308
     309/**
     310 * Lazily sync in the debug state
     311 *
     312 * @returns VBox status code.
     313 * @param   pVM         VM handle.
     314 * @param   pCtx        CPU context
     315 * @param   fDR6        Include DR6 or not
     316 */
     317CPUMR0DECL(int) CPUMR0LoadGuestDebugState(PVM pVM, PCPUMCTX pCtx, bool fDR6)
     318{
     319    /* Save the host state. */
     320    pVM->cpum.s.Host.dr0 = ASMGetDR0();
     321    pVM->cpum.s.Host.dr1 = ASMGetDR1();
     322    pVM->cpum.s.Host.dr2 = ASMGetDR2();
     323    pVM->cpum.s.Host.dr3 = ASMGetDR3();
     324    pVM->cpum.s.Host.dr6 = ASMGetDR6();
     325    pVM->cpum.s.Host.dr7 = ASMGetDR7();
     326    /* Make sure DR7 is harmless or else we could trigger breakpoints when restoring dr0-3 (!) */
     327    ASMSetDR7(X86_DR7_INIT_VAL);
     328
     329    /* Activate the guest state DR0-3; DR7 is left to the caller. */
     330    ASMSetDR0(pCtx->dr0);
     331    ASMSetDR1(pCtx->dr1);
     332    ASMSetDR2(pCtx->dr2);
     333    ASMSetDR3(pCtx->dr3);
     334    if (fDR6)
     335        ASMSetDR6(pCtx->dr6);
     336
     337    pVM->cpum.s.fUseFlags |= CPUM_USE_DEBUG_REGS;
     338    return VINF_SUCCESS;
     339}
  • trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp

    r12554 r12578  
    6464    /** Ring 0 handlers for VT-x and AMD-V. */
    6565    DECLR0CALLBACKMEMBER(int, pfnEnterSession,(PVM pVM, PHWACCM_CPUINFO pCpu));
    66     DECLR0CALLBACKMEMBER(int, pfnLeaveSession,(PVM pVM));
     66    DECLR0CALLBACKMEMBER(int, pfnLeaveSession,(PVM pVM, CPUMCTX *pCtx));
    6767    DECLR0CALLBACKMEMBER(int, pfnSaveHostState,(PVM pVM));
    6868    DECLR0CALLBACKMEMBER(int, pfnLoadGuestState,(PVM pVM, CPUMCTX *pCtx));
     
    747747    CPUMDeactivateGuestFPUState(pVM);
    748748
    749 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    750     /*
    751      * Check if host debug registers are armed. All context switches set DR7 back to 0x400.
    752      */
    753     uint64_t u64DR7 = ASMGetDR7();
    754     if (u64DR7 & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
    755     {
    756         pVM->hwaccm.s.savedhoststate.dr7  = u64DR7;
    757         pVM->hwaccm.s.savedhoststate.fHostDR7Saved = true;
    758     }
    759     else
    760         pVM->hwaccm.s.savedhoststate.fHostDR7Saved = false;
    761 #endif
     749    /* Always load the guest's debug state on-demand. */
     750    CPUMDeactivateGuestDebugtate(pVM);
    762751
    763752    /* Always reload the host context and the guest's CR0 register. (!!!!) */
     
    818807    }
    819808
    820 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    821     /* Restore the host debug registers. First dr0-3, then dr6 and only then dr7! */
    822     if (pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved)
    823     {
    824         ASMSetDR0(pVM->hwaccm.s.savedhoststate.dr0);
    825         ASMSetDR1(pVM->hwaccm.s.savedhoststate.dr1);
    826         ASMSetDR2(pVM->hwaccm.s.savedhoststate.dr2);
    827         ASMSetDR3(pVM->hwaccm.s.savedhoststate.dr3);
    828         ASMSetDR6(pVM->hwaccm.s.savedhoststate.dr6);
    829         pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved = false;
    830 
    831         STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxContextSwitch);
    832     }
    833     if (pVM->hwaccm.s.savedhoststate.fHostDR7Saved)
    834     {
    835         ASMSetDR7(pVM->hwaccm.s.savedhoststate.dr7);
    836         pVM->hwaccm.s.savedhoststate.fHostDR7Saved = false;
    837     }
    838 #endif
    839 
    840     /* Resync the debug register on the next entry. */
    841     pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_DEBUG;
    842     rc = HWACCMR0Globals.pfnLeaveSession(pVM);
     809    rc = HWACCMR0Globals.pfnLeaveSession(pVM, pCtx);
    843810
    844811#ifdef VBOX_STRICT
     
    11651132}
    11661133
    1167 HWACCMR0DECL(int) HWACCMR0DummyLeave(PVM pVM)
     1134HWACCMR0DECL(int) HWACCMR0DummyLeave(PVM pVM, PCPUMCTX pCtx)
    11681135{
    11691136    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r12554 r12578  
    276276        pVMCB->ctrl.u16InterceptWrCRx = RT_BIT(0) | RT_BIT(4) | RT_BIT(8);
    277277
    278     /* Intercept all DRx reads and writes. (@todo not necessary to intercept all) */
     278    /* Intercept all DRx reads and writes by default. Changed later on. */
    279279    pVMCB->ctrl.u16InterceptRdDRx = 0xFFFF;
    280280    pVMCB->ctrl.u16InterceptWrDRx = 0xFFFF;
     
    686686    if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_DEBUG)
    687687    {
    688         pCtx->dr7 &= 0xffffffff;                                              /* upper 32 bits reserved */
    689         pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
    690         pCtx->dr7 |= 0x400;                                                   /* must be one */
    691 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
     688        pCtx->dr6 |= X86_DR6_INIT_VAL;                                          /* set all reserved bits to 1. */
     689        pCtx->dr6 &= ~RT_BIT(12);                                               /* must be zero. */
     690
     691        pCtx->dr7 &= 0xffffffff;                                                /* upper 32 bits reserved */
     692        pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));      /* must be zero */
     693        pCtx->dr7 |= 0x400;                                                     /* must be one */
     694
    692695        pVMCB->guest.u64DR7 = pCtx->dr7;
    693 #else
    694         pVMCB->guest.u64DR7 = 0x400;
    695 #endif
    696696        pVMCB->guest.u64DR6 = pCtx->dr6;
    697697
    698 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    699         /* Any guest breakpoints enabled? */
    700         if (    (pCtx->dr7 & X86_DR7_ENABLED_MASK)
    701             &&  !pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved)
    702         {
    703             /* Save the host debug register; a bit paranoid if the host has no active breakpoints set in dr7, but we
    704              * do not want anything from the guest to leak into the host!
    705              */
    706             pVM->hwaccm.s.savedhoststate.dr0 = ASMGetDR0();
    707             pVM->hwaccm.s.savedhoststate.dr1 = ASMGetDR1();
    708             pVM->hwaccm.s.savedhoststate.dr2 = ASMGetDR2();
    709             pVM->hwaccm.s.savedhoststate.dr3 = ASMGetDR3();
    710             pVM->hwaccm.s.savedhoststate.dr6 = ASMGetDR6();
    711             pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved = true;
    712 
    713             /* Make sure DR7 is harmless or else we could trigger breakpoints when restoring dr0-3 (!) */
    714             ASMSetDR7(0x400);
    715         }
    716 
    717         if (pCtx->dr7 & (X86_DR7_L0|X86_DR7_G0))
    718         {
    719             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR0Armed);
    720             ASMSetDR0(pCtx->dr0);
    721             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    722         }
    723         if (pCtx->dr7 & (X86_DR7_L1|X86_DR7_G1))
    724         {
    725             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR1Armed);
    726             ASMSetDR1(pCtx->dr1);
    727             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    728         }
    729         if (pCtx->dr7 & (X86_DR7_L2|X86_DR7_G2))
    730         {
    731             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR2Armed);
    732             ASMSetDR2(pCtx->dr2);
    733             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    734         }
    735         if (pCtx->dr7 & (X86_DR7_L3|X86_DR7_G3))
    736         {
    737             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR3Armed);
    738             ASMSetDR3(pCtx->dr3);
    739             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    740         }
    741 
    742         /* No need to sync DR6; all DR6 reads are intercepted. */
    743 #endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */
     698        /* Sync the debug state now if any breakpoint is armed. */
     699        if (    (pCtx->dr7 & (X86_DR7_ENABLED_MASK|X86_DR7_GD))
     700            &&  !CPUMIsGuestDebugStateActive(pVM)
     701            &&  !DBGFIsStepping(pVM))
     702        {
     703            STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxArmed);
     704
     705            /* Disable drx move intercepts. */
     706            pVMCB->ctrl.u16InterceptRdDRx = 0;
     707            pVMCB->ctrl.u16InterceptWrDRx = 0;
     708
     709            /* Save the host and load the guest debug state. */
     710            int rc = CPUMR0LoadGuestDebugState(pVM, pCtx, false /* exclude DR6 */);
     711            AssertRC(rc);
     712        }
    744713    }
    745714
     
    13111280        switch (vector)
    13121281        {
    1313 #ifdef DEBUG
    13141282        case X86_XCPT_DB:
    13151283        {
    1316 #if 0 /* revisit */
    1317             rc = DBGFR0Trap01Handler(pVM, CPUMCTX2CORE(pCtx), pVMCB->guest.u64DR6);
    1318             Assert(rc != VINF_EM_RAW_GUEST_TRAP);
     1284            STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitGuestDB);
     1285
     1286            /* Note that we don't support guest and host-initiated debugging at the same time. */
     1287            Assert(DBGFIsStepping(pVM));
     1288
     1289            rc = DBGFR0Trap01Handler(pVM, CPUMCTX2CORE(pCtx), pCtx->dr6);
     1290            if (rc == VINF_EM_RAW_GUEST_TRAP)
     1291            {
     1292                Log(("Trap %x (debug) at %VGv\n", vector, pCtx->rip));
     1293
     1294                /* Reinject the exception. */
     1295                Event.au64[0]    = 0;
     1296                Event.n.u3Type   = SVM_EVENT_EXCEPTION; /* trap or fault */
     1297                Event.n.u1Valid  = 1;
     1298                Event.n.u8Vector = X86_XCPT_DB;
     1299
     1300                SVMR0InjectEvent(pVM, pVMCB, pCtx, &Event);
     1301
     1302                STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     1303                goto ResumeExecution;
     1304            }
     1305            /* Return to ring 3 to deal with the debug exit code. */
    13191306            break;
    1320 #endif
    1321             /* @todo we don't really need to intercept this here. It's easy to sync back dr7 & dr6 after each world switch. */
    1322             /* Sync back DR6 and DR7 here. */
    1323             pCtx->dr6  = pVMCB->guest.u64DR6;
    1324             pCtx->dr7  = pVMCB->guest.u64DR7;
    1325 
    1326             STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitGuestDB);
    1327             Log(("Trap %x (debug) at %VGv\n", vector, pCtx->rip));
    1328 
    1329             /* Reinject the exception. */
    1330             Event.au64[0]    = 0;
    1331             Event.n.u3Type   = SVM_EVENT_EXCEPTION; /* trap or fault */
    1332             Event.n.u1Valid  = 1;
    1333             Event.n.u8Vector = X86_XCPT_DB;
    1334 
    1335             SVMR0InjectEvent(pVM, pVMCB, pCtx, &Event);
    1336 
    1337             STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    1338             goto ResumeExecution;
    1339         }
    1340 #endif
     1307        }
    13411308
    13421309        case X86_XCPT_NM:
     
    17301697        Log2(("SVM: %VGv mov dr%d, x\n", pCtx->rip, exitCode - SVM_EXIT_WRITE_DR0));
    17311698        STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitDRxRead);
     1699
     1700        if (!DBGFIsStepping(pVM))
     1701        {
     1702            STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxContextSwitch);
     1703
     1704            /* Disable drx move intercepts. */
     1705            pVMCB->ctrl.u16InterceptRdDRx = 0;
     1706            pVMCB->ctrl.u16InterceptWrDRx = 0;
     1707
     1708            /* Save the host and load the guest debug state. */
     1709            rc = CPUMR0LoadGuestDebugState(pVM, pCtx, false /* exclude DR6 */);
     1710            AssertRC(rc);
     1711
     1712            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     1713            goto ResumeExecution;
     1714        }
     1715
    17321716        rc = EMInterpretInstruction(pVM, CPUMCTX2CORE(pCtx), 0, &cbSize);
    17331717        if (rc == VINF_SUCCESS)
     
    17531737        Log2(("SVM: %VGv mov dr%d, x\n", pCtx->rip, exitCode - SVM_EXIT_READ_DR0));
    17541738        STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitDRxRead);
     1739
     1740        if (!DBGFIsStepping(pVM))
     1741        {
     1742            STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxContextSwitch);
     1743
     1744            /* Disable drx move intercepts. */
     1745            pVMCB->ctrl.u16InterceptRdDRx = 0;
     1746            pVMCB->ctrl.u16InterceptWrDRx = 0;
     1747
     1748            /* Save the host and load the guest debug state. */
     1749            rc = CPUMR0LoadGuestDebugState(pVM, pCtx, false /* exclude DR6 */);
     1750            AssertRC(rc);
     1751
     1752            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     1753            goto ResumeExecution;
     1754        }
     1755
    17551756        rc = EMInterpretInstruction(pVM, CPUMCTX2CORE(pCtx), 0, &cbSize);
    17561757        if (rc == VINF_SUCCESS)
     
    20112012 * @returns VBox status code.
    20122013 * @param   pVM         The VM to operate on.
     2014 * @param   pCtx        CPU context
    20132015 */
    2014 HWACCMR0DECL(int) SVMR0Leave(PVM pVM)
     2016HWACCMR0DECL(int) SVMR0Leave(PVM pVM, PCPUMCTX pCtx)
    20152017{
     2018    SVM_VMCB *pVMCB = (SVM_VMCB *)pVM->hwaccm.s.svm.pVMCB;
     2019
    20162020    Assert(pVM->hwaccm.s.svm.fSupported);
     2021
     2022    /* Save the guest debug state if necessary. */
     2023    if (CPUMIsGuestDebugStateActive(pVM))
     2024    {
     2025        CPUMR0SaveGuestDebugState(pVM, pCtx, false /* skip DR6 */);
     2026
     2027        /* Intercept all DRx reads and writes again. Changed later on. */
     2028        pVMCB->ctrl.u16InterceptRdDRx = 0xFFFF;
     2029        pVMCB->ctrl.u16InterceptWrDRx = 0xFFFF;
     2030
     2031        /* Resync the debug registers the next time. */
     2032        pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_DEBUG;
     2033    }
     2034    else
     2035        Assert(pVMCB->ctrl.u16InterceptRdDRx == 0xFFFF && pVMCB->ctrl.u16InterceptWrDRx == 0xFFFF);
     2036
    20172037    return VINF_SUCCESS;
    20182038}
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.h

    r10502 r12578  
    5656 * @returns VBox status code.
    5757 * @param   pVM         The VM to operate on.
     58 * @param   pCtx        CPU context
    5859 */
    59 HWACCMR0DECL(int) SVMR0Leave(PVM pVM);
     60HWACCMR0DECL(int) SVMR0Leave(PVM pVM, PCPUMCTX pCtx);
    6061
    6162/**
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r12554 r12578  
    380380     * @note only possible if the current state is actually ours (X86_CR0_TS flag)
    381381     */
    382     rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, HWACCM_VMX_TRAP_MASK);
     382    pVM->hwaccm.s.vmx.u32TrapMask = HWACCM_VMX_TRAP_MASK;
     383    rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, pVM->hwaccm.s.vmx.u32TrapMask);
    383384    AssertRC(rc);
    384385
     
    866867                if (!pVM->hwaccm.s.fFPUOldStyleOverride)
    867868                {
    868                     rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, HWACCM_VMX_TRAP_MASK | RT_BIT(X86_XCPT_MF));
     869                    pVM->hwaccm.s.vmx.u32TrapMask |= RT_BIT(X86_XCPT_MF);
     870                    rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, pVM->hwaccm.s.vmx.u32TrapMask);
    869871                    AssertRC(rc);
    870872                    pVM->hwaccm.s.fFPUOldStyleOverride = true;
     
    966968    if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_DEBUG)
    967969    {
    968         pCtx->dr7 &= 0xffffffff;                                              /* upper 32 bits reserved */
    969         pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
    970         pCtx->dr7 |= 0x400;                                                   /* must be one */
    971 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    972         rc |= VMXWriteVMCS(VMX_VMCS_GUEST_DR7,  pCtx->dr7);
    973 #else
    974         rc |= VMXWriteVMCS(VMX_VMCS_GUEST_DR7,  0x400);
    975 #endif
    976         AssertRC(rc);
    977 
    978 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    979         /* Any guest breakpoints enabled? */
    980         if (    (pCtx->dr7 & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
    981             &&  !pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved)
    982         {
    983             /* Save the host debug register; a bit paranoid if the host has no active breakpoints set in dr7, but we
    984              * do not want anything from the guest to leak into the host!
    985              */
    986             pVM->hwaccm.s.savedhoststate.dr0 = ASMGetDR0();
    987             pVM->hwaccm.s.savedhoststate.dr1 = ASMGetDR1();
    988             pVM->hwaccm.s.savedhoststate.dr2 = ASMGetDR2();
    989             pVM->hwaccm.s.savedhoststate.dr3 = ASMGetDR3();
    990             pVM->hwaccm.s.savedhoststate.dr6 = ASMGetDR6();
    991             pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved = true;
    992 
    993             /* Make sure DR7 is harmless or else we could trigger breakpoints when restoring dr0-3 (!) */
    994             ASMSetDR7(0x400);
    995         }
    996 
    997         if (pCtx->dr7 & (X86_DR7_L0|X86_DR7_G0))
    998         {
    999             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR0Armed);
    1000             ASMSetDR0(pCtx->dr0);
    1001             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    1002         }
    1003         if (pCtx->dr7 & (X86_DR7_L1|X86_DR7_G1))
    1004         {
    1005             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR1Armed);
    1006             ASMSetDR1(pCtx->dr1);
    1007             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    1008         }
    1009         if (pCtx->dr7 & (X86_DR7_L2|X86_DR7_G2))
    1010         {
    1011             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR2Armed);
    1012             ASMSetDR2(pCtx->dr2);
    1013             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    1014         }
    1015         if (pCtx->dr7 & (X86_DR7_L3|X86_DR7_G3))
    1016         {
    1017             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDR3Armed);
    1018             ASMSetDR3(pCtx->dr3);
    1019             Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved);
    1020         }
    1021 
    1022         /* No need to sync DR6; all DR6 reads are intercepted. */
    1023 #endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */
     970        pCtx->dr6 |= X86_DR6_INIT_VAL;                                          /* set all reserved bits to 1. */
     971        pCtx->dr6 &= ~RT_BIT(12);                                               /* must be zero. */
     972
     973        pCtx->dr7 &= 0xffffffff;                                                /* upper 32 bits reserved */
     974        pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));      /* must be zero */
     975        pCtx->dr7 |= 0x400;                                                     /* must be one */
     976
     977        /* Resync DR7 */
     978        rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr7);
     979        AssertRC(rc);
     980
     981        /* Sync the debug state now if any breakpoint is armed. */
     982        if (    (pCtx->dr7 & (X86_DR7_ENABLED_MASK|X86_DR7_GD))
     983            &&  !CPUMIsGuestDebugStateActive(pVM)
     984            &&  !DBGFIsStepping(pVM))
     985        {
     986            STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxArmed);
     987
     988            /* Disable drx move intercepts. */
     989            pVM->hwaccm.s.vmx.proc_ctls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT;
     990            rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVM->hwaccm.s.vmx.proc_ctls);
     991            AssertRC(rc);
     992
     993            /* Save the host and load the guest debug state. */
     994            rc = CPUMR0LoadGuestDebugState(pVM, pCtx, true /* include DR6 */);
     995            AssertRC(rc);
     996        }
    1024997
    1025998        /* IA32_DEBUGCTL MSR. */
     
    11131086        pVM->hwaccm.s.vmx.pfnStartVM  = VMXR0StartVM32;
    11141087    }
     1088
     1089#ifdef DEBUG
     1090    /* Intercept X86_XCPT_DB if stepping is enabled */
     1091    if (DBGFIsStepping(pVM))
     1092        pVM->hwaccm.s.vmx.u32TrapMask |= RT_BIT(X86_XCPT_DB);
     1093    else
     1094        pVM->hwaccm.s.vmx.u32TrapMask &= ~RT_BIT(X86_XCPT_DB);
     1095
     1096    rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, pVM->hwaccm.s.vmx.u32TrapMask);
     1097#endif
    11151098
    11161099    /* Done. */
     
    15641547    CPUMSetGuestCR2(pVM, ASMGetCR2());
    15651548
    1566     /* No need to sync back DR7 here; it can only be changed by DR7 writes and debug exceptions. Both are intercepted. */
     1549    /* Sync back DR7 here. */
     1550    VMXReadVMCS(VMX_VMCS_GUEST_DR7, &val);
     1551    pCtx->dr7 = val;
    15671552
    15681553    /* Guest CPU context: ES, CS, SS, DS, FS, GS. */
     
    17731758            case X86_XCPT_DB:   /* Debug exception. */
    17741759            {
     1760                uint64_t uDR6;
     1761
    17751762                /* DR6, DR7.GD and IA32_DEBUGCTL.LBR are not updated yet.
    17761763                 *
     
    17821769                 * 63:15    Reserved (0)
    17831770                 */
    1784 
    1785 #ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT
    1786                 /* Update DR6 here. */
    1787                 pCtx->dr6  = X86_DR6_INIT_VAL;
    1788                 pCtx->dr6 |= (exitQualification & (X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3|X86_DR6_BD|X86_DR6_BS));
    1789 
    1790                 /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
    1791                 pCtx->dr7 &= ~X86_DR7_GD;
    1792 
    1793                 /* Paranoia. */
    1794                 pCtx->dr7 &= 0xffffffff;                                              /* upper 32 bits reserved */
    1795                 pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
    1796                 pCtx->dr7 |= 0x400;                                                   /* must be one */
    1797 
    1798                 /* Resync DR7 */
    1799                 rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr7);
    1800                 AssertRC(rc);
    1801 #endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */
    1802 
    18031771                STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitGuestDB);
    1804                 Log(("Trap %x (debug) at %VGv exit qualification %VX64\n", vector, pCtx->rip, exitQualification));
    1805                 rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
    1806                 AssertRC(rc);
    1807 
    1808                 STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    1809                 goto ResumeExecution;
     1772
     1773                /* Note that we don't support guest and host-initiated debugging at the same time. */
     1774                Assert(DBGFIsStepping(pVM));
     1775
     1776                uDR6  = X86_DR6_INIT_VAL;
     1777                uDR6 |= (exitQualification & (X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3|X86_DR6_BD|X86_DR6_BS));
     1778                rc = DBGFR0Trap01Handler(pVM, CPUMCTX2CORE(pCtx), uDR6);
     1779                if (rc == VINF_EM_RAW_GUEST_TRAP)
     1780                {
     1781                    /* Update DR6 here. */
     1782                    pCtx->dr6  = uDR6;
     1783
     1784                    /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
     1785                    pCtx->dr7 &= ~X86_DR7_GD;
     1786
     1787                    /* Paranoia. */
     1788                    pCtx->dr7 &= 0xffffffff;                                              /* upper 32 bits reserved */
     1789                    pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
     1790                    pCtx->dr7 |= 0x400;                                                   /* must be one */
     1791
     1792                    /* Resync DR7 */
     1793                    rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr7);
     1794                    AssertRC(rc);
     1795
     1796                    Log(("Trap %x (debug) at %VGv exit qualification %VX64\n", vector, pCtx->rip, exitQualification));
     1797                    rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
     1798                    AssertRC(rc);
     1799
     1800                    STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     1801                    goto ResumeExecution;
     1802                }
     1803                /* Return to ring 3 to deal with the debug exit code. */
     1804                break;
    18101805            }
    18111806
     
    20362031    case VMX_EXIT_DRX_MOVE:             /* 29 Debug-register accesses. */
    20372032    {
     2033        if (!DBGFIsStepping(pVM))
     2034        {
     2035            /* Disable drx move intercepts. */
     2036            pVM->hwaccm.s.vmx.proc_ctls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT;
     2037            rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVM->hwaccm.s.vmx.proc_ctls);
     2038            AssertRC(rc);
     2039
     2040            /* Save the host and load the guest debug state. */
     2041            rc = CPUMR0LoadGuestDebugState(pVM, pCtx, true /* include DR6 */);
     2042            AssertRC(rc);
     2043
     2044#ifdef VBOX_WITH_STATISTICS
     2045            STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxContextSwitch);
     2046            if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
     2047                STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitDRxWrite);
     2048            else
     2049                STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitDRxRead);
     2050#endif
     2051
     2052            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     2053            goto ResumeExecution;
     2054        }
     2055
    20382056        /** @todo clear VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT after the first time and restore drx registers afterwards */
    20392057        if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
     
    23862404 * @returns VBox status code.
    23872405 * @param   pVM         The VM to operate on.
     2406 * @param   pCtx        CPU context
    23882407 */
    2389 HWACCMR0DECL(int) VMXR0Leave(PVM pVM)
     2408HWACCMR0DECL(int) VMXR0Leave(PVM pVM, PCPUMCTX pCtx)
    23902409{
    23912410    Assert(pVM->hwaccm.s.vmx.fSupported);
    23922411
     2412    /* Save the guest debug state if necessary. */
     2413    if (CPUMIsGuestDebugStateActive(pVM))
     2414    {
     2415        CPUMR0SaveGuestDebugState(pVM, pCtx, true /* save DR6 */);
     2416
     2417        /* Enable drx move intercepts again. */
     2418        pVM->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT;
     2419        int rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVM->hwaccm.s.vmx.proc_ctls);
     2420        AssertRC(rc);
     2421
     2422        /* Resync the debug registers the next time. */
     2423        pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_DEBUG;
     2424    }
     2425    else
     2426        Assert(pVM->hwaccm.s.vmx.proc_ctls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT);
     2427
    23932428    /* Clear VM Control Structure. Marking it inactive, clearing implementation specific data and writing back VMCS data to memory. */
    23942429    int rc = VMXClearVMCS(pVM->hwaccm.s.vmx.pVMCSPhys);
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.h

    r10502 r12578  
    5656 * @returns VBox status code.
    5757 * @param   pVM         The VM to operate on.
    58  */
    59 HWACCMR0DECL(int) VMXR0Leave(PVM pVM);
     58 * @param   pCtx        CPU context
     59 */
     60HWACCMR0DECL(int) VMXR0Leave(PVM pVM, PCPUMCTX pCtx);
    6061
    6162
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