VirtualBox

Changeset 12121

Show
Ignore:
Timestamp:
09/05/08 11:41:05 (3 months ago)
Author:
vboxsync
Message:

Committed hardware breakpoint support for VT-x and AMD-V. Untested and disabled.

Files:

Legend:

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

    r12016 r12121  
    707707    pCtx->trHid.Attr.n.u4Type       = X86_SEL_TYPE_SYS_386_TSS_BUSY; 
    708708 
    709     pCtx->dr6                       = UINT32_C(0xFFFF0FF0)
     709    pCtx->dr6                       = X86_DR6_INIT_VAL
    710710    pCtx->dr7                       = 0x400; 
    711711 
  • trunk/src/VBox/VMM/HWACCM.cpp

    r12078 r12121  
    126126    STAM_REG(pVM, &pVM->hwaccm.s.StatExitGuestMF,   STAMTYPE_COUNTER, "/HWACCM/Exit/Trap/Guest/#MF",    STAMUNIT_OCCURENCES,    "Nr of occurances"); 
    127127    STAM_REG(pVM, &pVM->hwaccm.s.StatExitGuestDE,   STAMTYPE_COUNTER, "/HWACCM/Exit/Trap/Guest/#DE",    STAMUNIT_OCCURENCES,    "Nr of occurances"); 
     128    STAM_REG(pVM, &pVM->hwaccm.s.StatExitGuestDB,   STAMTYPE_COUNTER, "/HWACCM/Exit/Trap/Guest/#DB",    STAMUNIT_OCCURENCES,    "Nr of occurances"); 
    128129    STAM_REG(pVM, &pVM->hwaccm.s.StatExitInvpg,     STAMTYPE_COUNTER, "/HWACCM/Exit/Instr/Invlpg",      STAMUNIT_OCCURENCES,    "Nr of occurances"); 
    129130    STAM_REG(pVM, &pVM->hwaccm.s.StatExitInvd,      STAMTYPE_COUNTER, "/HWACCM/Exit/Instr/Invd",        STAMUNIT_OCCURENCES,    "Nr of occurances"); 
  • trunk/src/VBox/VMM/HWACCMInternal.h

    r12090 r12121  
    3434#include <iprt/mp.h> 
    3535 
     36////#define VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT 
     37 
    3638#if HC_ARCH_BITS == 64 
    3739/* Enable 64 bits guest support. */ 
     
    110112 */ 
    111113#ifdef VBOX_STRICT 
    112 #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) 
     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) 
    113115#define HWACCM_SVM_TRAP_MASK                HWACCM_VMX_TRAP_MASK 
    114116#else 
    115 #define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF) 
    116 #define HWACCM_SVM_TRAP_MASK                HWACCM_VMX_TRAP_MASK 
     117#define HWACCM_VMX_TRAP_MASK                RT_BIT(X86_XCPT_DB) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF) 
     118#define HWACCM_SVM_TRAP_MASK                RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_PF) 
    117119#endif 
    118120/** @} */ 
     
    377379 
    378380 
    379 #ifdef VBOX_SAVE_HOST_DEBUG_REGISTERS 
     381#ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT 
    380382    struct 
    381383    { 
     
    383385        uint64_t                dr0, dr1, dr2, dr3, dr6, dr7; 
    384386        bool                    fHostDR7Saved; 
     387        bool                    fHostDebugRegsSaved; 
    385388    } savedhoststate; 
    386389#endif 
     
    401404    STAMCOUNTER             StatExitGuestGP; 
    402405    STAMCOUNTER             StatExitGuestDE; 
     406    STAMCOUNTER             StatExitGuestDB; 
    403407    STAMCOUNTER             StatExitGuestMF; 
    404408    STAMCOUNTER             StatExitInvpg; 
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r11764 r12121  
    21992199    if (VBOX_SUCCESS(rc)) 
    22002200    { 
     2201        /* @todo: we don't fail if illegal bits are set/cleared for e.g. dr7 */ 
    22012202        rc = CPUMSetGuestDRx(pVM, DestRegDrx, val); 
    22022203        if (VBOX_SUCCESS(rc)) 
  • trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp

    r12090 r12121  
    744744    CPUMDeactivateGuestFPUState(pVM); 
    745745 
    746 #ifdef VBOX_WITH_DEBUG_REGISTER_SUPPORT 
     746#ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT 
    747747    /* 
    748748     * Check if host debug registers are armed. All context switches set DR7 back to 0x400. 
    749749     */ 
    750750    uint64_t u64DR7 = ASMGetDR7(); 
    751     if (u32DR7 & X86_DR7_ENABLED_MASK) 
     751    if (u64DR7 & X86_DR7_ENABLED_MASK) 
    752752    { 
    753753        pVM->hwaccm.s.savedhoststate.dr7  = u64DR7; 
     
    806806    } 
    807807 
    808 #ifdef VBOX_WITH_DEBUG_REGISTER_SUPPORT 
     808#ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT 
     809    /* Restore the host debug registers. First dr0-3, then dr6 and only then dr7! */ 
     810    if (pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved) 
     811    { 
     812        ASMSetDR0(pVM->hwaccm.s.savedhoststate.dr0); 
     813        ASMSetDR1(pVM->hwaccm.s.savedhoststate.dr1); 
     814        ASMSetDR2(pVM->hwaccm.s.savedhoststate.dr2); 
     815        ASMSetDR3(pVM->hwaccm.s.savedhoststate.dr3); 
     816        ASMSetDR6(pVM->hwaccm.s.savedhoststate.dr6); 
     817        pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved = false; 
     818    } 
    809819    if (pVM->hwaccm.s.savedhoststate.fHostDR7Saved) 
    810820    { 
     
    814824#endif 
    815825 
     826    /* Resync the debug register on the next entry. */ 
     827    pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_DEBUG; 
    816828    return HWACCMR0Globals.pfnLeaveSession(pVM); 
    817829} 
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r12091 r12121  
    276276        pVMCB->ctrl.u16InterceptWrCRx = RT_BIT(0) | RT_BIT(4) | RT_BIT(8); 
    277277 
    278     /* Intercept all DRx reads and writes. */ 
    279     pVMCB->ctrl.u16InterceptRdDRx = RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7)
    280     pVMCB->ctrl.u16InterceptWrDRx = RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7)
     278    /* Intercept all DRx reads and writes. (@todo not necessary to intercept all) */ 
     279    pVMCB->ctrl.u16InterceptRdDRx = 0xFFFF
     280    pVMCB->ctrl.u16InterceptWrDRx = 0xFFFF
    281281 
    282282    /* Currently we don't care about DRx reads or writes. DRx registers are trashed. 
     
    686686    if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_DEBUG) 
    687687    { 
    688         val  = pCtx->dr7; 
    689         val &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */ 
    690         val |= 0x400;                                       /* must be one */ 
    691 #ifndef VBOX_WITH_DEBUG_REGISTER_SUPPORT 
    692         val = 0x400
    693 #endif 
    694         pVMCB->guest.u64DR7 = val
    695  
     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 
     692        pVMCB->guest.u64DR7 = pCtx->dr7
     693#else 
     694        pVMCB->guest.u64DR7 = 0x400
     695#endif 
    696696        pVMCB->guest.u64DR6 = pCtx->dr6; 
     697 
     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            ASMSetDR0(pCtx->dr0); 
     720            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     721        } 
     722        if (pCtx->dr7 & (X86_DR7_L1|X86_DR7_G1)) 
     723        { 
     724            ASMSetDR1(pCtx->dr1); 
     725            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     726        } 
     727        if (pCtx->dr7 & (X86_DR7_L2|X86_DR7_G2)) 
     728        { 
     729            ASMSetDR2(pCtx->dr2); 
     730            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     731        } 
     732        if (pCtx->dr7 & (X86_DR7_L3|X86_DR7_G3)) 
     733        { 
     734            ASMSetDR3(pCtx->dr3); 
     735            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     736        } 
     737 
     738        /* No need to sync DR6; all DR6 reads are intercepted. */ 
     739#endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */ 
    697740    } 
    698741 
     
    12001243    Log2(("exitCode = %x\n", exitCode)); 
    12011244 
    1202     /* Sync back the debug registers. */ 
     1245    /* Sync back DR6 as it could have been changed by hitting breakpoints. */ 
    12031246    pCtx->dr6 = pVMCB->guest.u64DR6; 
     1247    /* DR7.GD can be cleared by debug exceptions, so sync it back as well. */ 
    12041248    pCtx->dr7 = pVMCB->guest.u64DR7; 
    12051249 
     
    12651309#ifdef DEBUG 
    12661310        case X86_XCPT_DB: 
     1311        { 
     1312#if 0 /* revisit */ 
    12671313            rc = DBGFR0Trap01Handler(pVM, CPUMCTX2CORE(pCtx), pVMCB->guest.u64DR6); 
    12681314            Assert(rc != VINF_EM_RAW_GUEST_TRAP); 
    12691315            break; 
     1316#endif 
     1317            /* @todo we don't really need to intercept this here. It's easy to sync back dr7 & dr6 after each world switch. */ 
     1318            /* Sync back DR6 and DR7 here. */ 
     1319            pCtx->dr6  = pVMCB->guest.u64DR6; 
     1320            pCtx->dr7  = pVMCB->guest.u64DR7; 
     1321 
     1322            STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitGuestDB); 
     1323            Log(("Trap %x (debug) at %VGv\n", vector, pCtx->rip)); 
     1324 
     1325            /* Reinject the exception. */ 
     1326            Event.au64[0]    = 0; 
     1327            Event.n.u3Type   = SVM_EVENT_EXCEPTION; /* trap or fault */ 
     1328            Event.n.u1Valid  = 1; 
     1329            Event.n.u8Vector = X86_XCPT_DB; 
     1330 
     1331            SVMR0InjectEvent(pVM, pVMCB, pCtx, &Event); 
     1332 
     1333            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x); 
     1334            goto ResumeExecution; 
     1335        } 
    12701336#endif 
    12711337 
     
    14141480        case X86_XCPT_GP:   /* General protection failure exception.*/ 
    14151481        case X86_XCPT_UD:   /* Unknown opcode exception. */ 
    1416         case X86_XCPT_DE:   /* Debug exception. */ 
     1482        case X86_XCPT_DE:   /* Divide error. */ 
    14171483        case X86_XCPT_SS:   /* Stack segment exception. */ 
    14181484        case X86_XCPT_NP:   /* Segment not present exception. */ 
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r12091 r12121  
    966966    if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_DEBUG) 
    967967    { 
    968         val  = pCtx->dr7 & 0xffffffff;                                  /* upper 32 bits reserved */ 
    969         val &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */ 
    970         val |= 0x400;                                                   /* must be one */ 
    971 #ifdef VBOX_WITH_DEBUG_REGISTER_SUPPORT 
    972         rc |= VMXWriteVMCS(VMX_VMCS_GUEST_DR7,              val); 
     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); 
    973973#else 
    974         rc |= VMXWriteVMCS(VMX_VMCS_GUEST_DR7,            0x400); 
    975 #endif 
    976         AssertRC(rc); 
     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) 
     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            ASMSetDR0(pCtx->dr0); 
     1000            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     1001        } 
     1002        if (pCtx->dr7 & (X86_DR7_L1|X86_DR7_G1)) 
     1003        { 
     1004            ASMSetDR1(pCtx->dr1); 
     1005            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     1006        } 
     1007        if (pCtx->dr7 & (X86_DR7_L2|X86_DR7_G2)) 
     1008        { 
     1009            ASMSetDR2(pCtx->dr2); 
     1010            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     1011        } 
     1012        if (pCtx->dr7 & (X86_DR7_L3|X86_DR7_G3)) 
     1013        { 
     1014            ASMSetDR3(pCtx->dr3); 
     1015            Assert(pVM->hwaccm.s.savedhoststate.fHostDebugRegsSaved); 
     1016        } 
     1017 
     1018        /* No need to sync DR6; all DR6 reads are intercepted. */ 
     1019#endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */ 
    9771020 
    9781021        /* IA32_DEBUGCTL MSR. */ 
     
    15131556    CPUMSetGuestCR2(pVM, ASMGetCR2()); 
    15141557 
    1515     VMXReadVMCS(VMX_VMCS_GUEST_DR7,              &val); 
    1516     CPUMSetGuestDR7(pVM, val); 
    1517  
    15181558    /* Guest CPU context: ES, CS, SS, DS, FS, GS. */ 
    15191559    VMX_READ_SELREG(ES, es); 
     
    17211761            } 
    17221762 
     1763            case X86_XCPT_DB:   /* Debug exception. */ 
     1764            { 
     1765                /* DR6, DR7.GD and IA32_DEBUGCTL.LBR are not updated yet.  
     1766                 * 
     1767                 * Exit qualification bits: 
     1768                 *  3:0     B0-B3 which breakpoint condition was met 
     1769                 * 12:4     Reserved (0) 
     1770                 * 13       BD - debug register access detected 
     1771                 * 14       BS - single step execution or branch taken 
     1772                 * 63:15    Reserved (0) 
     1773                 */ 
     1774 
     1775#ifdef VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT 
     1776                /* Update DR6 here. */ 
     1777                pCtx->dr6  = X86_DR6_INIT_VAL; 
     1778                pCtx->dr6 |= (exitQualification & (X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3|X86_DR6_BD|X86_DR6_BS)); 
     1779 
     1780                /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */ 
     1781                pCtx->dr7 &= ~X86_DR7_GD; 
     1782 
     1783                /* Paranoia. */ 
     1784                pCtx->dr7 &= 0xffffffff;                                              /* upper 32 bits reserved */ 
     1785                pCtx->dr7 &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */ 
     1786                pCtx->dr7 |= 0x400;                                                   /* must be one */ 
     1787 
     1788                /* Resync DR7 */ 
     1789                rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr7); 
     1790                AssertRC(rc); 
     1791#endif /* VBOX_WITH_HWACCM_DEBUG_REGISTER_SUPPORT */ 
     1792 
     1793                STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitGuestDB); 
     1794                Log(("Trap %x (debug) at %VGv exit qualification %VX64\n", vector, pCtx->rip, exitQualification)); 
     1795                rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode); 
     1796                AssertRC(rc); 
     1797 
     1798                STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x); 
     1799                goto ResumeExecution; 
     1800            } 
     1801 
    17231802#ifdef VBOX_STRICT 
     1803            case X86_XCPT_DE:   /* Divide error. */ 
    17241804            case X86_XCPT_GP:   /* General protection failure exception.*/ 
    17251805            case X86_XCPT_UD:   /* Unknown opcode exception. */ 
    1726             case X86_XCPT_DE:   /* Debug exception. */ 
    17271806            case X86_XCPT_SS:   /* Stack segment exception. */ 
    17281807            case X86_XCPT_NP:   /* Segment not present exception. */ 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy