VirtualBox

Changeset 12121 in vbox


Ignore:
Timestamp:
Sep 5, 2008 9:41:05 AM (16 years ago)
Author:
vboxsync
Message:

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

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

Legend:

Unmodified
Added
Removed
  • 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. */
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